X86反汇编:透视之眼_反编译特训(1-2)

引言

曾经,你以为只有源代码才是真理,汇编只是冰冷的机器残渣。 面对屏幕上杂乱无章的 JNZ 和 JMP,你感到过恐惧,就像在没有地图的迷宫中行走。

但在这个阶段,你练就了一双'透视之眼'。 你不再试图一行行去'读'代码,而是学会了去'看'结构。 你明白了:汇编不是乱码,它是被压扁了的逻辑。

你学会了在迷雾中插上路标(写注释),你学会了把破碎的镜子拼回原状(还原C语言)。 从此刻起,编译器不再是你的黑箱,而是你的笔友。 你听懂了它的方言。

Level_1

反汇编代码

c 复制代码
__declspec(naked) int login_check(int password, int is_admin)
{
    __asm {
        // ... (函数头) ...

        // === 检查 A ===
        mov eax, dword ptr ds:[ebp + 8]   ; 取 password
        cmp eax, 123456                   ; 比较 123456
        je SHORT_PASS_OK                  ; 【注意看】JE = 相等跳转

        // === 路径 B (密码不对走这里) ===
        mov eax, 0                        ; 返回 0
        jmp SHORT_END                     ; 结束

    SHORT_PASS_OK:
        // === 检查 C (密码对了走这里) ===
        mov eax, dword ptr ds:[ebp + 0xC] ; 取 is_admin
        cmp eax, 1                        ; 比较 1
        je SHORT_ADMIN_LOGIN              ; 【注意看】JE = 相等跳转

        // === 路径 D (是普通人) ===
        mov eax, 1                        ; 返回 1
        jmp SHORT_END

    SHORT_ADMIN_LOGIN:
        // === 路径 E (是管理员) ===
        mov eax, 2                        ; 返回 2
        jmp SHORT_END

    SHORT_END:
        // ... (函数尾) ...
        ret
    }
}

具体代码

c 复制代码
int login_check(int password, int is_admin)
{
	if(password == 123456)
	{
		if(is_admin == 1)
		{
			return 2;
		}
		return 1;
	}
	return 0;
}

Level_2:殊途同归

反汇编代码

c 复制代码
__declspec(naked) int can_equip(int level, int is_vip)
{
    __asm {
        // ... (函数头) ...

        // === 第一道坎 ===
        mov eax, dword ptr ds:[ebp + 8]   ; 取 level
        cmp eax, 50                       ; 比较 50
        jge SHORT_SUCCESS                 ; 【关键】如果 >= 50,直接跳去 SUCCESS

        // === 第二道坎 (没跳走才会来这里) ===
        mov eax, dword ptr ds:[ebp + 0xC] ; 取 is_vip
        cmp eax, 1                        ; 比较 1
        je SHORT_SUCCESS                  ; 【关键】如果 == 1,也跳去 SUCCESS

        // === 失败路径 (两个条件都没满足) ===
        mov eax, 0                        ; 返回 0 (不可装备)
        jmp SHORT_END

    SHORT_SUCCESS:
        // === 成功路径 ===
        mov eax, 1                        ; 返回 1 (可以装备)
        jmp SHORT_END

    SHORT_END:
        // ... (函数尾) ...
        ret
    }
}

具体代码

c 复制代码
int can_equip(int level, int is_vip)
{
	if(level >= 50 || is_vip == 1)
	{
		return 1;
	}
	return 0;
}

Level_3:严苛的门卫

反汇编代码

c 复制代码
__declspec(naked) int login(int id, int password)
{
    __asm {
        // ... (函数头) ...

        // === 第一关:检查 ID ===
        mov eax, dword ptr ds:[ebp + 8]   ; 取 id
        cmp eax, 888                      ; 比较 888
        jne SHORT_FAIL                    ; 【关键】如果 != 888,直接踢去 FAIL

        // === 第二关:检查 密码 (能走到这说明ID对了) ===
        mov eax, dword ptr ds:[ebp + 0xC] ; 取 password
        cmp eax, 123456                   ; 比较 123456
        jne SHORT_FAIL                    ; 【关键】如果 != 123456,也踢去 FAIL

        // === 成功路径 (两关都过了) ===
        mov eax, 1                        ; 返回 1 (登录成功)
        jmp SHORT_END

    SHORT_FAIL:
        // === 失败路径 ===
        mov eax, 0                        ; 返回 0 (登录失败)
        jmp SHORT_END

    SHORT_END:
        // ... (函数尾) ...
        ret
    }
}

具体代码

c 复制代码
int login(int id, int password)
{
	if(id == 888 && password == 123456)
	{
		return 1;
	}
	return 0;
}

Level_4

反汇编代码

