栈溢出逆向分析

栈溢出漏洞逆向分析

摘要:针对StackOverflow.cpp程序,首先将其编译为二进制文件,进而通过动态逆向分析工具,以汇编指令为粒度,详细分析指令的功能及漏洞触发和利用方法。

关键词:栈溢出 逆向分析

工具:Windows10 Dev-C++ Ollydbg[吾爱]

栈溢出漏洞原理

栈溢出属于缓冲区溢出,指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致其写入与其相邻的栈,导致相邻栈中数据改变。

利用方式有:

通过覆盖某些局部变量值达到绕过验证效果

通过移植恶意代码并修改返回地址达到某种目的

代码逆向分析

  • 首先将stackoverflow.cpp编译生成exe文件,并用OD打开动态调试。找到程序运行的入口和main函数入口并下断点,完成准备工作。

  • 对stackoverflow.cpp次要部分进行简要理解

  • 我们跟进到scanf函数那里,测试栈溢出的情形,首先我们尝试正常的错误密码1234561

    我们可以看到它的存入方式是从右到左从上到下的。

再尝试溢出的错误密码555555555

我们可以看到它抢占了当前位置+0x4的栈帧空间,可能会导致未知的错误。

  • 接着我们进入重点分析的verify_password函数中,主要观察函数的返回位置和栈帧的变化。
00401500    55              push ebp						
00401501    89E5            mov ebp,esp
00401503    83EC 28         sub esp,0x28                  #更新栈基址指针,提升栈顶指针,分配一段0x28空间

00401506    C74424 04 00404>mov dword ptr ss:[esp+0x4],StackOve.0040400> #将“1234567”字符串变量地址存入esp+0x4
0040150E    8B45 08         mov eax,dword ptr ss:[ebp+0x8]				 #将ebp+0x8变量地址存入eax
00401511    890424          mov dword ptr ss:[esp],eax			 		 #将eax中的地址存入esp的字符串变量

由c语言程序分析,这里的返回值是strcmp产生的,而strcpy则是起到存储此密码的作用,这两个函数在栈溢出的情形很可能造成未知的错误,所以F7步入函数内部查看。

这里我的输入密码为:88888888

764496A0    8B5424 04       mov edx,dword ptr ss:[esp+0x4]
764496A4    8B4C24 08       mov ecx,dword ptr ss:[esp+0x8]              #使用edxecx存储esp+0x4esp+0x8
764496A8    F7C2 03000000   test edx,0x3                                #也就是“1234567”和输入值,test会将ZF置1
764496AE    75 3C           jnz short msvcrt.764496EC                   #于是这里跳转
764496B0    8B02            mov eax,dword ptr ds:[edx]                  #将edx变量地址放入eax
764496B2    3A01            cmp al,byte ptr ds:[ecx]					#比较eaxecx中变量的低位,ZF置1
764496B4    75 2E           jnz short msvcrt.764496E4                   #于是这里不跳转
764496E4    1BC0            sbb eax,eax                                 #eax归零
764496E6    D1E0            shl eax,1                                   #移位
764496E8    83C0 01         add eax,0x1                                 #加1,此时eax值为00000001
764496EB    C3              retn                                        #返回

strcmp函数似乎没有引发错误,返回值正确

返回main函数

00401519    8945 F4         mov dword ptr ss:[ebp-0xC],eax				#eax中的变量放入ebp-0xC位置
0040151C    8B45 08         mov eax,dword ptr ss:[ebp+0x8]				#将ebp+0x8变量地址放入eax
0040151F    894424 04       mov dword ptr ss:[esp+0x4],eax              #将eax中地址放入esp+0x4位置
00401523    8D45 EC         lea eax,dword ptr ss:[ebp-0x14]             #将ebp-0x14变量地址装入eax
00401526    890424          mov dword ptr ss:[esp],eax					#将eax变量地址值放入esp位置

现在我们知道重点关注的是存储返回值的位置ebp-0xC也就是0062FA6C ,接下来F7进入strcpy函数看看是否有事发生。由于栈溢出,存储位置向下的高地址最可能被覆盖。

我们快进到strcpy中的关键语句

76446819    8917            mov dword ptr ds:[edi],edx			
7644681B    83C7 04         add edi,0x4                         
7644681E    BA FFFEFE7E     mov edx,0x7EFEFEFF                  
76446823    8B01            mov eax,dword ptr ds:[ecx]
76446825    03D0            add edx,eax
76446827    83F0 FF         xor eax,-0x1
7644682A    33C2            xor eax,edx
7644682C    8B11            mov edx,dword ptr ds:[ecx]
7644682E    83C1 04         add ecx,0x4
76446831    A9 00010181     test eax,0x81010100
76446836    74 E1           je short msvcrt.76446819

这里4字节为单位依次存入我们所输入变量的数据。

76446870    8817            mov byte ptr ds:[edi],dl		#将edx低位存入edi
76446872    8B4424 08       mov eax,dword ptr ss:[esp+0x8]  #将esp+0x8地址放入eax
76446876    5F              pop edi							#edi出栈

注意到这里edi的地址为0062FA6C,也就是我们重点关切的地方,如果这里被覆盖为0则会使错误的密码通过验证

为什么会引起覆盖,虽然我输入的是“88888888”似乎刚好占用了两个栈帧,但是一般字符串后面会带有一个空字符,空字符的ascii码为0,并且入栈方式是从右向左,从高地址到低地址的所以这里刚好覆盖了我们的返回值。

利用方式

漏洞触发的地方是在verify_password函数中的strcmp函数的返回值,在strcpy函数中进行赋值的过程中,栈溢出导致高地址的栈帧数据被覆盖,从而改变了返回值,使程序验证判定出现错误。

  • 利用字符串覆盖返回值

首先我们知道strcmp的返回值有三种情况

大于返回00000001 可以通过构造字符串进行覆盖,利用字符串结尾的空字符

等于返回00000000

小于返回FFFFFFFF 不太容易进行构造覆盖,因为\0无法输入

  • 利用字符串覆盖返回地址

这种方式在源代码的方式难以进行,具体思路是:

将字符串覆盖到EIP地址,通过修改返回地址为“congratulation~”对应地址,直接跳转到验证成功语句。

  • 利用恶意代码修改程序

由于栈溢出导致覆盖的漏洞,导致恶意代码可以肆意寻找着陆点,如修改程序走向,这里不详细介绍。

posted @   merk11  阅读(206)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
Live2D
欢迎阅读『栈溢出逆向分析』
点击右上角即可分享
微信分享提示