练习二缓冲区溢出.docx
- 文档编号:27583103
- 上传时间:2023-07-03
- 格式:DOCX
- 页数:26
- 大小:710.21KB
练习二缓冲区溢出.docx
《练习二缓冲区溢出.docx》由会员分享,可在线阅读,更多相关《练习二缓冲区溢出.docx(26页珍藏版)》请在冰豆网上搜索。
练习二缓冲区溢出
2012-2013学年第2学期
《网络安全课程设计》实验报告
实验名称:
缓冲区溢出——本地缓冲区溢出
完成时间:
2014.6.18
姓名:
柳鑫学号:
110342118
指导教师:
崔鸿班级:
110342A
实验效果
实验报告
总评
任务一利用跳转指令实现缓冲区溢出
本练习单人为一组。
首先使用“快照X”恢复Windows系统环境。
一.溢出程序演示
(1)进入实验平台,单击工具栏“演示目录”按钮,进入实验目录。
进入Mission1目录,双击overflow_win.exe,加载ShellCode执行溢出操作。
二.溢出实现
本练习操作通过缓冲区溢出来实现弹出消息框(MessageBox对话框)。
针对windows平台实现缓冲区溢出,该实验实现溢出的方式及流程具有着一定的通用性。
我们需要开发实现两部分内容:
一部分是漏洞程序overflow,该程序通过memcpy函数实现缓冲区溢出(添加shellcode的代码到缓冲区中,使缓冲区溢出),当然你也可以通过其它函数实现溢出。
另一部分内容则是生成shellcode,shellcode是程序溢出后欲执行的指令代码,如通过shellcode实现程序溢出后弹出对话框等功能。
对照图22-2-1,在程序正常执行时,memcpy函数被执行完毕后,指令指针会返回至ret地址处,继续执行memcpy函数调用处的后续指令;同时,执行完ret指令后ESP指针也会指向堆栈原始区(调用memcpy函数前一时刻的堆栈分布)。
因此,我们可以将溢出代码shellcode存在堆栈原始区,而剩下的工作就是在memcpy执行ret返回时让EIP指针指向原始区(也就是ESP指针指向的地址)即可。
如何通过ret返回地址确定此时的堆栈ESP指针指向呢?
在这里采用的方法是通过跳转指令“jmpesp”(无条件跳转至esp指向处执行)。
通过在用户地址空间中查找到包含有“jmpesp”指令的存储地址,用该地址覆盖ret返回地址就可以了。
在具体实现时,我们通过三个步骤完成缓冲区溢出:
(1)编写前导码。
所谓前导码就是用于覆盖局部变量到ret返回地址之间的堆栈空间(不包括ret返回地址空间)的指令码。
前导码仅是用于填充堆栈,所以其内容不受限制。
我们需要在实际的调试中来确定前导码的大小。
「说明」cl、gcc等诸多C编译器在为局部变量申请内存空间时,经常要多出若干字节。
(2)查找jmpesp指令地址。
用”jmpesp”指令的地址覆盖ret,就可以在memcpy执行返回后,让CPU执行跳转指令,所以首要解决的是在用户空间中找到含有“jmpesp”指令的地址。
通过VC++6.0的反汇编功能得到“jmpesp”指令的机器码为0xFFE4。
利用FindJmpesp工具进行指令查找,确定一个含有“jmpesp”指令的内存地址。
「注」在用户地址空间中会存在多个包含有jmpesp指令的地址。
(3)shellcode功能体。
shellcode功能体实现了溢出后主要的执行功能,如创建超级用户,提升用户权限等。
在这里我们通过自定义指令来实现弹出用户对话框。
1.编写前导码
单击工具栏“VC6”按钮,启动VC++6.0。
选择“File”|“OpenWorkspace…”加载工程文件“C:
\ExpNIS\NetAD-Lab\Projects\OverFlow\Mission1\overflow.dsw”,该工程包含两个项目,overflow和CreateShellcode项目,建议在debug版下进行开发调试。
将overflow项目设置为启动项目(SetasActiveProject),该项目仅有一个源文件overflow.c,在此源文件中提供了部分代码,注释的地方需要你根据实际调试结果来填写。
程序中提供了一个超长前导码,你需要对程序进行调试来确定实际需要的前导码长度。
调试过程如图22-2-2所示。
实验结果及截图:
设置断点:
遇到ret返回指令:
执行ret指令之后跳转到49484746地址处:
0x46,0x47,0x48,0x49被替换,需要替换成JMPESP指令地址:
在图22-2-2中可以看出,0x49484746四字节覆盖了ret返回地址,请根据调试结果重新确定shellcode指令集长度,确定ret返回地址能够被前导码的后续4字节覆盖。
2.查找jmpesp指令地址
我们需要在用户地址空间中找到包含有jmpesp指令(机器码为0xFFE4)的地址。
运行FindJmpesp工具,选取一个地址追加到shellcode尾(追加填加地址时注意数组高字节对应地址高位),所选jmpesp指令地址是0x77e424da。
跟踪调试程序,确定在memcpy执行返回时jmpesp指令是否被执行。
调试过程如图22-2-3所示。
「说明」可以在shellcode尾部继续追加空指令(0x90,空指令不进行任何操作),这样便于确定执行jmpesp后指令指针的指向。
实现结果及截图:
在cmd下查找JMPESP指令的地址:
将查找到得JMPESP地址写入shellcode[],并在后边添加0x90空指令用于调试:
即将要执行ret返回指令:
执行到jmpesp指令处:
进入jmpesp指令中执行(我们想要执行jmpesp指令跳转到shellcode程序):
从图22-2-3可以看出,在jmpesp指令执行完毕后,指令指针紧接着执行了3个空指令,而空指令是追加在shellcode尾部的。
所以我们下一步所要做的工作就是将实现弹出对话框的指令码追加至shellcod中jmpesp指令地址的后面。
3.生成实现弹出对话框的指令码
我们最终的目的是要通过缓冲区溢出实现弹出消息对话框,而这些功能都应该在shellcode得以实现。
通过在shellcode中调用MessageBoxA API函数,并确定好MessageBoxA所需的4个参数:
窗体句柄、标题显示、内容显示和风格即可以实现弹出指定内容的对话框。
根据WindowsAPI文档,MessageBoxA依赖于user32.lib,也就是说它位于user32.dll动态链接库中。
单击工具栏“Depends”按钮,启动Depends工具,Depends打开应用程序C:
\ExpNIS\NetAD-Lab\Tools\OverFlow\Mission1\overflow_win.exe,可以发现它将加载user32.dll。
然后寻找MessageBoxA函数的内存位置。
具体操作如图22-2-4所示。
(1)在左侧Module树状视图中选中“USER32.DLL”节点;
(2)在右侧导出函数列表视图中遍历Function属性列,查找函数“MessageBoxA”(序号480);
(3)在下侧Module列表视图中遍历Module属性列,查找模块“USER32.DLL”。
在这里的user32.dll中,MessageBoxA(ASCII版本)函数的偏移量(EntryPoint)为0x0003D8DE。
User32.dll(Module)在内存中的起始地址(Base)为0x77E10000。
将两者相加即可得到MessageBoxA函数的绝对内存地址。
所以我们需要在汇编代码中正确设置堆栈并调用MessageBoxA函数的绝对内存地址,该地址为0x0003D8DE+0x77E10000=0x77E4D8DE。
另外还需要调用执行函数ExitProcess(位于KERNEL32.dll中),其目的就是在单击弹出框“确定”按钮后程序自动退出,函数ExitProcess的绝对内存地址0x00013039+0x7c800000=0x7c813039。
在overflow工程中将Createshellcode项目设置为启动项目,该项目仅有一个源文件Createshellcode.c,在此源文件中提供了全部的代码及注释说明。
代码的主体部分是用汇编语言实现的,其功能就是在实现了弹出对话框后自动退出程序。
将函数MessageBoxA和ExitProcess的绝对内存地址填写到指定位置。
在理解了Createshellcode.c中的汇编部分代码后,就可以利用VC++6.0反汇编功能获取代码字节,调试过程如图22-2-5所示。
将代码字节以十六进制数据形式继续追加到shellcode尾。
重新编译执行。
实验结果及截图:
打开C:
\ExpNIS\NetAD-Lab\Tools\OverFlow\Mission1\overflow_win.exe:
寻找MessageBoxA函数的入口地址,查找到EntryPoint为0x0003D8DE:
查找MessageBoxA函数的起始地址(Base)为0x77E10000:
寻找执行函数ExitProcess(位于KERNEL32.dll中)的入口地址,查找到EntryPoint为0x00013039:
查找ExitProcess函数的起始地址(Base)为0x7C800000:
填写绝对地址到源文件Createshellcode.c中:
在shellcode尾添加代码:
任务二定位参数地址实现缓冲区溢出
一.溢出程序演示
(1)进入实验平台,单击工具栏“演示目录”按钮,进入实验目录。
进入Mission2目录,该目录中有三个文件:
OverFlowClient.exe
该文件是执行体文件,功能是新建Administrators组用户jlcss,用户密码1234。
CreateShellCode.exe
该文件是shellcode生成文件,功能是从OverFlowClient.exe文件中提取功能代码,并最终生成完整的shellcode.shc文件。
OverFlowServer.exe
该文件是漏洞溢出文件,功能是加载shellcode.shc文件,并实现通过缓冲区溢出完成新建Administrators组用户jlcss。
(2)执行OverFlowClient
执行OverFlowClient文件,当出现“ShellCode执行完毕,请按回车退出”提示信息时,表明程序已被成功执行,退出程序。
右键单击“我的电脑”,选择“管理”进入“计算机管理”,依次选择“本地用户和组”|“用户”,查看右侧“jlcss”用户信息及其隶属组。
删除jlcss用户。
程序已被成功执行:
“jlcss”用户信息及其隶属组:
删除jlcss用户:
(3)执行CreateShellCode
执行CreateShellCode文件,当出现“Shellcode指令集生成完毕,请按回车退出”提示信息时,表明程序已被成功执行,并且shellcode.shc文件已成功生成。
右键单击生成的shellcode.shc文件,使用“UltraEdit-32”打开,查看shellcode指令码。
这些指令码就是CreateShellCode从OverFlowClient.exe中提取出来的功能码。
退出UltraEdit-32。
执行CreateShellCode文件,shellcode.shc文件成功生成:
shellcode指令码:
(4)执行OverFlowServer
执行OverFlowServer.exe,当出现“溢出成功!
请按回车键退出”提示信息时,表明程序已被成功执行,并且缓冲区溢出操作成功。
再次打开“计算机管理”查看系统用户jlcss信息。
OverFlowServer.exe就是加载了shellcode.shc文件,在缓冲区溢出后执行了其中的指令码。
执行OverFlowServer.exe:
OverFlowServer.exe就是加载shellcode.shc文件,生成用户jlcss成功:
二.溢出实现
「注」进行此操作步骤前,删除jlcss用户。
1.进入工程
单击工具栏“VC6”按钮,启动VC++6.0。
选择“File”|“OpenWorkspace…”加载工程文件“C:
\ExpNIS\NetAD-Lab\Projects\OverFlow\Mission2\OverFlowServer.dsw”。
该工程包含三个项目:
CreateShellCode、OverFlowClient和OverFlowServer。
项目功能说明见源文件。
2.生成shellcode功能体
(1)首先设置OverFlowClient项目为启动项。
(2)双击打开OverFlowClient.cpp源文件,在该源文件中需要填写的代码有:
kernel32.dll基址(第21行),LoadlibraryA函数的绝对内存地址(第23行)和shellExecuteA函数(隶属于Shell32.dll动态库)的绝对内存地址(第25行)。
使用Depends工具打开C:
\ExpNIS\NetAD-Lab\Tools\BufferLeakTools\FindShellBase\FindShellBase.exe文件定位上述内存地址,具体操作参见任务一。
kernel32.dll基址:
LoadlibraryA函数地址:
Shell32.dll基址:
shellExecuteA函数函数地址:
(3)编译并生成OverFlowClient.exe,执行OverFlowClient.exe,确定系统是否新建了jlcss用户,并隶属Administrators组。
3.生成shellcode指令码
(1)设置CreateShellCode为启动项。
双击打开CreateShellCode.cpp源文件,CreateShellCode的工作流程是:
首先生成shellcode头,并将相关指令码写入shellcode.shc文件中;接下来是生成shellcode功能体,功能体代码来自OverFlowClient.exe中shellcode函数执行体,将功能体代码追加到shellcode.shc中;最后是生成shellcode尾,同样将其指令码追加到shellcode.shc中。
(2)这里需要填写的宏数值有:
第16行SHELLCODE_BODY_START(OverFlowClient.exe中ShellCode主体起始偏移地址);
第17行SHELLCODE_BODY_LEN(OverFlowClient.exe中ShellCode主体代码长度);
第18、66行CORRECT_RETURN_ADDR(OverFlowServer中overflow调用完成后程序正常执行返回地址,即OverFlow正常调用完成后的下一条指令地址);
第72行在OverFlowServer中函数OverFlow调用执行前,ebp基地指针地址;
第76行OverFlow溢出返回地址,即函数溢出后shellcode得以执行的首地址。
①获取SHELLCODE_BODY_START、SHELLCODE_BODY_LEN值
调试OverFlowClient.exe(将该项目设置为启动项)确定ShellCode函数入口偏移地址及函数体大小,调试过程参见图22-2-6所示。
ShellCode函数入口偏移地址:
ShellCode函数结束偏移地址:
两者相减得shellcode大小为0x00000197。
.
②根据调试结果填写CreateShellCode.cpp源文件中SHELLCODE_BODY_START宏和SHELLCODE_BODY_LEN宏的值。
③其它数值需要通过调试OverFlowServer来获取,而OverFlowServer的执行又依赖于shellcode.shc文件,所以暂且编译生成CreateShellCode.exe文件,执行该文件生成临时shellcode.shc文件。
4.调用OverFlowServer
上接步骤3,我们已经获得了ShellCode执行体指令码,还需要获取溢出后程序正常返回地址、OverFlow函数调用前ebp基础指针地址和shellcode执行的缓冲区首地址。
(1)OverFlow正常调用返回时的下一条指令地址。
设置OverFlowServerfiles为启动项,双击打开OverFlowServer.cpp文件。
程序首先打开存放shellcode指令码的文件(默认名称为shellcode.shc),读取shellcode.shc的全部内容至接收缓冲区中。
接下来就是利用memcpy函数实现接收缓冲区的拷贝,目标地址是OverFlow函数内的局部缓冲区,该缓冲区默认大小为450字节,需要根据实际调试结果重新确定其大小。
最后在OverFlow调用完成后程序继续执行(溢出执行后程序依然能够正常继续运行)。
调整TempBuffer缓冲区大小,使其大于临时shellcode指令码长度,这样做的目的是让程序正常执行(不发生溢出),以便我们能够获取OverFlow函数执行调用后的正确返回地址。
调试获取OverFlow函数正常调用执行后的下一条指令地址。
调试过程如图22-2-7所示。
填写该指针地址到CreateShellCode.cpp文件中。
18行:
66行:
(2)OverFlow函数调用前ebp基地址指针。
单步调试程序定位到OverFlow函数入口处,获取此时的EBP指针地址,如图22-2-8所示。
填写EBP指针地址到CreateShellCode.cpp文件中。
(3)最后我们来确定shellcode的最后4字节,从实验原理中可知需用这4字节数覆盖调用返回地址,使得shellcode得以执行。
从OverFlowServer程序又可知shellcode最后被加载到TempBuffer缓冲区,所以只要用TempBuffer缓冲区首地址覆盖调用返回地址,在程序溢出后shellcode便会执行了。
调用OverFlowServer.exe确定OverFlow调用执行过程中TempBuffer缓冲区的首地址。
调试过程如图22-2-9所示。
将TempBuffer缓冲区首地址填写到CreateShellCode.cpp文件中。
至此全部的shellcode指令生成完毕,运行Createshellcode.exe生成完整的shellcode.sh文件,使用UltraEdit编辑器对其进行查看。
5.调试确定TempBuffer缓冲区大小
调试OverFlowServer.exe得到OverFlow调用返回时的地址,将返回地址与shellcode.shc中的十六数相比较,有三种比较结果:
(1)返回地址是shellcode最后4字节数据。
函数返回时执行shellcode。
(2)返回地址没有在shellcode.sh中,缓冲区空间过大,溢出未发生。
可以缩小缓冲区空间或在最后8个字节前用0x90(空指令)补充。
(3)返回地址在shellcode.sh中(不是最后4字节数据),缓冲区空间过小。
放大缓冲区空间。
当改变TempBuffer缓冲区大小时,其首地址可能会发生变动,调试确定TempBuffer首地址,重新填写CreateShellCode.cpp,并重新生成shellcode.shc。
经过多次调试后确定缓冲区大小,当满足第一种比较结果时,缓冲区溢出就可以执行下去。
运行程序,查看系统用户jlcss(若jlcss用户已存在,请先将其删除再运行程序)及其所属用户组。
6.回答问题
请根据调试结果填写实验结果。
(1)OverFlowServer.exe程序中,shellcode函数入口偏移地址0x00401020及函数体大小0x00000197(字节)。
(2)OverFlowServer.exe程序中,在OverFlow调用前ebp基地址0x0012ff80和正常调用返回时的指令地址0x0040110a。
(3)OverFlowServer.exe程序中,TempBuffer缓冲区内存地址(首地址)0x0012f968及其大小430(字节)。
Createshellcode:
OverFlowClient:
OverFlowServer:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 练习 缓冲区 溢出