zoukankan      html  css  js  c++  java
  • OD 实验(三)

    需要破解的程序

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

    逆向程序

    用 OD 打开

    LoadIconA 为加载图标

    LoadCursorA 为加载鼠标

    F8 走一下程序

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

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

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

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

    地址 0040109A 走下去是调用 ReadFile

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

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

    jnz 跳转的条件是 ZF=0

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

    按 F8 往下走

    程序实现了跳转

    然后 F8 继续往下走

    然后走到 ReadFile 读取文件

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

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

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

    再看看地址 004010F7 上的指令

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

    看来要执行 jnz 跳转指令

    将 ZF 置 0,按 F8 进行跳转

    之后有一个 jl 跳转指令

    看看地址 004010F7 上的指令

    看来不能进行这个跳转

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

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

    F8 往下走

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

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

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

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

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

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

    看看地址 00401205 上的指令

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

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

    按 F8 走 jmp 跳转

    然后按 F8 进行往下走

    成功

    修改程序

    重新走一下程序

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

    改完按 F8,进行跳转

    然后接着走

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

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

    这个地方不能跳,改为 nop

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

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

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

    修改完成了

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

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

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

    成功

    逆向算法

    重新载入程序

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

    将 ZF 置 0,让其跳转

    跳转之后按 F8 往下走

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

    往下走

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

    跳转到 xor 异或指令

    xor ebx,ebx
    

    该 xor 异或指令会将 ebx 清 0

    程序在

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

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

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

    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 字节的话,将会走到下一条指令,然后跳转

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

    接下来是

    语句

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

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

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

    然后

    cmp al,0x0
    

    比较 al 是否为 0

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

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

    所以 esi 要大于 8

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

    然后会走到

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

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

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

    esi 的值至少要为 9

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

    创建一个 Keyfile.dat 文件

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

    现在直接运行原程序

    成功

  • 相关阅读:
    数据结构基础(二)排序算法
    数据结构基础(一) 时间空间复杂度分析
    347. Top K Frequent Elements, O(N) solution
    409. Longest Palindrome
    556. Next Greater Element III
    CH0103 最短Hamilton路径(状压DP)
    牛客OI周赛13-提高组A-0还是1(简单DP)
    Codeforces Round #678 (Div. 2) C. Binary Search(二分查找/思维/排列组合)
    Codeforces Round #677 (Div. 3) A-E
    函数实现复合命题的计算及判断两个命题是否等值——中缀表达式转后缀表达式
  • 原文地址:https://www.cnblogs.com/sch01ar/p/9563386.html
Copyright © 2011-2022 走看看