8月17日pwn学习
题目:Stack2
题目描述:
题目本来的描述是没有的,但是这个题又是一种全新形式的题目,然后writeup也不是太具体,要新学的和深入理解的地方很多,所以我做了很久很久。题目类型是不检查数组长度造成的的溢出。
题目分析:
1.checksec和file查看文件
32位程序,用32位ida打开
2.ida反编译分析文件
程序的结果是挺复杂的,但是概括下来的话,就是求平均数,这里虽然对输入的长度没有限制,但是没有开启栈溢出,通过使用scanf普通的栈溢出是不可行的。但是这里我们学到了新的知识,
在这里,数组的长度是没有检查的,所以我们可以在离数组首地址任意长度的地方写入任意值,那么我就也就可以用这一点溢出操作,找到一个会return函数的地方,调用我们需要的函数。
左边的函数栏中首先有个hackhere
但是参数并非我们想要得到的。但有system调用,我们也就可以用这个system
在plt表中,system函数地址为0x08048450
还有要找到参数‘sh”,这里学到了一个新命令行命令:ROPgadget --binary [文件名] --string “查找字符”,就会在内存地址中找到有相应字符的地址,用来查找参数,如下图所示:看了很多writeup都没有把这一点说清楚,所以找了很久的资料,做详细说明。
找到了想要找的调用的系统函数,但现在的问题又出现了,数组的序号该是多少,也就是说,要找到一个return函数地址,用我们系统函数地址覆盖,也就是说,求数组的首地址到这个return函数的偏移。
由于这里需要寻找的内存地址,所以又要用到新的工具了,gdb,当时花了很大的功夫下载下来,这次是第一次使用,适用于程序调试,能查看在运行每一步代码时,查看代码,寄存器和栈的状态。
gdb调试的基本操作
我们在进行数组初始化时的代码地址打上断点,看寄存器的状态,查看把数据送去的第一个内存地址就是数组的首地址,
这里就是在数组初始化时的代码地址,这里又要涉及到汇编一块的知识了
我就一步一步来解释一下在我们输入我们的数字后的每一步操作
0x080486C2:add esp,0x10 ; 堆栈顶部指针加下移长度10h
0x080486C5:mov eax,DWORD PTR [ebp-0x88] ;赋值操作,将eax的值存入离栈底88h的地方,也就是变量var_88
0x080486CB:mov ecx,eax ;数值交换
0x080486CD:lea edx,[ebp-0x70] ;距栈底70h距离的变量为数组,唤起该处的内存地址并存入edx中,这里我们就已经知道了数组的首地址
0x080486D0:mov eax,DWRD PTR [ebp-0x7c] ;该变量为i,赋值到eax作为计数器
0x080486D3:add eax,edx ;eax加上eax也就是数组首地址。
0x080486D5:mov BYTE PTR [eax],cl ;cl是ECX的低位,将一开始存到ECX的输入,赋值到数组首地址
从上面的分析可知,0xffffd218为数组首地址,
另一边找ret的返回地址就方便了许多,由于该程序基本没有函数调用,只有主函数末尾有一个return函数了。
在用gdb在0x080488F2处打断点看栈的状态即可
ESP栈顶指针指的即使返回地址0xffffd29c
所以返回地址距离数组首地址0xffffd29c-0xffffd218=0x84,偏移为0x84
3.写exp
问题解决得都差不多了
注意这里有一点,写地址的时候都是倒着写的。
4.得到结果