第二题
程序运行
开启端口12543
ida打开程序,在函数initFunctions中会将之后要使用的系统函数以及字符串的地址保存在一个表中。
如下图
之后会调用函数parrot如下图,在该函数中会调用unk_603820处的函数,通过之前的initFunction函数可发现该处对应函数callFuntion。
在callfunction函数中,首先会调用mmap函数分配一段可执行内存,之后会将加密过的服务器通信函数拷贝到该断内存中,然后解密这段内存,最后运行,而该题的溢出点也发生在该被加密的函数中。
调用mmap函数分配内存,该处分配的内存为0x7ffff7ff6000
之后将加密之后的函数字符串拷贝到该内存中(此处使用函数memcpy函数进行拷贝,源地址为0x400eb8,目标地址为0x7ffff7ff6000)
拷贝前后
之后调用函数dectyptFunction函数进行解密
解密之后
通过gdb的反编译很容易发现此处是一个函数,开头通用的堆栈操作
发送一段超长字符,程序崩溃
通过ida发现,改程序中可能造成溢出的函数只有memory,同时因为溢出漏洞的函数被加密,调试的时候不便直接对该处下断点(必须等到内存解密),因此我们对函数memory的函数表下硬件读断点(因为该处肯定会被加密函数使用到,因此断下之后肯定位于被解密的函数中)。
运行发包之后断在函数0x7ffff7ff6129中,此处读取了memcpy的地址,同时在0x7ffff7ff615a出发生了溢出
查看此时的堆栈,以及寄存器rbx,即可发现该处确实是memcpy
此时的堆栈,返回地址0x7fffffffe308处的数据已经被覆盖
查看覆盖偏移,为280
重新构造发送的数据包。
此时eip已被控制。
该题的总思路就是服务器会将用于和用通信的函数加密,只在程序运行的时候动态解密,但是该函数中对传入的数值长度没有做校验导致溢出,稍微麻烦的就是处理加密函数。