首页
社区
课程
招聘
[原创]栈溢出基础及利用
发表于: 2021-3-7 21:37 12316

[原创]栈溢出基础及利用

2021-3-7 21:37
12316

学习,得向基础看齐。之前面试,别人问了我栈溢出,又问了堆溢出,索性今天就栈溢出基础弄个总结,并结合IDA。希望自己可以有新收获。

1)我们先回顾一下call和ret指令,可以认为是函数调用栈。
call的操作是,调用一个过程,指挥处理器从新的内存地址开始执行。过程使用ret来将处理器转回到该过程被调用的程序点上。
从物理的角度来解释,call指令将其返回地址压入堆栈,再把被调用过程的地址复制到指令指针寄存器。当过程准备返回时,它的ret指令从堆栈把返回地址弹回到指令指针寄存器。
函数调用栈在内存中从高地址向低地址生长,所以栈顶对应的内存地址在压栈时变小,退栈时变大。

图片描述

2)函数调用背景。
函数状态主要涉及三个寄存器--esp,ebp,eip。esp 用来存储函数调用栈的栈顶地址,在压栈和退栈时发生变化。ebp 用来存储当前函数状态的基地址,在函数运行时不变,可以用来索引确定函数参数或局部变量的位置。eip 用来存储即将执行的程序指令的地址。

a.将被调用函数的参数压入栈内
图片描述
b.将被调用函数的返回地址压入栈内
图片描述
c.将调用函数的基地址(ebp)压入栈内,并将当前栈顶地址传到 ebp 寄存器内
图片描述
d.将被调用函数的局部变量压入栈内
图片描述
e.将被调用函数的局部变量弹出栈外
图片描述
f.将调用函数(caller)的基地址(ebp)弹出栈外,并存到 ebp 寄存器内
图片描述
g.将被调用函数的返回地址弹出栈外,并存到 eip 寄存器内
图片描述

3)当函数正在执行内部指令的过程中我们无法拿到程序的控制权,只有在发生函数调用或者结束函数调用时,程序的控制权会在函数状态之间发生跳转,这时才可以通过修改函数状态来实现攻击。
我们只需要让溢出数据用攻击指令的地址来覆盖返回地址就可以了。我们可以在溢出数据内包含一段攻击指令,也可以在内存其他位置寻找可用的攻击指令。

图片描述
自此,栈溢出的基础理论讲完。

与此相关的技术,有下面这些。
修改返回地址,让其指向溢出数据中的一段指令(shellcode)
修改返回地址,让其指向内存中已有的某个函数(return2libc)
修改返回地址,让其指向内存中已有的一段指令(ROP)
修改某个被调用函数的地址,让其指向另一个函数(hijack GOT)

1)实验目的:证明存在栈溢出漏洞
2)实验环境:IDA,OD,小程序。
3)要求(个人要求):个人突破,熟练使用IDA和OD。
准备代码如下:

看到代码后,怎样来利用了?步骤是怎样的?
1)运行程序,观察情况,特别需要注意字符串和一些特殊的函数。
2)在上一步的基础上,我们在关键点上设下断点。
3)控制台交互,观察栈的运行情况,从而发现破绽。

1),导入OD,或者IDA,都可以。当然导入OD,较为简单。这里我选择用IDA,执行本地调试。先执行win32_remote.exe,然后在IDA界面,点击debugger,具体的环境设置,网上很全,当然如果有问题,也可以和我交流。按F9开始执行,看到“please input password:”。这个字符串,很重要,将是我们的突破口。
图片描述
(其实用IDA来调试,查看栈的情况,也可以,但是没有OD方便。)
2)通过上一步的字符串,来定位到该位置。alt+T,可以全局搜索该字符串。在00C717D6这里。
图片描述
搜索到后,选中这一代码段的标记,sub_C717B0,快捷键N,实现改名。
图片描述
为了进一步确定,我们可以通过查看伪代码,具体的情况,如图。
图片描述
这里注意到一个关键的函数,sub_C712AD,我们双击进入,看到返回的是另一个函数sub_C71640,我们继续点击,看到了这个代码段。
图片描述
这里可以确认,密码是“1234567”。有些时候,某些程序的密码就在程序的内部,也有的是一个密码生成器,自动生成,需要逆向算法。j_strcmp是一个比较的接口,j_strcpy是将输入的密码,复制到&Dest上。可以确定这个&Dest就是栈的开头。下图是该栈的情况。
图片描述
图片描述
这里有个8很明显。记住。
我们进入OD,Ctrl+G,搜索这个,00C717D6,并F2,下断点。
图片描述
F9运行程序,可以看到正好停在这里。
这时,我输入“12345678”,这个比正确的密码多了一个8,结果竟然成功了。
图片描述
这不是重点,重点是观察寄存器的变化。
3)上一步,我们已经设置了断点,输入了8个数,就成功的通过了。我们来单步执行,重点观察一下寄存器。

