需要破解的程序

OD 实验(三) - 破解程序的文件验证

双击程序,提示需要许可证文件

用 OD 打开

OD 实验(三) - 破解程序的文件验证

LoadIconA 为加载图标

LoadCursorA 为加载鼠标

F8 走一下程序

OD 实验(三) - 破解程序的文件验证

走到了这里,调用了 CreateFileA,打开或创建文件 Keyfile.dat

但是当前目录没有 Keyfile.dat 文件

接下来是有个跳转指令 jnz 指令跳转到地址 0040109A

先看一下地址 0040109A 上的指令

OD 实验(三) - 破解程序的文件验证

地址 0040109A 走下去是调用 ReadFile

如果这个 jnz 语句没跳转而是直走的话,程序将退出

所以要让 jnz 这个语句实现跳转,当前的条件不足以让这个 jnz 进行跳转

jnz 跳转的条件是 ZF=0

把 ZF 改为 0,让这个 jnz 指令进行跳转

OD 实验(三) - 破解程序的文件验证

OD 实验(三) - 破解程序的文件验证

按 F8 往下走

OD 实验(三) - 破解程序的文件验证

程序实现了跳转

然后 F8 继续往下走

然后走到 ReadFile 读取文件

之后有个 jnz 跳转指令,还是有一个 jmp 跳转指令

OD 实验(三) - 破解程序的文件验证

该跳转哪个跳转指令还不能确定

先看看地址 004010B4 上有什么指令,为 xor ebx, ebx

再看看地址 004010F7 上的指令

OD 实验(三) - 破解程序的文件验证

这个是最早运行程序弹出来的对话框

看来要执行 jnz 跳转指令

OD 实验(三) - 破解程序的文件验证

将 ZF 置 0,按 F8 进行跳转

OD 实验(三) - 破解程序的文件验证

之后有一个 jl 跳转指令

看看地址 004010F7 上的指令

OD 实验(三) - 破解程序的文件验证

看来不能进行这个跳转

jl 跳转指令为当 SF != OF 的时候才进行跳转

OD 实验(三) - 破解程序的文件验证

将 SF 的 1 修改为 0,不让 jl 跳转指令进行跳转

F8 往下走

OD 实验(三) - 破解程序的文件验证

有个 je 跳转指令,跳转到地址 004010D3

不知道下面的情况怎么样,执行 je 跳转指令看看情况

OD 实验(三) - 破解程序的文件验证

然后有两个跳转指令 jl 和 jmp

从上面的步骤可以知道,地址 004010F7 不能走,那就不跳转 jl 指令,执行 jmp 跳转指令

OD 实验(三) - 破解程序的文件验证

这个跳转已经实现了,把 SF 设置为 0,为 SF = OF 不进行跳转

然后按 F8 往下走,到 jmp 跳转指令

看看地址 00401205 上的指令

OD 实验(三) - 破解程序的文件验证

这个地址上的指令是最终想要的

所以执行这个 jmp 跳转指令是正确的

按 F8 走 jmp 跳转

OD 实验(三) - 破解程序的文件验证

然后按 F8 进行往下走

OD 实验(三) - 破解程序的文件验证

成功

修改程序

重新走一下程序

OD 实验(三) - 破解程序的文件验证

这个 jnz 跳转指令需要跳转,可以改为 jmp 跳转指令,jmp 跳转指令为无条件跳转

OD 实验(三) - 破解程序的文件验证

改完按 F8,进行跳转

OD 实验(三) - 破解程序的文件验证

然后接着走

OD 实验(三) - 破解程序的文件验证

这个 jnz 跳转指令也需要跳转,那就也改成 jmp

OD 实验(三) - 破解程序的文件验证

然后接着走,之后有个 jl 指令

这个地方不能跳,改为 nop

然后往下走,有个 je 跳转指令,他会直接跳,让他跳

OD 实验(三) - 破解程序的文件验证

接下来是一条 jl 跳转指令,这个跳转不能跳,改为 nop

OD 实验(三) - 破解程序的文件验证

最后 jmp 指令跳往正确的地方

修改完成了

选中所修改的区域,即最初修改的地方到最后修改的地方

点击右键 -> 复制到可执行文件 -> 选择

OD 实验(三) - 破解程序的文件验证

然后右键 -> 备份 -> 保存数据到文件

OD 实验(三) - 破解程序的文件验证

成功

逆向算法

重新载入程序

OD 实验(三) - 破解程序的文件验证

走到第一条跳转指令前,这条指令显示为灰色是因为刚才修改过这个地方

将 ZF 置 0,让其跳转

跳转之后按 F8 往下走

OD 实验(三) - 破解程序的文件验证

这段指令是程序的核心算法

往下走

OD 实验(三) - 破解程序的文件验证

将 ZF 置 0,让 jnz 跳转指令跳转

跳转到 xor 异或指令

xor ebx,ebx

该 xor 异或指令会将 ebx 清 0

OD 实验(三) - 破解程序的文件验证

程序在

cmp dword ptr ds:[0x402173],0x10

上对地址为 0x402173 的值和 0x10 进行判断

往上拉可以看到程序往 402173 上放了什么

OD 实验(三) - 破解程序的文件验证

402173 上放的是 ReadFile 的第四个参数

函数参数的入栈顺序是:第一个参数先入栈,在最下面,接着是第二个参数入栈放在倒二下的位置,以此类推

ReadFile 函数:

BOOL ReadFile(
    HANDLE hFile,                  //文件的句柄
    LPVOID lpBuffer,               //用于保存读入数据的一个缓冲区
    DWORD nNumberOfBytesToRead,    //要读入的字节数
    LPDWORD lpNumberOfBytesRead,   //指向实际读取字节数的指针
    LPOVERLAPPED lpOverlapped
    //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。
    //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
);

ReadFile 函数的第四个参数为读取文件内容的字节数

cmp 比较文件内容字节数和 16 字节的关系(0x10 的十进制为 16)

如果文件内容的字节数小于 16 字节的话,将会走到下一条指令,然后跳转

OD 实验(三) - 破解程序的文件验证

所以文件内容至少为 16 字节,将不进行跳转

接下来是

OD 实验(三) - 破解程序的文件验证

语句

mov al,byte ptr ds:[ebx+0x40211A]

把地址 0x40211A 上的值加上 ebx 的值给 al

地址 0x40211A 为 ReadFile 的第二个参数

然后

cmp al,0x0

比较 al 是否为 0

如果 al 等于 0,ZF 就置 1,然后 je 跳转语句会跳转到

OD 实验(三) - 破解程序的文件验证

如果 esi 等于 8 的话,就会跳转到

OD 实验(三) - 破解程序的文件验证

所以 esi 要大于 8

要让 al 大于 0,不进行跳转

然后会走到

OD 实验(三) - 破解程序的文件验证

0x47 是字符 G 的 ASCII 码值 71 的十六进制

如果 al 的值等于 0x47 的话,ZF 就会置 1,下一条的 jnz 语句将不会进行跳转

之后执行指令 inc esi,递增 esi

esi 的值至少要为 9

所以 Keyfile.dat 中的值至少要有 9 个 G

创建一个 Keyfile.dat 文件

OD 实验(三) - 破解程序的文件验证

内容为 9 个 G,然后是数字 1,2,3,4,5,6,7,8,一共十七个字节

现在直接运行原程序

OD 实验(三) - 破解程序的文件验证

成功

相关文章:

  • 2021-09-01
  • 2022-12-23
  • 2022-12-23
  • 2021-05-31
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-18
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案