1

软安实验2-栈溢出

 1 year ago
source link: https://suyumen.github.io/2022/10/17/2022-10-17-%E8%BD%AF%E5%AE%89%E5%AE%9E%E9%AA%8C2-%E6%A0%88%E6%BA%A2%E5%87%BA/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

软安实验2-栈溢出

Word count: 1.2k | Reading time: 4min
  1. 理解程序堆栈调用关系
  2. 分析堆栈溢出的基本原理
  3. 实际动手练习堆栈溢出利用方法
测试步骤与结果
  1. 打开VM workstation,打开WIN2000的VMX文件,开启虚拟机。将网盘下载得到的文件夹“实验代码”下载并复制到虚拟机里,点击桌面上的VC的快捷方式,打开文件夹stackvar下的main.cpp文件。

阅读源代码并绘制流程图。

流程图

在VC中,新建projects类型为win32 console application,再新建C++ Source File添加到刚才新建的项目,在该文件下编写或复制main.cpp,运行程序。简单测试,符合逻辑。

写多位密码,本应该输出incorrect password并要求用户继续输入密码,但是由于缓冲区溢出产生了错误的输出,表现为直接结束程序了。

  1. 打开OllyDbg,打开刚才编译生成的exe文件。通过查看调用树,反汇编窗口跟踪命令,找到strcpy的代码段。

F2下断点,运行程序,输入“12111”,击中断点,F8单步步过,查看堆栈0012FAC4,右键堆栈窗口中跟随,可以看到地址0012FB18处填入了12111。

内存

重新运行程序,输入qqqqqqqqrst击中断点,F8单步步过,右键堆栈窗口中跟随,查看堆栈0012FB18处的变化,可以看出,由于填写的字符串超过位数,已经将位于0012FB20的邻接变量authenticated 覆盖。

堆栈

重新运行程序,输入qqqqqqqq击中断点,F8单步步过,右键堆栈窗口中跟随,查看堆栈0012FB18处的情况,发现由于填写的字符串超过位数,已经将位于0012FB20的邻接变量authenticated 覆盖成了字符串的结尾00,导致verify_password函数返回0,在后续的判断中判定为密码正确。

堆栈

修改原理

在上述过程中,为了截取密码正确后的图片,我在动态调试过程中在main函数的返回前下了断点,以防止程序直接退出。

  1. 尝试另一种打开文件调试的方法,用VC打开工程文件,然后运行,打开OllyDbg,选择文件->附加->选择到要调试的进程,这样就可以看到最后的提示信息了。

附加进程
  1. 验证补码的问题:输入的密码小于1234567 时,strcmp会返回-1,而-1是用补码表示的,输入的密码末尾的 null只是淹没-1补码的后两位,变成0xFFFFFF00,程序不会朝着我们希望的方向继续下去。

输入01234567,复制后看到堆栈0012FB20的authenticated 变量变成FFFFFF00而不是00000000,继而输出密码错误。

补码问题
  1. 新建工程和文件,将overflowret文件夹下的main.cpp的内容复制进新建立的文件中并运行。在Debug文件夹下建立password.txt文件,用OllyDbg启动程序,查看调用树,反汇编窗口转到main函数,找到跳转条件的地方,F2下断点。

当密码正确的时候,跳转到0040112F,不正确的时候,跳转到00401120。

用UltraEdit打开password.txt文件,为了覆盖返回地址0012FB28,需要长度为20个字节的password。输入43214321432143214321,切换到16进制格式,在第5个4321处的16进制按1234的顺序填入密码正确时的返回地址0040112F。

a998f60babe64332bde4a08621e23b3b.png

保存后运行程序,发现程序输出密码正确,但是在0040113C处发生异常。

1c1504b5450c4569bbae0b3118863b6e.png

MessageBox的函数定义如下:


int MessageBox(

HWND hWnd,

LPCTSTR lpText,

LPCTSTR lpCaption,

UINT uType

);

有4个参数,hWnd表示要创建的消息框的所有者窗口的句柄。如果此参数为NULL,则消息框没有所有者窗口;lPtext表示要显示的消息;lpCaption表示对话框标题;uType表示对话框的内容和行为。对于弹窗bupt来说,这里的三个参数可以分别设置为null,bupt字符串地址,lab2字符串地址,null。

VC打开main.cpp新建项目并生成exe文件,OllyDbg打开,查找调用树找到memcpy函数位置,F2下断点。运行到击中断点,此时ESP即参数复制字符串的目的地址是0012FAF0,而函数的返回地址即ebp+4位于0012FB24。即需要填充52个字节才能覆盖到memcpy函数的返回地址,在此基础上,还要传4个参数一个返回地址,即一共需要72个字节。

在Debug文件夹下新建文件password.txt用UltraEdit打开,输入20组4321,在第14组填入MessageBoxA函数地址77E23D68覆盖memcpy函数的返回地址,在第15组填入ExitProcess函数地址77E7B0BB作为MessageBoxA函数的返回地址,在第16-19组填入MessageBoxA的参数00000000,0012FB40,0012FB3C,00000000在第20组填入字符串内容,最后添加字符串结尾20。

ed4d1ba762974fbea98d33199364d3be.png

823f68627d254c158b0742cda1edd8d2.png

03089420a633478aa1c6a0da88a3f68b.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK