+1 (315) 557-6473 

Trying Different Password Combinations in Assembly Language Assignment Solution.


Instructions

Objective
Write program to try different password combinations in assembly language Assembly language.

Requirements and Specifications

A valid password consists of up to 7 characters and must contain one lowercase letter, one uppercase letter, and one digit from 0-9. You are a security consultant for XYZ. Your job is to assess the security of their password-protected network. To enter their network, the user must pass the password checker. This is accomplished by calling a function and passing into the function a password string:
int check_password(char *passwd);
check_password returns a 7-digit integer of 0s and 1s to indicate which character was correct (0 to indicate a character was incorrect, 1 to indicate it is correct, and 2 to indicate it was not used). If the password entered is "aB2" and the passwd is "a11", then check_password returns the integer 2222100. If the password entered is "ab2", then check_password returns the integer 2222101.
To write an assembly language assignment function "hack_password" that will find the secret password stored in "check_password" by iterating through all possible combinations of a-z, A-Z, and 0-9 according to password rule given above and calling the function check_password to determine when the return value is all 1's and 2's (e.g., 2211111,
1111111, 2222111, etc...). Note that the correct password decoder returns an indicator that a character was not used as well. hack_password will print out the correct password.
Screenshots of output
program to try different password in assembly language

Source Code
check_password
arch armv7 br>
.cpu cortex-a53
.data
password: .asciz "pA5SwD" @ internal password
.text
@ check the password that contains lowercase, uppercase and digits by comparing
@ it with the internal password, returns the number with the comparison result
@ The function expects r0 = password to check
@ Returns r0 = ckeck result number
.global check_password
.type check_password, %function
check_password:
    push {r4-r7, fp, lr} @ save used registers
    mov r4, r0 @ copy string address in r4
    bl str_len @ calculate string length
    mov r5, r0 @ save length in r5
    ldr r0, =password @ load password string address
    mov r7, r0 @ save pointer
    bl str_len @ calculate string length
    mov r6, r5 @ load test pwd len
    mov r3, #0 @ start num in zero
    mov r2, #6 @ maximum length - 1
    mov r1, #10 @ to multiply by 10
chk1_loop:
    cmp r2, r0 @ if i >= passwd len
    blt low1
    mul r3, r1, r3 @ multiply old number by 10
    add r3, r3, #2 @ save current digit (not used)
    cmp r2, r6 @ if i < test passwd len
    bge chk1_next
    sub r5, r5, #1 @ decrement test string length
    add r4, r4, #1 @ increment test string start
    b chk1_next
low1:
    cmp r2, r6 @ if i >= test passwd len
    blt compare
    mul r3, r1, r3 @ multiply old number by 10 (save zero)
    add r7, r7, #1 @ increment pwd string start
chk1_next:
    sub r2, r2, #1 @ decrement chars to check
    cmp r2, #0 @ if i >= 0
    bge chk1_loop @ repeat loop
compare:
    mov r0, r5 @ loop length of test string
chk2_loop:
    ldrb r1, [r4], #1 @ load char from tst password
    ldrb r2, [r7], #1 @ load char from preset password
    cmp r1, r2 @ compare chars
    bne not_eq @ if equal
    mov r2, #1 @ save a 1
    b chk2_nxt
not_eq:
    mov r2, #0 @ else, save a zero
chk2_nxt:
    mov r1, #10 @ to multiply by 10
    mul r3, r1, r3 @ multiply old number by 10
    add r3, r3, r2 @ save current digit
    sub r0, r0, #1 @ decrement chars to check
    cmp r0, #0 @ if not zero
    bne chk2_loop @ repeat loop
    mov r0, r3 @ return number
ret1:
    pop {r4-r7, fp, lr} @ restore used registers
    bx lr @ return
@ Calculate the string length
@ Expects r0 = string address
@ Returns r0 = string length
.type str_len, %function
str_len:
    push {r4-r5,fp, lr} @ save used registers
    mov r4, r0 @ copy string address
    mov r0, #0 @ count of chars is zero
len_loop:
    ldrb r5, [r4], #1 @ load char and advance position
    cmp r5, #0 @ if end of string
    beq len_end @ end loop
    add r0, r0, #1 @ else increment length
    b len_loop @ repeat loop
len_end:
    pop {r4-r5, fp, lr} @ restore used registers
    bx lr @ return
hack_password
.arch armv7
.cpu cortex-a53
.data
pass: .space 8 @ max 7 chars + ending zero
result: .asciz "Password is: %s\n"
.text
.type hack_password, %function
.global hack_password
hack_password:
    push {r4, fp, lr} @ save used registers
    ldr r0, =pass @ point to password string
    mov r1, #7 @ clear 7 chars
    bl zero_pass @ set pass as all zeros
    ldr r0, =pass @ point to password string
    bl get_pwd_len @ calculate password length
    mov r4, r0 @ save length in r4
    ldr r0, =pass @ point to password string
    mov r1, r4 @ use found password length
    bl zero_pass @ set pass as all zeros
