1.目标
(1)了解shellcode注入原理。
(2)理解给出的弹出对话框的汇编代码。
(3)通过淹没静态地址来实现shellcode的代码植入。
(4)通过跳板来实现shellcode的代码植入。
(5)尝试修改汇编语句的shellcode实现修改标题等简单操作。
在这一过程中,我需要详述程序的修改过程,在实验的关键处进行截图说明,并绘制程序修改原理的图示。
(6)解决思考题,即:在不修改StackOverrun程序源代码的情况下,构造shellcode,通过JMP ESP的方式实现通过记事本打开shellcode.txt(可使用CreateProcessA或WinExec等API)。
2.测试步骤与结果
(1)进入虚拟机,使用VC6打开code/overflow_exe文件夹中的main.cpp并分析:
可以看到,这个程序与之前的实验的程序有3处不同:
i.增加头文件windows.h,以便能调用LoadLibrary函数去装载user32.dll;
ii.verify_password的buffer变量增加到44字节,以便能够承载我们的shellcode;
iii.main函数装载user32.dll以便能在植入代码中调用MessageBox。
(2)通过VC6将main.cpp的内容编译成工程:
运行程序,可以看到没有报错:
(3)运行depends.exe程序,打开刚才生成的exe文件:
点击剖析->开始剖析,参数保持默认即可:
点击kernel32.dll,在右侧能找到exitprocess的函数入口点0x0001B0BB:
在下面的窗口中能够查到kernel32.dll的实际基址0x77E60000:
将两个地址相加即可得到exitprocess的入口地址:
0x0001B0BB+0x77E60000=0x77E7B0BB。
用相同的步骤查出MessageBoxA的函数入口地址,此函数属于user32.dll库:
将两个地址相加即可得到MessageBoxA的入口地址:
0x00033D68+0x77DF0000=0x77E23D68。
(4)新建工程文件,将code/shellcode文件夹中main.cpp的内容粘贴进新建的工程文件中:
可以看到,程序中的两个函数的入口地址和前面计算出的一致,因此无需进行修改。
运行程序,可以看到成功弹出对话框:
(5)使用ollydbg打开刚才生成的exe文件,并找到编写shellcode的汇编语言:
复制选定需要的部分:从xor ebx,ebx开始,到call eax结束(调用exit process的那个call eax),并右键保存到文件,得到操作码的文件:
(6)通过淹没静态地址来实现shellcode的代码植入
在overflow/debug文件夹下创建password.txt,并在其中写入1234567:
在ollydbg中打开overflow.exe,并在strcpy处设置断点,执行到断点处:
查看缓冲区信息,可以看到dest指向地址0x0012FAF0,其为数组的存放起始位置,也就是shellcode注入的起始位置。
用Ultraedit在password.txt中写入payload,根据分析结构应为shellcode+填充字符+shellcode在缓冲区的起始地址。其中shellcode为前面获得的操作码,填充字符应保证其与shellcode的和为52字节,shellcode缓冲区地址为dest指向地址:
重新运行overflow.exe,可以看到弹出窗口,说明通过淹没静态地址成功实现了shellcode的代码植入:
(7)通过跳板来实现shellcode的代码植入
用ollydbg打开overflow.exe,在strcpy函数上设置断点,运行至断点,进行搜索:
等待搜索完毕后点击日志查看:
可以看到一条在user32.text中的JMP ESP指令的地址为0x77E2E32A。
用Ultraedit打开password.txt,这次的文件结构为 52字节填充物 + 4字节JMP ESP地址(逆序)+ shellcode (可选 + 若干0x90):
重新运行overflow.exe,可以看到弹出窗口,说明通过跳板成功实现了shellcode的代码植入:
(8)尝试修改汇编语句的shellcode实现修改标题等简单操作
只需修改password.txt在buptbupt处的操作码即可。下面是随意修改了此次的操作码并运行程序后的结果:
3.测试结论
可以看出栈溢出对程序运行的安全性有很大的威胁,如果不对栈进行保护,只要系统中存在栈溢出漏洞,即可令攻击者通过非正当方法获取操作权限。因此,需要对栈中保存数据的可执行权限做严格的管理,并且系统要能判断栈溢出从而采取相应的保护措施。
通过这次测试,我对软件安全有了更深刻的认识,也意识到软件面临着极大的安全隐患,需要我们去保护和守卫。而要达到这一点,我们要去主动学习更多的知识、熟悉更加强有力的工具。
4.思考题
在不修改StackOverrun程序源代码的情况下,构造shellcode,通过JMP ESP的方式实现通过记事本打开shellcode.txt(可使用CreateProcessA或WinExec等API)。
(1)StackOverrun.cpp的内容如下:
可以看到strcpy将输入的内容复制到栈中,此处会导致栈溢出漏洞。另外main函数有两个参数,第一个参数int argc为传入的字符串个数,第二个参数是字符串指针数组,用于存放传入的字符串指针。
此处选用WinExec("cmd.exe,SW_SHOWNORMAL"),其第一个参数为要打开的程序名称,第二个参数为窗口大小。当调用该命令时还需要加入cmd的参数,/k dir表示执行完dir命令后不关闭命令窗口,命令如下:
WinExec("cmd.exe /k dir > dir.txt", SW_SHOWNORMAL)
(2)利用Dependency Walker获取WinExec函数的地址:
根据地址计算到其真实地址0x0018601 + 0x77E60000 = 0x77E78601。
(3)在Ultraedit中将WinExec的参数用十六进制表示:
(4)编写shellcode,如下图所示,并编译生成exe文件:
(5)用ollydbg打开刚刚生成的exe文件,找到对应的汇编语句,并右键复制到文件获取机器码:
(6)用ollydbg打开前面生成的stackoverrun.exe,并在strcpy函数处下断点,运行到断点处,搜索JMP ESP:
可以看到一条在user32.text中的JMP ESP指令的地址为0x77E2E32A。
(7)根据以上信息构造的payload如下:
(8)用ollydbg打开stackoverrun.exe,添加参数“payload”:
将前面构造的payload作为参数输入:
重新运行程序,可以看到程序跳到了编写的shellcode汇编处结束:
在stackoverrun/debug可以看到生成了dir.txt文件,其中记录了执行指令后输出的当前目录信息: