maximilianfeldthusen/x86BackToC

GitHub: maximilianfeldthusen/x86BackToC

将x86二进制可执行文件反编译还原为C源代码的逆向工程教学与研究工具

Stars: 0 | Forks: 0

## x86BackToC ### 将 x86 二进制文件还原为 C 源代码 ![C](https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white) ![AssemblyScript](https://img.shields.io/badge/assembly%20script-%23000000.svg?style=for-the-badge&logo=assemblyscript&logoColor=white) title: "将 x86 二进制文件还原为 C 代码" layout: post date: 2025-05-25 22:44 headerImage: false tag: - assembly - c - reverse engineering star: true category: blog author: maximilian feldthusen description: Reverse Engineering * 目标:将 x86 二进制可执行文件还原为 C 源代码。 * 理解编译器如何将 C 语言转换为汇编代码。 * 底层 OS 结构和可执行文件格式。 算术指令 ``` mov eax,2 ; eax = 2 mov ebx,3 ; ebx = 3 add eax,ebx ; eax = eax + ebx sub ebx, 2 ; ebx = ebx - 2 ``` 访问内存 ``` mox eax, [1234] ; eax = *(int*)1234 mov ebx, 1234 ; ebx = 1234 mov eax, [ebx] ; eax = *ebx mov [ebx], eax ; *ebx = eax ``` 条件分支 ``` cmp eax, 2 ; compare eax with 2 je label1 ; if(eax==2) goto label1 ja label2 ; if(eax>2) goto label2 jb label3 ; if(eax<2) goto label3 jbe label4 ; if(eax<=2) goto label4 jne label5 ; if(eax!=2) goto label5 jmp label6 ; unconditional goto label6 ``` 函数调用 首先调用一个函数: call func ; 将返回地址存储在堆栈上并跳转到 func 第一个操作是保存返回指针: ``` pop esi ; save esi Right before leaving the function: pop esi ; restore esi ret ; read return address from the stack and jump to it ``` 现代编译器架构 C 代码 --> 解析 --> 中间表示 --> 优化 --> 低级中间表示 --> 寄存器分配 --> x86 汇编 高级优化 内联 例如,函数 c: ``` int foo(int a, int b){ return a+b } c = foo(a, b+1) ``` 转换为 ``` c = a+b+1 ``` 循环展开 循环: ``` for(i=0; i<2; i++){ a[i]=0; } ``` 变为 ``` a[0]=0; a[1]=0; ``` 循环不变量外提 ``` The loop: for (i = 0; i < 2; i++) { a[i] = p + q; } ``` 变为: ``` temp = p + q; for (i = 0; i < 2; i++) { a[i] = temp; } ``` 公共子表达式消除 变量赋值: * 目标:将 x86 二进制可执行文件还原为 C 源代码。 * 理解编译器如何将 C 语言转换为汇编代码。 * 底层 OS 结构和可执行文件格式。 算术指令 ``` mov eax,2 ; eax = 2 mov ebx,3 ; ebx = 3 add eax,ebx ; eax = eax + ebx sub ebx, 2 ; ebx = ebx - 2 ``` 访问内存 ``` mox eax, [1234] ; eax = *(int*)1234 mov ebx, 1234 ; ebx = 1234 mov eax, [ebx] ; eax = *ebx mov [ebx], eax ; *ebx = eax ``` 条件分支 ``` cmp eax, 2 ; compare eax with 2 je label1 ; if(eax==2) goto label1 ja label2 ; if(eax>2) goto label2 jb label3 ; if(eax<2) goto label3 jbe label4 ; if(eax<=2) goto label4 jne label5 ; if(eax!=2) goto label5 jmp label6 ; unconditional goto label6 ``` 函数调用 首先调用一个函数: call func ; 将返回地址存储在堆栈上并跳转到 func 第一个操作是保存返回指针: ``` pop esi ; save esi Right before leaving the function: pop esi ; restore esi ret ; read return address from the stack and jump to it ``` 现代编译器架构 C 代码 --> 解析 --> 中间表示 --> 优化 --> 低级中间表示 --> 寄存器分配 --> x86 汇编 高级优化 内联 例如,函数 c: ``` int foo(int a, int b){ return a+b } c = foo(a, b+1) ``` 转换为 ``` c = a+b+1 ``` 循环展开 循环: ``` for(i=0; i<2; i++){ a[i]=0; } ``` 变为 ``` a[0]=0; a[1]=0; ``` 循环不变量外提 ``` The loop: for (i = 0; i < 2; i++) { a[i] = p + q; } ``` 变为: ``` temp = p + q; for (i = 0; i < 2; i++) { a[i] = temp; } ``` 公共子表达式消除 变量赋值: ``` a = b + (z + 1) p = q + (z + 1) ``` 变为 ``` temp = z + 1 a = b + z p = q + z ``` 常量折叠与传播 赋值: ``` a = 3 + 5 b = a + 1 func(b) ``` 变为: ``` func(9) ``` 死代码消除 删除不必要的代码: ``` a = 1 if (a < 0) { printf(“ERROR!”) } ``` 为 ``` a = 1 ``` 低级优化 强度削弱 代码如: ``` y = x * 2 y = x * 15 ``` 变为: ``` y = x + x y = (x << 4) - x ``` 代码块重排 代码如 : ``` if (a < 10) goto l1 printf(“ERROR”) goto label2 l1: printf(“OK”) l2: return; ``` 变为: ``` if (a > 10) goto l1 printf(“OK”) l2: return l1: printf(“ERROR”) goto l2 ``` 寄存器分配 * 内存访问比寄存器慢。 * 尝试将尽可能多的局部变量放入寄存器中。 * 局部变量到堆栈位置和寄存器的映射不是恒定的。 指令调度 汇编代码如: ``` mov eax, [esi] add eax, 1 mov ebx, [edi] add ebx, 1 ``` 变为: ``` mov eax, [esi] mov ebx, [edi] add eax, 1 add ebx, 1 a = b + (z + 1) p = q + (z + 1) ``` 变为 ``` temp = z + 1 a = b + z p = q + z ``` 常量折叠与传播 赋值: ``` a = 3 + 5 b = a + 1 func(b) ``` 变为: ``` func(9) ``` 死代码消除 删除不必要的代码: ``` a = 1 if (a < 0) { printf(“ERROR!”) } ``` 为 ``` a = 1 ``` 低级优化 强度削弱 代码如: ``` y = x * 2 y = x * 15 ``` 变为: ``` y = x + x y = (x << 4) - x ``` 代码块重排 代码如 : ``` if (a < 10) goto l1 printf(“ERROR”) goto label2 l1: printf(“OK”) l2: return; ``` 变为: ``` if (a > 10) goto l1 printf(“OK”) l2: return l1: printf(“ERROR”) goto l2 ``` 寄存器分配 * 内存访问比寄存器慢。 * 尝试将尽可能多的局部变量放入寄存器中。 * 局部变量到堆栈位置和寄存器的映射不是恒定的。 * 目标:将 x86 二进制可执行文件还原为 C 源代码。 * 理解编译器如何将 C 语言转换为汇编代码。 * 底层 OS 结构和可执行文件格式。 算术指令 ``` mov eax,2 ; eax = 2 mov ebx,3 ; ebx = 3 add eax,ebx ; eax = eax + ebx sub ebx, 2 ; ebx = ebx - 2 ``` 访问内存 ``` mox eax, [1234] ; eax = *(int*)1234 mov ebx, 1234 ; ebx = 1234 mov eax, [ebx] ; eax = *ebx mov [ebx], eax ; *ebx = eax ``` 条件分支 ``` cmp eax, 2 ; compare eax with 2 je label1 ; if(eax==2) goto label1 ja label2 ; if(eax>2) goto label2 jb label3 ; if(eax<2) goto label3 jbe label4 ; if(eax<=2) goto label4 jne label5 ; if(eax!=2) goto label5 jmp label6 ; unconditional goto label6 ``` 函数调用 首先调用一个函数: call func ; 将返回地址存储在堆栈上并跳转到 func 第一个操作是保存返回指针: ``` pop esi ; save esi Right before leaving the function: pop esi ; restore esi ret ; read return address from the stack and jump to it ``` 现代编译器架构 C 代码 --> 解析 --> 中间表示 --> 优化 --> 低级中间表示 --> 寄存器分配 --> x86 汇编 高级优化 内联 例如,函数 c: ``` int foo(int a, int b){ return a+b } c = foo(a, b+1) ``` 转换为 ``` c = a+b+1 ``` 循环展开 循环: ``` for(i=0; i<2; i++){ a[i]=0; } ``` ``` becomes a[0]=0; a[1]=0; ``` 循环不变量外提 循环: ``` for (i = 0; i < 2; i++) { a[i] = p + q; } ``` 变为: ``` temp = p + q; for (i = 0; i < 2; i++) { a[i] = temp; } ``` 公共子表达式消除 变量赋值: * 目标:将 x86 二进制可执行文件还原为 C 源代码。 * 理解编译器如何将 C 语言转换为汇编代码。 * 底层 OS 结构和可执行文件格式。 算术指令 ``` mov eax,2 ; eax = 2 mov ebx,3 ; ebx = 3 add eax,ebx ; eax = eax + ebx sub ebx, 2 ; ebx = ebx - 2 ``` 访问内存 ``` mox eax, [1234] ; eax = *(int*)1234 mov ebx, 1234 ; ebx = 1234 mov eax, [ebx] ; eax = *ebx mov [ebx], eax ; *ebx = eax ``` 条件分支 ``` cmp eax, 2 ; compare eax with 2 je label1 ; if(eax==2) goto label1 ja label2 ; if(eax>2) goto label2 jb label3 ; if(eax<2) goto label3 jbe label4 ; if(eax<=2) goto label4 jne label5 ; if(eax!=2) goto label5 jmp label6 ; unconditional goto label6 ``` 函数调用 首先调用一个函数: call func ; 将返回地址存储在堆栈上并跳转到 func 第一个操作是保存返回指针: ``` pop esi ; save esi Right before leaving the function: pop esi ; restore esi ret ; read return address from the stack and jump to it ``` 现代编译器架构 C 代码 --> 解析 --> 中间表示 --> 优化 --> 低级中间表示 --> 寄存器分配 --> x86 汇编 高级优化 内联 例如,函数 c: ``` int foo(int a, int b){ return a+b } c = foo(a, b+1) ``` 转换为 ``` c = a+b+1 ``` 循环展开 循环: ``` for(i=0; i<2; i++){ a[i]=0; } ``` 变为 ``` a[0]=0; a[1]=0; ``` 循环不变量外提 ``` The loop: for (i = 0; i < 2; i++) { a[i] = p + q; } ``` 变为: ``` temp = p + q; for (i = 0; i < 2; i++) { a[i] = temp; } ``` 公共子表达式消除 变量赋值: ``` a = b + (z + 1) p = q + (z + 1) ``` 变为 ``` temp = z + 1 a = b + z p = q + z ``` 常量折叠与传播 赋值: ``` a = 3 + 5 b = a + 1 func(b) ``` 变为: ``` func(9) ``` 死代码消除 删除不必要的代码: ``` a = 1 if (a < 0) { printf(“ERROR!”) } ``` 为 ``` a = 1 ``` 低级优化 强度削弱 代码如: ``` y = x * 2 y = x * 15 ``` 变为: ``` y = x + x y = (x << 4) - x ``` 代码块重排 代码如 : ``` if (a < 10) goto l1 printf(“ERROR”) goto label2 l1: printf(“OK”) l2: return; ``` 变为: ``` if (a > 10) goto l1 printf(“OK”) l2: return l1: printf(“ERROR”) goto l2 ``` 寄存器分配 * 内存访问比寄存器慢。 * 尝试将尽可能多的局部变量放入寄存器中。 * 局部变量到堆栈位置和寄存器的映射不是恒定的。 指令调度 汇编代码如: ``` mov eax, [esi] add eax, 1 mov ebx, [edi] add ebx, 1 ``` 变为: ``` mov eax, [esi] mov ebx, [edi] add eax, 1 add ebx, 1 a = b + (z + 1) p = q + (z + 1) ``` 变为 ``` temp = z + 1 a = b + z p = q + z ``` 常量折叠与传播 赋值: ``` a = 3 + 5 b = a + 1 func(b) ``` 变为: ``` func(9) ``` 死代码消除 删除不必要的代码: ``` a = 1 if (a < 0) { printf(“ERROR!”) } ``` 为 ``` a = 1 ``` 低级优化 强度削弱 代码如: ``` y = x * 2 y = x * 15 ``` 变为: ``` y = x + x y = (x << 4) - x ``` 代码块重排 代码如 : ``` if (a < 10) goto l1 printf(“ERROR”) goto label2 l1: printf(“OK”) l2: return; ``` 变为: ``` if (a > 10) goto l1 printf(“OK”) l2: return l1: printf(“ERROR”) goto l2 ``` 寄存器分配 * 内存访问比寄存器慢。 * 尝试将尽可能多的局部变量放入寄存器中。 * 局部变量到堆栈位置和寄存器的映射不是恒定的。 指令调度 汇编代码如: ``` mov eax, [esi] add eax, 1 mov ebx, [edi] add ebx, 1 ``` 变为: ``` mov eax, [esi] mov ebx, [edi] add eax, 1 add ebx, 1 ``` 指令调度 汇编代码如: ``` mov eax, [esi] add eax, 1 mov ebx, [edi] add ebx, 1 ``` 变为: ``` mov eax, [esi] mov ebx, [edi] add eax, 1 add ebx, 1 ```
标签:AST抽象语法树, TLS抓取, x86架构, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 代码重构, 反编译器, 可执行文件格式, 可配置连接, 安全报告生成, 寄存器分配, 快速连接, 恶意代码分析, 指令集, 控制流恢复, 机器码转C, 汇编语言, 程序分析, 编译原理, 软件安全, 逆向工程, 配置文件, 静态分析