gen_loop:
    ldr r0, =pass @ point to password string
    bl is_correct @ test if current pass is correct
    cmp r0, #0 @ if correct
    bne gen_end @ end and print
    mov r2, r1 @ pass correct mask
    ldr r0, =pass @ point to password string
    mov r1, r4 @ use given length
    bl inc_pass @ increment previous password
    b gen_loop @ test new password
gen_end:
    ldr r0, =result @ load result message
    ldr r1, =pass @ load generated password
    bl printf @ print result
    pop {r4, fp, lr} @ restore used registers
    bx lr @ return
@ Generate a password with only zeros
@ Expects r0 = password address, r1 = password length
.type zero_pass, %function
zero_pass:
    mov r2, #'0' @ save 0's as initial pass
init:
    strb r2, [r0], #1 @ save initial char
    sub r1, r1, #1 @ decrement length
    cmp r1, #0 @ repeat while not zero
    bne init
    strb r1, [r0] @ save ending zero
    bx lr @ return
@ Increment password, incrementing each char 0 to 9, then A to Z, then a to z
@ and start over to 0 incrementing next character if incrementing z
@ Expects r0 = password address, r1 = password length, r2 = correct mask
.type inc_pass, %function
inc_pass:
    add r0, r0, r1 @ point to last character
    sub r0, r0, #1
inc_loop:
    and r3, r2, #1 @ check if current character is correct
    cmp r3, #0
    beq inc_char @ if not correct, increment
    lsr r2, r2, #1 @ else, shift mask position
    b chg_advance @ and go to next char
inc_char:
    ldrb r3, [r0] @ load character
    cmp r3, #'9' @ if last digit
    beq chg_upper @ change to upper
    cmp r3, #'Z' @ if last uppercase
    beq chg_lower @ change to lowercase
    cmp r3, #'z' @ if last lowercase
    beq chg_next @ start over and change next
    add r3, r3, #1 @ else, increment ascii
    b inc_end @ and return
chg_upper:
    mov r3, #'A' @ use first uppercase
    b inc_end @ and return
chg_lower:
    mov r3, #'a' @ use first uppercase
    b inc_end @ and return
chg_next:
    mov r3, #'0' @ wrap around
    strb r3, [r0] @ save updated character
chg_advance:
    sub r0, r0, #1 @ advance to next char
    sub r1, r1, #1 @ decrement length
    cmp r1, #0
    bne inc_loop @ repeat if not zero
    b inc_ret
inc_end:
    strb r3, [r0] @ save updated character
inc_ret:
    bx lr @ return
@ get password length by using a test string
@ Expects r0 = password address
@ Returns r0 = password length
.type get_pwd_len, %function
get_pwd_len:
    push {r4-r6, fp, lr} @ save used registers
    bl check_password @ check the password
    mov r1, #10 @ to divide by 10
    mov r2, #0 @ length is zero
    mov r3, #7 @ check 7 digits
len_loop:
    udiv r4, r0, r1 @ divide number by 10
    mul r5, r4, r1 @ multiply result by 10
    sub r6, r0, r5 @ subtract to get remainder
    cmp r6, #2 @ if unused
    beq len_end @ end loop
    add r2, r2, #1 @ else, increment length
    mov r0, r4 @ save quotient as number
    sub r3, r3, #1 @ decrement digits
    cmp r3, #0 @ repeat while not zero
    bne len_loop
len_end:
    mov r0, r2 @ return length
    pop {r4-r6, fp, lr} @ restore used registers
    bx lr @ return
@ Check if password is correct
@ Expects r0 = password address
@ Returns r0 = 1 if correct, 0 if not, r1 = correct mask
.type is_correct, %function
is_correct:
    push {r4-r7, fp, lr} @ save used registers
    bl check_password @ check the password
    mov r1, #10 @ to divide by 10
    mov r2, #1 @ assume correct
    mov r3, #0 @ current digit =0
    mov r7, #0 @ start mask as all not correct
tst_loop:
    udiv r4, r0, r1 @ divide number by 10
    mul r5, r4, r1 @ multiply result by 10
    sub r6, r0, r5 @ subtract to get remainder
    cmp r6, #1 @ if correct
    beq save_bit @ save bit 1
    cmp r6, #0 @ if incorrect
    bne save_zero
    mov r2, #0 @ set as incorrect
save_zero:
    mov r6, #0 @ else, save zero
save_bit:
    lsl r6, r6, r3 @ move to bit position
    orr r7, r7, r6 @ set correct bit
    mov r0, r4 @ save quotient as new number
    add r3, r3, #1 @ increment digits
    cmp r3, #7 @ repeat while not 7
    blt tst_loop
    mov r0, r2 @ return correct flag
    mov r1, r7 @ return correct mask
    pop {r4-r7, fp, lr} @ restore used registers
    bx lr @ return
Main program
#include
extern int hack_password();
int main(int argc, char **argv)
{
    hack_password();
    return 0;
}