这道题和vortex8几乎是一样的,只是题目说了栈不能执行,所以只能ROP了。我开始还想用mprotect来恢复执行权限,但要传的参数里有\x00,比如地址必须是page size的倍数;而strcpy遇到\x00就停止了,所以最后没能用mprotect
思路还是和vortex8是一样的:在主线程里修改PLT,然后子线程里就调用了我们提供的函数,只是这里我们提供库函数system。
在主线程里,用strcpy来修改。我开始是直接把返回地址写成strcpy,但发现根本没有copy;后来用的是自己的指令call strcpy
开始想修改printf地址,但那个地址是以\x00结尾的,我试着把dest的地址取为printf之前,但segfault了,可能是不能写?但objdump显示那部分内存不是RO啊……不知道是怎么回事儿
于是我只能改fflush了。fflush的参数是stdout,打印发现其内容可以看成是字符串”\x84\x2a\xad\xfb”,于是思路就是在当前文件夹下创建以此为文件名的脚本:
$ echo -e '#!/bin/sh\ncat /etc/vortex_pass/vortex13 > /tmp/nabla/123' > `perl -e 'print "\x84\x2a\xad\xfb"'`
再把当前文件夹加入PATH,那么system在执行的时候就会把密码保存到我们的文件里
(这个文件名有些怪异啊……如果printf可以改的话,那么文件名就取’%d’了,那就方便多了)
此外,为了子线程执行sleep时不要失败,我们在改got时还要多写4个字符以使sleep地址不变,不这么做的话sleep地址会被破坏,因为strcpy会附加\x00到末尾。而紧接着的getuid地址会被破坏,但这没问题因为之后再不调用它了
另一点,在第一次strcpy时,我把ebp的值也保留不变;这样可以省去一些麻烦,不用考虑改完got后主线程该做什么了。现在这样的话,主线程相当于进入死循环了,反复地修改got
$ /vortex/vortex12 `perl -e 'print "A"x1032 . "\xe8\xd2\xff\xff" . "\x19\x86\x04\x08" . "\x04\xa0\x04\x08" . "\xf8\xd2\xff\xff" . "\x30\x2e\xfc\xf7\xd0\x48\xec\xf7"'`