攻防世界pwn题stack2
下载附件拖进ida之后观察main函数:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
并未发现明显的漏洞利用点,没有像之前read这样的明显栈溢出
后来观察发现这里存在一个v13数组的边界溢出,并且checksec发现存在canary,不能进行简单粗暴的溢出
1 | if ( v6 != 3 ) |
序号为3的change功能这里并未对v5进行检查,导致我们可以任意输入v5进行栈溢出修改,这样就可以控制溢出的位置,绕过canary,同时看到有后门函数hackhere
1 | int hackhere() |
一眼看成/bin/sh,仔细一看发现是bash(lol),但是问题不大,我们可以自己传参数
既然是要用changenumber功能来修改数组之外的内存,我们就需要计算返回地址和v13的偏移
ida中可以看到这个char v13[100]; // [esp+38h] [ebp-70h]
那么ret地址我们就直接当作ebp+4,所以偏移是0x74
然后我们找出需要的地址:
system:0x08048450
sh:0x08048987
然后注意传参顺序,写出这样的exp:
1 | from pwn import* |
但是并打不通,查阅网上师傅们的wp得知偏移地址有问题,应该是0x84,那这里就试着调试看看
先看到这一段汇编:
根据汇编得知v13的首地址会存放在ax中,那么当程序运行到0x080486D5的时候ax寄存器中存放的就是v13数组的首地址
而main endp的上方有retn,可以得知返回地址会存放在sp栈顶中
先在0x80486d5(mov [eax], cl)打断点,观察到如下:
这里eax记录了v13数组的首地址为0xffffcf68
接着在ret的位置(0x080488F2)打断点,观察如下:
这里esp记录了返回地址0xffffcfec
计算得知,偏移offset = 0xffffcfec - 0xffffcf68 = 0x84
exp
1 | from pwn import* |
学到的东西
1、system里面直接可以传sh,这样也可以获取shell
2、一种新的溢出方式,数组边界的溢出
3、直接利用题目里的change function绕过canary