通过查阅资料,得到了下面的一些启发。
程序的关键地方是strcpy(buffer,password);
栈内的依次存放的是authenticated、局部变量char buffer[8]。
图片描述
当我们输入的密码,超过buffer的长度,正好覆盖掉authenticated。而在源代码中authenticated是否等于0,用来说明当前密码正确与否的状态,。转换到汇编代码中,[ebp-4]是否等于0,用来判断密码是否正确。
图片描述
所以,只需要输入任意八位数字,填满buffer,利用字符截断符NULL来填充[ebp-0x4]的值,就可以绕过密码验证。
图片描述

当我们输入更长的数字后,会发生什么呢?
首先authenticated会修改,同时后面的EBP和返回地址也会修改,查阅资料上解释的是,程序崩溃,出现异常。但是我觉得不是的。因为当我故意夸大输入的长度时,才会出现奔溃。当我仅仅输入10个数字的时候,是没有出现崩溃的。 图片描述
至于它的崩溃点是那里,这里可以通过pattern字符来验证,我不做深究。
从逻辑上,可以认为是,当我们输入的长度过长,覆盖了ret,会导致栈无法正常返回,从而堆栈不平衡,导致崩溃。
如果大家对此,有什么好的看法,请私信告诉我。下一篇,堆溢出。

 
 
 
#include<iostream>
#include<stdio.h>
using namespace std;
 
#define PASSWORD "1234567"         //The macro defines the value of the password
int verify_password(char* password)
{
    int authenticated;
    char buffer[8];               // add local buffer to be overflowed
    authenticated = strcmp(password, PASSWORD);     //compare the two values
    strcpy(buffer, password);    //over flowed here!
    return authenticated;
}
int main(){
    int valid_flag = 0;
    char password[1024];
    while (1)
    {
        printf("please input password: ");
        scanf("%s", password);
        valid_flag = verify_password(password);
        if (valid_flag)
        {
            printf("incorrect password!\n\n");
        }
        else
        {
            printf("Congratulation! You have passed the verification!\n");
            break;
        }
    }
    return 0;
}
 
 }
 }
}
#include<iostream>
#include<stdio.h>
using namespace std;
 
#define PASSWORD "1234567"         //The macro defines the value of the password
int verify_password(char* password)
{
    int authenticated;
    char buffer[8];               // add local buffer to be overflowed
    authenticated = strcmp(password, PASSWORD);     //compare the two values
    strcpy(buffer, password);    //over flowed here!
    return authenticated;
}
int main(){
    int valid_flag = 0;
    char password[1024];
    while (1)

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-3-8 19:52 被奋进的小杨编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (5)
雪    币: 15187
活跃值: (16852)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
2
等待师傅完善,支持
2021-3-8 09:02
0
雪    币: 1859
活跃值: (2245)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
有毒 等待师傅完善,支持
版主,帮帮看看,哪些需要修改的
2021-3-9 09:01
0
雪    币: 1475
活跃值: (14652)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
4
坐等堆溢出
2021-3-10 15:41
0
雪    币: 4372
活跃值: (1718)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习了
2021-3-19 08:09
0
雪    币: 365
活跃值: (559)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
配图简直太好了,一清二楚
2023-10-12 22:16
0
游客
登录 | 注册 方可回帖
返回
//