21、补丁与修改:二进制补丁(Hex编辑)、内存补丁、修改跳转实现破解

各位同学,今天我们来聊聊逆向工程里最“动手”的一个环节——打补丁。

说白了,补丁就是修改。你分析完一个程序,找到了它的弱点,接下来怎么办?总不能每次都拿调试器手动改吧?这时候就需要把修改“固化”下来。我个人习惯把补丁分成两类:静态补丁动态补丁。前者改文件,后者改内存。

核心思想:补丁的本质是“欺骗”——让程序执行我们想要的逻辑,而不是它原本的逻辑。

21.1 二进制补丁:直接改文件

这是最基础、最粗暴的方式。你拿一个十六进制编辑器(比如 HxD、010 Editor、WinHex),直接打开目标 exe 或 dll,找到关键字节,改掉它。

我在项目中遇到过一个小软件,它每次启动都弹注册框。我懒得写 keygen,直接找到判断跳转的机器码,把 75(jne)改成 90 90(NOP NOP),世界清净了。

常见修改场景:

  • 改跳转条件:74(je)改成 75(jne),或者改成 EB(jmp)强制跳转。
  • 改函数调用:E8(call)改成 90 90 90 90 90(NOP 掉),让某个功能失效。
  • 改字符串:把 "Trial Version" 改成 "Full Version",虽然只是自欺欺人,但有时候够用。

小技巧:用十六进制编辑器搜索时,别直接搜汇编指令。搜特征字节序列更靠谱。比如 0F 84 是 je 的变体,E9 是 jmp 的远跳转。记住这些常见 opcode,能省很多时间。

21.2 内存补丁:运行时修改

静态补丁有个问题——文件有校验怎么办?或者程序加壳了,你改不了文件?这时候就得用内存补丁。

原理很简单:程序加载到内存后,我们用外部工具(比如 Cheat Engine、x64dbg 的脚本功能)直接修改内存中的指令。

实现方式:

  1. 找到目标进程的 PID。
  2. OpenProcess 获取句柄。
  3. WriteProcessMemory 写入新指令。
  4. VirtualProtect 修改内存页属性(如果页面是只读的)。

我曾经写过一个内存补丁工具,专门对付那些每次启动地址都变(ASLR)的程序。思路是:先找到模块基址,加上偏移量,算出目标地址,再写补丁。嗯,这里要注意,64位程序的内存地址是 8 字节的,别用 4 字节去写,会崩。

避坑指南:我曾经在写内存补丁时,忘了恢复内存页的原始保护属性。结果程序跑着跑着就蓝屏了。后来养成了习惯:改之前先 VirtualQuery 查一下,改完立刻恢复。

21.3 修改跳转:最经典的破解手法

你想想看,一个程序判断注册码对不对,最终不就是一个跳转指令吗?要么跳向“成功”,要么跳向“失败”。我们只要把这个跳转反过来,破解就完成了。

典型流程:

  • 找到关键比较指令,比如 CMP EAX, 0
  • 找到条件跳转,比如 JE 0x401234(成功分支)。
  • JE 改成 JNE,或者直接改成 JMP

举个例子,假设原始代码是这样的:

00401000  |.  83F8 00       CMP EAX, 0
00401003  |.  74 0A         JE SHORT 0040100F   ; 如果 EAX=0,跳向成功
00401005  |.  68 00304000   PUSH 0x00403000     ; "注册失败"
0040100A  |.  E8 10000000   CALL MessageBox
0040100F  |>  68 10304000   PUSH 0x00403010     ; "注册成功"

我们只需要把 74 0A 改成 EB 0A(强制跳转),或者改成 75 0A(反过来跳)。这样不管 EAX 是什么,程序都会走成功分支。

注意:修改跳转时,一定要算好偏移量。JMP 和 JE 的机器码长度可能不一样,改完要确保后面的指令还能正确执行。我见过有人把短跳转改成长跳转,结果把后面的指令覆盖了,程序直接崩溃。

21.4 知识体系图

下面这张图帮你理清补丁修改的三种方式及其关系:

补丁与修改 二进制补丁 内存补丁 修改跳转 Hex编辑器 改机器码 WriteProcessMemory Cheat Engine JE→JNE JMP强制 核心:找到关键判断 → 修改条件 → 固化修改

21.5 实战中的选择

三种方式各有适用场景,我整理了一个对比表:

方式 优点 缺点 适用场景
二进制补丁 一次修改,永久生效 文件校验会失效,加壳程序无法直接改 无保护的小程序、自己写的测试程序
内存补丁 绕过文件校验,灵活 每次运行都要打补丁,依赖外部工具 有反调试、有校验的商业软件
修改跳转 简单直接,效果明显 需要准确找到跳转点,偏移量容易算错 注册验证、功能开关类判断

我的建议:初学者先从二进制补丁入手,找个小程序练手。等你熟悉了机器码和跳转偏移,再尝试内存补丁。别一上来就搞复杂的内存注入,容易把自己搞晕。

好了,这一章的内容就到这里。记住,补丁不是目的,理解程序的执行流才是关键。你改得越多,对汇编和操作系统的理解就越深。


公众号:蓝海资料掘金营,微信deep3321