- UID
- 67309
注册时间2010-5-26
阅读权限10
最后登录1970-1-1
周游历练
该用户从未签到
|
本帖最后由 月之精灵 于 2010-6-2 18:13 编辑
【破文标题】【PYG学员】【9小组】【中华灯谜】【算法分析】
【破文作者】sohd
【作者邮箱】[email protected]
【作者主页】
【破解工具】OD
【破解平台】win2003
【软件名称】中华灯谜 2008 build 12.15
【软件大小】2.87M
【原版下载】http://www.onlinedown.net/softdown/863_2.htm
【保护方式】aspack
【软件简介】〖中华灯谜〗软件是目前国产最好的灯谜软件,软件受到数十家刊物的特别撰文推荐。
【破解声明】只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
------------------------------------------------------------------------
【破解过程】第一次完整分析这个注册代码,有误之处还请见谅。我简单说一下几个重要的代码。
首先来到关键处
0054EF06 |. 8B85 6CFFFFFF mov eax, dword ptr [ebp-94]
0054EF0C |. 50 push eax
0054EF0D |. 8D95 64FFFFFF lea edx, dword ptr [ebp-9C]
0054EF13 |. 8B83 C0030000 mov eax, dword ptr [ebx+3C0]
0054EF19 |. E8 6A8CEFFF call <GetRegInfo> ;获取定单号 GetRegInfo 这个是我做的标签。
0054EF1E |. 8B85 64FFFFFF mov eax, dword ptr [ebp-9C]
0054EF24 |. E8 DBA6EBFF call <C_Compute1> ; 把序号的数*10再相加 这里进去看看 看下面的 C_Compute1处代码
0054EF29 |. B9 3A000000 mov ecx, 3A
0054EF2E |. 99 cdq
0054EF2F |. F7F9 idiv ecx ; 把上面算出来的数,除3A 取余数给 eax
0054EF31 |. 8BC2 mov eax, edx
0054EF33 |. 8D95 68FFFFFF lea edx, dword ptr [ebp-98] ; 一个局部地址 一会会把算到的注册码前几个字符串地址写到这里。
0054EF39 |. E8 62A6EBFF call 004095A0 ; 获取注册码的前几个字符。。这个函数有点绕 这里进去看看 看下面的 004095A0 处代码
0054EF3E |. 8D85 68FFFFFF lea eax, dword ptr [ebp-98]
0054EF44 |. 50 push eax
0054EF45 |. 8D95 58FFFFFF lea edx, dword ptr [ebp-A8]
0054EF4B |. 8B83 C0030000 mov eax, dword ptr [ebx+3C0]
0054EF51 |. E8 328CEFFF call <GetRegInfo> ; 获取定单号 GetRegInfo 这个是我做的标签。
0054EF56 |. 8B85 58FFFFFF mov eax, dword ptr [ebp-A8]
0054EF5C |. E8 A3A6EBFF call <C_Compute1> ; 把序号的数*10再相加 这里进去看看 看下面的 C_Compute1处代码
0054EF61 |. 8D95 5CFFFFFF lea edx, dword ptr [ebp-A4]
0054EF67 |. E8 80DCFFFF call 0054CBEC ; 进去一个计算。 这里进去看看 看下面的 0054CBEC 处代码
0054EF6C |. 8B85 5CFFFFFF mov eax, dword ptr [ebp-A4]
0054EF72 |. E8 8DA6EBFF call <C_Compute1>
0054EF77 |. 8D95 60FFFFFF lea edx, dword ptr [ebp-A0]
0054EF7D |. E8 4ADDFFFF call <Compute2> ; 出来一串注册码 进去看看 看下面的 Compute2 处代码
0054EF82 |. 8B95 60FFFFFF mov edx, dword ptr [ebp-A0] ; |
0054EF88 |. 58 pop eax ; |
0054EF89 |. E8 E25CEBFF call <strcat> ; \strcat
0054EF8E |. 8B95 68FFFFFF mov edx, dword ptr [ebp-98]
0054EF94 |. 58 pop eax
0054EF95 |. E8 125EEBFF call 00404DAC
0054EF9A |. 0F85 8F000000 jnz 0054F02F
0054EFA0 |. B8 F4F05400 mov eax, 0054F0F4 ; 注册成功,谢谢你的注册!
0054EFA5 |. E8 D21DEFFF call 00440D7C
0054EFAA |. BA 18F15400 mov edx, 0054F118 ; 本软件已注册
0054EFAF |. 8B83 B0030000 mov eax, dword ptr [ebx+3B0]
0054EFB5 |. E8 FE8BEFFF call 00447BB8
0054EFBA |. 8D85 54FFFFFF lea eax, dword ptr [ebp-AC]
0054EFC0 |. B9 30F15400 mov ecx, 0054F130 ; \dc0n.dll
0054EFC5 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054EFC8 |. E8 E75CEBFF call 00404CB4
0054EFCD |. 8B8D 54FFFFFF mov ecx, dword ptr [ebp-AC]
0054EFD3 |. B2 01 mov dl, 1
0054EFD5 |. A1 B8184700 mov eax, dword ptr [4718B8]
0054EFDA |. E8 8929F2FF call 00471968
0054EFDF |. 8BF0 mov esi, eax
0054EFE1 |. 8D95 50FFFFFF lea edx, dword ptr [ebp-B0]
0054EFE7 |. 8B83 C0030000 mov eax, dword ptr [ebx+3C0]
0054EFED |. E8 968BEFFF call <GetRegInfo>
0054EFF2 |. 8B85 50FFFFFF mov eax, dword ptr [ebp-B0]
0054EFF8 |. 50 push eax
0054EFF9 |. B9 44F15400 mov ecx, 0054F144 ; sepop
0054EFFE |. BA 54F15400 mov edx, 0054F154 ; syssetup
0054F003 |. 8BC6 mov eax, esi
0054F005 |. 8B18 mov ebx, dword ptr [eax]
0054F007 |. FF53 04 call dword ptr [ebx+4]
0054F00A |. 8D85 4CFFFFFF lea eax, dword ptr [ebp-B4]
0054F010 |. B9 30F15400 mov ecx, 0054F130 ; \dc0n.dll
0054F015 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054F018 |. E8 975CEBFF call 00404CB4
0054F01D |. 8B85 4CFFFFFF mov eax, dword ptr [ebp-B4]
0054F023 |. BA 02000000 mov edx, 2
0054F028 |. E8 03A9EBFF call 00409930
0054F02D |. EB 17 jmp short 0054F046
0054F02F |> B8 68F15400 mov eax, 0054F168 ; 注册码错误,请重新输入!
0054F034 |. E8 431DEFFF call 00440D7C
C_Compute1 代码如下(只贴关键代码):
004033B6 |> 80EB 30 /sub bl, 30
004033B9 |. |80FB 09 |cmp bl, 9 ; 必须为数字。
004033BC |. |77 25 |ja short 004033E3 ;不是数字就跳走了。
004033BE |. |39F8 |cmp eax, edi
004033C0 |. |77 21 |ja short 004033E3
004033C2 |. |8D0480 |lea eax, dword ptr [eax+eax*4] ; EAX第一次是0 ------------------------
004033C5 |. |01C0 |add eax, eax ; 这断在循环的把数字相加
004033C7 |. |01D8 |add eax, ebx
004033C9 |. |8A1E |mov bl, byte ptr [esi] ; eai为字符串首地址
004033CB |. |46 |inc esi
004033CC |. |84DB |test bl, bl
004033CE |.^\75 E6 \jnz short 004033B6 ; -------------------------------------
转换成C++代码为:
char* pszOrderID = "358588"; // 假如这个就是定单号。
DWORD dwNum = 0;
while (*pszOrderID != 0)
{
dwNum = dwNum*10;
dwNum += (*pszOrderID-0x30);
pszOrderID++;
}
return dwNum;
以上就是 C_Compute1 函数大概作用。。当然函数的其它代码可能还有别的作用。暂不深入看了。。
0054CBEC 代码如下(只贴关键代码):
0054CC09 |. 81F3 F1250B00 xor ebx, 0B25F1 ; ebx就是前面算出来的数 和 0B25F1 xor
0054CC0F |. 8BC3 mov eax, ebx
0054CC11 |. 33D2 xor edx, edx
0054CC13 |. 52 push edx ; |format => NULL
0054CC14 |. 50 push eax ; |s
0054CC15 |. 8D45 FC lea eax, dword ptr [ebp-4] ; |
0054CC18 |. E8 B3C9EBFF call <sprintf> ; \%d 到一个内存里。 sprintf我定义的标签 只能说是近似函数
0054CC1D |. 8B45 FC mov eax, dword ptr [ebp-4]
0054CC20 |. 0FB600 movzx eax, byte ptr [eax] ; 10进制数的第一个
0054CC23 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CC26 |. 0FB652 01 movzx edx, byte ptr [edx+1] ; 10进制数的第2个
0054CC2A |. 03C2 add eax, edx ; 相加
0054CC2C |. B9 05000000 mov ecx, 5
0054CC31 |. 99 cdq
0054CC32 |. F7F9 idiv ecx ; 除5
0054CC34 |. 80C2 34 add dl, 34 ; 余数+34
0054CC37 |. 8855 F8 mov byte ptr [ebp-8], dl ; 第一个数值 保存
0054CC3A |. 8B45 FC mov eax, dword ptr [ebp-4]
0054CC3D |. 0FB640 02 movzx eax, byte ptr [eax+2]
0054CC41 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CC44 |. 0FB652 03 movzx edx, byte ptr [edx+3]
0054CC48 |. 03C2 add eax, edx
0054CC4A |. B9 05000000 mov ecx, 5
0054CC4F |. 99 cdq
0054CC50 |. F7F9 idiv ecx
0054CC52 |. 8BDA mov ebx, edx
0054CC54 |. 80C3 33 add bl, 33
0054CC57 |. 885D F9 mov byte ptr [ebp-7], bl ; 第2个数值 保存
0054CC5A |. 8D45 F4 lea eax, dword ptr [ebp-C]
0054CC5D |. 8A55 F8 mov dl, byte ptr [ebp-8]
0054CC60 |. E8 2B7FEBFF call <new_copy> ;这函数会先new一个空间,再把数值copy到新空间。
0054CC65 |. 8B45 F4 mov eax, dword ptr [ebp-C]
0054CC68 |. 8D55 FC lea edx, dword ptr [ebp-4]
0054CC6B |. B9 1B000000 mov ecx, 1B
0054CC70 |. E8 D382EBFF call <strInsert> ; 这个就是字符串插入函数 1B是要插入的位置 一般我们的定单号算出来的不会有1B长。所以 都是直接把数值往后插
0054CC75 |. 8D45 F0 lea eax, dword ptr [ebp-10]
0054CC78 |. 8BD3 mov edx, ebx
0054CC7A |. E8 117FEBFF call <new_copy> ; 同上
0054CC7F |. 8B45 F0 mov eax, dword ptr [ebp-10]
0054CC82 |. 8D55 FC lea edx, dword ptr [ebp-4]
0054CC85 |. B9 19000000 mov ecx, 19
0054CC8A |. E8 B982EBFF call <strInsert> ; 同上
转换成C++代码为:
dwNum ^= 0x0B25F1;
char szNum[100] = {0};
sprintf(szNum, "%d", dwNum);
char szTemp[5] = {0};
szTemp[0] = (*(szNum) + *(szNum+1))%5 + 0x34;
szTemp[1] = (*(szNum+2) + *(szNum+3))%5 + 0x33;
strcat(szNum, szTemp);
004095A0 代码如下(只贴关键代码):
下面这段代码并非 004095A0 函数的 是子函数内的。调用过程中的代码就不贴了,
00409E80 > \895D DC mov dword ptr [ebp-24], ebx
00409E83 . 8975 D8 mov dword ptr [ebp-28], esi
00409E86 . 51 push ecx
00409E87 . 52 push edx
00409E88 . E8 95000000 call 00409F22 ; 这里改变了ESI 进去
00409F22 代码如下(只贴关键代码):
0040A076 |$ B9 0A000000 mov ecx, 0A ; Case 55 ('U') of switch 0040A04A
0040A07B |> 8D75 9F lea esi, dword ptr [ebp-61]
0040A07E |> 31D2 /xor edx, edx
0040A080 |. F7F1 |div ecx
0040A082 |. 80C2 30 |add dl, 30 ; 这块是算注册码 前面的几个字串
0040A085 |. 80FA 3A |cmp dl, 3A
0040A088 |. 72 03 |jb short 0040A08D
0040A08A |. 80C2 07 |add dl, 7
0040A08D |> 4E |dec esi
0040A08E |. 8816 |mov byte ptr [esi], dl
0040A090 |. 09C0 |or eax, eax ; 商不为0 就继续。
0040A092 |.^ 75 EA \jnz short 0040A07E
上面这一块就是核心代码了。 算出来前N位字符
转换成C++代码为:
CString strRegCode;
int nNum = 0;
nNum = dwNum%0x3A;
int n1, n2, nTemp;
n1 = nNum;
do
{
nTemp = n1;
n1 = n1/0x0A; // 商
n2 = nTemp%0x0A; // 余数
n2 += 0x30;
strRegCode.Insert(0, (char*)&n2);
} while (n1);
Compute2 代码如下(只贴关键代码):
0054CCEB |. 81F3 8776FBDD xor ebx, DDFB7687 ; ebx前面代码计算出来的值 和DDFB7687 xor
0054CCF1 |. 8BC3 mov eax, ebx
0054CCF3 |. 33D2 xor edx, edx
0054CCF5 |. 52 push edx ; |format => NULL
0054CCF6 |. 50 push eax ; |s
0054CCF7 |. 8D45 FC lea eax, dword ptr [ebp-4] ; |
0054CCFA |. E8 D1C8EBFF call <sprintf> ; \sprintf 格式化为十进制数
0054CCFF |. 8B45 FC mov eax, dword ptr [ebp-4]
0054CD02 |. 0FB600 movzx eax, byte ptr [eax] ; 第一个数
0054CD05 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CD08 |. 0FB652 01 movzx edx, byte ptr [edx+1] ; 第2个数
0054CD0C |. 03C2 add eax, edx
0054CD0E |. B9 05000000 mov ecx, 5
0054CD13 |. 99 cdq
0054CD14 |. F7F9 idiv ecx ; 除5
0054CD16 |. 80C2 66 add dl, 66 ; 余数+66
0054CD19 |. 8855 F8 mov byte ptr [ebp-8], dl ; 保存第一个值。
0054CD1C |. 8B45 FC mov eax, dword ptr [ebp-4]
0054CD1F |. 0FB640 02 movzx eax, byte ptr [eax+2]
0054CD23 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CD26 |. 0FB652 03 movzx edx, byte ptr [edx+3]
0054CD2A |. 03C2 add eax, edx
0054CD2C |. B9 05000000 mov ecx, 5
0054CD31 |. 99 cdq
0054CD32 |. F7F9 idiv ecx
0054CD34 |. 80C2 75 add dl, 75
0054CD37 |. 8855 F9 mov byte ptr [ebp-7], dl ; 保存第2个值。
0054CD3A |. 8B45 FC mov eax, dword ptr [ebp-4]
0054CD3D |. 0FB640 04 movzx eax, byte ptr [eax+4]
0054CD41 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CD44 |. 0FB652 05 movzx edx, byte ptr [edx+5]
0054CD48 |. 03C2 add eax, edx
0054CD4A |. B9 05000000 mov ecx, 5
0054CD4F |. 99 cdq
0054CD50 |. F7F9 idiv ecx
0054CD52 |. 80C2 7A add dl, 7A
0054CD55 |. 8855 FA mov byte ptr [ebp-6], dl ; 保存第3个值。
0054CD58 |. 8B45 FC mov eax, dword ptr [ebp-4]
0054CD5B |. 0FB640 06 movzx eax, byte ptr [eax+6]
0054CD5F |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CD62 |. 0FB652 07 movzx edx, byte ptr [edx+7]
0054CD66 |. 03C2 add eax, edx
0054CD68 |. 8B55 FC mov edx, dword ptr [ebp-4]
0054CD6B |. 0FB652 08 movzx edx, byte ptr [edx+8]
0054CD6F |. 03C2 add eax, edx
0054CD71 |. B9 05000000 mov ecx, 5
0054CD76 |. 99 cdq
0054CD77 |. F7F9 idiv ecx
0054CD79 |. 80C2 69 add dl, 69
0054CD7C |. 8855 FB mov byte ptr [ebp-5], dl ; 保存第4个值。
0054CD7F |. 8D45 F4 lea eax, dword ptr [ebp-C]
0054CD82 |. 8A55 F8 mov dl, byte ptr [ebp-8]
0054CD85 |. E8 067EEBFF call <new_copy> ;这函数会先new一个空间,再把数值copy到新空间。
0054CD8A |. 8B45 F4 mov eax, dword ptr [ebp-C]
0054CD8D |. 8D55 FC lea edx, dword ptr [ebp-4]
0054CD90 |. B9 07000000 mov ecx, 7
0054CD95 |. E8 AE81EBFF call <strInsert> ; 这个就是字符串插入函数 7是要插入的位置
0054CD9A |. 8D45 F0 lea eax, dword ptr [ebp-10]
0054CD9D |. 8A55 FB mov dl, byte ptr [ebp-5]
0054CDA0 |. E8 EB7DEBFF call <new_copy> ;同上
0054CDA5 |. 8B45 F0 mov eax, dword ptr [ebp-10]
0054CDA8 |. 8D55 FC lea edx, dword ptr [ebp-4]
0054CDAB |. B9 03000000 mov ecx, 3
0054CDB0 |. E8 9381EBFF call <strInsert> ;同上
0054CDB5 |. 8D45 EC lea eax, dword ptr [ebp-14]
0054CDB8 |. 8A55 F9 mov dl, byte ptr [ebp-7]
0054CDBB |. E8 D07DEBFF call <new_copy> ;同上
0054CDC0 |. 8B45 EC mov eax, dword ptr [ebp-14]
0054CDC3 |. 8D55 FC lea edx, dword ptr [ebp-4]
0054CDC6 |. B9 05000000 mov ecx, 5
0054CDCB |. E8 7881EBFF call <strInsert> ;同上
0054CDD0 |. 8D45 E8 lea eax, dword ptr [ebp-18]
0054CDD3 |. 8A55 FA mov dl, byte ptr [ebp-6]
0054CDD6 |. E8 B57DEBFF call <new_copy> ;同上
0054CDDB |. 8B45 E8 mov eax, dword ptr [ebp-18]
0054CDDE |. 8D55 FC lea edx, dword ptr [ebp-4]
0054CDE1 |. B9 09000000 mov ecx, 9
0054CDE6 |. E8 5D81EBFF call <strInsert> ;同上
转换成C++代码为:
dwNum ^= 0xDDFB7687;
memset(szNum, 0, sizeof(szNum));
sprintf(szNum, "%lu", dwNum);
szTemp[0] = (*(szNum) + *(szNum+1))%5 + 0x66;
szTemp[1] = (*(szNum+2) + *(szNum+3))%5 + 0x75;
szTemp[2] = (*(szNum+4) + *(szNum+5))%5 + 0x7A;
szTemp[3] = (*(szNum+6) + *(szNum+7) + *(szNum+8))%5 + 0x69;
CString strTemp(szNum);
strTemp.Insert(7-1, szTemp[0]);
strTemp.Insert(3-1, szTemp[3]);
strTemp.Insert(5-1, szTemp[1]);
strTemp.Insert(9-1, szTemp[2]);
下面是注册的整体代码:
CString strOrderID;
GetDlgItemText(EDT_DDH, strOrderID); // 获取到定单号
char* pszOrderID = strOrderID.GetBuffer(0);
strOrderID.ReleaseBuffer();
DWORD dwNum = 0;
while (*pszOrderID != 0)
{
dwNum = dwNum*10;
dwNum += (*pszOrderID-0x30);
pszOrderID++;
}
CString strRegCode;
int nNum = 0;
nNum = dwNum%0x3A;
int n1, n2, nTemp;
n1 = nNum;
do
{
nTemp = n1;
n1 = n1/0x0A; // 商
n2 = nTemp%0x0A; // 余数
n2 += 0x30;
strRegCode.Insert(0, (char*)&n2);
} while (n1);
dwNum ^= 0x0B25F1;
char szNum[100] = {0};
sprintf(szNum, "%d", dwNum);
char szTemp[5] = {0};
szTemp[0] = (*(szNum) + *(szNum+1))%5 + 0x34;
szTemp[1] = (*(szNum+2) + *(szNum+3))%5 + 0x33;
strcat(szNum, szTemp);
char* pszNum = szNum;
dwNum = 0;
while (*pszNum != 0)
{
dwNum = dwNum*10;
dwNum += (*pszNum-0x30);
pszNum++;
}
dwNum ^= 0xDDFB7687;
memset(szNum, 0, sizeof(szNum));
sprintf(szNum, "%lu", dwNum);
szTemp[0] = (*(szNum) + *(szNum+1))%5 + 0x66;
szTemp[1] = (*(szNum+2) + *(szNum+3))%5 + 0x75;
szTemp[2] = (*(szNum+4) + *(szNum+5))%5 + 0x7A;
szTemp[3] = (*(szNum+6) + *(szNum+7) + *(szNum+8))%5 + 0x69;
CString strTemp(szNum);
strTemp.Insert(7-1, szTemp[0]);
strTemp.Insert(3-1, szTemp[3]);
strTemp.Insert(5-1, szTemp[1]);
strTemp.Insert(9-1, szTemp[2]);
strRegCode += strTemp;
SetDlgItemText(EDT_REGCODE, strRegCode); // 最终注册码。
------------------------------------------------------------------------
【破解总结】
------------------------------------------------------------------------
【版权声明】 |
评分
-
查看全部评分
|