c 复制代码
__declspec(naked) int func(int val)
{
    __asm {
        push ebp
        mov ebp, esp

        mov eax, dword ptr ds:[ebp + 8]	//取出val放入寄存器
        cmp eax, 10						//跟10进行比较
        jl SHORT_LABEL_A				//如果小于10,则跳转
		
		//能执行到这里说明 val >= 10
        mov eax, dword ptr ds:[ebp + 8]	//重新取出val
        cmp eax, 20						//跟20进行比较
        jg SHORT_LABEL_A				//如果大于20说明进行跳转
	
		//到此为止,得出以下结论, 10<= val <= 20
        mov eax, 1						//return 1
        jmp SHORT_END

    SHORT_LABEL_A:						//return 0
        xor eax, eax

    SHORT_END:
        pop ebp
        ret
    }
}

具体代码

c 复制代码
int func(int val)
{
	if(10 <= val && val <=20)
	{
		return 1;
	}
	return 0;
}

Level_5

反汇编代码

c 复制代码
__declspec(naked) int func(int n)
{
    __asm {
        push ebp
        mov ebp, esp
		
		//核心代码
        mov eax, dword ptr ds:[ebp + 8] //取出n放入寄存器
        cmp eax, 0						//跟0进行比较
        jg SHORT_LABEL_A				//大于0,进行跳转_A

        mov eax, dword ptr ds:[ebp + 8] //重新取出n放入寄存器
        cmp eax, 0						//跟0进行比较
        jl SHORT_LABEL_B				//小于0,进行跳转_B
			
		//执行核心代码
        mov eax, 0						//return 0
        jmp SHORT_END

    SHORT_LABEL_A:
        mov eax, 1						//return 1
        jmp SHORT_END

    SHORT_LABEL_B:
        mov eax, -1						//return -1
        jmp SHORT_END

    SHORT_END:
        pop ebp
        ret
    }
}

具体代码

c 复制代码
int func(int n)
{
	if(n > 0)
	{
		return 1;
	}
	if(n < 0)
	{
		return -1;
	}
	return 0;
}

Level_6

反汇编代码

c 复制代码
__declspec(naked) int logic_maze(int a, int b)
{
    __asm {
        push ebp
        mov ebp, esp

        ; === 第一阶段 ===
        mov eax, dword ptr ds:[ebp + 8] 	//取出a
        cmp eax, dword ptr ds:[ebp + 0xC]	//跟b进行比较
        jle SHORT_PATH_BLUE					//如果小于等于则跳转

        ; === 红色路径 (a > b) ===
        mov eax, dword ptr ds:[ebp + 8]		//取出a,放入寄存器中
        cmp eax, 100						//跟100进行比较
        jge SHORT_RED_BOSS					//大于等于即可跳转
		
		//没有跳转,则执行下面代码
        mov eax, 1             ; 普通红色怪
        jmp SHORT_END						//对eax进行赋值1,然后跳转到集合点
		
		//标签_boss
    SHORT_RED_BOSS:
        mov eax, 100           ; 红色BOSS
        jmp SHORT_END						//对eax进行赋值100,然后跳转到集合点

    SHORT_PATH_BLUE:
        ; === 蓝色路径 (a <= b) ===
        mov eax, dword ptr ds:[ebp + 0xC]
        cmp eax, 100
        jge SHORT_BLUE_BOSS

        mov eax, 2             ; 普通蓝色怪
        jmp SHORT_END

    SHORT_BLUE_BOSS:
        mov eax, 200           ; 蓝色BOSS
        jmp SHORT_END

    SHORT_END:
        pop ebp
        ret
    }
}

具体代码

c 复制代码
int logic_maze(int a, int b)
{
	if(a > b)
	{
		if(a < 100)
		{
			return 1;
		}
		else
		{
			return 100;
		}
	}
	else
	{
		if(b < 100)
		{
			return 2;
		}
		else
		{
			return 200;
		}
	}
}

Level_7

反汇编代码

