pwn68
目录
题目
预计时间
2h
题目分析与截图
nop seld 的原理我在pwn67的wp中提到,这里我不在说了
这道题和前面的pwn67几乎是一样的题目,唯一不同就是pwn67是32位,pwn68是64位。
我们先checksec看一下程序的保护机制
和pwn67一样都是开启的canary但是没有开NX,那么我们仍然可以使用shellcode注入
我们先看一下ida反编译出来的 main函数
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
query_position函数
1 | char *query_position() |
程序的逻辑:
- 程序先输出一串字符串+position(query_position函数return的
&v1+v2) - 用户输入一串长度为4096的字符串
- 输入v5的地址
写题思路:
我们看main函数可以发现,栈中有一个大小为4096的seed数组并且需要我们自己写入,那么我们就可以将我们的shellcode写入,并且在程序提示我们要输入v5的地址时将我们shellcode的地址输入进去
canary怎么办??
我们需要明白,canary是在返回地址的前面,当我们使用覆盖返回地址的方法来写shellcode时,我们才需要去处理shellcode,但是在这道题中我们并不使用覆盖返回地址的方法来写的,而是通过在seed中写入shellcode并且输入v5的地址跳转到shellcode
我只是大致说一下思路,我并没有去考虑nop,所以我直接说的就是shellcode,但是并不影响
我大致画了一下栈的布局
我们这里需要算一下v5的位置,因为v5是需要我们输入的,并且程序会输出一个position(v1+v2),我们就可以利用position来反推v5的位置
我们一步一步来推导
- position = &v1 + v2
- v2 = rand() % 1337 - 668
- position = &v1 + random()% 1337 - 668
- v1 = position - random()%1337 + 668
- v1到seed的距离: 0x15 + 0x8 + 0x8 + (1018h-1010h) = 0x2d
- seed的位置是:v1+0x2d = position - random()%1337 + 668 + 0x2d
- v5:position + 668 + 0x2d
- nop的数量可以是:max(random()%1337)= 1336
所以我们的shellcode = nop * 1336 + arm(shellcraft.sh())
exp如下:
1 | from pwn import * |
写exp的时候遇到了一个特别不起眼的问题,但是就是这个问题让我一直打不通
1 | p.sendline(hex(v5_addr)) |
我这行原来写的是:p.sendline(str(v5_addr))
str与hex的区别就是
- 当我使用
str时,地址会转化成10进制,那么我们发送地址就会失败,不能打通 - 当我使用
hex时,地址会转化成16进制,发送的地址就是16进制的,可以打通