好友
阅读权限 20
听众
最后登录 1970-1-1
封心锁爱
发表于 2013-12-14 17:33
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
本帖最后由 Chief 于 2013-12-14 17:47 编辑
[文章标题]: [吾爱2013CM大赛解答]--LoveKido Update-- JoyChou追码分析
[作者信息]: 封心锁爱
[操作平台]: Win7 Sp1
[使用工具]: OD
[软件名称]: LoveKido Update-- JoyChou
[下载地址]: http://www.52pojie.cn/thread-228422-1-1.html
第一关:
1> 激活按钮,下断点 bp EnableWindow, f9运行,Alt+F9返回,会返回到mfc90u模块中,继续单步几下走到程序模块,网上翻一点, 找到push 0, 改为push 1
01241A3F 6A 00 push 0x0 ; 改为TRUE启用按钮
01241A41 . 68 EB030000 push 0x3EB
01241A46 . 8BCE mov ecx, esi
01241A48 . E8 310B0000 call <jmp.&mfc90u.#2904>
01241A4D . 8BC8 mov ecx, eax
01241A4F . E8 240B0000 call <jmp.&mfc90u.#2360> ; 禁用按钮
01241A54 . E8 37FAFFFF call 01241490 ; 从mfc90u返回到这里
2> 反调试,从 01241A9E - 01241ADA中的JNZ全部不能调,NOP掉
01241A54 . E8 37FAFFFF call 01241490 ; ┓
01241A59 . 85C0 test eax, eax ; ┃
01241A5B . 0F85 AF000000 jnz 01241B10 ; ┃
01241A61 . E8 CAFAFFFF call 01241530 ; ┃
01241A66 . 85C0 test eax, eax ; ┃
01241A68 . 0F85 A2000000 jnz 01241B10 ; ┣ 这几个call为检测虚拟机 的几个方法
01241A6E . E8 FDFBFFFF call 01241670 ; ┃
01241A73 . 85C0 test eax, eax ; ┃
01241A75 . 0F85 95000000 jnz 01241B10 ; ┃
01241A7B . E8 50FCFFFF call 012416D0 ; ┃
01241A80 . 85C0 test eax, eax ; ┃
01241A82 . 0F85 88000000 jnz 01241B10 ; ┛
01241A88 . E8 83F9FFFF call 01241410 ; 清除硬件断点
01241A8D . E8 2EF9FFFF call 012413C0 ; 获取MessageBoxA函数,并将MessageBoxA保护属性改为PAGE_EXECUTE_READWRITE
01241A92 . E8 A9F8FFFF call 01241340 ; 查找MessageBoxA中是否存在内存断点
01241A97 . E8 64F5FFFF call 01241000 ; 查找是否存在调试器进程 "OllyDbg .EXE" "吾爱破解 .EXE" "ICEYOD.EXE" "OLLYICE.EXE" "WINGUARD.EXE"
01241A9C . 85C0 test eax, eax
01241A9E 75 54 jnz short 01241AF4
01241AA0 . E8 9BF7FFFF call 01241240 ; 查找窗口类"OLLYXE"
01241AA5 . 85C0 test eax, eax
01241AA7 75 4B jnz short 01241AF4
01241AA9 . E8 F2F7FFFF call 012412A0 ; 判断父进程是不是explorer来反调试
01241AAE . 85C0 test eax, eax
01241AB0 75 42 jnz short 01241AF4
01241AB2 . FF15 6C402401 call dword ptr [<&KERNEL32.GetCurrent>; [GetCurrentProcess
01241AB8 . 8D4C24 10 lea ecx, dword ptr [esp+0x10]
01241ABC . 51 push ecx
01241ABD . 50 push eax
01241ABE . C74424 18 000>mov dword ptr [esp+0x18], 0x0
01241AC6 . FF15 68402401 call dword ptr [<&KERNEL32.CheckRemot>; kernel32.CheckRemoteDebuggerPresent
01241ACC . 837C24 10 01 cmp dword ptr [esp+0x10], 0x1 ; 调用CheckRemoteDebuggerPresent检查是否存在调试器
01241AD1 74 21 je short 01241AF4
01241AD3 . E8 B8F8FFFF call 01241390 ; 根据执行时间反调试
01241AD8 . 85C0 test eax, eax
01241ADA 75 18 jnz short 01241AF4
3> 按钮激活后,开始找Key,要比较Key是否正确,当然需要获取Key的内容,这里F9运行,随便输入Key,然后下断点
bp GetWindowTextW, 返回到程序模块
00091D18 . 8D4424 0C lea eax, dword ptr [esp+0xC]
00091D1C . 50 push eax
00091D1D . 68 E9030000 push 0x3E9
00091D22 . 8BCE mov ecx, esi
00091D24 . C68424 B00000>mov byte ptr [esp+0xB0], 0x1
00091D2C . E8 6B080000 call <jmp.&mfc90u.#2909> ; 获取Key
00091D31 . 8B4C24 0C mov ecx, dword ptr [esp+0xC] ; ecx = Key -->到了程序模块后在这里
00091D35 . 8B41 F4 mov eax, dword ptr [ecx-0xC] ; eax = StrLen
下面单步继续往下走,寻找比较Key的地方, 下面是一些除法运算(还原除数原理参见C++反汇编与逆向分析技术揭秘),还原后可知下面几个条件, 下面的Key(10)代表Key的10进制值:
Key(10) - ((Key(10) / 3) * 3) == 1 &&
Key(10) - ((Key(10) / 5) * 5) == 2 &&
Key(10) - ((Key(10) / 7) * 7) == 4 &&
Key(10) - ((Key(10) / 13) * 13) == 6 &&
Key(10) - ((Key(10) / 17) * 17) == 8
这5个条件必须全部为TRUE,这里用了枚举方法算出Key,为18232,C代码见Code<1>
00091DA1 . FFD6 call esi ; 将Key转换为10进制
00091DA3 . 8BC8 mov ecx, eax ; 除法运算 Key(10进制) / 3 除数的计算方法: 2^32 / 0x55555556四舍五入
00091DA5 . B8 56555555 mov eax, 0x55555556
00091DAA . F7E9 imul ecx
00091DAC . 8BC2 mov eax, edx
00091DAE . C1E8 1F shr eax, 0x1F
00091DB1 . 03C2 add eax, edx ; eax = 商
00091DB3 . 8D1440 lea edx, dword ptr [eax+eax*2] ; 商 * 3
00091DB6 . 8BC1 mov eax, ecx ; eax = Key10进制
00091DB8 . 2BC2 sub eax, edx
00091DBA . 83C4 08 add esp, 0x8
00091DBD . 83F8 01 cmp eax, 0x1 ; Key(10进制) - (商 * 3) == 1
00091DC0 . 0F85 FD000000 jnz 00091EC3
00091DC6 . B8 67666666 mov eax, 0x66666667 ; 除法运算 Key(10) / 5 除数=2^33 / 0x66666667四舍五入
00091DCB . F7E9 imul ecx ; ecx = Key(10)
00091DCD . D1FA sar edx, 1 ; edx为乘法的高32位,相当于已经右移的32位,再右移1位为33位
00091DCF . 8BC2 mov eax, edx
00091DD1 . C1E8 1F shr eax, 0x1F
00091DD4 . 03C2 add eax, edx ; eax = 商
00091DD6 . 8D1480 lea edx, dword ptr [eax+eax*4] ; 商 * 5
00091DD9 . 8BC1 mov eax, ecx
00091DDB . 2BC2 sub eax, edx ; Key(10) - (商 * 5) == 2
00091DDD . 83F8 02 cmp eax, 0x2
00091DE0 . 0F85 DD000000 jnz 00091EC3
00091DE6 . B8 93244992 mov eax, 0x92492493 ; 除法运算 Key(10) / 7 除数=2^34 / 0x92492493四舍五入
00091DEB . F7E9 imul ecx
00091DED . 03D1 add edx, ecx
00091DEF . C1FA 02 sar edx, 0x2
00091DF2 . 8BC2 mov eax, edx
00091DF4 . C1E8 1F shr eax, 0x1F
00091DF7 . 03C2 add eax, edx ; eax = 商
00091DF9 . 8D14C5 000000>lea edx, dword ptr [eax*8] ; 商 * 8
00091E00 . 2BD0 sub edx, eax ; edx = 商 * 7
00091E02 . 8BC1 mov eax, ecx ; eax = Key(10)
00091E04 . 2BC2 sub eax, edx
00091E06 . 83F8 04 cmp eax, 0x4 ; Key(10) - (商 * 7) == 4
00091E09 . 0F85 B4000000 jnz 00091EC3
00091E0F . B8 4FECC44E mov eax, 0x4EC4EC4F ; 除法运算 Key(10) / 13 除数:2^34 / 0x4ec4ec4f四舍五入
00091E14 . F7E9 imul ecx
00091E16 . C1FA 02 sar edx, 0x2
00091E19 . 8BC2 mov eax, edx
00091E1B . C1E8 1F shr eax, 0x1F
00091E1E . 03C2 add eax, edx ; eax = 商
00091E20 . 6BC0 0D imul eax, eax, 0xD ; 商 * 13
00091E23 . 8BD1 mov edx, ecx
00091E25 . 2BD0 sub edx, eax ; Key(10) - (商 * 13) == 6
00091E27 . 83FA 06 cmp edx, 0x6
00091E2A . 0F85 93000000 jnz 00091EC3
00091E30 . B8 79787878 mov eax, 0x78787879 ; 除法运算 Key(10) / 17 除数:2^35 / 0x78787879四舍五入
00091E35 . F7E9 imul ecx
00091E37 . C1FA 03 sar edx, 0x3
00091E3A . 8BC2 mov eax, edx
00091E3C . C1E8 1F shr eax, 0x1F
00091E3F . 03C2 add eax, edx ; eax = 商
00091E41 . 8BD0 mov edx, eax
00091E43 . C1E2 04 shl edx, 0x4
00091E46 . 03D0 add edx, eax ; 商 * 17
00091E48 . 2BCA sub ecx, edx ; Key(10) - (商 * 17) == 8
00091E4A . 83F9 08 cmp ecx, 0x8
00091E4D . 75 74 jnz short 00091EC3
第二关:
和上面同理,要判断Key,就必须获取Key,同样下断点bp GetWindowTextW,输入Key点按钮断下,返回到程序模块
0009207D . 8D4424 18 lea eax, dword ptr [esp+0x18]
00092081 . 50 push eax
00092082 . 68 EE030000 push 0x3EE
00092087 . 8BCE mov ecx, esi
00092089 . C74424 6C 000>mov dword ptr [esp+0x6C], 0x0
00092091 . E8 06050000 call <jmp.&mfc90u.#2909> ; 获取Key
00092096 . 8B3D 40650900 mov edi, dword ptr [0x96540] ; edi = 机器码 ->> 返回到程序模块后在这里
下面根据机器码计算Key, 下面说的字符长度和字节长度在Unicode环境下才有区别,便于理解,这里举个例子:
String: "Hello"
上面这个字符串的字符长度不管是Unicode还是非Unicode都是5,而字节长度在Ansi下是5,在Unicode就是10,因为一个Unicode字符2字节
000920C0 > /8D444D 00 lea eax, dword ptr [ebp+ecx*2]
000920C4 . |66:8B5404 30 mov dx, word ptr [esp+eax+0x30] ; 取机器码一个字符
000920C9 . |66:42 inc dx ; 加1
000920CB . |66:83F2 1F xor dx, 0x1F ; 和0x1f异或
000920CF . |8BC7 mov eax, edi
000920D1 . |66:89544C 30 mov word ptr [esp+ecx*2+0x30], dx ; 保存算出的Key
000920D6 . |41 inc ecx
000920D7 . |8D70 02 lea esi, dword ptr [eax+0x2]
000920DA . |8D9B 00000000 lea ebx, dword ptr [ebx]
000920E0 > |66:8B10 mov dx, word ptr [eax]
000920E3 . |83C0 02 add eax, 0x2
000920E6 . |66:85D2 test dx, dx
000920E9 .^|75 F5 jnz short 000920E0
000920EB . |2BC6 sub eax, esi ; 机器码字节长度
000920ED . |D1F8 sar eax, 1 ; 机器码字符长度
000920EF . |3BC8 cmp ecx, eax
000920F1 .^\72 CD jb short 000920C0
继续, 下面这段将机器码字节长度与0x11异或然后输出成为一个字符串
00092109 . 8B0D 40650900 mov ecx, dword ptr [0x96540] ; 机器码
0009210F . 8B41 F4 mov eax, dword ptr [ecx-0xC] ; 机器码字符长度
00092112 . 8B35 30420900 mov esi, dword ptr [<&mfc90u.#2537>] ; mfc90u.#2537
00092118 . 8D1400 lea edx, dword ptr [eax+eax] ; edx = 机器码字节长度
0009211B . 83F2 11 xor edx, 0x11 ; 机器码字节长度与0x11异或
0009211E . 52 push edx
0009211F . 8D4424 18 lea eax, dword ptr [esp+0x18]
00092123 . 68 B04C0900 push 00094CB0 ; UNICODE "%d"
00092128 . 50 push eax
00092129 . FFD6 call esi ; mfc90u.#2537; <&mfc90u.#2537>
下面将上面根据机器码计算出的Key与刚才输出的字符串连接
0009214E . 8D4424 20 lea eax, dword ptr [esp+0x20]
00092152 . 50 push eax
00092153 . 8D4C24 2C lea ecx, dword ptr [esp+0x2C]
00092157 . 51 push ecx
00092158 . 8D4C24 24 lea ecx, dword ptr [esp+0x24]
0009215C . E8 2F020000 call 00092390 ; 将Key字节长度异或0x11后的值接入串后面
此时eax指向的内存保存着Key的地址
下面就是比较Key和我们的输入的Key了
00092189 . 52 push edx ; 我们输入的Key
0009218A . 8D4C24 14 lea ecx, dword ptr [esp+0x14]
0009218E . 884424 24 mov byte ptr [esp+0x24], al ; 这些mov是成功提示字符串
00092192 . C64424 25 A7 mov byte ptr [esp+0x25], 0xA7
00092197 . C64424 26 CF mov byte ptr [esp+0x26], 0xCF
0009219C . C64424 27 B2 mov byte ptr [esp+0x27], 0xB2
000921A1 . C64424 28 00 mov byte ptr [esp+0x28], 0x0
000921A6 . C64424 2C B3 mov byte ptr [esp+0x2C], 0xB3
000921AB . C64424 2D C9 mov byte ptr [esp+0x2D], 0xC9
000921B0 . 884424 2E mov byte ptr [esp+0x2E], al
000921B4 . C64424 2F A6 mov byte ptr [esp+0x2F], 0xA6
000921B9 . C64424 30 00 mov byte ptr [esp+0x30], 0x0
000921BE . FF15 3C420900 call dword ptr [<&mfc90u.#1599>] ; 比较Key
000921C4 . 85C0 test eax, eax
000921C6 . 75 13 jnz short 000921DB
好了,计算Key已经看完了,现在来整理下:
机器码的每个字符 + 1 ^ 0x1f组成字符串和机器码的字节长度 ^ 0x11后的字符串连接
根据上面这个我们来写KeyGen,见Code<2>
Code<1>
[C++] 纯文本查看 复制代码
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bFound = FALSE;
unsigned int nValue = 0;
do
{
if (nValue - ((nValue / 3) * 3) == 1 &&
nValue - ((nValue / 5) * 5) == 2 &&
nValue - ((nValue / 7) * 7) == 4 &&
nValue - ((nValue / 13) * 13) == 6 &&
nValue - ((nValue / 17) * 17) == 8)
{
bFound = TRUE;
break;
}
} while (++nValue <= 100000);
if (bFound)
_tprintf(TEXT("%d\r\n"), nValue);
else
_tprintf(TEXT("Not Found!\r\n"));
return 0;
}
Code<2>
C代码:
[C++] 纯文本查看 复制代码
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szMac[64];
_tscanf_s(TEXT("%s"), szMac, _countof(szMac));
TCHAR szSN[64];
int nLen = _tcslen(szMac);
int nIndex;
for (nIndex = 0; nIndex < nLen; nIndex++)
{
szSN[nIndex] = szMac[nIndex] + 1 ^ 0x1f;
}
szSN[nIndex++] = (nLen * 2 ^ 0x11) + 0x30;
szSN[nIndex] = TEXT('\0');
_tprintf(TEXT("%s\r\n"), szSN);
return 0;
}
吾爱破解 注册机源码:
[Visual Basic] 纯文本查看 复制代码
Function GetMC(X)
GetMC=X
MC=GetMC
End Function
Function GetName(X)
End Function
Function GetSN()
mcLen = Len(MC)
Key=""
n = 1
do while n <= mcLen
tmp = Asc(Mid(MC, n, 1)) + 1
tmp = tmp xor &H1f
Key = Key & Chr(tmp)
n = n + 1
loop
mcLen = mcLen * 2
mcLen = mcLen xor &H11
Key = Key & mcLen
GetSN=Key
End Function
[版权声明]: 本文原创于封心锁爱, 转载请注明作者并保持文章的完整, 谢谢!
免费评分
查看全部评分