1. 脱壳过程
这个crackme有2个文件
发现加了壳
先来脱壳, 使用ESP守恒, pushad后立马下硬件访问断点
F9直接运行, 立马到popad处
接着走几步就到了OEP
下面使用LordPE来转储映像, 为了防止别人修改PE中的ImageSize, 先尝试修正下ImageSize, 然后dump full即可
接着用x64dbg调试器重新打开dump后的文件, 准备修复入口点和IAT表, 在这之前往内存里瞄了一眼, 发现主模块的PE头部被设置了只读属性, 首先先将其改成可读写
这样就舒服多了
使用ImportREC打开当前被调试的进程, 并且修改OEP为之前脱壳后第一句代码的RVA地址,注意, 这个地址要减去ImageBase才是RVA地址, 接着选择IAT自动搜索, 如果没什么问题会弹出如下弹框
然后选择获取导入表, 即可发现该exe所导入的模块, 并且其后面都是有效
最后选择修正转储选择要修正的转储文件即可
2. 逆向分析过程
这个程序比较简单, 作者的目的估计主要是为了让我们练习脱壳。脱完壳后, 再次调试就发现图片变成了CRACKED
但是不进行调试的状态, 就会显示是LOCKED状态
这里先解决这个问题, 让它永远变成cracked状态, 可以确定的是, 他做这些事肯定是在WM_INITDIALOG中的,因为在程序运行的过程中是没有任何变化, 定位WndProc然后找到WM_INITDIALOG后重新跑
可以看到了关键API LoadBitmapA
使用Resource hacker查看一下程序有什么bitmap资源, Ooops, 找到了这张图片的资源ID是101, 十六进制是0x65
这里圈出来的call决定了最终你将选择哪张图片
里面是把0x401000和0x402000处的代码计算哈希然后运算决定的, 很明显脱壳会对这个造成影响
这里直接选择进行爆破, 直接把0x65传入LoadBitmapA中
好了, 这样永远就是cracked的状态了。
下面继续进行破解, 运行以下后发现Register按钮是被禁用的, 尝试搜索以下EnableWindow这个API, 定位到该位置后发现上方还有2个GetDlgItemText, 很明显是为了获取name和输入的key的。在EnableWindow上面还有一个call应该就是key的生成算法
随便进行了一次测试, 由于这里要求密码必须是8位, 所以首先我把密码设置成8位, 这样方便调试Key运算的部分
这个函数最终会返回eax, 也就是说如果eax为1, 那么EnableWindow就会激活Register按钮, 那也就能顺利注册, 否则就不行
再看以下Key运算部分, 这里是一个jne循环, 如果ecx不为4就会循环满足某个条件会让ecx增加1, 只有ecx为4才是正确的serial
这里经过红色框部分的运算后, 满足2个橘色框的条件则ecx有机会增加1,经过4次判断都满足条件key即为正确
3. 编写注册机
这个注册机编写很容易, 为了躲避使用ror之类的带进位指令, 我直接使用了内联汇编来编写
下面放出核心代码:
BOOL GetSerialKey(LPCSTR pszName, LPSTR pszKeyBuf, DWORD nKeyBufSize)
{
int iNameLen = 0;
DWORD dwFix = 0x44414D4E;
DWORD dwTmp = 0;
CHAR cch = 0;
int iKeyLen = 0;
int iPtr1 = 1;
int iPtr0 = 0;
if (!pszName || !pszKeyBuf || nKeyBufSize < 9)
{
return(FALSE);
}
iNameLen = strlen(pszName);
if (!iNameLen)
{
return(FALSE);
}
for (size_t nIdx = 0; nIdx < iNameLen; ++nIdx)
{
cch = pszName[nIdx];
dwTmp += cch;
__asm
{
push eax
push ecx
xor ecx, ecx
mov cl, byte ptr [nIdx]
ror dword ptr[dwFix], 1
ror dword ptr[dwFix], cl
pop ecx
pop eax
}
dwFix ^= dwTmp;
}
dwFix |= 0x10101010;
for (size_t nIdx = 0; nIdx < 4; ++nIdx)
{
__asm
{
push eax
xor eax, eax
rol dword ptr[dwFix], 8
mov al, byte ptr[dwFix]
mov cch, al
mov byte ptr[dwTmp], al
and cch, 0xF
shr byte ptr[dwTmp], 4
and byte ptr[dwTmp], 0xF
cmp cch, 0xA
sbb cch, 0x69
mov al, cch
das
mov cch, al
}
pszKeyBuf[nIdx * 2 + 1] = cch;
__asm
{
mov al, byte ptr[dwTmp]
mov cch, al
cmp cch, 0xA
sbb cch, 0x69
mov al, cch
das
mov cch, al
pop eax
}
pszKeyBuf[nIdx * 2] = cch;
}
return(TRUE);
}
(完)