-
-
[原创]是男人就上120层 破解
-
发表于:
2007-4-25 09:41
8537
-
【文章标题】: 是男人就上120层 破解
【文章作者】: Nukou.G
【软件名称】: 是男人就上120层
【软件大小】: 480K
【下载地址】: 黑客X档案4月份附书光盘中
【加壳方式】: 无
【保护方式】: 序列号
【编写语言】: VC4.0
【使用工具】: OllyDBG
【操作平台】: WinXP
【软件介绍】: 这个游戏没玩过也该听过吧
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
当输入的注册码不正确时弹出一个对话框提示错误。在MessageBoxA上下断点,输入注册码
会断在这里:
00402FE1 . 8D85 FCFDFFFF lea eax, dword ptr [ebp-204]
00402FE7 . 50 push eax
00402FE8 . E8 C0010000 call 004031AD ; 验证注册码的函数
00402FED . 83C4 04 add esp, 4
00402FF0 . 85C0 test eax, eax
00402FF2 . 0F85 37000000 jnz 0040302F
00402FF8 . 68 00010000 push 100 ; /Count = 100 (256.)
00402FFD . 8D85 FCFEFFFF lea eax, dword ptr [ebp-104] ; |
00403003 . 50 push eax ; |Buffer
00403004 . 6A 04 push 4 ; |RsrcID = STRING "Registration number is incorrect."
00403006 . A1 98D24000 mov eax, dword ptr [40D298] ; |
0040300B . 50 push eax ; |hInst => NULL
0040300C . FF15 BCF34000 call dword ptr [<&USER32.LoadStringA>] ; \LoadStringA
00403012 . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00403014 . 68 6CC24000 push 0040C26C ; |Title = "NS-TOWER"
00403019 . 8D85 FCFEFFFF lea eax, dword ptr [ebp-104] ; |
0040301F . 50 push eax ; |Text
00403020 . 8B45 08 mov eax, dword ptr [ebp+8] ; |
00403023 . 50 push eax ; |hOwner
00403024 . FF15 B8F34000 call dword ptr [<&USER32.MessageBoxA>] ; \MessageBoxA
可见004031AD就是验证注册码的函数了
来到004031AD 处:
004031AD $ 55 push ebp
004031AE . 8BEC mov ebp, esp
004031B0 . 83EC 04 sub esp, 4
004031B3 . 53 push ebx
004031B4 . 56 push esi
004031B5 . 57 push edi
004031B6 . 8B45 08 mov eax, dword ptr [ebp+8]
004031B9 . 33C9 xor ecx, ecx
004031BB . 8A48 07 mov cl, byte ptr [eax+7] ; 注册码的长度要小于8
004031BE . 85C9 test ecx, ecx
004031C0 . 0F84 07000000 je 004031CD
.......
00403315 . C9 leave
00403316 . C3 retn
中间的汇编代码略去,该段代码等价于:
{
...
int i = 0;
while(i < 0x7)
{
if (fun(serial[i]) > 24)
{
return(0);
}
i++;
}
if ((( fun(serial[5])*2 + fun(serial[2]) + 0x1C) % 0x24) == fun(serial[0]))
{
if ((( fun(serial[4])*2 + fun(serial[1])+ 0x1C) % 0x24) == fun(serial[6]))
{
if ((( fun(serial[6])*2 + fun(serial[0]) + 0x1C) % 0x24) == fun(serial[3]))
{
return(1);
}
}
}
return(0);
}
其中fun()函数是00403317处的函数,其代码等价于:
char fun(char key)
{
if (key >= 0x61)
{
key -= 0x20;
}
else if (key >= 0x41)
{
key -= 0x7;
}
key -= 0x30;
return(key);
}
一切都很明显了。
==========
注册机编写
当然是穷举,不过在这之前仔细观察一下3个条件:
(( fun(serial[5])*2 + fun(serial[2]) + 0x1C) % 0x24) == fun(serial[0])
(( fun(serial[4])*2 + fun(serial[1])+ 0x1C) % 0x24) == fun(serial[6])
(( fun(serial[6])*2 + fun(serial[0]) + 0x1C) % 0x24) == fun(serial[3])
看出来了吧?serial[6]和serial[0]是两个关键位,先确定这两个位,剩下的就简单了:
#include <stdio.h>
#include <stdlib.h>
char defun(char key)
{
key += 0x30;
if (key >= 0x41-0x7)
{
key += 0x7;
}
else if (key >= 0x61-0x20)
{
key += 0x20;
}
return(key);
}
void main()
{
char serial[7];
int i;
serial[5] = 0;
serial[4] = 0;
for (serial[6] = 0; serial[6] < 0x24; serial[6]++)
{
for (serial[0] = 0; serial[0] < 0x24; serial[0]++)
{
serial[3] = ((serial[6]*2 + serial[0])+ 0x1C) % 0x24;
for (serial[2] = 0; serial[2] < 0x24; serial[2]++)
{
if (serial[6] == (serial[2]+ 0x1C) % 0x24)
for (serial[1] = 0; serial[1] < 0x24; serial[1]++)
{
if (serial[4] == (serial[1]+ 0x1C) % 0x24)
{
for (i = 0; i < 7; i++)
{
serial[i] = defun(serial[i]);
printf("%c", serial[i]);
}
system("pause");
printf("\n");
}
}
}
}
}
}
--------------------------------------------------------------------------------
【经验总结】
以前没耐心看汇编代码,很少能独立解决一个软件。经过一段时间的锻炼,阅读汇编不是那么痛苦的事情了,能独立解决的
问题也多了起来了。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年04月25日 9:37:12
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!