【实验】栈溢出攻击:代码植入

《0day安全》书中的代码植入实验

向 password.txt 文件里植入二进制的机器码,并用这段机器码来调用 Windows的一个 API 函数 MessageBoxA ,最终在桌面上弹出一个消息框,并显示一个字符串。

实验程序源代码:

#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#define PASSWORD "1234567"
int verify_password(char *password)
{
    int authenticated;
    char buffer[44];
    authenticated = strcmp(password, PASSWORD);
    strcpy(buffer, password); // over flowed here!
    return authenticated;
}
int main()
{
    int valid_flag = 0;
    char password[1024];
    FILE *fp;
    LoadLibrary("user32.dll"); // prepare for messagebox
    if (!(fp = fopen("password.txt", "rw+")))
    {
        exit(0);
    }
    fscanf(fp, "%s", password);
    valid_flag = verify_password(password);
    if (valid_flag)
    {
        printf("incorrect password!\n");
    }
    else
    {
        printf("Congratulation! You have passed the verification!\n");
    }
    fclose(fp);
    system("pause");
    return 0;
}

在这个实验中,将buffer数组的大小扩大到了44个字节。

大致步骤:

(1)分析并调试漏洞程序,获得淹没返回地址的偏移。

(2)获得buffer 的起始地址,并将其写入password.txt 的相应偏移处,用来冲刷返回地址。

(3)向password.txt 中写入可执行的机器代码,用来调用API 弹出一个消息框。

第一步:调试栈的布局

调试漏洞程序,在password.txt根据buffer数组的大小编写11个4321,刚好到达buffer数组末尾。

第12 个输入单元将authenticated 覆盖;第13 个输入单元将前栈帧EBP 值覆盖;第14 个输入单元将返回地址覆盖。

在ollydbg中调试exe文件之后,在堆栈区中搜索4321相关字符串内容,就能够找到他的地址开始分析。

找到buffer数组的地址为0x0019FB30,作为之后的覆盖的返回地址,在buffer数组中存入植入代码。在上面的截图可以看到0019FB5C中的内容最后的两位为00,这里其实就是authenticated的内容,00是上面的字符串最后的结束符NULL的ASCII码。本来strcmp()函数在遇到不相等的时候返回到是一个非0的数,只有当匹配成功的时候才返回0,这里就是被溢出修改了。

按照理论来说,后面三个字节的地址应该为authenticated, EBP, 返回地址的地址。

第二步:查找MessageBoxA的入口地址

获得user32.dll的加载基址,以此加上MessageBoxA的文件偏移量来计算MessageBoxA的入口地址。

使用Process Explore找到了user32.dll的加载地址:0x00007FF8C0D80000(其实不是这个,往后面看)

在64位系统中查看MessageBoxA的偏移地址:

  1. 在C:\Windows\system32目录下使用dumpbin命令来查看user32.dll文件的导出表:dumpbin /exports user32.dll

  2. 在导出表中查找MessageBoxA函数,RVA为0x00078A40

所以MessageBoxA的入口为:0x00007FF8C0D80000 + 0x00078A40 = 0x00007FF8C0DF8A40。这里有些不太正确的地方,因为程序本身是32位的程序,所以这个user32.dll的基址不应该是这个。

在64位系统上运行32位程序需要使用WoW64子系统,该子系统允许在64位操作系统中运行32位应用程序。要在WoW64中调用user32.dll模块中的MessageBoxA函数,需要使用32位版本的user32.dll模块

然后我又用Process Explore重新查找了C:\Windows\SysWOW64下面的user32.dll的基址和RVA

32-bit的user32.dll加载基址为:0x0000000075230000,偏移地址还是和64-bit版本一样的为:0x00078A40,所以MessageBoxA在这个32位程序中的入口地址为:0x0000000075230000 + 0x00078A40 = 0x00000000752A8A40

0x00000000764C0000

在32位程序中将0x752A8A40作为MessageBoxA函数的入口点地址来调用该函数。

第三步:编写16进制的API函数

16进制可执行代码和对应的汇编码:

这4位是填写MessageBoxA的入口地址

最后4位是buffer数组的入口地址

更改弹出窗口的文字为Cracked!,找到对应的ASCII码,68是PUSH指令

最后完成的截图

注:重启完电脑之后好像user32.dll的基址可能会发生变更,需要使用Process Explore查看,并与偏移量进行计算,重新得到加载地址,password.txt中需要更改的位置为第二行中FF前面四位。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值