# Assembly analysis for override # level00 ``` objdump -M intel -d level00 objdump -s -j .data level00 -> -s stands for full content, -j stands for section ``` ## main ``` 8048494: 55 push ebp 8048495: 89 e5 mov ebp,esp 8048497: 83 e4 f0 and esp,0xfffffff0 ``` - `8048494` to `8048494` Sets up the stack frame by moving the stack pointers away from the parents esp to the current ebp - `8048497` Stack alignment to the closes 8 bytes. The esp moves up by 8 bytes. --- ``` 804849a: 83 ec 20 sub esp,0x20 804849d: c7 04 24 f0 85 04 08 mov DWORD PTR [esp],0x80485f0 80484a4: e8 e7 fe ff ff call 8048390 <puts@plt> 80484a9: c7 04 24 14 86 04 08 mov DWORD PTR [esp],0x8048614 80484b0: e8 db fe ff ff call 8048390 <puts@plt> 80484b5: c7 04 24 f0 85 04 08 mov DWORD PTR [esp],0x80485f0 80484bc: e8 cf fe ff ff call 8048390 <puts@plt> ``` - `804849a` bulk allocates 32 bytes in the stack - `804849d - 804849d` calls ``` puts("***********************************"); puts ("-Level00 -"); puts("***********************************"); ``` --- ``` 80484c1: b8 2c 86 04 08 mov eax,0x804862c 80484c6: 89 04 24 mov DWORD PTR [esp],eax 80484c9: e8 b2 fe ff ff call 8048380 <printf@plt> ``` - `80484c1 - 80484c9` calls printf("Password: ") --- ``` 80484ce: b8 36 86 04 08 mov eax,0x8048636 80484d3: 8d 54 24 1c lea edx,[esp+0x1c] 80484d7: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 80484db: 89 04 24 mov DWORD PTR [esp],eax 80484de: e8 ed fe ff ff call 80483d0 <__isoc99_scanf@plt> 80484e3: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 80484e7: 3d 9c 14 00 00 cmp eax,0x149c ``` - `80484ce` prepares the "%d" string in eax - `80484d3` loads a variable (pointer is at esp + 0x1c) to edx, which will be used by scanf later. Lets call this `input` - `80484d7 - 80484de` Calls ``` in_buf = scanf("%d", &input); ``` - `80484e3 - 80484e7` derefrences the pointer to `input` and compares it with 5276 --- ``` 80484ec: 75 1f jne 804850d <main+0x79> 80484ee: c7 04 24 39 86 04 08 mov DWORD PTR [esp],0x8048639 80484f5: e8 96 fe ff ff call 8048390 <puts@plt> 80484fa: c7 04 24 49 86 04 08 mov DWORD PTR [esp],0x8048649 8048501: e8 9a fe ff ff call 80483a0 <system@plt> 8048506: b8 00 00 00 00 mov eax,0x0 804850b: eb 11 jmp 804851e <main+0x8a> 804850d: c7 04 24 51 86 04 08 mov DWORD PTR [esp],0x8048651 8048514: e8 77 fe ff ff call 8048390 <puts@plt> 8048519: b8 01 00 00 00 mov eax,0x1 804851e: c9 leave 804851f: c3 ret ``` - `80484ec` if the comparison is not equal, jump to `804850d` - `80484ee - 8048501` calls `puts("Authenticated!")` and runs `system("/bin/sh")` - `804850b` return 0 - `804850d - 8048514` calls `puts("Invalid Password!")` - `8048519 - 804851f` return 1 # level01 ``` objdump -M intel -d level01 objdump -s -j .data level01 ``` ## main ``` 80484d0: 55 push ebp 80484d1: 89 e5 mov ebp,esp 80484d3: 57 push edi 80484d4: 53 push ebx 80484d5: 83 e4 f0 and esp,0xfffffff0 80484d8: 83 ec 60 sub esp,0x60 80484db: 8d 5c 24 1c lea ebx,[esp+0x1c] 80484df: b8 00 00 00 00 mov eax,0x0 80484e4: ba 10 00 00 00 mov edx,0x10 80484e9: 89 df mov edi,ebx 80484eb: 89 d1 mov ecx,edx 80484ed: f3 ab rep stos DWORD PTR es:[edi],eax 80484ef: c7 44 24 5c 00 00 00 mov DWORD PTR [esp+0x5c],0x0 ``` - `80484d0 - 80484d5` Stack frame setup and stack alignment - `80484d8 - 80484db` Allocates 96 bytes on the stack and loads a buffer at [esp + 0x1c] to ebx. Call this **child_input** - `80484df - 80484ed` Repeatedly fill up the data pointed in `edi` (child_input) with the value in `eax`, which is 16, for `edx` times which is 10. The `es` is an explicit segmentation specifier for compatibility issues. Effectively, this does `memset(child_input, 0, 16);` ``` 80484ef: c7 44 24 5c 00 00 00 mov DWORD PTR [esp+0x5c],0x0 80484f6: 00 80484f7: c7 04 24 b8 86 04 08 mov DWORD PTR [esp],0x80486b8 80484fe: e8 7d fe ff ff call 8048380 <puts@plt> 8048503: b8 df 86 04 08 mov eax,0x80486df 8048508: 89 04 24 mov DWORD PTR [esp],eax 804850b: e8 50 fe ff ff call 8048360 <printf@plt> ``` - `80484ef` Write 0 to a pointer at [esp + 0x5c], Call this **num** - `80484f7 - 80484fe` Effectively call `puts("********* ADMIN LOGIN PROMPT *********")` - `804850b` Effectively call `printf("Enter Username:")` ``` 8048510: a1 20 a0 04 08 mov eax,ds:0x804a020 8048515: 89 44 24 08 mov DWORD PTR [esp+0x8],eax 8048519: c7 44 24 04 00 01 00 mov DWORD PTR [esp+0x4],0x100 8048520: 00 8048521: c7 04 24 40 a0 04 08 mov DWORD PTR [esp],0x804a040 8048528: e8 43 fe ff ff call 8048370 <fgets@plt> 804852d: e8 32 ff ff ff call 8048464 <verify_user_name> ``` - `8048510` Load a static global buffer into eax from `0x804a020`, call this **input_buf** - `8048515 - 8048528` Effectively call `fgets(input_buf, 256, stdin)` - `804852d` Call `verify_user_name` with the return value of fgets. ``` 8048532: 89 44 24 5c mov DWORD PTR [esp+0x5c],eax 8048536: 83 7c 24 5c 00 cmp DWORD PTR [esp+0x5c],0x0 804853b: 74 13 je 8048550 <main+0x80> 804853d: c7 04 24 f0 86 04 08 mov DWORD PTR [esp],0x80486f0 8048544: e8 37 fe ff ff call 8048380 <puts@plt> 8048549: b8 01 00 00 00 mov eax,0x1 804854e: eb 5f jmp 80485af <main+0xdf> ``` - `8048532 - 804853b` Load the return value of `verify_user_name` and write it to **num**. Compare it with value 0. If the result is equal, jump to `<main+0x80>`. - `804853d - 804854e` If not, call `puts("nope, incorrect username")` and return 1. ``` 8048550: c7 04 24 0d 87 04 08 mov DWORD PTR [esp],0x804870d 8048557: e8 24 fe ff ff call 8048380 <puts@plt> 804855c: a1 20 a0 04 08 mov eax,ds:0x804a020 8048561: 89 44 24 08 mov DWORD PTR [esp+0x8],eax 8048565: c7 44 24 04 64 00 00 mov DWORD PTR [esp+0x4],0x64 804856c: 00 804856d: 8d 44 24 1c lea eax,[esp+0x1c] 8048571: 89 04 24 mov DWORD PTR [esp],eax 8048574: e8 f7 fd ff ff call 8048370 <fgets@plt> 8048579: 8d 44 24 1c lea eax,[esp+0x1c] 804857d: 89 04 24 mov DWORD PTR [esp],eax 8048580: e8 1e ff ff ff call 80484a3 <verify_user_pass> ``` - `8048550 - 8048557` Effectively call `puts("Enter Password:")` - `804855c - 8048574` Effectively call `fgets(child_input, 100, stdin)` - `8048579 - 8048580` Effectively call `verify_user_pass` with the return value of fgets earlier ``` 8048585: 89 44 24 5c mov DWORD PTR [esp+0x5c],eax 8048589: 83 7c 24 5c 00 cmp DWORD PTR [esp+0x5c],0x0 804858e: 74 07 je 8048597 <main+0xc7> 8048590: 83 7c 24 5c 00 cmp DWORD PTR [esp+0x5c],0x0 8048595: 74 13 je 80485aa <main+0xda> 8048597: c7 04 24 1e 87 04 08 mov DWORD PTR [esp],0x804871e 804859e: e8 dd fd ff ff call 8048380 <puts@plt> 80485a3: b8 01 00 00 00 mov eax,0x1 80485a8: eb 05 jmp 80485af <main+0xdf> 80485aa: b8 00 00 00 00 mov eax,0x0 80485af: 8d 65 f8 lea esp,[ebp-0x8] 80485b2: 5b pop ebx 80485b3: 5f pop edi 80485b4: 5d pop ebp 80485b5: c3 ret ``` - `8048585 - 80485a8` Essentially the same operations earlier after we verify username, we compare the return value to 0, `puts("nope, incorrect password")` if its not and return 1 - `80485aa - 80485b5` return 0 ## verify_user_name ``` 8048464: 55 push ebp 8048465: 89 e5 mov ebp,esp 8048467: 57 push edi 8048468: 56 push esi 8048469: 83 ec 10 sub esp,0x10 804846c: c7 04 24 90 86 04 08 mov DWORD PTR [esp],0x8048690 8048473: e8 08 ff ff ff call 8048380 <puts@plt> 8048478: ba 40 a0 04 08 mov edx,0x804a040 804847d: b8 a8 86 04 08 mov eax,0x80486a8 8048482: b9 07 00 00 00 mov ecx,0x7 8048487: 89 d6 mov esi,edx 8048489: 89 c7 mov edi,eax 804848b: f3 a6 repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 804848d: 0f 97 c2 seta dl 8048490: 0f 92 c0 setb al 8048493: 89 d1 mov ecx,edx 8048495: 28 c1 sub cl,al 8048497: 89 c8 mov eax,ecx 8048499: 0f be c0 movsx eax,al 804849c: 83 c4 10 add esp,0x10 804849f: 5e pop esi 80484a0: 5f pop edi 80484a1: 5d pop ebp 80484a2: c3 ret ``` - `8048464 - 8048469` Sets up stack frame and allocates 16 bytes in stack - `804846c - 8048473` Effectively call `puts("verifying username....")` - `8048478 - 804848b` Sets up **input_buf** in `esi` and `"dat_wil"(from data section)` in `edi` and compare them. - `804848d - 8048490` Records the differences in `dl` or `al`. If the comparisons are equal, both of them should be 0 - `8048493 - 8048499` Perform arithmethic on the differences to get the actual return value, since `al` or `dl` does not reflect the full registers - there might have other things unintentionally - `804849f - 80484a2` Return the difference earlier. ## verify_user_pass ``` 80484a3: 55 push ebp 80484a4: 89 e5 mov ebp,esp 80484a6: 57 push edi 80484a7: 56 push esi 80484a8: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 80484ab: 89 c2 mov edx,eax 80484ad: b8 b0 86 04 08 mov eax,0x80486b0 80484b2: b9 05 00 00 00 mov ecx,0x5 80484b7: 89 d6 mov esi,edx 80484b9: 89 c7 mov edi,eax 80484bb: f3 a6 repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 80484bd: 0f 97 c2 seta dl 80484c0: 0f 92 c0 setb al 80484c3: 89 d1 mov ecx,edx 80484c5: 28 c1 sub cl,al 80484c7: 89 c8 mov eax,ecx 80484c9: 0f be c0 movsx eax,al 80484cc: 5e pop esi 80484cd: 5f pop edi 80484ce: 5d pop ebp 80484cf: c3 ret ``` - `80484a3 - 80484a8` Set up stack frame and load the first argument into `eax` - `80484ab - 80484cf` Compare it with the string "admin" from data segment, the rest is the same with `verify_user_name` # level02 ``` objdump -M intel -d level02 objdump -s -j .data level02 ``` ## main ``` 400814: 55 push rbp 400815: 48 89 e5 mov rbp,rsp 400818: 48 81 ec 20 01 00 00 sub rsp,0x120 40081f: 89 bd ec fe ff ff mov DWORD PTR [rbp-0x114],edi 400825: 48 89 b5 e0 fe ff ff mov QWORD PTR [rbp-0x120],rsi 40082c: 48 8d 55 90 lea rdx,[rbp-0x70] 400830: b8 00 00 00 00 mov eax,0x0 400835: b9 0c 00 00 00 mov ecx,0xc 40083a: 48 89 d7 mov rdi,rdx 40083d: f3 48 ab rep stos QWORD PTR es:[rdi],rax ```` - `400814 - 400815` preparing stack frame addresses - `400818 - 400825` allocates 288 bytes for the stack, loads the value of `edi` into `[rbp-0x114]` (call this **init_edi**), Load `rsi` into `[rbp-0x120]` (**init_rsi**) - `40082c - 40083d` Loads `[rbp-0x70]` into `rdx` (call this **username**) effectively call `memset(username, 0, 12)` --- ``` 400840: 48 89 fa mov rdx,rdi 400843: 89 02 mov DWORD PTR [rdx],eax 400845: 48 83 c2 04 add rdx,0x4 400849: 48 8d 95 60 ff ff ff lea rdx,[rbp-0xa0] 400850: b8 00 00 00 00 mov eax,0x0 400855: b9 05 00 00 00 mov ecx,0x5 40085a: 48 89 d7 mov rdi,rdx 40085d: f3 48 ab rep stos QWORD PTR es:[rdi],rax 400860: 48 89 fa mov rdx,rdi 400863: 88 02 mov BYTE PTR [rdx],al 400865: 48 83 c2 01 add rdx,0x1 ``` - `400840` Null terminates `username` and increments it by 4 (why?) - `400849 - 40085d` Loads `[rbp-0xa0]` aka **pass_file_content** into rdx and effectively call `memset(pass_file_content, 0, 5)` - `400860 - 400863` Null terminates `pass_file_content` and increments it by 1 (why?) --- ``` 400869: 48 8d 95 f0 fe ff ff lea rdx,[rbp-0x110] 400870: b8 00 00 00 00 mov eax,0x0 400875: b9 0c 00 00 00 mov ecx,0xc 40087a: 48 89 d7 mov rdi,rdx 40087d: f3 48 ab rep stos QWORD PTR es:[rdi],rax 400880: 48 89 fa mov rdx,rdi 400883: 89 02 mov DWORD PTR [rdx],eax 400885: 48 83 c2 04 add rdx,0x4 ``` - `400869 - 400883` Do the same thing as above for another variable `[rbp-0x110]` aka **pass** using `memset(pass, 0, 12)`, this time it increments 4 in the end. --- ``` 400889: 48 c7 45 f8 00 00 00 mov QWORD PTR [rbp-0x8],0x0 400890: 00 400891: c7 45 f4 00 00 00 00 mov DWORD PTR [rbp-0xc],0x0 400898: ba b0 0b 40 00 mov edx,0x400bb0 40089d: b8 b2 0b 40 00 mov eax,0x400bb2 4008a2: 48 89 d6 mov rsi,rdx 4008a5: 48 89 c7 mov rdi,rax 4008a8: e8 53 fe ff ff call 400700 <fopen@plt> 4008ad: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax 4008b1: 48 83 7d f8 00 cmp QWORD PTR [rbp-0x8],0x0 4008b6: 75 2e jne 4008e6 <main+0xd2> 4008b8: 48 8b 05 91 09 20 00 mov rax,QWORD PTR [rip+0x200991] # 601250 <stderr@@GLIBC_2.2.5> 4008bf: 48 89 c2 mov rdx,rax 4008c2: b8 d0 0b 40 00 mov eax,0x400bd0 4008c7: 48 89 d1 mov rcx,rdx 4008ca: ba 24 00 00 00 mov edx,0x24 4008cf: be 01 00 00 00 mov esi,0x1 4008d4: 48 89 c7 mov rdi,rax 4008d7: e8 44 fe ff ff call 400720 <fwrite@plt> 4008dc: bf 01 00 00 00 mov edi,0x1 4008e1: e8 2a fe ff ff call 400710 <exit@plt> ``` - `400889 - 4008a8` Declares **open_passfile** at `[rbp-0x8]` and **read_pass_status** at `[rbp-0xc]` Prepares arguments to call `fopen("/home/users/level03/", "r")` - `4008ad - 4008b1` Save the return value above in `[rbp-0x8]` aka **open_passfile** and compares it with 0. It its not equal, jump to `4008e6` - `4008b8 - 4008e1` If it is 0, call `fwrite("ERROR: failed to open password file", 1, 24, stderr)` and `exit(1)` --- ``` 4008e6: 48 8d 85 60 ff ff ff lea rax,[rbp-0xa0] 4008ed: 48 8b 55 f8 mov rdx,QWORD PTR [rbp-0x8] 4008f1: 48 89 d1 mov rcx,rdx 4008f4: ba 29 00 00 00 mov edx,0x29 4008f9: be 01 00 00 00 mov esi,0x1 4008fe: 48 89 c7 mov rdi,rax 400901: e8 8a fd ff ff call 400690 <fread@plt> 400906: 89 45 f4 mov DWORD PTR [rbp-0xc],eax 400909: 48 8d 85 60 ff ff ff lea rax,[rbp-0xa0] 400910: be f5 0b 40 00 mov esi,0x400bf5 400915: 48 89 c7 mov rdi,rax 400918: e8 b3 fd ff ff call 4006d0 <strcspn@plt> 40091d: c6 84 05 60 ff ff ff mov BYTE PTR [rbp+rax*1-0xa0],0x0 400924: 00 400925: 83 7d f4 29 cmp DWORD PTR [rbp-0xc],0x29 400929: 74 52 je 40097d <main+0x169> 40092b: 48 8b 05 1e 09 20 00 mov rax,QWORD PTR [rip+0x20091e] # 601250 <stderr@@GLIBC_2.2.5> 400932: 48 89 c2 mov rdx,rax 400935: b8 f8 0b 40 00 mov eax,0x400bf8 40093a: 48 89 d1 mov rcx,rdx 40093d: ba 24 00 00 00 mov edx,0x24 400942: be 01 00 00 00 mov esi,0x1 400947: 48 89 c7 mov rdi,rax 40094a: e8 d1 fd ff ff call 400720 <fwrite@plt> 40094f: 48 8b 05 fa 08 20 00 mov rax,QWORD PTR [rip+0x2008fa] # 601250 <stderr@@GLIBC_2.2.5> 400956: 48 89 c2 mov rdx,rax 400959: b8 f8 0b 40 00 mov eax,0x400bf8 40095e: 48 89 d1 mov rcx,rdx 400961: ba 24 00 00 00 mov edx,0x24 400966: be 01 00 00 00 mov esi,0x1 40096b: 48 89 c7 mov rdi,rax 40096e: e8 ad fd ff ff call 400720 <fwrite@plt> 400973: bf 01 00 00 00 mov edi,0x1 400978: e8 93 fd ff ff call 400710 <exit@plt> ``` - `4008e6 - 400901` Calls `fread(pass_file_content, 1, 29, open_passfile)` and stores the result in **read_pass_status** - `400909 - 400918` Prepares arguments and calls `strcspn(pass_file_content, "\n")` which returns the number of bytes of **pass_file_content** which are not in the "\n". - `40091d` pass_file_content[<ret_above>] = 0 - `400925 - 400978` Compare **read_pass_status** with `41`. If the are equal, jump to `40097d`. If they are not, `frwite("ERROR: failed to read password file", 1, 24, stderr)` twice and call `exit(1)` --- ``` 40097d: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8] 400981: 48 89 c7 mov rdi,rax 400984: e8 17 fd ff ff call 4006a0 <fclose@plt> 400989: bf 20 0c 40 00 mov edi,0x400c20 40098e: e8 ed fc ff ff call 400680 <puts@plt> 400993: bf 50 0c 40 00 mov edi,0x400c50 400998: e8 e3 fc ff ff call 400680 <puts@plt> 40099d: bf 80 0c 40 00 mov edi,0x400c80 4009a2: e8 d9 fc ff ff call 400680 <puts@plt> 4009a7: bf b0 0c 40 00 mov edi,0x400cb0 4009ac: e8 cf fc ff ff call 400680 <puts@plt> 4009b1: b8 d9 0c 40 00 mov eax,0x400cd9 4009b6: 48 89 c7 mov rdi,rax 4009b9: b8 00 00 00 00 mov eax,0x0 4009be: e8 fd fc ff ff call 4006c0 <printf@plt> ``` - `40097d - 400984` Closes the password file by calling `fclose(open_passfile)` - `400989 - 4009be` Calls `puts()` for all the lines of the following output and calls `printf("--[ Username:")` at the end. ``` ===== [ Secure Access System v1.0 ] ===== /***************************************\ | You must login to access this system. | \**************************************/ ``` --- ``` 4009c3: 48 8b 05 7e 08 20 00 mov rax,QWORD PTR [rip+0x20087e] # 601248 <__bss_start> 4009ca: 48 89 c2 mov rdx,rax 4009cd: 48 8d 45 90 lea rax,[rbp-0x70] 4009d1: be 64 00 00 00 mov esi,0x64 4009d6: 48 89 c7 mov rdi,rax 4009d9: e8 12 fd ff ff call 4006f0 <fgets@plt> 4009de: 48 8d 45 90 lea rax,[rbp-0x70] 4009e2: be f5 0b 40 00 mov esi,0x400bf5 4009e7: 48 89 c7 mov rdi,rax 4009ea: e8 e1 fc ff ff call 4006d0 <strcspn@plt> 4009ef: c6 44 05 90 00 mov BYTE PTR [rbp+rax*1-0x70],0x0 4009f4: b8 e8 0c 40 00 mov eax,0x400ce8 4009f9: 48 89 c7 mov rdi,rax 4009fc: b8 00 00 00 00 mov eax,0x0 400a01: e8 ba fc ff ff call 4006c0 <printf@plt> ``` - `4009c3 - 4009d9` Effectively calls `fgets(username, 100, stdin)` - `4009de - 400a01` finds the index of newline string in **username**, and replaces the newline with nullbyte. Calls `printf(" --[ Password:")` after that --- ``` 400a06: 48 8b 05 3b 08 20 00 mov rax,QWORD PTR [rip+0x20083b] # 601248 <__bss_start> 400a0d: 48 89 c2 mov rdx,rax 400a10: 48 8d 85 f0 fe ff ff lea rax,[rbp-0x110] 400a17: be 64 00 00 00 mov esi,0x64 400a1c: 48 89 c7 mov rdi,rax 400a1f: e8 cc fc ff ff call 4006f0 <fgets@plt> 400a24: 48 8d 85 f0 fe ff ff lea rax,[rbp-0x110] 400a2b: be f5 0b 40 00 mov esi,0x400bf5 400a30: 48 89 c7 mov rdi,rax 400a33: e8 98 fc ff ff call 4006d0 <strcspn@plt> 400a38: c6 84 05 f0 fe ff ff mov BYTE PTR [rbp+rax*1-0x110],0x0 400a3f: 00 ``` - `400a06 - 400a3f` Essentially do the same with **pass** by calling `fgets(pass, 100, stdin)` and null terminates it --- ``` 400a40: bf f8 0c 40 00 mov edi,0x400cf8 400a45: e8 36 fc ff ff call 400680 <puts@plt> 400a4a: 48 8d 8d f0 fe ff ff lea rcx,[rbp-0x110] 400a51: 48 8d 85 60 ff ff ff lea rax,[rbp-0xa0] 400a58: ba 29 00 00 00 mov edx,0x29 400a5d: 48 89 ce mov rsi,rcx 400a60: 48 89 c7 mov rdi,rax 400a63: e8 08 fc ff ff call 400670 <strncmp@plt> 400a68: 85 c0 test eax,eax 400a6a: 75 2a jne 400a96 <main+0x282> 400a6c: b8 22 0d 40 00 mov eax,0x400d22 400a71: 48 8d 55 90 lea rdx,[rbp-0x70] 400a75: 48 89 d6 mov rsi,rdx 400a78: 48 89 c7 mov rdi,rax 400a7b: b8 00 00 00 00 mov eax,0x0 400a80: e8 3b fc ff ff call 4006c0 <printf@plt> 400a85: bf 32 0d 40 00 mov edi,0x400d32 400a8a: e8 21 fc ff ff call 4006b0 <system@plt> 400a8f: b8 00 00 00 00 mov eax,0x0 400a94: c9 leave 400a95: c3 ret 400a96: 48 8d 45 90 lea rax,[rbp-0x70] 400a9a: 48 89 c7 mov rdi,rax 400a9d: b8 00 00 00 00 mov eax,0x0 400aa2: e8 19 fc ff ff call 4006c0 <printf@plt> 400aa7: bf 3a 0d 40 00 mov edi,0x400d3a 400aac: e8 cf fb ff ff call 400680 <puts@plt> 400ab1: bf 01 00 00 00 mov edi,0x1 400ab6: e8 55 fc ff ff call 400710 <exit@plt> ``` - `400a40 - 400a45` Calls `puts("*****************************************")` - `400a4a - 400a68` Calls `strncmp(pass_file_content, pass, 41)` and test if the result is 0 - `400a6a` If its not equal, jump to `400a96` - `400a6c - 400a95` call `printf("Greetings, %s!", username)` and `system("/bin/sh")`, and returns 0 - `400a96 - 400ab6` call `printf(username)` and `puts("does not have access!")` and `exit(1)` # level03 ``` objdump -M intel -d level03 objdump -s -j .data level03 ``` ## main ``` 804885a: 55 push ebp 804885b: 89 e5 mov ebp,esp 804885d: 83 e4 f0 and esp,0xfffffff0 8048860: 83 ec 20 sub esp,0x20 8048863: 50 push eax 8048864: 31 c0 xor eax,eax 8048866: 74 03 je 804886b <main+0x11> 8048868: 83 c4 04 add esp,0x4 804886b: 58 pop eax 804886c: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 8048873: e8 38 fc ff ff call 80484b0 <time@plt> 8048878: 89 04 24 mov DWORD PTR [esp],eax 804887b: e8 80 fc ff ff call 8048500 <srand@plt> 8048880: c7 04 24 48 8a 04 08 mov DWORD PTR [esp],0x8048a48 8048887: e8 44 fc ff ff call 80484d0 <puts@plt> 804888c: c7 04 24 6c 8a 04 08 mov DWORD PTR [esp],0x8048a6c 8048893: e8 38 fc ff ff call 80484d0 <puts@plt> 8048898: c7 04 24 48 8a 04 08 mov DWORD PTR [esp],0x8048a48 804889f: e8 2c fc ff ff call 80484d0 <puts@plt> 80488a4: b8 7b 8a 04 08 mov eax,0x8048a7b 80488a9: 89 04 24 mov DWORD PTR [esp],eax 80488ac: e8 cf fb ff ff call 8048480 <printf@plt> 80488b1: b8 85 8a 04 08 mov eax,0x8048a85 80488b6: 8d 54 24 1c lea edx,[esp+0x1c] 80488ba: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 80488be: 89 04 24 mov DWORD PTR [esp],eax 80488c1: e8 6a fc ff ff call 8048530 <__isoc99_scanf@plt> 80488c6: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 80488ca: c7 44 24 04 0d d0 37 mov DWORD PTR [esp+0x4],0x1337d00d 80488d1: 13 80488d2: 89 04 24 mov DWORD PTR [esp],eax 80488d5: e8 6d fe ff ff call 8048747 <test> 80488da: b8 00 00 00 00 mov eax,0x0 80488df: c9 leave 80488e0: c3 ret ``` - `804885a - 8048860` Stack setup, alignment and allocating 32 bytes for the stack - `8048863 - 804886b` I dont know why they would do this but looks like it is just clearing out eax and making sure the stack is ok? - `804886c - 8048873` Call `srand(time(0))` - `8048880 - 804889f` For each line below, call `puts()` on it ``` *********************************** * level03 ** *********************************** ``` - `80488a4 - 80488ac` Call `printf("Password:")` - `80488ac - 80488c1` Loads `[esp + 0x1c]` aka **pwinput** to `eax`. Calls `scanf("%d", &pwinput)` - `80488c6 - 80488e0` Calls `test(pwinput, 0x1337d00d)` and returns 0 ## test ``` 8048747: 55 push ebp 8048748: 89 e5 mov ebp,esp 804874a: 83 ec 28 sub esp,0x28 804874d: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 8048750: 8b 55 0c mov edx,DWORD PTR [ebp+0xc] 8048753: 89 d1 mov ecx,edx 8048755: 29 c1 sub ecx,eax 8048757: 89 c8 mov eax,ecx 8048759: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 804875c: 83 7d f4 15 cmp DWORD PTR [ebp-0xc],0x15 8048760: 0f 87 e4 00 00 00 ja 804884a <test+0x103> 8048766: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048769: c1 e0 02 shl eax,0x2 804876c: 05 f0 89 04 08 add eax,0x80489f0 8048771: 8b 00 mov eax,DWORD PTR [eax] 8048773: ff e0 jmp eax 8048775: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048778: 89 04 24 mov DWORD PTR [esp],eax 804877b: e8 e0 fe ff ff call 8048660 <decrypt> 8048780: e9 d3 00 00 00 jmp 8048858 <test+0x111> 8048785: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048788: 89 04 24 mov DWORD PTR [esp],eax 804878b: e8 d0 fe ff ff call 8048660 <decrypt> 8048790: e9 c3 00 00 00 jmp 8048858 <test+0x111> 8048795: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048798: 89 04 24 mov DWORD PTR [esp],eax 804879b: e8 c0 fe ff ff call 8048660 <decrypt> 80487a0: e9 b3 00 00 00 jmp 8048858 <test+0x111> 80487a5: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487a8: 89 04 24 mov DWORD PTR [esp],eax 80487ab: e8 b0 fe ff ff call 8048660 <decrypt> 80487b0: e9 a3 00 00 00 jmp 8048858 <test+0x111> 80487b5: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487b8: 89 04 24 mov DWORD PTR [esp],eax 80487bb: e8 a0 fe ff ff call 8048660 <decrypt> 80487c0: e9 93 00 00 00 jmp 8048858 <test+0x111> 80487c5: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487c8: 89 04 24 mov DWORD PTR [esp],eax 80487cb: e8 90 fe ff ff call 8048660 <decrypt> 80487d0: e9 83 00 00 00 jmp 8048858 <test+0x111> 80487d5: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487d8: 89 04 24 mov DWORD PTR [esp],eax 80487db: e8 80 fe ff ff call 8048660 <decrypt> 80487e0: eb 76 jmp 8048858 <test+0x111> 80487e2: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487e5: 89 04 24 mov DWORD PTR [esp],eax 80487e8: e8 73 fe ff ff call 8048660 <decrypt> 80487ed: eb 69 jmp 8048858 <test+0x111> 80487ef: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487f2: 89 04 24 mov DWORD PTR [esp],eax 80487f5: e8 66 fe ff ff call 8048660 <decrypt> 80487fa: eb 5c jmp 8048858 <test+0x111> 80487fc: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80487ff: 89 04 24 mov DWORD PTR [esp],eax 8048802: e8 59 fe ff ff call 8048660 <decrypt> 8048807: eb 4f jmp 8048858 <test+0x111> 8048809: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 804880c: 89 04 24 mov DWORD PTR [esp],eax 804880f: e8 4c fe ff ff call 8048660 <decrypt> 8048814: eb 42 jmp 8048858 <test+0x111> 8048816: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048819: 89 04 24 mov DWORD PTR [esp],eax 804881c: e8 3f fe ff ff call 8048660 <decrypt> 8048821: eb 35 jmp 8048858 <test+0x111> 8048823: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048826: 89 04 24 mov DWORD PTR [esp],eax 8048829: e8 32 fe ff ff call 8048660 <decrypt> 804882e: eb 28 jmp 8048858 <test+0x111> 8048830: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048833: 89 04 24 mov DWORD PTR [esp],eax 8048836: e8 25 fe ff ff call 8048660 <decrypt> 804883b: eb 1b jmp 8048858 <test+0x111> 804883d: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 8048840: 89 04 24 mov DWORD PTR [esp],eax 8048843: e8 18 fe ff ff call 8048660 <decrypt> 8048848: eb 0e jmp 8048858 <test+0x111> 804884a: e8 d1 fc ff ff call 8048520 <rand@plt> 804884f: 89 04 24 mov DWORD PTR [esp],eax 8048852: e8 09 fe ff ff call 8048660 <decrypt> 8048857: 90 nop 8048858: c9 leave 8048859: c3 ret ``` - `8048747 - 8048750` Set up stack frame and load **pwinput** at `[ebp+0x8]` to `eax` and **init_addr**`[ebp+0xc]` which is now equal to `0x1337d00d` to `edx` - `8048753 - 8048759` **init_addr** -= **pwinput** - `804875c - 8048760` comapre **init_addr** with `21`. If its more than, jump to `804884a`. - `8048766 - 8048780` load **init_addr** in some temp variable and shift left by 2, which means multiply by 4 and add `0x80489f0` to that value. The temp variable is the derefrenced and jumped to. - `804877b - 8048858` Continiously call `decrypt(init_addr)` and return ## decrypt ``` 8048660: 55 push ebp 8048661: 89 e5 mov ebp,esp 8048663: 57 push edi 8048664: 56 push esi 8048665: 83 ec 40 sub esp,0x40 8048668: 65 a1 14 00 00 00 mov eax,gs:0x14 804866e: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 8048671: 31 c0 xor eax,eax 8048673: c7 45 e3 51 7d 7c 75 mov DWORD PTR [ebp-0x1d],0x757c7d51 804867a: c7 45 e7 60 73 66 67 mov DWORD PTR [ebp-0x19],0x67667360 8048681: c7 45 eb 7e 73 66 7b mov DWORD PTR [ebp-0x15],0x7b66737e 8048688: c7 45 ef 7d 7c 61 33 mov DWORD PTR [ebp-0x11],0x33617c7d 804868f: c6 45 f3 00 mov BYTE PTR [ebp-0xd],0x0 8048693: 50 push eax 8048694: 31 c0 xor eax,eax 8048696: 74 03 je 804869b <decrypt+0x3b> 8048698: 83 c4 04 add esp,0x4 804869b: 58 pop eax 804869c: 8d 45 e3 lea eax,[ebp-0x1d] 804869f: c7 45 d4 ff ff ff ff mov DWORD PTR [ebp-0x2c],0xffffffff 80486a6: 89 c2 mov edx,eax 80486a8: b8 00 00 00 00 mov eax,0x0 80486ad: 8b 4d d4 mov ecx,DWORD PTR [ebp-0x2c] 80486b0: 89 d7 mov edi,edx 80486b2: f2 ae repnz scas al,BYTE PTR es:[edi] 80486b4: 89 c8 mov eax,ecx 80486b6: f7 d0 not eax 80486b8: 83 e8 01 sub eax,0x1 80486bb: 89 45 dc mov DWORD PTR [ebp-0x24],eax 80486be: c7 45 d8 00 00 00 00 mov DWORD PTR [ebp-0x28],0x0 80486c5: eb 1e jmp 80486e5 <decrypt+0x85> 80486c7: 8d 45 e3 lea eax,[ebp-0x1d] 80486ca: 03 45 d8 add eax,DWORD PTR [ebp-0x28] 80486cd: 0f b6 00 movzx eax,BYTE PTR [eax] 80486d0: 89 c2 mov edx,eax 80486d2: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 80486d5: 31 d0 xor eax,edx 80486d7: 89 c2 mov edx,eax 80486d9: 8d 45 e3 lea eax,[ebp-0x1d] 80486dc: 03 45 d8 add eax,DWORD PTR [ebp-0x28] 80486df: 88 10 mov BYTE PTR [eax],dl 80486e1: 83 45 d8 01 add DWORD PTR [ebp-0x28],0x1 80486e5: 8b 45 d8 mov eax,DWORD PTR [ebp-0x28] 80486e8: 3b 45 dc cmp eax,DWORD PTR [ebp-0x24] 80486eb: 72 da jb 80486c7 <decrypt+0x67> 80486ed: 8d 45 e3 lea eax,[ebp-0x1d] 80486f0: 89 c2 mov edx,eax 80486f2: b8 c3 89 04 08 mov eax,0x80489c3 80486f7: b9 11 00 00 00 mov ecx,0x11 80486fc: 89 d6 mov esi,edx 80486fe: 89 c7 mov edi,eax 8048700: f3 a6 repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 8048702: 0f 97 c2 seta dl 8048705: 0f 92 c0 setb al 8048708: 89 d1 mov ecx,edx 804870a: 28 c1 sub cl,al 804870c: 89 c8 mov eax,ecx 804870e: 0f be c0 movsx eax,al 8048711: 85 c0 test eax,eax 8048713: 75 0e jne 8048723 <decrypt+0xc3> 8048715: c7 04 24 d4 89 04 08 mov DWORD PTR [esp],0x80489d4 804871c: e8 bf fd ff ff call 80484e0 <system@plt> 8048721: eb 0c jmp 804872f <decrypt+0xcf> 8048723: c7 04 24 dc 89 04 08 mov DWORD PTR [esp],0x80489dc 804872a: e8 a1 fd ff ff call 80484d0 <puts@plt> 804872f: 8b 75 f4 mov esi,DWORD PTR [ebp-0xc] 8048732: 65 33 35 14 00 00 00 xor esi,DWORD PTR gs:0x14 8048739: 74 05 je 8048740 <decrypt+0xe0> 804873b: e8 80 fd ff ff call 80484c0 <__stack_chk_fail@plt> 8048740: 83 c4 40 add esp,0x40 8048743: 5e pop esi 8048744: 5f pop edi 8048745: 5d pop ebp 8048746: c3 ret ``` - `8048660 - 8048671` Prepare the stack and allocate 64 bytes for the stack. Load `20` into `[ebp-0xc]` aka **canary** and clears `eax`. - `8048673 - 804863f` declates **cipher1** in `[ebp-0x1d]` with `0x757c7d51`, **cipher2** in `[ebp-0x19]` with `0x67667360`,**cipher3** in `[ebp-0x15]` with `0x7b66737e`,**cipher4** in `[ebp-0x11]` with `0x33617c7d`, **cipher5** in `[ebp-0xd]` with `0`. - `8048693 - 804869b` I have no idea why they want to pop `eax` like that, so cant provide any context here yet..... (im guessing stack canary?) - `804869c - 80486c5` **cipher1** has been loaded into `eax` and `0xffffffff` has been written to `[ebp-0x2c]` aka **clear_mask**. - `80486a6 - 80486b2` evaluate string length of **cipher1** - `80486b4 - 80486b8` store the value at eax and flip the polarity, since the result of the strlen was negative (direction flag), and then subtract 1 - `80486bb - 80486c5`Move the length into `[ebp-0x24]` aka **cipherlen** and zero into `[ebp-0x28]` aka **count**, jump to `80486e5`, which seems to be a loop checker - `80486c7 - 80486e1` Load **cipher1**s address into `eax` and add the value of **count**. Derefrence the resultant address and write that result to `edx`. Load argument 1 (**init_addr**) into `eax` and xor it with `edx`, or our **cipher1addr + count**. -> **xor_res**. **cipher1[count] = xor_res**. `count += 1` - `80486e5 - 80486eb` if **count** < **cipherlen** jump to `80486c7` - `8048700 - 8048740` Comapres **cipher1** with the string `Congratulations!` using `strncmp(cipher1, "Congratulations!", 17)`. if its the same, `system("/bin/sh")`, else `puts("Invalid Password")` and return while checking for stack overflow. # level04 ``` objdump -M intel -d level04 objdump -s -j .data level04 ``` ## main ``` 80486c8: 55 push ebp 80486c9: 89 e5 mov ebp,esp 80486cb: 57 push edi 80486cc: 53 push ebx 80486cd: 83 e4 f0 and esp,0xfffffff0 80486d0: 81 ec b0 00 00 00 sub esp,0xb0 80486d6: e8 75 fe ff ff call 8048550 <fork@plt> 80486db: 89 84 24 ac 00 00 00 mov DWORD PTR [esp+0xac],eax 80486e2: 8d 5c 24 20 lea ebx,[esp+0x20] 80486e6: b8 00 00 00 00 mov eax,0x0 80486eb: ba 20 00 00 00 mov edx,0x20 80486f0: 89 df mov edi,ebx 80486f2: 89 d1 mov ecx,edx 80486f4: f3 ab rep stos DWORD PTR es:[edi],eax 80486f6: c7 84 24 a8 00 00 00 mov DWORD PTR [esp+0xa8],0x0 80486fd: 00 00 00 00 8048701: c7 44 24 1c 00 00 00 mov DWORD PTR [esp+0x1c],0x0 8048708: 00 8048709: 83 bc 24 ac 00 00 00 cmp DWORD PTR [esp+0xac],0x0 8048710: 00 8048711: 75 56 jne 8048769 <main+0xa1> 8048713: c7 44 24 04 01 00 00 mov DWORD PTR [esp+0x4],0x1 804871a: 00 804871b: c7 04 24 01 00 00 00 mov DWORD PTR [esp],0x1 8048722: e8 19 fe ff ff call 8048540 <prctl@plt> 8048727: c7 44 24 0c 00 00 00 mov DWORD PTR [esp+0xc],0x0 804872e: 00 804872f: c7 44 24 08 00 00 00 mov DWORD PTR [esp+0x8],0x0 8048736: 00 8048737: c7 44 24 04 00 00 00 mov DWORD PTR [esp+0x4],0x0 804873e: 00 804873f: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 8048746: e8 25 fe ff ff call 8048570 <ptrace@plt> 804874b: c7 04 24 03 89 04 08 mov DWORD PTR [esp],0x8048903 8048752: e8 a9 fd ff ff call 8048500 <puts@plt> 8048757: 8d 44 24 20 lea eax,[esp+0x20] 804875b: 89 04 24 mov DWORD PTR [esp],eax 804875e: e8 4d fd ff ff call 80484b0 <gets@plt> 8048763: e9 b2 00 00 00 jmp 804881a <main+0x152> 8048768: 90 nop 8048769: 8d 44 24 1c lea eax,[esp+0x1c] 804876d: 89 04 24 mov DWORD PTR [esp],eax 8048770: e8 7b fd ff ff call 80484f0 <wait@plt> 8048775: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 8048779: 89 84 24 a0 00 00 00 mov DWORD PTR [esp+0xa0],eax 8048780: 8b 84 24 a0 00 00 00 mov eax,DWORD PTR [esp+0xa0] 8048787: 83 e0 7f and eax,0x7f 804878a: 85 c0 test eax,eax 804878c: 74 1e je 80487ac <main+0xe4> 804878e: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 8048792: 89 84 24 a4 00 00 00 mov DWORD PTR [esp+0xa4],eax 8048799: 8b 84 24 a4 00 00 00 mov eax,DWORD PTR [esp+0xa4] 80487a0: 83 e0 7f and eax,0x7f 80487a3: 83 c0 01 add eax,0x1 80487a6: d0 f8 sar al,1 80487a8: 84 c0 test al,al 80487aa: 7e 0e jle 80487ba <main+0xf2> 80487ac: c7 04 24 1d 89 04 08 mov DWORD PTR [esp],0x804891d 80487b3: e8 48 fd ff ff call 8048500 <puts@plt> 80487b8: eb 60 jmp 804881a <main+0x152> 80487ba: c7 44 24 0c 00 00 00 mov DWORD PTR [esp+0xc],0x0 80487c1: 00 80487c2: c7 44 24 08 2c 00 00 mov DWORD PTR [esp+0x8],0x2c 80487c9: 00 80487ca: 8b 84 24 ac 00 00 00 mov eax,DWORD PTR [esp+0xac] 80487d1: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 80487d5: c7 04 24 03 00 00 00 mov DWORD PTR [esp],0x3 80487dc: e8 8f fd ff ff call 8048570 <ptrace@plt> 80487e1: 89 84 24 a8 00 00 00 mov DWORD PTR [esp+0xa8],eax 80487e8: 83 bc 24 a8 00 00 00 cmp DWORD PTR [esp+0xa8],0xb 80487ef: 0b 80487f0: 0f 85 72 ff ff ff jne 8048768 <main+0xa0> 80487f6: c7 04 24 31 89 04 08 mov DWORD PTR [esp],0x8048931 80487fd: e8 fe fc ff ff call 8048500 <puts@plt> 8048802: c7 44 24 04 09 00 00 mov DWORD PTR [esp+0x4],0x9 8048809: 00 804880a: 8b 84 24 ac 00 00 00 mov eax,DWORD PTR [esp+0xac] 8048811: 89 04 24 mov DWORD PTR [esp],eax 8048814: e8 07 fd ff ff call 8048520 <kill@plt> 8048819: 90 nop 804881a: b8 00 00 00 00 mov eax,0x0 804881f: 8d 65 f8 lea esp,[ebp-0x8] 8048822: 5b pop ebx 8048823: 5f pop edi 8048824: 5d pop ebp 8048825: c3 ret 8048826: 90 nop ``` - `80486c8 - 80486d6` Sets up stack, does stack alignment and allocates 176 bytes on the stack - `80486d6 - 80486f4` Calls `fork()` and stores the return value on `[esp+0xac]` aka **pid**. Loads a buffer at `[esp+0x20]` aka **child_input** and call `memset(child_input, 0, 32)` - `80486f6 - 8048711` Write 0 to `[esp+0xa8]` aka **ptrace_res** and `[esp+0x1c]` aka **wait_status**. Check if `pid == 0`. If not, jump to `8048769` - `8048713 - 80487aa` This is the child fork. Call `prctl(1, 1)` [prctl man](https://linux.die.net/man/2/prctl), which according to [the header](https://github.com/torvalds/linux/blob/master/include/uapi/linux/prctl.h), is `prctl(PR_SET_PDEATHSIG, SIGHUP)`. This will make the child receive a SIGHUP signal if the parent dies. Call `ptrace(0, 0, 0, 0)`, which can be translated to `ptrace(PTRACE_TRACEME, 0, 0, 0)`. What it does is that it allows the parent to inspect the childs program behaviour. `puts(".Give me some shellcode, k")` is called, a buffer is loaded at `[esp+0x20]` aka **child_input** and `gets(child_input)` is called. Once `gets` finished, the program returns. - `8048769 - 8048824` Call `wait(&wait_status)`, write **wait_status** into a temp variable and `and 127` or according to the [header for wait](https://elixir.bootlin.com/linux/latest/source/tools/include/nolibc/types.h#L107) `WIFEXITED(wait_status)`. If its true, jump to `80487ac`. Else, check `WIFSIGNALED(wait_status)`. If its not true, jump to `80487ba`. - `80487ac - 80487b8` Call `puts("child is exiting")` and return. - `80487ba - 8048824` Call `ptrace(3, pid, 44, 0)` which corresponds to `ptrace(PTRACE_PEEKUSER, pid, 44, NULL);` and write the return value to `ptrace_res`. Compare it with `11`. If its not equal, return. Else, `puts("no exec() for you")` and `kill(pid, 9)` and return. Judging by the output, it seems like the ptrace is looking for an `exec()` call by the child before killing it. # level05 ``` objdump -M intel -d level05 objdump -s -j .data level05 ``` ## main ``` 08048444 <main>: 8048444: 55 push ebp 8048445: 89 e5 mov ebp,esp 8048447: 57 push edi 8048448: 53 push ebx 8048449: 83 e4 f0 and esp,0xfffffff0 804844c: 81 ec 90 00 00 00 sub esp,0x90 8048452: c7 84 24 8c 00 00 00 mov DWORD PTR [esp+0x8c],0x0 8048459: 00 00 00 00 804845d: a1 f0 97 04 08 mov eax,ds:0x80497f0 8048462: 89 44 24 08 mov DWORD PTR [esp+0x8],eax 8048466: c7 44 24 04 64 00 00 mov DWORD PTR [esp+0x4],0x64 804846d: 00 804846e: 8d 44 24 28 lea eax,[esp+0x28] 8048472: 89 04 24 mov DWORD PTR [esp],eax 8048475: e8 d6 fe ff ff call 8048350 <fgets@plt> 804847a: c7 84 24 8c 00 00 00 mov DWORD PTR [esp+0x8c],0x0 8048481: 00 00 00 00 8048485: eb 4c jmp 80484d3 <main+0x8f> 8048487: 8d 44 24 28 lea eax,[esp+0x28] 804848b: 03 84 24 8c 00 00 00 add eax,DWORD PTR [esp+0x8c] 8048492: 0f b6 00 movzx eax,BYTE PTR [eax] 8048495: 3c 40 cmp al,0x40 8048497: 7e 32 jle 80484cb <main+0x87> 8048499: 8d 44 24 28 lea eax,[esp+0x28] 804849d: 03 84 24 8c 00 00 00 add eax,DWORD PTR [esp+0x8c] 80484a4: 0f b6 00 movzx eax,BYTE PTR [eax] 80484a7: 3c 5a cmp al,0x5a 80484a9: 7f 20 jg 80484cb <main+0x87> 80484ab: 8d 44 24 28 lea eax,[esp+0x28] 80484af: 03 84 24 8c 00 00 00 add eax,DWORD PTR [esp+0x8c] 80484b6: 0f b6 00 movzx eax,BYTE PTR [eax] 80484b9: 89 c2 mov edx,eax 80484bb: 83 f2 20 xor edx,0x20 80484be: 8d 44 24 28 lea eax,[esp+0x28] 80484c2: 03 84 24 8c 00 00 00 add eax,DWORD PTR [esp+0x8c] 80484c9: 88 10 mov BYTE PTR [eax],dl 80484cb: 83 84 24 8c 00 00 00 add DWORD PTR [esp+0x8c],0x1 80484d2: 01 80484d3: 8b 9c 24 8c 00 00 00 mov ebx,DWORD PTR [esp+0x8c] 80484da: 8d 44 24 28 lea eax,[esp+0x28] 80484de: c7 44 24 1c ff ff ff mov DWORD PTR [esp+0x1c],0xffffffff 80484e5: ff 80484e6: 89 c2 mov edx,eax 80484e8: b8 00 00 00 00 mov eax,0x0 80484ed: 8b 4c 24 1c mov ecx,DWORD PTR [esp+0x1c] 80484f1: 89 d7 mov edi,edx 80484f3: f2 ae repnz scas al,BYTE PTR es:[edi] 80484f5: 89 c8 mov eax,ecx 80484f7: f7 d0 not eax 80484f9: 83 e8 01 sub eax,0x1 80484fc: 39 c3 cmp ebx,eax 80484fe: 72 87 jb 8048487 <main+0x43> 8048500: 8d 44 24 28 lea eax,[esp+0x28] 8048504: 89 04 24 mov DWORD PTR [esp],eax 8048507: e8 34 fe ff ff call 8048340 <printf@plt> 804850c: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 8048513: e8 58 fe ff ff call 8048370 <exit@plt> 8048518: 90 nop ``` - `8048444 - 804844c` Prep stack and stack alignment, allocates 144 bytes for the stack. - `8048452 - 80484a9` Write 0 to a variable called **count** at `[esp+0x8c]`. Load a buffer from `[esp+0x28]` aka **inputbuf**, call `fgets(inputbuf, 100, stdin)`. Write 0 to **count** again and then jump to `80484d3` (I dont know why its so abrupt, loop maybe?), load address **inputbuf** to a tmp variable and increment the address by **count**. Derefrence the inputbuf and compare it with `64` and `90`. If its less or equals than `64` or more than `90` (not capital alphabet), jump to `80484cb`. - `80484ab - 8048513` Load address of **inputbuf** and increment by **count**. Derefrence the index at **inputbuf** and `xor 32` the element. `inputbuf[count] = xorred_res` and increment **count**. while `strlen(inputbuf)` is more than **count**, jump back to `8048487.` When the loop exits, `printf(inputbuf)` and `exit(0)` # level06 ``` objdump -M intel -d level06 objdump -s -j .data level06 ``` ## main ``` 8048879: 55 push ebp 804887a: 89 e5 mov ebp,esp 804887c: 83 e4 f0 and esp,0xfffffff0 804887f: 83 ec 50 sub esp,0x50 8048882: 8b 45 0c mov eax,DWORD PTR [ebp+0xc] 8048885: 89 44 24 1c mov DWORD PTR [esp+0x1c],eax 8048889: 65 a1 14 00 00 00 mov eax,gs:0x14 804888f: 89 44 24 4c mov DWORD PTR [esp+0x4c],eax 8048893: 31 c0 xor eax,eax 8048895: 50 push eax 8048896: 31 c0 xor eax,eax 8048898: 74 03 je 804889d <main+0x24> 804889a: 83 c4 04 add esp,0x4 804889d: 58 pop eax 804889e: c7 04 24 d4 8a 04 08 mov DWORD PTR [esp],0x8048ad4 80488a5: e8 e6 fc ff ff call 8048590 <puts@plt> 80488aa: c7 04 24 f8 8a 04 08 mov DWORD PTR [esp],0x8048af8 80488b1: e8 da fc ff ff call 8048590 <puts@plt> 80488b6: c7 04 24 d4 8a 04 08 mov DWORD PTR [esp],0x8048ad4 80488bd: e8 ce fc ff ff call 8048590 <puts@plt> 80488c2: b8 08 8b 04 08 mov eax,0x8048b08 80488c7: 89 04 24 mov DWORD PTR [esp],eax 80488ca: e8 41 fc ff ff call 8048510 <printf@plt> 80488cf: a1 60 a0 04 08 mov eax,ds:0x804a060 80488d4: 89 44 24 08 mov DWORD PTR [esp+0x8],eax 80488d8: c7 44 24 04 20 00 00 mov DWORD PTR [esp+0x4],0x20 80488df: 00 80488e0: 8d 44 24 2c lea eax,[esp+0x2c] 80488e4: 89 04 24 mov DWORD PTR [esp],eax 80488e7: e8 64 fc ff ff call 8048550 <fgets@plt> 80488ec: c7 04 24 d4 8a 04 08 mov DWORD PTR [esp],0x8048ad4 80488f3: e8 98 fc ff ff call 8048590 <puts@plt> 80488f8: c7 04 24 1c 8b 04 08 mov DWORD PTR [esp],0x8048b1c 80488ff: e8 8c fc ff ff call 8048590 <puts@plt> 8048904: c7 04 24 d4 8a 04 08 mov DWORD PTR [esp],0x8048ad4 804890b: e8 80 fc ff ff call 8048590 <puts@plt> 8048910: b8 40 8b 04 08 mov eax,0x8048b40 8048915: 89 04 24 mov DWORD PTR [esp],eax 8048918: e8 f3 fb ff ff call 8048510 <printf@plt> 804891d: b8 60 8a 04 08 mov eax,0x8048a60 8048922: 8d 54 24 28 lea edx,[esp+0x28] 8048926: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 804892a: 89 04 24 mov DWORD PTR [esp],eax 804892d: e8 ae fc ff ff call 80485e0 <__isoc99_scanf@plt> 8048932: 8b 44 24 28 mov eax,DWORD PTR [esp+0x28] 8048936: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 804893a: 8d 44 24 2c lea eax,[esp+0x2c] 804893e: 89 04 24 mov DWORD PTR [esp],eax 8048941: e8 02 fe ff ff call 8048748 <auth> 8048946: 85 c0 test eax,eax 8048948: 75 1f jne 8048969 <main+0xf0> 804894a: c7 04 24 52 8b 04 08 mov DWORD PTR [esp],0x8048b52 8048951: e8 3a fc ff ff call 8048590 <puts@plt> 8048956: c7 04 24 61 8b 04 08 mov DWORD PTR [esp],0x8048b61 804895d: e8 3e fc ff ff call 80485a0 <system@plt> 8048962: b8 00 00 00 00 mov eax,0x0 8048967: eb 05 jmp 804896e <main+0xf5> 8048969: b8 01 00 00 00 mov eax,0x1 804896e: 8b 54 24 4c mov edx,DWORD PTR [esp+0x4c] 8048972: 65 33 15 14 00 00 00 xor edx,DWORD PTR gs:0x14 8048979: 74 05 je 8048980 <main+0x107> 804897b: e8 00 fc ff ff call 8048580 <__stack_chk_fail@plt> 8048980: c9 leave 8048981: c3 ret 8048982: 90 nop ``` - `8048879 - 804887f` Set up stack frame, stack alignment and allocates 80 bytes for the stack - `8048882 - 8048898` Load argv into `[esp+0x1c]` aka **argv** and 20 into `[esp+0x4c]` aka **canary**. and save `canary ^ canary` in memory, aka **canary_xor**. `canary ^ canary` again, and if its true, jump to `804889d` - `804889a - 80488ca` Idk why they want to shrink the stack by 4 and pop the result to eax, I assume its for stack canary. Call these in order : ``` puts("***********************************"); puts("* level06 *"); puts("***********************************"); printf("-> Enter Login:"); ``` - `80488cf - 8048918` Load a buffer to `[esp+0x2c]` aka **logininput** and call `fgets(logininput, 32, stdin)` and calls these in order: ``` puts("***********************************"); puts("* NEW ACOUNT DETECTED *"); puts("***********************************"); printf("-> Enter Serial:"); ``` - `804891d - 804897b` Load an unsigned int in `[esp+0x28]` aka **serial_input**. Call `scanf("%u", &serialinput);`. After that, call `auth(logininput, serialinput)`. If the return value is not equal zero, check the stack overflow and return. If it is, `system("/bin/sh")` ## auth ``` 8048748: 55 push ebp 8048749: 89 e5 mov ebp,esp 804874b: 83 ec 28 sub esp,0x28 804874e: c7 44 24 04 63 8a 04 mov DWORD PTR [esp+0x4],0x8048a63 8048755: 08 8048756: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 8048759: 89 04 24 mov DWORD PTR [esp],eax 804875c: e8 bf fd ff ff call 8048520 <strcspn@plt> 8048761: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048764: c6 00 00 mov BYTE PTR [eax],0x0 8048767: c7 44 24 04 20 00 00 mov DWORD PTR [esp+0x4],0x20 804876e: 00 804876f: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 8048772: 89 04 24 mov DWORD PTR [esp],eax 8048775: e8 56 fe ff ff call 80485d0 <strnlen@plt> 804877a: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 804877d: 50 push eax 804877e: 31 c0 xor eax,eax 8048780: 74 03 je 8048785 <auth+0x3d> 8048782: 83 c4 04 add esp,0x4 8048785: 58 pop eax 8048786: 83 7d f4 05 cmp DWORD PTR [ebp-0xc],0x5 804878a: 7f 0a jg 8048796 <auth+0x4e> 804878c: b8 01 00 00 00 mov eax,0x1 8048791: e9 e1 00 00 00 jmp 8048877 <auth+0x12f> 8048796: c7 44 24 0c 00 00 00 mov DWORD PTR [esp+0xc],0x0 804879d: 00 804879e: c7 44 24 08 01 00 00 mov DWORD PTR [esp+0x8],0x1 80487a5: 00 80487a6: c7 44 24 04 00 00 00 mov DWORD PTR [esp+0x4],0x0 80487ad: 00 80487ae: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 80487b5: e8 36 fe ff ff call 80485f0 <ptrace@plt> 80487ba: 83 f8 ff cmp eax,0xffffffff 80487bd: 75 2e jne 80487ed <auth+0xa5> 80487bf: c7 04 24 68 8a 04 08 mov DWORD PTR [esp],0x8048a68 80487c6: e8 c5 fd ff ff call 8048590 <puts@plt> 80487cb: c7 04 24 8c 8a 04 08 mov DWORD PTR [esp],0x8048a8c 80487d2: e8 b9 fd ff ff call 8048590 <puts@plt> 80487d7: c7 04 24 b0 8a 04 08 mov DWORD PTR [esp],0x8048ab0 80487de: e8 ad fd ff ff call 8048590 <puts@plt> 80487e3: b8 01 00 00 00 mov eax,0x1 80487e8: e9 8a 00 00 00 jmp 8048877 <auth+0x12f> 80487ed: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 80487f0: 83 c0 03 add eax,0x3 80487f3: 0f b6 00 movzx eax,BYTE PTR [eax] 80487f6: 0f be c0 movsx eax,al 80487f9: 35 37 13 00 00 xor eax,0x1337 80487fe: 05 ed ed 5e 00 add eax,0x5eeded 8048803: 89 45 f0 mov DWORD PTR [ebp-0x10],eax 8048806: c7 45 ec 00 00 00 00 mov DWORD PTR [ebp-0x14],0x0 804880d: eb 4c jmp 804885b <auth+0x113> 804880f: 8b 45 ec mov eax,DWORD PTR [ebp-0x14] 8048812: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048815: 0f b6 00 movzx eax,BYTE PTR [eax] 8048818: 3c 1f cmp al,0x1f 804881a: 7f 07 jg 8048823 <auth+0xdb> 804881c: b8 01 00 00 00 mov eax,0x1 8048821: eb 54 jmp 8048877 <auth+0x12f> 8048823: 8b 45 ec mov eax,DWORD PTR [ebp-0x14] 8048826: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048829: 0f b6 00 movzx eax,BYTE PTR [eax] 804882c: 0f be c0 movsx eax,al 804882f: 89 c1 mov ecx,eax 8048831: 33 4d f0 xor ecx,DWORD PTR [ebp-0x10] 8048834: ba 2b 3b 23 88 mov edx,0x88233b2b 8048839: 89 c8 mov eax,ecx 804883b: f7 e2 mul edx 804883d: 89 c8 mov eax,ecx 804883f: 29 d0 sub eax,edx 8048841: d1 e8 shr eax,1 8048843: 01 d0 add eax,edx 8048845: c1 e8 0a shr eax,0xa 8048848: 69 c0 39 05 00 00 imul eax,eax,0x539 804884e: 89 ca mov edx,ecx 8048850: 29 c2 sub edx,eax 8048852: 89 d0 mov eax,edx 8048854: 01 45 f0 add DWORD PTR [ebp-0x10],eax 8048857: 83 45 ec 01 add DWORD PTR [ebp-0x14],0x1 804885b: 8b 45 ec mov eax,DWORD PTR [ebp-0x14] 804885e: 3b 45 f4 cmp eax,DWORD PTR [ebp-0xc] 8048861: 7c ac jl 804880f <auth+0xc7> 8048863: 8b 45 0c mov eax,DWORD PTR [ebp+0xc] 8048866: 3b 45 f0 cmp eax,DWORD PTR [ebp-0x10] 8048869: 74 07 je 8048872 <auth+0x12a> 804886b: b8 01 00 00 00 mov eax,0x1 8048870: eb 05 jmp 8048877 <auth+0x12f> 8048872: b8 00 00 00 00 mov eax,0x0 8048877: c9 leave 8048878: c3 ret 8048748: 55 push ebp 8048749: 89 e5 mov ebp,esp 804874b: 83 ec 28 sub esp,0x28 804874e: c7 44 24 04 63 8a 04 mov DWORD PTR [esp+0x4],0x8048a63 8048755: 08 8048756: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 8048759: 89 04 24 mov DWORD PTR [esp],eax 804875c: e8 bf fd ff ff call 8048520 <strcspn@plt> 8048761: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048764: c6 00 00 mov BYTE PTR [eax],0x0 8048767: c7 44 24 04 20 00 00 mov DWORD PTR [esp+0x4],0x20 804876e: 00 804876f: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 8048772: 89 04 24 mov DWORD PTR [esp],eax 8048775: e8 56 fe ff ff call 80485d0 <strnlen@plt> 804877a: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 804877d: 50 push eax 804877e: 31 c0 xor eax,eax 8048780: 74 03 je 8048785 <auth+0x3d> 8048782: 83 c4 04 add esp,0x4 8048785: 58 pop eax 8048786: 83 7d f4 05 cmp DWORD PTR [ebp-0xc],0x5 804878a: 7f 0a jg 8048796 <auth+0x4e> 804878c: b8 01 00 00 00 mov eax,0x1 8048791: e9 e1 00 00 00 jmp 8048877 <auth+0x12f> 8048796: c7 44 24 0c 00 00 00 mov DWORD PTR [esp+0xc],0x0 804879d: 00 804879e: c7 44 24 08 01 00 00 mov DWORD PTR [esp+0x8],0x1 80487a5: 00 80487a6: c7 44 24 04 00 00 00 mov DWORD PTR [esp+0x4],0x0 80487ad: 00 80487ae: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 80487b5: e8 36 fe ff ff call 80485f0 <ptrace@plt> 80487ba: 83 f8 ff cmp eax,0xffffffff 80487bd: 75 2e jne 80487ed <auth+0xa5> 80487bf: c7 04 24 68 8a 04 08 mov DWORD PTR [esp],0x8048a68 80487c6: e8 c5 fd ff ff call 8048590 <puts@plt> 80487cb: c7 04 24 8c 8a 04 08 mov DWORD PTR [esp],0x8048a8c 80487d2: e8 b9 fd ff ff call 8048590 <puts@plt> 80487d7: c7 04 24 b0 8a 04 08 mov DWORD PTR [esp],0x8048ab0 80487de: e8 ad fd ff ff call 8048590 <puts@plt> 80487e3: b8 01 00 00 00 mov eax,0x1 80487e8: e9 8a 00 00 00 jmp 8048877 <auth+0x12f> 80487ed: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] 80487f0: 83 c0 03 add eax,0x3 80487f3: 0f b6 00 movzx eax,BYTE PTR [eax] 80487f6: 0f be c0 movsx eax,al 80487f9: 35 37 13 00 00 xor eax,0x1337 80487fe: 05 ed ed 5e 00 add eax,0x5eeded 8048803: 89 45 f0 mov DWORD PTR [ebp-0x10],eax 8048806: c7 45 ec 00 00 00 00 mov DWORD PTR [ebp-0x14],0x0 804880d: eb 4c jmp 804885b <auth+0x113> 804880f: 8b 45 ec mov eax,DWORD PTR [ebp-0x14] 8048812: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048815: 0f b6 00 movzx eax,BYTE PTR [eax] 8048818: 3c 1f cmp al,0x1f 804881a: 7f 07 jg 8048823 <auth+0xdb> 804881c: b8 01 00 00 00 mov eax,0x1 8048821: eb 54 jmp 8048877 <auth+0x12f> 8048823: 8b 45 ec mov eax,DWORD PTR [ebp-0x14] 8048826: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048829: 0f b6 00 movzx eax,BYTE PTR [eax] 804882c: 0f be c0 movsx eax,al 804882f: 89 c1 mov ecx,eax 8048831: 33 4d f0 xor ecx,DWORD PTR [ebp-0x10] 8048834: ba 2b 3b 23 88 mov edx,0x88233b2b 8048839: 89 c8 mov eax,ecx 804883b: f7 e2 mul edx 804883d: 89 c8 mov eax,ecx 804883f: 29 d0 sub eax,edx 8048841: d1 e8 shr eax,1 8048843: 01 d0 add eax,edx 8048845: c1 e8 0a shr eax,0xa 8048848: 69 c0 39 05 00 00 imul eax,eax,0x539 804884e: 89 ca mov edx,ecx 8048850: 29 c2 sub edx,eax 8048852: 89 d0 mov eax,edx 8048854: 01 45 f0 add DWORD PTR [ebp-0x10],eax 8048857: 83 45 ec 01 add DWORD PTR [ebp-0x14],0x1 804885b: 8b 45 ec mov eax,DWORD PTR [ebp-0x14] 804885e: 3b 45 f4 cmp eax,DWORD PTR [ebp-0xc] 8048861: 7c ac jl 804880f <auth+0xc7> 8048863: 8b 45 0c mov eax,DWORD PTR [ebp+0xc] 8048866: 3b 45 f0 cmp eax,DWORD PTR [ebp-0x10] 8048869: 74 07 je 8048872 <auth+0x12a> 804886b: b8 01 00 00 00 mov eax,0x1 8048870: eb 05 jmp 8048877 <auth+0x12f> 8048872: b8 00 00 00 00 mov eax,0x0 8048877: c9 leave 8048878: c3 ret ``` - `8048748 - 804875c` Set up stack and allocate 40 bytes for stack, load **logininput** to `[epb+0x8]` and call `strcspn(logininput, "\n")` - `8048761 - 804877a` Replace the character "\n" with a nullbyte for **logininput**. Call `strnlen(logininput, 32)`, save the result in a variable at `[ebp-0xc]` aka **loginlen** - `804877d - 80487b5` Do some weird canary shit until `8048785`, where it checks if **loginlen** is greater than 5. If it is, jump to `8048796`. If not, junp to `8048877` which returns. Calls `ptrace(0, 0, 1, 0)`, can be translated to `ptrace(PTRACE_TRACEME, 0, 1, 0)` which means allow parent to trace me. - `80487bd - 80487e8` If the return value of the ptrace is -1, run the following in order: ``` puts("\033[32m.---------------------------."); puts("\033[31m| !! TAMPERING DETECTED !! |"); puts("\033[32m'---------------------------'"); return 1; ``` - `80487ed - 8048818` Store **logininput[3]** in a temp variable and XOR it with `0x1337 (4919)` and add `0x5eeded (6221293)`. The result is stored in `[ebp-0x10]` aka **enc_logininput** and 0 is stored in `[ebp-0x14]` aka **count**. Jump to `804885b` (loop check). Derefrence **logininput[count]** and compares it with 31. If is less or equal than, return 1. - `8048823 - 8048861` **logininput[count]** is loaded into `ecx` and it is XOR'd against **enc_logininput** to `eax`. `0x88233b2b` which is loaded into `edx`, and we are multiplying `0x88233b2b * **logininput[count]**` and shifting the result by 1 to the right. It add back **logininput[count]** and shifts right by 10. It then multiplies 1337 and stores the value in `eax`. After that, **enc_logininput -= logininput[count]** and move **enc_logininput** to `eax`. **enc_logininput + logininput[count]** and increments **count**, compares count with login length. - `8048863 - 8048877` Compare **serialinput** with the **enc_logininput** If its equal, return 0, else return 1 # level07 ## main ``` 8048723: 55 push ebp 8048724: 89 e5 mov ebp,esp 8048726: 57 push edi 8048727: 56 push esi 8048728: 53 push ebx 8048729: 83 e4 f0 and esp, 804872c: 81 ec d0 01 00 00 sub esp,0x1d0 ``` This section sets up the stack frame and does stack alignment. Also allocates 464 bytes on the stack. ``` 8048732: 8b 45 0c mov eax,DWORD PTR [ebp+0xc] 8048735: 89 44 24 1c mov DWORD PTR [esp+0x1c],eax 8048739: 8b 45 10 mov eax,DWORD PTR [ebp+0x10] 804873c: 89 44 24 18 mov DWORD PTR [esp+0x18],eax 8048740: 65 a1 14 00 00 00 mov eax,gs:0x14 8048746: 89 84 24 cc 01 00 00 mov DWORD PTR [esp+0x1cc],eax 804874d: 31 c0 xor eax,eax ``` This section takes in argv and writes it to `[esp+0x1c]` aka **argv**, also writes envp in `[esp+0x18]` aka **envp**, writes 20 in `[esp+0x1cc]` aka **num1** and sets up the canary mechanism ``` 804874f: c7 84 24 b4 01 00 00 mov DWORD PTR [esp+0x1b4],0x0 8048756: 00 00 00 00 804875a: c7 84 24 b8 01 00 00 mov DWORD PTR [esp+0x1b8],0x0 8048761: 00 00 00 00 8048765: c7 84 24 bc 01 00 00 mov DWORD PTR [esp+0x1bc],0x0 804876c: 00 00 00 00 8048770: c7 84 24 c0 01 00 00 mov DWORD PTR [esp+0x1c0],0x0 8048777: 00 00 00 00 804877b: c7 84 24 c4 01 00 00 mov DWORD PTR [esp+0x1c4],0x0 8048782: 00 00 00 00 8048786: c7 84 24 c8 01 00 00 mov DWORD PTR [esp+0x1c8],0x0 804878d: 00 00 00 00 8048791: 8d 5c 24 24 lea ebx,[esp+0x24] 8048795: b8 00 00 00 00 mov eax,0x0 804879a: ba 64 00 00 00 mov edx,0x64 804879f: 89 df mov edi,ebx 80487a1: 89 d1 mov ecx,edx 80487a3: f3 ab rep stos DWORD PTR es:[edi],eax 80487a5: eb 43 jmp 80487ea <main+0xc7> ``` Declares 6 variables on the stack, `[esp+0x1b4]` aka **op_ret**, `[esp+0x1b8]` aka **user_cmd**, `[esp+0x1bc]` aka **var3**, `[esp+0x1c0]` aka **var4**, `[esp+0x1c4]` aka **var5**, `[esp+0x1c8]` aka **var7**, all of them have value 0 inside them. **var3 to var7** may be part of the same array. Load a buffer from `[esp+0x24]` aka **meat** and call `memset(meat, 0, 100)` and jump to `80487ea` (looks like a loop). ``` 80487a7: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 80487ab: 8b 00 mov eax,DWORD PTR [eax] 80487ad: c7 44 24 14 ff ff ff mov DWORD PTR [esp+0x14],0xffffffff 80487b4: ff 80487b5: 89 c2 mov edx,eax 80487b7: b8 00 00 00 00 mov eax,0x0 80487bc: 8b 4c 24 14 mov ecx,DWORD PTR [esp+0x14] 80487c0: 89 d7 mov edi,edx 80487c2: f2 ae repnz scas al,BYTE PTR es:[edi] 80487c4: 89 c8 mov eax,ecx 80487c6: f7 d0 not eax 80487c8: 8d 50 ff lea edx,[eax-0x1] 80487cb: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 80487cf: 8b 00 mov eax,DWORD PTR [eax] 80487d1: 89 54 24 08 mov DWORD PTR [esp+0x8],edx 80487d5: c7 44 24 04 00 00 00 mov DWORD PTR [esp+0x4],0x0 80487dc: 00 80487dd: 89 04 24 mov DWORD PTR [esp],eax 80487e0: e8 0b fd ff ff call 80484f0 <memset@plt> 80487e5: 83 44 24 1c 04 add DWORD PTR [esp+0x1c],0x4 80487ea: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 80487ee: 8b 00 mov eax,DWORD PTR [eax] 80487f0: 85 c0 test eax,eax 80487f2: 75 b3 jne 80487a7 <main+0x84> 80487f4: eb 43 jmp 8048839 <main+0x116> 80487f6: 8b 44 24 18 mov eax,DWORD PTR [esp+0x18] 80487fa: 8b 00 mov eax,DWORD PTR [eax] 80487fc: c7 44 24 14 ff ff ff mov DWORD PTR [esp+0x14],0xffffffff 8048803: ff 8048804: 89 c2 mov edx,eax 8048806: b8 00 00 00 00 mov eax,0x0 804880b: 8b 4c 24 14 mov ecx,DWORD PTR [esp+0x14] 804880f: 89 d7 mov edi,edx 8048811: f2 ae repnz scas al,BYTE PTR es:[edi] 8048813: 89 c8 mov eax,ecx 8048815: f7 d0 not eax 8048817: 8d 50 ff lea edx,[eax-0x1] 804881a: 8b 44 24 18 mov eax,DWORD PTR [esp+0x18] 804881e: 8b 00 mov eax,DWORD PTR [eax] 8048820: 89 54 24 08 mov DWORD PTR [esp+0x8],edx 8048824: c7 44 24 04 00 00 00 mov DWORD PTR [esp+0x4],0x0 804882b: 00 804882c: 89 04 24 mov DWORD PTR [esp],eax 804882f: e8 bc fc ff ff call 80484f0 <memset@plt> 8048834: 83 44 24 18 04 add DWORD PTR [esp+0x18],0x4 8048839: 8b 44 24 18 mov eax,DWORD PTR [esp+0x18] 804883d: 8b 00 mov whi eax,DWORD PTR [eax] 804883f: 85 c0 test eax,eax 8048841: 75 b3 jne 80487f6 <main+0xd3> ``` Load argv from **argv** and calls strlen on it after defref `strlen(*argv)` and call `memset(*argv, 0, <strlen res>)`. Increment the address of **argv** by 4 (next argument) and compare it with 0. If its not equal, loop back to `80487a7`, essentially repeating this until argv is fully cleared. Do the same thing for envp. ``` 8048843: c7 04 24 38 8b 04 08 mov DWORD PTR [esp],0x8048b38 804884a: e8 71 fc ff ff call 80484c0 <puts@plt> 804884f: b8 4b 8d 04 08 mov eax,0x8048d4b 8048854: 89 04 24 mov DWORD PTR [esp],eax 8048857: e8 14 fc ff ff call 8048470 <printf@plt> 804885c: c7 84 24 b4 01 00 00 mov DWORD PTR [esp+0x1b4],0x1 8048863: 01 00 00 00 8048867: a1 40 a0 04 08 mov eax,ds:0x804a040 804886c: 89 44 24 08 mov DWORD PTR [esp+0x8],eax 8048870: c7 44 24 04 14 00 00 mov DWORD PTR [esp+0x4],0x14 8048877: 00 8048878: 8d 84 24 b8 01 00 00 lea eax,[esp+0x1b8] 804887f: 89 04 24 mov DWORD PTR [esp],eax 8048882: e8 19 fc ff ff call 80484a0 <fgets@plt> 8048887: 8d 84 24 b8 01 00 00 lea eax,[esp+0x1b8] 804888e: c7 44 24 14 ff ff ff mov DWORD PTR [esp+0x14],0xffffffff 8048895: ff 8048896: 89 c2 mov edx,eax 8048898: b8 00 00 00 00 mov eax,0x0 804889d: 8b 4c 24 14 mov ecx,DWORD PTR [esp+0x14] 80488a1: 89 d7 mov edi,edx 80488a3: f2 ae repnz scas al,BYTE PTR es:[edi] 80488a5: 89 c8 mov eax,ecx 80488a7: f7 d0 not eax 80488a9: 83 e8 01 sub eax,0x1 80488ac: 83 e8 01 sub eax,0x1 80488af: c6 84 04 b8 01 00 00 mov BYTE PTR [esp+eax*1+0x1b8],0x0 80488b6: 00 ``` Call these in order :- ``` puts("----------------------------------------------------\n"\ " Welcome to wil's crappy number storage service! \n"\ "----------------------------------------------------\n"\ " Commands: \n"\ " store - store a number into the data storage \n"\ " read - read a number from the data storage \n"\ " quit - exit the program \n"\ "----------------------------------------------------\n"\ " wil has reserved some storage :> \n"\ "----------------------------------------------------\n"\ "\n"); printf("Input command: "); fgets(user_cmd, 20, stdin); op_ret = 1; ``` Once the fgets returns, find the newline character in the string and replace it with a nullbyte using . ``` 80488b7: 8d 84 24 b8 01 00 00 lea eax,[esp+0x1b8] 80488be: 89 c2 mov edx,eax 80488c0: b8 5b 8d 04 08 mov eax,0x8048d5b 80488c5: b9 05 00 00 00 mov ecx,0x5 80488ca: 89 d6 mov esi,edx 80488cc: 89 c7 mov edi,eax 80488ce: f3 a6 repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 80488d0: 0f 97 c2 seta dl 80488d3: 0f 92 c0 setb al 80488d6: 89 d1 mov ecx,edx 80488d8: 28 c1 sub cl,al 80488da: 89 c8 mov eax,ecx 80488dc: 0f be c0 movsx eax,al 80488df: 85 c0 test eax,eax 80488e1: 75 15 jne 80488f8 <main+0x1d5> 80488e3: 8d 44 24 24 lea eax,[esp+0x24] 80488e7: 89 04 24 mov DWORD PTR [esp],eax 80488ea: e8 41 fd ff ff call 8048630 <store_number> 80488ef: 89 84 24 b4 01 00 00 mov DWORD PTR [esp+0x1b4],eax 80488f6: eb 6d jmp 8048965 <main+0x242> ``` Comapre **user_cmd** with "store" using `strncmp(user_cmd, "store", 5)`. If its not equal, jump to `80488f8`, which should check next command. If it is, call `store_number(meat)` and place the return value at **op_ret**, go back to the loop start by jumping to `8048965` ``` 80488f8: 8d 84 24 b8 01 00 00 lea eax,[esp+0x1b8] 80488ff: 89 c2 mov edx,eax 8048901: b8 61 8d 04 08 mov eax,0x8048d61 8048906: b9 04 00 00 00 mov ecx,0x4 804890b: 89 d6 mov esi,edx 804890d: 89 c7 mov edi,eax 804890f: f3 a6 repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 8048911: 0f 97 c2 seta dl 8048914: 0f 92 c0 setb al 8048917: 89 d1 mov ecx,edx 8048919: 28 c1 sub cl,al 804891b: 89 c8 mov eax,ecx 804891d: 0f be c0 movsx eax,al 8048920: 85 c0 test eax,eax 8048922: 75 15 jne 8048939 <main+0x216> 8048924: 8d 44 24 24 lea eax,[esp+0x24] 8048928: 89 04 24 mov DWORD PTR [esp],eax 804892b: e8 a7 fd ff ff call 80486d7 <read_number> 8048930: 89 84 24 b4 01 00 00 mov DWORD PTR [esp+0x1b4],eax 8048937: eb 2c jmp 8048965 <main+0x242> ``` Do the same thing to `read`, `strncmp(user_cmd, "read", 4)` and call `read_number(meat)` , saving the output at **op_ret** and jumping to `8048965` ``` 8048939: 8d 84 24 b8 01 00 00 lea eax,[esp+0x1b8] 8048940: 89 c2 mov edx,eax 8048942: b8 66 8d 04 08 mov eax,0x8048d66 8048947: b9 04 00 00 00 mov ecx,0x4 804894c: 89 d6 mov esi,edx 804894e: 89 c7 mov edi,eax 8048950: f3 a6 repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 8048952: 0f 97 c2 seta dl 8048955: 0f 92 c0 setb al 8048958: 89 d1 mov ecx,edx 804895a: 28 c1 sub cl,al 804895c: 89 c8 mov eax,ecx 804895e: 0f be c0 movsx eax,al 8048961: 85 c0 test eax,eax 8048963: 74 6a je 80489cf <main+0x2ac> ``` Do the same thing to `"quit"`, `strncmp(user_cmd, "quit", 4)` and jump to `80489cf`, which checks for canary and returns. ``` 8048965: 83 bc 24 b4 01 00 00 cmp DWORD PTR [esp+0x1b4],0x0 804896c: 00 804896d: 74 1a je 8048989 <main+0x266> 804896f: b8 6b 8d 04 08 mov eax,0x8048d6b 8048974: 8d 94 24 b8 01 00 00 lea edx,[esp+0x1b8] 804897b: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 804897f: 89 04 24 mov DWORD PTR [esp],eax 8048982: e8 e9 fa ff ff call 8048470 <printf@plt> 8048987: eb 18 jmp 80489a1 <main+0x27e> 8048989: b8 88 8d 04 08 mov eax,0x8048d88 804898e: 8d 94 24 b8 01 00 00 lea edx,[esp+0x1b8] 8048995: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 8048999: 89 04 24 mov DWORD PTR [esp],eax 804899c: e8 cf fa ff ff call 8048470 <printf@plt> 80489a1: 8d 84 24 b8 01 00 00 lea eax,[esp+0x1b8] 80489a8: c7 00 00 00 00 00 mov DWORD PTR [eax],0x0 80489ae: c7 40 04 00 00 00 00 mov DWORD PTR [eax+0x4],0x0 80489b5: c7 40 08 00 00 00 00 mov DWORD PTR [eax+0x8],0x0 80489bc: c7 40 0c 00 00 00 00 mov DWORD PTR [eax+0xc],0x0 80489c3: c7 40 10 00 00 00 00 mov DWORD PTR [eax+0x10],0x0 80489ca: e9 80 fe ff ff jmp 804884f <main+0x12c> 80489cf: 90 nop 80489d0: b8 00 00 00 00 mov eax,0x0 80489d5: 8b b4 24 cc 01 00 00 mov esi,DWORD PTR [esp+0x1cc] 80489dc: 65 33 35 14 00 00 00 xor esi,DWORD PTR gs:0x14 80489e3: 74 05 je 80489ea <main+0x2c7> 80489e5: e8 c6 fa ff ff call 80484b0 <__stack_chk_fail@plt> 80489ea: 8d 65 f4 lea esp,[ebp-0xc] 80489ed: 5b pop ebx 80489ee: 5e pop esi 80489ef: 5f pop edi 80489f0: 5d pop ebp 80489f1: c3 ret ``` Check for empty **op_ret** If it is empty or 0, jump to `8048989` which calls `printf(" Completed %s command successfully\n", user_cmd)`, clears all vars and goes back to loop. If the loop exits, check canary and return. If **op_ret** is non zero, call `printf("Failed to do %s command\n", user_cmd)` ## read_number ``` 080486d7 <read_number>: 80486d7: 55 push ebp 80486d8: 89 e5 mov ebp,esp 80486da: 83 ec 28 sub esp,0x28 80486dd: c7 45 f4 00 00 00 00 mov DWORD PTR [ebp-0xc],0x0 80486e4: b8 dd 8a 04 08 mov eax,0x8048add 80486e9: 89 04 24 mov DWORD PTR [esp],eax 80486ec: e8 7f fd ff ff call 8048470 <printf@plt> 80486f1: e8 f1 fe ff ff call 80485e7 <get_unum> 80486f6: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 80486f9: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80486fc: c1 e0 02 shl eax,0x2 80486ff: 03 45 08 add eax,DWORD PTR [ebp+0x8] 8048702: 8b 10 mov edx,DWORD PTR [eax] 8048704: b8 1b 8b 04 08 mov eax,0x8048b1b 8048709: 89 54 24 08 mov DWORD PTR [esp+0x8],edx 804870d: 8b 55 f4 mov edx,DWORD PTR [ebp-0xc] 8048710: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 8048714: 89 04 24 mov DWORD PTR [esp],eax 8048717: e8 54 fd ff ff call 8048470 <printf@plt> 804871c: b8 00 00 00 00 mov eax,0x0 8048721: c9 leave 8048722: c3 ret ``` Sets up stack and allocates 40 bytes on the stack. Clears out `[ebp-0xc]` aka **num_input** and calls `printf("Index: ")` and then calls `get_unum()`, and stores the value in **num_input**. The number is then shifted left by 2 and added by the first argument in `[ebp+0x8]` aka **meat**. **meat** is then derefrenced and put to `edx` and calls `printf("Number at data[%u] is %u, ", num_input, meat)`. Returns 0 ## store_number ``` 8048630: 55 push ebp 8048631: 89 e5 mov ebp,esp 8048633: 83 ec 28 sub esp,0x28 8048636: c7 45 f0 00 00 00 00 mov DWORD PTR [ebp-0x10],0x0 804863d: c7 45 f4 00 00 00 00 mov DWORD PTR [ebp-0xc],0x0 8048644: b8 d3 8a 04 08 mov eax,0x8048ad3 8048649: 89 04 24 mov DWORD PTR [esp],eax 804864c: e8 1f fe ff ff call 8048470 <printf@plt> 8048651: e8 91 ff ff ff call 80485e7 <get_unum> 8048656: 89 45 f0 mov DWORD PTR [ebp-0x10],eax 8048659: b8 dd 8a 04 08 mov eax,0x8048add 804865e: 89 04 24 mov DWORD PTR [esp],eax 8048661: e8 0a fe ff ff call 8048470 <printf@plt> 8048666: e8 7c ff ff ff call 80485e7 <get_unum> 804866b: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 804866e: 8b 4d f4 mov ecx,DWORD PTR [ebp-0xc] 8048671: ba ab aa aa aa mov edx,0xaaaaaaab 8048676: 89 c8 mov eax,ecx 8048678: f7 e2 mul edx 804867a: d1 ea shr edx,1 804867c: 89 d0 mov eax,edx 804867e: 01 c0 add eax,eax 8048680: 01 d0 add eax,edx 8048682: 89 ca mov edx,ecx 8048684: 29 c2 sub edx,eax 8048686: 85 d2 test edx,edx 8048688: 74 0d je 8048697 <store_number+0x67> 804868a: 8b 45 f0 mov eax,DWORD PTR [ebp-0x10] 804868d: c1 e8 18 shr eax,0x18 8048690: 3d b7 00 00 00 cmp eax,0xb7 8048695: 75 2b jne 80486c2 <store_number+0x92> 8048697: c7 04 24 e6 8a 04 08 mov DWORD PTR [esp],0x8048ae6 804869e: e8 1d fe ff ff call 80484c0 <puts@plt> 80486a3: c7 04 24 f8 8a 04 08 mov DWORD PTR [esp],0x8048af8 80486aa: e8 11 fe ff ff call 80484c0 <puts@plt> 80486af: c7 04 24 e6 8a 04 08 mov DWORD PTR [esp],0x8048ae6 80486b6: e8 05 fe ff ff call 80484c0 <puts@plt> 80486bb: b8 01 00 00 00 mov eax,0x1 80486c0: eb 13 jmp 80486d5 <store_number+0xa5> 80486c2: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 80486c5: c1 e0 02 shl eax,0x2 80486c8: 03 45 08 add eax,DWORD PTR [ebp+0x8] 80486cb: 8b 55 f0 mov edx,DWORD PTR [ebp-0x10] 80486ce: 89 10 mov DWORD PTR [eax],edx 80486d0: b8 00 00 00 00 mov eax,0x0 80486d5: c9 leave 80486d6: c3 ret ``` Sets up stack and allocates 40 bytes on the stack. Clears up `[ebp-0x10]` aka **num_input** and `[ebp-0xc]` aka **idx_input**. Call `printf("Number: ")` and then call `get_unum()`, which assigns the return value to **num_input** Do the same for **idx_input**, with the print being `printf("Index: ")`. The pseudocode for `8048671 - 8048686` is like so. ``` let idx_input = ...; let temp1 = 0xaaaaaaab; idx_input += temp1 temp1 >> 1 let temp2 = temp1 temp2 *= 2 temp2 += temp1 let temp3 = 0xaaaaaaab - temp2 temp3 == 0? ``` If the condition is true jump to `8048697` which calls ``` puts(" *** ERROR! ***"); puts(" This index is reserved for wil!"); puts(" *** ERROR! ***"); ``` and return 1 The pseudocode for `804868a - 8048690` is like so ``` num_input >> 0x18 == 0xb7? ``` If its not true, jump to `80486c2` which does `meat[idx_input] = num_input;` and return 0. jump to `8048697` if its not. ## get_unum ``` 80485e7: 55 push ebp 80485e8: 89 e5 mov ebp,esp 80485ea: 83 ec 28 sub esp,0x28 80485ed: c7 45 f4 00 00 00 00 mov DWORD PTR [ebp-0xc],0x0 80485f4: a1 60 a0 04 08 mov eax,ds:0x804a060 80485f9: 89 04 24 mov DWORD PTR [esp],eax 80485fc: e8 7f fe ff ff call 8048480 <fflush@plt> 8048601: b8 d0 8a 04 08 mov eax,0x8048ad0 8048606: 8d 55 f4 lea edx,[ebp-0xc] 8048609: 89 54 24 04 mov DWORD PTR [esp+0x4],edx 804860d: 89 04 24 mov DWORD PTR [esp],eax 8048610: e8 eb fe ff ff call 8048500 <__isoc99_scanf@plt> 8048615: e8 aa ff ff ff call 80485c4 <clear_stdin> 804861a: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc] 804861d: c9 leave 804861e: c3 ret ``` Setup stack and allocate 40 bytes for the stack, declare a variable at `[ebp-0xc]` aka **res**, call `fflush(stdout)` and then ` scanf("%u", &res)`. Call `clear_stdin()` and return **res** ## clear_stdin ``` 080485c4 <clear_stdin>: 80485c4: 55 push ebp 80485c5: 89 e5 mov ebp,esp 80485c7: 83 ec 18 sub esp,0x18 80485ca: c6 45 f7 00 mov BYTE PTR [ebp-0x9],0x0 80485ce: eb 01 jmp 80485d1 <clear_stdin+0xd> 80485d0: 90 nop 80485d1: e8 ba fe ff ff call 8048490 <getchar@plt> 80485d6: 88 45 f7 mov BYTE PTR [ebp-0x9],al 80485d9: 80 7d f7 0a cmp BYTE PTR [ebp-0x9],0xa 80485dd: 74 06 je 80485e5 <clear_stdin+0x21> 80485df: 80 7d f7 ff cmp BYTE PTR [ebp-0x9],0xff 80485e3: 75 eb jne 80485d0 <clear_stdin+0xc> 80485e5: c9 leave 80485e6: c3 ret ``` Setup stack and allocate 24 bytes for the stack, declare a variable at `[ebp-0x9]` aka **curr**, jump to `80485d1` (loop start), calls `getchar()` and stores ret value at **curr**. Compare **curr** with '\n' and -1. Return of they are either equal. jump back to `80485d0` if they are not (infinite loop)