网鼎杯?难(P)顶(Y)杯!
两个vm一个盲打,看到题目👴气得浑身发抖,大热天的全身冷汗,手脚冰凉,这个社会还能不能好了,👴到底要怎样才能签上到,眼泪不争气的流了下来。这比赛到处充斥着对👴的压迫,堆栈题目什么时候才能真正的再次站起来?
boom1
这题,vm题。估计出题人从网上扒了c4源码然后删删改改成了一道题目。(听说本题坑点在于小版本libc,但是当时👴没做出来,就本地复现一下(ubuntu16))
本题关键在于开始的malloc区域过大,是mmap出的空间与libc相邻,导致存在地址任意写。
另外就是,有限制只可以调用一次系统调用,所以本题思路大致两个:
首先就是地址任意写+一次系统调用getshell,这里方法很多,比如改free_hook或malloc_hook为system,改exit_hook为one_gadget等等。
另一个思路就是改变系统调用次数,然后就可以放飞自我得到flag。
这里我利用得是地址任意写+改free_hook为system后free(‘/bin/sh’)。
exp:
1 | from pwn import * |
可以看到,实际上我们的payload只有一句话,但是计算偏移花费了👴几个小时。
首先,要明确一点,就是这个&s-1中的1到底是多少:
1 | #payload='''char *s;int main(){s="1p0ch";*(&s+4)=&s-1;printf(&(s));}''' |
这里的(&s-1)中的1实际上是8*1,所以注意计算最后偏移的时候要除以8
这里的指针主要是
1 | 0x00007f40076f1010-->0x00007f40076f1018-->'1p0ch' |
我们使用printf(&(s))
打印出来的地址是0x00007f40076f1018
,但是利用地址任意写时候的&s
实际上是0x00007f40076f1010
,所以这里计算到free_hook和system的偏移的时候,注意利用0x00007f40076f1010
来计算。
然后看一下我们payload中的*(&s-168205)=&s-627600;
实际上就是改写free_hook为system的地址,168205是到free_hook偏移,627600是到system的偏移。
改写后可以发现free_hook以及变成system的地址,然后执行free('/bin/sh');
实际上就是system('/bin/sh');