pwnable.tw->Death Note
前言
又是花了两天+做出来的题,所幸这次没看别人的writeup,师姐提示了一下,昨晚肝出来的时候有种打了两天加时最后绝杀的感觉。这基本是纯考alphanumeric shellcode的题,动手看和写很重要
程序逻辑
程序有三个功能,Add、Show和Delete。其中Add、Delete和Show都没有对Index检查,会造成越界读写,范围是比Note_addr低的地址
Add可以被用来覆写got表或者plt表
Show可以被用来泄露函数地址,进而得到Libc地址,这个题没有给Libc,可以考虑用DynELF或者Libcsearcher,这个后面再分析
del同样没有检查index,可以把任意地址的内容作为一个chunk释放
漏洞利用
开始考虑把libc版本猜出来,DynELF要求的是泄露任意地址的值,但是我们这里的Show是%s输出,并不满足其要求,对于Libcsearcher,我尝试使用read和printf和free的地址做泄露,出来的地址算出来的libc版本没有交集,不太明白这是怎么做到的,不过这条路似乎不通了。
另一条路出现在Gdb调试的时候,发现heap,bss后面的权限都是rwxp,可读可写可执行,我们可以根据Index的问题在某个函数比如free的got表上malloc一个新的chunk,这个chunk的内容是shellcode,在调用free@got的时候就会去shellcode执行,注意这时候的is_printable限制输入只能使用可见字符,我们可以在reference去找下可以用的字符,以及这个更全的opcode结合调试写shellcode。
shellcode编写
我们最终的目的是构造system(“/bin//sh”,0,0),即eax = 0xb,ebx = binsh_addr,ecx = edx = 0。int 0x80其中eax = 0可以使用1
2
3push 0x30;
pop eax;
xor al,0x30;
来完成,为了抬高栈(减小esp从而让之后的寻址偏移大于0x1F)
ebx = esp可以用1
2
3
4push 0x68732f2f;
push 0x6e69622f;
push esp;
pop ebx;
al = 0xb可以按照刚才方法给eax清零之后inc11次1
2
3
4
5push 0x30;
pop eax;
xor al,0x30;
inc eax;
...
int 0x80可以使用edx作为跳板,开始根据偏移存储text_code地址,之后用xor把int 0x80(0xcd80)写到将要执行的最后一条指令1
2xor edx,[ebx+0x30];
xor [edx+0x38],di;
由于全程没用ecx,所以ecx一直为0
xor edx,[ebx+0x30];将edx清零,之后int 0x80执行sys_ececv(“/bin/sh\x00”)
exp.py
1 | #coding=utf-8 |