我得快点了

说明

  后面的一些样本都在这,来源是 B 站的“艮艮为山”,在此感谢 UP 的分享!
   链接:https://pan.baidu.com/s/1BaROP5e9UbJMSN1sgOOKbA
   提取码:z2i6

Keygenme

  一些不能一目了然的程序,还是先分析算法,防止爆破的不彻底。

查壳

无壳
无壳

字符串查找

  拖入 x32dbg,进去模块,按 shift + D 查看字符串。

字符串
字符串

  第一个字符串后缀为 KEY,点击跳转过去看看。

分析

读取文件
读取文件

  显然是个读取 KEY 文件进行校验的 Crackme,文件名为 “CRACKME3.KEY”,而且文件内容长度一定要大于 0x12(十进制:18)个字节。创建一个文件,随便写入超过 0x12 个字节的内容进去。

  继续往下看,发现了两个重点函数和结果校验的位置。

重点函数及结果校验
重点函数及结果校验

  进入处理函数 1 看看

处理函数 1
处理函数 1

  逻辑很简单,第一个字节与 A 异或,第二字节与 B 异或循环 0xE(十进制14)次存储在原来位置,并将循环次数和每次异或结果累加保存。如异或结果为 0 ,则提前结束循环。继续往下看

处理函数 2 及校验
处理函数 2 及校验

  处理函数 1 完成后,将异或累加结果与 0x12345678 进行异或并存入原来位置。处理函数 2 的作用是获取文件内容的第 15~18 字节并赋值给 eax(函数一目了然,不写了)。然后将 eax 与异或累加结果进行比较,相等则校验通过。这里将 eax 存储了,是因为后面还有成功弹窗要检测 al。

代码

#define _CRT_SECURE_NO_WARNINGS

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

#define MAX 100

int len = 0;

void Error()
{
    printf("校验失败\n");
}

DWORD Func1(char* dwBytesRead)
{
    char c = 'A';
    DWORD sum = NULL;
    for (int i = 0; i < 14; i++)
    {
        dwBytesRead[i] = dwBytesRead[i] ^ c;
        if (dwBytesRead == NULL)
        {
            return sum;
        }
        c += 1;
        sum += dwBytesRead[i];
        len += 1;    
    }
    return sum;
}

DWORD Func2(char* dwBytesRead)
{
    DWORD next;
    dwBytesRead += 14;
    next = *dwBytesRead * 0x1000000 + (*(dwBytesRead + 1)) * 0x10000 + (*(dwBytesRead + 2)) * 0x100 + (*(dwBytesRead + 3));
    return next;
}

int main(int argc, char* argv[])
{
    char Str1[MAX];
    char* pStr1 = Str1;
    DWORD dwBytesRead;
    DWORD prev;
    DWORD next;

    HANDLE hOpenFile = (HANDLE)CreateFile(L"CRACKME3.KEY", SE_GROUP_LOGON_ID, 0x00000003 , NULL, OPEN_EXISTING, 0x00000080, NULL);
    if (hOpenFile == INVALID_HANDLE_VALUE)
    {
        Error();
    }
    else
    {
        BOOL iRet = ReadFile(hOpenFile, pStr1, 0x12, &dwBytesRead, NULL);
        if (dwBytesRead < 12)
        {
            Error();
        }
        prev = Func1(pStr1);
        printf("处理函数1执行后累加值:%lx\n", prev);
        prev = prev ^ 0x12345678;

        printf("计算出后四位:%lx\n",prev);
        next = Func2(pStr1);
        printf("文件中后四位%lx\n", next);

        if (prev == next)
        {
            printf("Now try the next crackme!\n");
        }
        else 
        {
            Error();
        }
    }
    return 0;
}

执行结果
执行结果

Crackme

  根据前面,爆破只需要在同一目录下创建文件夹命名为“CRACKME3.KEY”,内容超过 18 个字节。然后将 0x0040109F 地址处的 je 改为 jne ,0x0040118A 处的 jne 改为 je 即可。

Crack
Crack