栈溢出:突破密码验证程序 – 控制程序执行流程

 

0x01 淹没帧状态值控制程序执行原理

/*****************************************************************************
      To be the apostrophe which changed "Impossible" into "I'm possible"!

POC code of chapter 2.2 in book "Vulnerability Exploit and Analysis Technique"

file name   : stack_overflow_var.c
author      : failwest  
date        : 2006.9.20
description : demo show nearby var overrun in stack
              input 8 letters to bypass authentication  
Noticed     : complied with VC6.0 and build into begug version
version     : 1.0
E-mail      : failwest@gmail.com

    Only for educational purposes    enjoy the fun from exploiting :)
******************************************************************************/
#include <stdio.h>

#define PASSWORD "1234567"

int verify_password (char *password)
{
    int authenticated;
    char buffer[8];// add local buff
    authenticated=strcmp(password,PASSWORD);
    strcpy(buffer,password);//over flowed here! 
    return authenticated;
}

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;
        }
    }

    system("pause");
}

 

1.1 动态调试结果

file

 

动态调试得到的栈帧数据

局部变量名 内存地址 偏移3处地址 偏移2处地址 偏移1处地址 偏移0处地址
buffer[0-3] 0019FAC8 0x71(’q’) 0x71(’q’) 0x71(’q’) 0x71(’q’)
buffer[4-7] 0019FACC NULL 0x71(’q’) 0x71(’q’) 0x71(’q’)
authenticated 0019FAD0 0x00 0x00 0x00 0x01
前栈帧 EBP 0019FAD4 0x00 0x19 0xFF 0x30
返回地址 0019FAD8 0x00 0x40 0x10 0xEB

 

1.2

用5组数据,也就是19个字符 "4321432143214321432" 把authenticated、前栈帧 EBP、返回地址全部淹没掉,观察栈的状态

file

 

1.3 分析

返回地址用于在当前函数返回时,重定向程序的代码,在函数返回 "retn"指令时,栈顶元素恰好是这个返回地址。"retn" 指令会把返回地址弹入EIP寄存器里,之后跳转到这个地址去执行。

从调试器中看出计算机发生的事件:

1、函数返回时,将返回地址放到了EIP寄存器

2、处理器按照EIP寄存器的地址0x00323334取值

3、内存0x00323334没有合法的指令,处理器不知如何处理,报错。

 

file

 

这里溢出程序返回到了无效的地址,那么如果这个地址是有效的,就可以让处理器到任意指令出去执行(比如:直接跳到程序验证通过的部分),也就是说,可以通过淹没函数返回地址而控制程序的执行流程。

 

0x02 控制程序的执行流程

用读文件的方式处理输入值,文件中便于操作十六进制的值(0x11 0x12等)。

/*****************************************************************************
      To be the apostrophe which changed "Impossible" into "I'm possible"!

POC code of chapter 2.3 in book "Vulnerability Exploit and Analysis Technique"

file name   : stack_overflow_ret.c
author      : failwest  
date        : 2006.9.30
description : demo show to redirect program execute flow via over run return address
                in stack. specify the exactly fake return address in password.txt file 
                to bypass the authentication  
Noticed     : should be complied with VC6.0 and build into debug version  
version     : 1.0
E-mail      : failwest@gmail.com

    Only for educational purposes    enjoy the fun from exploiting :)
******************************************************************************/
#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);

    system("pause");
}

 

2.1 实验环境:

操作系统 windows10
编译器 visual C++6.0 有个bug需要注意:在退出程序的时候,最好还是按任意键退出程序,直接关闭窗口这种操作方式,有可能会导致程序并没停止
编译选项 默认编译选项
build版本 debug版本 release和debug都可以

 

2.2

在PE文件目录下建立password.txt,写入测试用的密码,Olldbg就可以加载调试了。准备工作:

1、通过动态调试获取栈中的状况,如函数地址距离缓冲区的偏移量等

2、需要得到密码中程序验证通过的指令地址,方便程序直接跳到这里来执行。

3、在password.txt文件中相应的偏移处填上这个地址。

这样在verify_password函数返回后就直接跳转到验证通过的分支执行了。

 

2.3

用olldbg加载可执行的PE文件:

file

 

分析得到:程序验证通过的指令地址: 0x0040111F

程序通过的分支从0x0040111F这里开始压栈,就把返回地址覆盖为这个地址,verify_password函数返回的时候,就直接跳转到0x0040111F这里了。

 

2.4

分析得到:栈中的变量分布情况没有改变

file

 

地址全部淹没的情况:

buffer 需要2组 4321

authenticated 变量 需要1组 4321

前栈帧EBP需要1组 4321

返回地址需要1组 4321

现在需要把返回地址通过winhex工具修改为: 程序验证通过的指令地址0x0040111F
 

file

 

这4个字节在文本模式下显示是乱码

 

file

 

2.5 结果

Olldbg加载调试,堆栈如下:
 

file

 

执行状态:运行打开几秒就崩溃了,但是跳转到了正确的结果上。
 

file

由于栈内的EBP被覆盖为无效值,程序在退出时,堆栈无法平衡,导致崩溃,但已经成功淹没了返回地址,直接跳转并通过验证。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