c 复制代码
__declspec(naked) int final_exam(int a, int b, int c)
{
    __asm {
        push ebp
        mov ebp, esp
        sub esp, 4                      ; 开辟空间给局部变量 result

        ; === [Block 1] ===
        mov dword ptr ds:[ebp - 4], 0   ; 初始化 result = 0

        ; === [Block 2] ===
        mov eax, dword ptr ds:[ebp + 8]
        cmp eax, 0
        jl SHORT_ERROR                  ; 检查 a,小于0进行跳转

        mov eax, dword ptr ds:[ebp + 0xC]
        cmp eax, 0
        jl SHORT_ERROR                  ; 检查 b,小于0进行跳转

        mov eax, dword ptr ds:[ebp + 0x10]
        cmp eax, 0
        jl SHORT_ERROR                  ; 检查 c,小于0进行跳转

		//外层if
        ; === [Block 3] ===
        mov eax, dword ptr ds:[ebp + 8]
        cmp eax, 50
        jle SHORT_LOW_TIER              ; 关键:如果 a <= 50,去低级区
		//相干留下,继续执行下面判断
        mov eax, dword ptr ds:[ebp + 0xC]
        cmp eax, 50
        jle SHORT_LOW_TIER              ; 关键:如果 b <= 50,也去低级区
		//这里可以得到结论 if(a > 50 && b > 50),否则跳转
        
        //里层if
        ; === [Block 4: High Tier] ===
        ; 能走到这里,说明 a > 50 并且 b > 50
        mov dword ptr ds:[ebp - 4], 100 ; result = 100

        mov eax, dword ptr ds:[ebp + 0x10]
        cmp eax, 50
        jle SHORT_END                   ; 如果 c <= 50,结束

        add dword ptr ds:[ebp - 4], 100 ; result += 100
        jmp SHORT_END                   ; 强制结束

	//外层else
    SHORT_LOW_TIER:
        ; === [Block 5: Low Tier] ===
        mov dword ptr ds:[ebp - 4], 10  ; result = 10

        mov eax, dword ptr ds:[ebp + 0x10]
        cmp eax, 20
        jle SHORT_END                   ; 如果 c <= 20,结束

        add dword ptr ds:[ebp - 4], 20  ; result += 20
        jmp SHORT_END

	//返回-1
    SHORT_ERROR:
        ; === [Block 6: Error] ===
        mov eax, -1
        jmp SHORT_RET

    SHORT_END:
        ; === [Block 7: Success Return] ===
        mov eax, dword ptr ds:[ebp - 4] ; 把 result 放入返回值

    SHORT_RET:
        mov esp, ebp
        pop ebp
        ret
    }
}

具体代码

c 复制代码
int final_exam(int a, int b, int c)
{
	int result = 0;
	if(a < 0 || b < 0 || c < 0)
	{
		return -1;
	}
	if(a > 50 && b > 50)
	{
		result = 100;
		if(c > 50)
		{
			result += 100;
		}
	}
	else
	{
		result = 10;
		if(c > 20)
		{
			result += 20;
		}
	}
	return result;
}

战利品

  • 逻辑的形状 (Shape of Logic):

    • IF 的本质: 看透了 CMP + Jcc 的二元对立。

    • 殊途同归 (||): 识别出多个跳转指向同一个"成功地"即为逻辑或。

    • 一票否决 (&&): 识别出多个跳转指向同一个"失败地"即为逻辑与。

  • 层级的重建 (Hierarchy Reconstruction):

    • 克服了汇编"扁平化"的视觉欺骗,能够从线性的指令中还原出嵌套 (Nested) 的立体结构(盒子里套盒子)。
  • 补集思维 (Complementary Thinking):

    • 建立了"反向跳转 = 正向逻辑"的直觉。看到 JLE (小于等于跳走),脑中直接映射出 if ( > ) (大于则留下)。
  • 迷雾拼图法 (The Fog Puzzle Method):

    • 这是本卷最重要的心法。 养成了 "读一行、注一行、不急看终点" 的工程习惯。学会了先切分基本块 (Basic Block),再进行逻辑合并。

结语

我们已经征服了'分叉路口'。 在你的剑下,所有的 IF 和 ELSE 都已现出原形。 你证明了自己拥有在静态的迷宫中找到出口的能力。

但计算机的世界不仅仅是静态的选择,更是动态的律动。 接下来,我们要面对的是时间的魔法------循环 (Loop)。 路不再只是向前延伸,它会卷曲、折叠、首尾相连。

这将是一场对耐心的终极考验。 但既然你已拥有透视之眼,那些周而复始的圆圈,终将化作你登云的阶梯。

相关推荐
是星辰吖~9 小时前
X86反汇编:破茧成蝶 —— 赤裸逻辑与机械之心(1-1)
汇编
逆向命运12 小时前
PC企微搜索手机号窗口绕过
c语言·汇编·c++·飞书·企业微信
是星辰吖~1 天前
函数战争:内存领地的争夺与撤退
汇编
止观止2 天前
在 WSL2 上从零搭建 ARM 混合编程环境
汇编·arm开发·嵌入式开发·混合编程
say_fall2 天前
8086汇编程序设计_从基础到实战
开发语言·汇编·8086
浩浩测试一下3 天前
LoadPE &&& 原理以及作用 (ASM汇编版本)>>01
汇编·免杀·pe结构·windows编程·二进制逆向·系统loadpe
ThornArmor3 天前
【控制篇】斩断无休止空转:4-bit 指令集里的跳转律令与时序状态机
c语言·汇编·c++·单片机·嵌入式硬件
大阳1233 天前
ARM4.(通过汇编,c语言,固件库点亮LED)
c语言·开发语言·汇编
iCxhust3 天前
8086 汇编 TINY 和 SMALL 编程MODEL区别
汇编·单片机·嵌入式硬件·操作系统·微机原理·8088单板机