pwndbg
:(( ).If you're not using the OpenStack VM:
sudo apt install libc6-dev-i386 gcc-multilib
git clone https://github.com/pwndbg/pwndbg cd pwndbg ./setup.sh
To check if everything is OK, run the command gdb
with no arguments. The prompt should be similar to this:
➜ gdb GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1 ... pwndbg>
Enter q
to exit GDB. We are using PwnDbg instead of the classic GDB because it is much more user friendly. Hope you'll like it ;)
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!
Also check out one of the resources linked on top ^^ !
To find out what's different for a 64 bit program check this website.
Please check out a GDB cheatsheet for the most common operations.
You should see how to:
pwntools
will later prove very useful for!);break
points & execution control (n
/ s
/ ni
/ si
/ c
);p
/ x
+ C expressions + various formats);info
to see breakpoints / symbols;Please read GDB tutorial if you're missing any of the above knowledge.
PwnDbg is a very nice GDB plugin (written in Python) which displays a plethora of information at each breakpoint and provides many useful commands (some which may prove to be useful when writing exploits!); here's an example output:
22 if (argc == 1) { LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ─────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────── *EAX 0xffffd880 ◂— 0x2 *EBX 0x56558fcc (_GLOBAL_OFFSET_TABLE_) ◂— 0x3ed4 *ECX 0xffffd880 ◂— 0x2 *EDX 0xffffd8a0 —▸ 0xf7fa9000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x229dac *EDI 0xf7ffcb80 (_rtld_global_ro) ◂— 0x0 *ESI 0xffffd934 —▸ 0xffffdabd ◂— '/home/student/appsec/buggy' *EBP 0xffffd868 —▸ 0xf7ffd020 (_rtld_global) —▸ 0xf7ffda40 —▸ 0x56555000 ◂— 0x464c457f *ESP 0xffffd850 —▸ 0xffffd890 —▸ 0xf7fa9000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x229dac *EIP 0x56556281 (main+31) ◂— cmp dword ptr [eax], 1 ───────────────────────────────────[ DISASM / i386 / set emulate on ]──────────────────────────────────── ► 0x56556281 <main+31> cmp dword ptr [eax], 1 0x56556284 <main+34> jne main+61 <main+61> ↓ 0x5655629f <main+61> mov dword ptr [ebp - 0xc], 0x796568 0x565562a6 <main+68> mov eax, dword ptr [eax + 4] 0x565562a9 <main+71> add eax, 4 0x565562ac <main+74> mov eax, dword ptr [eax] 0x565562ae <main+76> sub esp, 4 0x565562b1 <main+79> push eax 0x565562b2 <main+80> lea eax, [ebp - 0xc] 0x565562b5 <main+83> push eax 0x565562b6 <main+84> lea eax, [ebx - 0x1f6e] ────────────────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────────────── In file: /home/student/appsec/buggy.c 17 gets(name); 18 printf("bye\n"); 19 } 20 21 int main(int argc, char **argv) { ► 22 if (argc == 1) { 23 puts("Usage: %s <name>\n"); 24 return 1; 25 } 26 char buf[] = "hey"; 27 ────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────── 00:0000│ esp 0xffffd850 —▸ 0xffffd890 —▸ 0xf7fa9000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x229dac 01:0004│-014 0xffffd854 —▸ 0xf7fbe66c —▸ 0xf7ffdba0 —▸ 0xf7fbe780 —▸ 0xf7ffda40 ◂— ... 02:0008│-010 0xffffd858 —▸ 0xf7fbeb20 —▸ 0xf7d99cc6 ◂— 'GLIBC_PRIVATE' 03:000c│-00c 0xffffd85c ◂— 0x1 04:0010│-008 0xffffd860 —▸ 0xffffd880 ◂— 0x2 05:0014│-004 0xffffd864 —▸ 0xf7fa9000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x229dac 06:0018│ ebp 0xffffd868 —▸ 0xf7ffd020 (_rtld_global) —▸ 0xf7ffda40 —▸ 0x56555000 ◂— 0x464c457f 07:001c│+004 0xffffd86c —▸ 0xf7da0519 (__libc_start_call_main+121) ◂— add esp, 0x10 ──────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────── ► 0 0x56556281 main+31 1 0xf7da0519 __libc_start_call_main+121 2 0xf7da05f3 __libc_start_main+147 3 0x565560cb _start+43 ─────────────────────────────────────────────────────────────────────────────────────────────────────────
Let's take a look at the previous output that PwnDbg prints. You can see it is seprated into 5 sections: REGISTERS, DISASM, SOURCE, STACK and TRACE. With the original GDB you would have to manually print registers, disassemble code and inspect the stack. Thanks, God, for PwnDbg!
Download the lab archive and unpack it somewhere in your home.
Run make
.
obfusflag
binary; you may study the code, but your task is clear: find out the obfuscated flag!gdb
, ofc!
-g
), take the variable's address, cast to pointer of desired type then dereference:
set variable *(int *)&myvar = value
buf
variable;buffovf
binary. There is a vulnerability in there, can you see it?
run args < <(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * N)')
for stdin redirection directly within GDB! ;)
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
call
er (also see the stack diagram above)?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;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);for_the_win
function (simply replace the address above with the function's virtual address)!docker run -d -p 31337:1337 --rm --name leakme -it ghcr.io/cs-pub-ro/isc-lab-buff-leakme
netcat
utility: nc localhost 31337
; after the test succeeds, simply quit… read on!leakme
code & binary. Try to overflow its input buffer!exploit_skel.py
code for further instructions ;).TEXT
(code segment) addresses using a format string attack and figure out the final call_me_maybe()
function's virtual address!pwntools
!
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 ;) ).
REMOTE = True
to get the real one!Please take a minute to fill in the feedback form for this lab.