Differences

This shows you the differences between two versions of the page.

Link to this comparison view

isc:labs:05 [2024/11/03 12:07]
florin.stancu
isc:labs:05 [2024/11/04 10:43] (current)
florin.stancu
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]],​ use the **m1.medium** flavor for 1.5GB of RAM (required by ''​pwndbg''​ :(( ).
  
 **If you're not using the OpenStack VM**: **If you're not using the OpenStack VM**:
Line 36: Line 43:
 A buffer overflow occurs when data written to a buffer overruns its boundary and overwrites adjacent memory locations, due to insufficient bounds checking. Thus, an exploiting this will be able to alter the execution flow of the program by overriding the previous instruction pointer register (prior to issuing the current function call) saved on stack and execute its own malicious code! A buffer overflow occurs when data written to a buffer overruns its boundary and overwrites adjacent memory locations, due to insufficient bounds checking. Thus, an exploiting this will be able to alter the execution flow of the program by overriding the previous instruction pointer register (prior to issuing the current function call) saved on stack and execute its own malicious code!
  
-{{http://​i.imgur.com/​mK1nsNl.png}}+{{:isc:​labs:​stack_layout.png?700}} 
 + 
 +Also check out one of the resources linked on top ^^ !
  
 <note tip> <note tip>
Line 51: Line 60:
 You should see how to: You should see how to:
  
-  * run a binary inside GDB, pass arguments (and, for advanced cases: programmatic standard input -- which ''​pwnlib''​ will later prove very useful for!);+  * run a binary inside GDB, pass arguments (and, for advanced cases: programmatic standard input -- which ''​pwntools''​ will later prove very useful for!);
   * add ''​break''​points & execution control (''​n''​ / ''​s''​ / ''​ni''​ / ''​si''​ / ''​c''​);​   * add ''​break''​points & execution control (''​n''​ / ''​s''​ / ''​ni''​ / ''​si''​ / ''​c''​);​
   * display variables and memory contents (''​p''​ / ''​x''​ + C expressions + various formats);   * display variables and memory contents (''​p''​ / ''​x''​ + C expressions + various formats);
Line 115: Line 124:
    3 0x565560cb _start+43    3 0x565560cb _start+43
 ───────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────────────────────────────────────────────────────────────────────────────────────────────────
- 
 </​code>​ </​code>​
  
Line 123: Line 131:
 ==== Exercises ==== ==== Exercises ====
  
-** TODO **+=== 00. Preparation === 
 + 
 +Download the {{ :​isc:​labs:​lab05-code.zip | lab archive }} and unpack it somewhere in your home. 
 + 
 +Run ''​make''​. 
 + 
 +=== [20p] 01. Obfuscated Code === 
 + 
 +  ​Run the ''​obfusflag''​ binary; you may study the code, but your task is clear: find out the obfuscated flag! 
 +    ​Use ''​gdb'',​ ofc! 
 +    ​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) === 
 + 
 +  * 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! 
 +  * First, try to crash the program. Use programmatically generated input (e.g., from Python3); 
 + 
 +<note tip> 
 +You can use ''​%%run args < <​(python3 -c '​import sys; sys.stdout.buffer.write(b"​A"​ * N)'​)%%''​ for stdin redirection directly within GDB! ;) 
 +</​note>​ 
 +<note warning>​ 
 +Do not use ''​print''​ in Python for this purpose as some installations (especially on Ubuntu) use a default UTF-8 encoding and auto-correct any unknown binary string to a valid sequence. This is why ''​sys.stdout.buffer.write()''​ was used in the snippet above, but beware: it requires a ''​bytes''​ object as argument! 
 +You can test the binary output using **xxd**: ''​python3 -c '... write here ...' | xxd -g 1''​ 
 +</​note>​ 
 + 
 +  * 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; 
 +    * 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)! 
 +    * Do not forget: x86 uses little endian encoding for multi-byte integers! 
 +  * As bonus, can you further chain calls to make the exploited program gracefully exit? 
 + 
 +<​solution -hidden>​ 
 +<​code>​ 
 +pwndbg> run "​Salam"​ < <​(python3 -c '​import sys; sys.stdout.buffer.write(b"​A"​ * 0x19 +b"​\xb6\x91\x04\x08"​ + b"​\x12\x93\x04\x08"​ + b"​\xbe\xba\xfe\xca"​)'​) 
 +</​code>​ 
 +</​solution>​ 
 + 
 +=== [30p] 03. Format string leak + pwntools === 
 + 
 +  * Run the following command to open a docker container: <​code>​ 
 +docker run -d -p 31337:1337 --rm --name leakme -it ghcr.io/​cs-pub-ro/​isc-lab-buff-leakme 
 +</​code>​ 
 +    * try if the server is up using the ''​netcat''​ utility: ''​nc localhost 31337'';​ after the test succeeds, simply quit... read on! 
 + 
 +  * Open (locally, ignore the container server for now) the ''​leakme''​ code & binary. Try to overflow its input buffer! 
 +  * For this task, you must use [[https://​docs.pwntools.com/​en/​stable/​|pwntools]]. Check the included ''​exploit_skel.py''​ code for further instructions ;) 
 +    * Note: ASLR is running (and don't just disable it :P); you'll need to leak some ''​.TEXT''​ (code segment) addresses using a format string attack and figure out the final ''​call_me_maybe()''​ function'​s virtual address! 
 +    * For practice, you could also (trivially) implement the exploit for the previous task in ''​pwntools''​! 
 +<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 crash reason ;) ). 
 +</​note>​ 
 + 
 +  * After successfully exploiting it, note that there'​s no flag file available locally! But you should have the exploit ready, so simply set the ''​REMOTE = True''​ to get the real one! 
 + 
 +<​solution -hidden>​ 
 +[[https://​github.com/​cs-pub-ro/​ISC-labs/​blob/​master/​lab05-appsec/​resources/​exploit_solved.py|View solution code (GitHub, requires login!)]] 
 +</​solution>​ 
 + 
 +=== Feedback === 
 + 
 +Please take a minute to fill in the [[https://​forms.gle/​5Lu1mFa63zptk2ox9|feedback form]] for this lab. 
isc/labs/05.1730628424.txt.gz · Last modified: 2024/11/03 12:07 by florin.stancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0