Crackme023 的逆向分析

1.程序观察

clipboard.png
当输入的序列号正确的时候,下面的状态应该会变。

2.简单查壳

clipboard.png
使用汇编语言写的,没有壳。

3.程序分析

使用 OD 载入程序,搜索字符串
clipboard.png

可以看到状态栏的字符串出现在了里面,我们进入对应的代码空间
clipboard.png

在地址 004012B3 处有一个比较语句,如果 eax 的值为 0x10,则程序跳转到正确提示处;如果 eax 的值不等于 0x10,程序则会跳转到错误提示处。

看来这里就是关键的比较了,那么 eax 的值是从哪里来的呢?
在地址 00401299 处可以看到,程序将内存 403166 处的值赋给了 eax。
那么问题又来了,内存 403166 处的值又是怎么来的呢?

我们在程序中查找常量 403166
clipboard.png

和内存 403166 有关的语句共有8句,有4句命令是让内存 403166 的值加4。
因为前面比较是让 403166 的值和 0x10 作比较,所以需要这四条命令全部执行才行。
这四处,分别是用来求得用户名,求得序列号,计算序列号,验证序列号。

求得用户名:
clipboard.png

程序先得到输入的用户名,然后求得用户名长度。接着使用循环将用户名后面一定长度的值清零。最后进行判断,如果用户名长度为0,则清零内存 403166 的值;如果不为0,则将内存 403166 的值加 0x4。

求得序列号:
clipboard.png
程序使用函数获取输入的序列号,如果函数返回值为0,也就是序列号为空的话,就会直接返回;如果序列号不为空,将内存 403166 的值加 0x4。

计算序列号:
clipboard.png
这是一个循环,循环次数要进行 0x10 次,内存 403166 处的值才会加 0x4。
在循环中:

  1. 程序得到用户名
  2. 用户名左移 i 位,i 为循环次数
  3. 求得输入的序列号
  4. 将序列号加1
  5. 让序列号和移位后的用户名进行异或运算
  6. 将计算出来的值存入内存 403188 处

验证序列号:
clipboard.png
将内存 401388 处序列号取出,加上 0x9112478,看结果是否为0。如果为0,就是正确的;如果非0,就是错误的。所以计算出来的序列号一定是 0 - 0x9112478 = 0xF6EEDB88。

4.注册机

#include <stdio.h>
#include <string.h>
#include <Windows.h>

int Key()
{
    unsigned long serial = 0xF6EEDB88;
    char szName[20] = { 0 };
    unsigned long* p;

    printf("请输入用户名:");
    scanf_s("%s", szName, 20);

    for (int i = 15; i >= 0; i--)
    {
        p = (unsigned long*)& szName[i];
        serial ^= *p;
        serial--;
    }

    printf("%u", serial);
    return 0;
}

int main(int argc, char* argv[])
{
    Key();
    return 0;
}

clipboard.png

相关文件在我的 Github


snow
4 声望0 粉丝

多么美好!


« 上一篇
Crackme022
下一篇 »
Crackme024