This shows you the differences between two versions of the page.
|
isc:labs:05 [2024/11/03 21:38] florin.stancu |
isc:labs:05 [2025/11/04 11:49] (current) david.gherghita [Exercises] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Lab 05 - Application Security ====== | ====== Lab 05 - Application Security ====== | ||
| + | |||
| + | ===== Objectives ===== | ||
| + | |||
| + | * Call conventions & stack structure | ||
| + | * Buffer overflow vulnerabilities | ||
| + | * Using pwndbg & pwntools to facilitate exploit development | ||
| ===== Resources ===== | ===== Resources ===== | ||
| - | *[[https://dhavalkapil.com/blogs/Buffer-Overflow-Exploit/|Buffer overflow explained]] | + | * [[https://dhavalkapil.com/blogs/Buffer-Overflow-Exploit/|Buffer overflow explained]] |
| - | *[[https://dhavalkapil.com/blogs/Shellcode-Injection/|Shellcode explained]] | + | * [[https://dhavalkapil.com/blogs/Shellcode-Injection/|Shellcode explained]] |
| + | * [[https://chatgpt.com/share/67279837-b05c-800e-a60a-6629ef3dd7f7|ChatGPT's record for stack structure & buffer overflow]] //(same length, but why bother read the opinion of some anonymous industry expert when you got the popular AI kid parroting the same stuff, right?)// | ||
| ===== Setup ===== | ===== Setup ===== | ||
| - | * [[:isc:info:virtualmachine|Open a lab VM instance]] on [[https://cloud.grid.pub.ro|OpenStack]], use the **m1.medium** flavor for 2GB of RAM (required by ''pwndbg'' :(( ). | + | * [[:isc:info:virtualmachine|Open a lab VM instance]] on [[https://cloud.grid.pub.ro|OpenStack]]. |
| - | **If you're not using the OpenStack VM**: | + | **If you're using the local VM for ARM 64 (AArch64)**: |
| - | * Install the 32-bit **libc** and **gcc-multilib** packages: <code> | + | * You have ''x86'' cross-compilers pre-installed! Use ''i686-linux-gnu-gcc'' to build 32-bit programs and ''x86_64-linux-gnu-gcc'' for AMD64 targets; |
| - | sudo apt install libc6-dev-i386 gcc-multilib | + | * You also have [[https://www.qemu.org/docs/master/user/main.html|qemu-user]] properly installed inside the local VM, so you can simply run any x86 binaries and they'll get emulated! |
| - | </code> | + | * If you intend to use ''objdump'' aarch64-hosted/emulated x86 binaries, you must use the cross compiler suite's, so make sure to prefix it, e.g.: ''x86_86-gnu-linux-objdump''! |
| - | * Install the PwnDbg plugin: <code> | + | |
| - | git clone https://github.com/pwndbg/pwndbg | + | |
| - | cd pwndbg | + | |
| - | ./setup.sh | + | |
| - | </code> | + | |
| - | + | ||
| - | To check if everything is OK, run the command ''gdb'' with no arguments. The prompt should be similar to this: | + | |
| - | + | ||
| - | <code> | + | |
| - | ➜ gdb | + | |
| - | GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1 | + | |
| - | ... | + | |
| - | pwndbg> | + | |
| - | </code> | + | |
| - | Enter ''q'' to exit GDB. We are using [[https://github.com/pwndbg/pwndbg|PwnDbg]] instead of the classic GDB because it is much more user friendly. Hope you'll like it ;) | + | Note that we are using [[https://github.com/pwndbg/pwndbg|PwnDbg]] instead of the classic GDB because it is much more user friendly. Hope you'll like it ;) |
| ===== Overview ===== | ===== Overview ===== | ||
| Line 37: | Line 30: | ||
| {{:isc:labs:stack_layout.png?700}} | {{:isc:labs:stack_layout.png?700}} | ||
| + | |||
| + | Also check out one of the resources linked on top ^^ ! | ||
| <note tip> | <note tip> | ||
| Line 133: | Line 128: | ||
| * Use ''gdb'', ofc! | * Use ''gdb'', ofc! | ||
| * Trouble navigating through the runtime code? see the tutorials / cheatsheets above! | * Trouble navigating through the runtime code? see the tutorials / cheatsheets above! | ||
| + | |||
| + | <note tip> | ||
| + | To change a variable without typing info built-in (not compiled using ''-g''), take the variable's address, cast to pointer of desired type then dereference:<code> | ||
| + | set variable *(int *)&myvar = value | ||
| + | </code> | ||
| + | </note> | ||
| + | |||
| + | * Hint: you're on 64-bit, check the links above for the calling convention... | ||
| + | * Hint 2: you also don't have debugging info compiled-in, so you must use disassembly to find the RBP offset of the ''buf'' variable; | ||
| + | <spoiler In case of emergency, expand> | ||
| + | If this seems too difficult or you wasted too much time, just add ''-g'' to the ''gcc'' rule inside the Makefile, recompile and try it this way :( | ||
| + | </spoiler> | ||
| + | |||
| + | <solution -hidden> | ||
| + | <code> | ||
| + | # gdb obfusflag | ||
| + | gdb> break check_fl0gz0rx | ||
| + | gdb> run 12345678901234567890 | ||
| + | gdb> set var *(int*)&deez = 1 | ||
| + | gdb> tbreak *check_fl0gz0rx + 159 # before strcmp | ||
| + | gdb> continue | ||
| + | gdb> x/10s $rbp - 0x30 # find out buf's RBP offset from disass | ||
| + | </code> | ||
| + | </solution> | ||
| === [50p] 02. Stack overflow (EZ) === | === [50p] 02. Stack overflow (EZ) === | ||
| - | * Run & study the ''buffovf'' binary. There is a stack overflow vulnerability in there, can you see it? | + | * Run & study the ''buffovf'' binary. There is a vulnerability in there, can you see it? |
| * Yep, you **must** use stack overflow to get this flag! | * Yep, you **must** use stack overflow to get this flag! | ||
| * First, try to crash the program. Use programmatically generated input (e.g., from Python3); | * First, try to crash the program. Use programmatically generated input (e.g., from Python3); | ||
| Line 149: | Line 168: | ||
| * Next, try to answer this question: how many bytes do I need to overflow until I get to the EIP saved by the ''call''er (also see the stack diagram above)? | * Next, try to answer this question: how many bytes do I need to overflow until I get to the EIP saved by the ''call''er (also see the stack diagram above)? | ||
| - | * Use either ''objdump -S'' or ''pwndbg> disass <name>'' on the //vulnerable function// to figure out the offset of the buffer variable from the EBP register using the assembly code; | + | * Use either ''objdump -S -M intel'' or ''pwndbg> disass <name>'' on the //vulnerable function// to figure out the offset of the buffer variable from the EBP register using the assembly code; |
| * In order to check if the answer is right, try to use an input of the following form: ''%%b"A" * N + b"\xEF\xCD\xAB\x98"%%''; this should make the program segfault with the end instruction pointer at ''0x98ABCDEF'' (readily visible in pwndbg's automatic registers printing); | * In order to check if the answer is right, try to use an input of the following form: ''%%b"A" * N + b"\xEF\xCD\xAB\x98"%%''; this should make the program segfault with the end instruction pointer at ''0x98ABCDEF'' (readily visible in pwndbg's automatic registers printing); | ||
| * Things start to become easy; call the ''for_the_win'' function (simply replace the address above with the function's virtual address)! | * Things start to become easy; call the ''for_the_win'' function (simply replace the address above with the function's virtual address)! | ||
| * Do not forget: x86 uses little endian encoding for multi-byte integers! | * Do not forget: x86 uses little endian encoding for multi-byte integers! | ||
| - | * Another warning: ASLR is enabled and the program is compiled as position independent code! Use ''gdb'' to "leak" the function's address, which shouldn't change while using ''gdb'' (it uses the same constant seed for ASLR's randomizer)! | + | * As bonus, can you further chain calls to make the exploited program gracefully exit? |
| <solution -hidden> | <solution -hidden> | ||
| <code> | <code> | ||
| - | pwndbg> run "briliantul" < <(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 24 + b"\xa6\x91\x04\x08")') | + | pwndbg> run "Salam" < <(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 0x19 +b"\xa6\x91\x04\x08" + b"\x0e\x93\x04\x08" + b"\xbe\xba\xfe\xca")') |
| - | ... | + | |
| - | hey, args | + | |
| - | what's ur last name? | + | |
| - | almost there, try to supply the correct arguments! | + | |
| - | bye | + | |
| - | + | ||
| - | Program received signal SIGSEGV, Segmentation fault. | + | |
| </code> | </code> | ||
| </solution> | </solution> | ||
| Line 181: | Line 193: | ||
| * For practice, you could also (trivially) implement the exploit for the previous task in ''pwntools''! | * For practice, you could also (trivially) implement the exploit for the previous task in ''pwntools''! | ||
| <note warning> | <note warning> | ||
| - | Beware of this behavior: if you overwrite just 1-2 extra bytes after the saved EIP, you will invalidate the ''get_user_info'' function's arguments, thus your program will crash earlier on one of those ''memcpy'' lines and won't get to return properly! Use the attached GDB and set breakpoints before these lines to debug (or just ''reverse-*'' your execution to discover the segfault reason ;) ). | + | Beware of this behavior: if you overwrite just 1-2 extra bytes after the saved EIP, you will invalidate the ''get_user_info'' function's arguments, thus your program will crash earlier on one of those ''memcpy'' lines and won't get to return properly! Use the attached GDB and set breakpoints before these lines to debug (or just ''reverse-*'' your execution to discover the crash reason ;) ). |
| </note> | </note> | ||