-
-
[原创]X-NUCA revenge骚思路getshell
-
发表于:
2018-11-28 19:08
10492
-
[原创]X-NUCA revenge骚思路getshell
哎。。本菜鸡看见了这个原题还惊喜了一下,可惜搜到的writeup都不是正确解法,好,既然搜不到它,那我就要分析它。一分析,这get shell
的思路也太特么的骚了吧。。现在一起来看看它是怎么个骚法。(首发先知社区
程序就这么的简单,一个输入加一个输出就结束了,而且是静态链接的程序,都不要libc了,libc已经静态编译到程序里了。
输入点在bss
段上的name字段:
输出也在这里。因为这题目是34C3的原题,所以先从原题入手来看这道题目。来看看字符串:
乖乖,flag
就在程序的内存里,通常遇到flag就在内存里的题目,自然而然会想到用__stack_chk_fail
方法来做,还需要控制PC去执行道我们所要的这个函数,程序经过我们输入后,只运行了一个printf
函数,所以要控制PC答案应该就在printf
里面,我们查一下printf
的源码,发现它调用了vfprintf
后:
我们看看这里所需要用到的指针所在内存的位置:
都在&name
的高地址位,可以覆盖到,我们执行过后可以跳到do_positional
处,往后看,可以发现一个最关键的函数代码:
这里可以看到一个关键位:
只要前面三个条件都为False,我们就可以执行到__printf_arginfo_table[spec->info.spec]
函数,而spec
是一个结构体,而info.spec
则是printf
函数的格式化字符串,在本程序中就是%s
,所以spec->info.spec
就是s
即0x73
。成为了__printf_arginfo_table
的下标。我们在IDA中也可以充分感受到这一点:
接下来就好利用了,只要构造字符串覆盖覆盖就好了,覆盖__printf_arginfo_table[0x73]
为所想要的__stack_chk_fail
函数就好了,但是这题是经过改编的,所以这个方法在这里是行不通的。下面再来看看直接getshell的骚思路。
记住前面我们所提到过的一点,只要覆盖了__printf_arginfo_table
我们就可以控制程序执行流程。程序既然是静态链接,又没有system
函数,那么我们就自己构造,用系统调用execve
来getshell
。先找ROP:
64位中系统调用号是59。ROP找好了,我们怎么去执行,让rsp指向我们构造的地址呢?接下来就是我们所需要做的事情。
我们首先将流程控制执行到0x46D935
处:
_dl_scope_free_list
在bss段上,我们可以覆盖到:
所以这里我们可以控制rax
的值,只要不为0且[rax]也不为0就可以执行到jmp
处,继续往后:
直接call
函数了。更巧的是_dl_wait_lookup_done
的值我们也可以控制:
骚不骚?别急,更骚的还在后面。因为前面我们可以控制了rax
,而我们又想把rsp
指向我们构造地址,这里把_dl_wait_lookup_done
指向一个数据段去,指到0x4a1a79
:
这里机器码转化成汇编则是:
刚好可以把esp
的值和eax
的值互换,前面我们可以控制了rax
的值,那么我们不就可以把rsp
的值指向我们构造的地方了?骚吧。。还能找到这么刁钻的一个地方。。我真佩服。接下来就可以指到我们的ROP去了,完成getshell
。写exp时候最需要注意的一点就是__printf_modifier_table
处必须为0,调试可知不为0程序会崩溃。(这种感觉就像是一道只能泄漏得到flag的题目活生生的被提权了一样。。tql
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!