This shows you the differences between two versions of the page.
cns:labs:lab-07 [2020/11/22 21:00] dennis.plosceanu [Extra: Format String Attack] |
cns:labs:lab-07 [2022/11/21 14:29] (current) mihai.dumitru2201 [Basic Format String Attack] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Lab 07 - Strings ====== | ====== Lab 07 - Strings ====== | ||
- | ===== Tasks ==== | + | ===== Tasks repository ==== |
All content necessary for the CNS laboratory tasks can be found in [[cns:resources:repo|the CNS public repository]]. | All content necessary for the CNS laboratory tasks can be found in [[cns:resources:repo|the CNS public repository]]. | ||
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 258: | Line 266: | ||
==== Basic Format String Attack ==== | ==== Basic Format String Attack ==== | ||
- | You will now do a basic format string attack using the ''basic-format-string/'' subfolder in the [[http://elf.cs.pub.ro/oss/res/labs/lab-07.tar.gz|lab archive]]. The source code is in ''basic_format_string.c'' and the executable is in ''basic_format_string''. | + | You will now do a basic format string attack using the ''03-basic-format-string/'' subfolder. The source code is in ''basic_format_string.c'' and the executable is in ''basic_format_string''. |
- | You need to use ''%n'' to overwrite the value of the ''v'' variable to ''200''. You have to do three steps: | + | You need to use ''%n'' to overwrite the value of the ''v'' variable to ''0x300''. You have to do three steps: |
- Determine the address of the ''v'' variable using ''nm''. | - Determine the address of the ''v'' variable using ''nm''. | ||
- Determine the ''n''-th parameter of ''printf()'' that you can write to using ''%n''. The ''buffer'' variable will have to be that parameter; you will store the address of the ''v'' variable in the ''buffer'' variable. | - Determine the ''n''-th parameter of ''printf()'' that you can write to using ''%n''. The ''buffer'' variable will have to be that parameter; you will store the address of the ''v'' variable in the ''buffer'' variable. | ||
- | - Construct a format string that enables the attack; the number of characters processed by ''printf()'' until ''%n'' is matched will have to be ''200''. | + | - Construct a format string that enables the attack; the number of characters processed by ''printf()'' until ''%n'' is matched will have to be ''0x300''. |
For the second step let's run the program multiple times and figure out where the ''buffer'' address starts. We fill ''buffer'' with the ''aaaa'' string and we expect to discover it using the ''printf()'' format specifiers. | For the second step let's run the program multiple times and figure out where the ''buffer'' address starts. We fill ''buffer'' with the ''aaaa'' string and we expect to discover it using the ''printf()'' format specifiers. | ||
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 |