动静结合分析

源代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void Attack() {
    printf("Hello!:-)\n");
    exit(0);
}

void fun() {
    char s_passwd[6] = "ABCDE";
    char str[6];
    FILE *f_o;
    if(!(f_o = fopen("C:\\Program Files\\Microsoft Visual Studio\\MyProjects\\reverseProject\\Debug\\passwd.txt", "r"))) exit(0);
    fscanf(f_o, "%s", str);

    str[5] = 0;
    if(strcmp(str, s_passwd) == 0) printf("OK\n");
    else printf("NO\n");
}

int main(int argc, char const *argv[]) {
    fun();
    return 0;
}

// passwd.txt(Hex)
6161 6161 6262 6262 6363 6363 6464 6464
6565 6565 3010 40

分析过程

静态分析

fun() 函数运行流程

先找到 fun 函数入口点 0x00401080 ,之后分析 fun 函数(总流程的图太模糊了,不知道当初怎么截的图)

dynamic_with_static_analysis_1.png
dynamic_with_static_analysis_2.png

子函数运行流程

仔细观察 fun 函数的流程,可以看到 fun 的 fopen() 分支,如果没有文件就直接 exit(0) ,程序结束。但在下面一个 if 分支,两种情况后又会继续向下执行,符合代码流程。静态分析还可以看到相应的汇编代码和虚拟地址,为动态分析提供流程指导

dynamic_with_static_analysis_3.png
dynamic_with_static_analysis_4.png

动态分析

fun() 函数初始化

利用 ollydbg 进行动态调试,程序运行到 0x00401096 处会把 0x0012fed8~0x0012ff28 ,51 个单位内存都置零,为 fun 函数栈帧初始化内存,fun 栈帧大小有 54 个内存单位。

0x0012fecc 为 ESP,0x0012ff2c 为 EBP ,0x0012ff2c ~ 0x0012ff80 为 Windows 内核函数的栈帧。 0x0012ff30 是 RET 地址。

shellcode 构建

初始化内存后,会在 EBP-0x8 处为 fun 函数中的变量 passwd[6] 在内存中开辟空间并置为相应的值(赋值“ABCDE” 内存中即 44434241 cccc0045)。

fscanf 函数会在 passwd[6] 往低地址的方向选择内存,即 EBP-0x14(20) 0x0012ff18 执行 fscanf 函数,这处地址的值是本函数的返回地址,为了执行完 fscanf 后能正常返回。

str 会从 0x12ff1c 开始写入,这就是我们要利用的缓冲区漏洞。所以我们对 shellcode 构建,前 20 字节可以随便写,21~24 字节要是我们寻找到的 JMP ESP 指令

dynamic_with_static_analysis_5.png
dynamic_with_static_analysis_6.png

shellcode 执行

进行缓冲区溢出攻击后,fun 函数栈帧及原 windows 内核函数的栈帧已被 shellcode 覆盖,fun 函数返回地址处的指令是 JMP ESP,而 fun 返回后 ESP 就是 0x0012ff34,是我们填充的 0x90 指令,此后程序按照我们的 shellcode 执行,直到执行完 shellcode 中 exitThread 函数后程序运行结束

dynamic_with_static_analysis_7.png
dynamic_with_static_analysis_8.png
dynamic_with_static_analysis_9.png

程序运行结果

dynamic_with_static_analysis_10.png
湘ICP备19014083号-1