【文章标题】: Crackme(C#编译,重启验证)(初级+) 算法简析
【文章作者】: hawking
【作者邮箱】: rich_hawking@hotmail.com
【作者主页】: inraining
【软件名称】: crackme1.exe
【软件大小】: 40.0k
【下载地址】: http://bbs.pediy.com/showthread.php?s=&threadid=32317&perpage=10&highlight=&pagenumber=1
【加壳方式】: MaxtoCode试用版
【保护方式】: 重启验证
【编写语言】: C#
【使用工具】: OD、PEiD
【操作平台】: 2k
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这个Crackme其实发布已经有一段时间了,不过一直运行不起来,所以就没加理会。现在发现之所以运行不起来,是因为用了MaxtoCode试用版加密的原因,因为是试用版,可能加了时间限制吧。Crackme发布没多久就过期了,所以打不开。调试的时候不得不将时间往前调了调(好像要在2006年10月以前)就OK了。
1 寻找关键代码
由于是C#程序,所以用Reflector打开看看。可惜由于用了MaxtoCode加过密了,所有的方法体都是空的。我们看看crackme程序本身,可以发现SoftWare\Crackme\No1\CrackmeInfo 及 UserName、Serial字样,并且程序本身是重启验证的,而我们随便输入用户名及密码之后程序所在的目录并没能生成新的文件,由此可初步判定验证信息是存放在注册表中的。
OD载入程序,下RegQueryValueExW断点(.net程序调用Win32API好像都是Unicode方式),并且对取到的UserName及Password值下硬件访问断点,就可以顺利跟踪到下面的关键代码段。
2 算法简析
039B5D23 55
push ebp
039B5D24 83EC 1C
sub esp, 1C
039B5D27 33C0
xor eax,
eax
039B5D29 894424 04
mov dword ptr [
esp+4],
eax
039B5D2D 33D2
xor edx,
edx
039B5D2F A1 D41EC401
mov eax,
dword ptr [1C41ED4]
;UserName 值取自HKEY_LOCAL_MACHINE\SOFTWARE\Crackme\No1\CrackmeInfo username
039B5D34 8378 08 00
cmp dword ptr [
eax+8], 0
039B5D38 0F8E 15020000
jle 039B5F53
039B5D3E A1 D01EC401
mov eax,
dword ptr [1C41ED0]
;Password 值取自HKEY_LOCAL_MACHINE\SOFTWARE\Crackme\No1\CrackmeInfo serial
039B5D43 8378 08 00
cmp dword ptr [
eax+8], 0
039B5D47 0F8E 06020000
jle 039B5F53
039B5D4D 8B1D 9830C401
mov ebx,
dword ptr [1C43098]
039B5D53 8B05 9C30C401
mov eax,
dword ptr [1C4309C]
039B5D59 894424 18
mov dword ptr [
esp+18],
eax
039B5D5D 33ED
xor ebp,
ebp
039B5D5F 8B0D D41EC401
mov ecx,
dword ptr [1C41ED4]
039B5D65 33D2
xor edx,
edx
039B5D67 8B71 08
mov esi,
dword ptr [
ecx+8]
039B5D6A 85F6
test esi,
esi
039B5D6C 7E 0C
jle short 039B5D7A
039B5D6E 0FB74451 0C
movzx eax,
word ptr [
ecx+
edx*2+C]
039B5D73 03E8
add ebp,
eax
039B5D75 42
inc edx
039B5D76 3BF2
cmp esi,
edx
039B5D78 ^ 7F F4
jg short 039B5D6E
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < sUserName.Length ; i++)
{
sumName += buffer[2*i] + buffer[2*i+1] * 0x100 ;
}
039B5D7A 8B3D 4030C401
mov edi,
dword ptr [1C43040]
039B5D80 33F6
xor esi,
esi
039B5D82 893424
mov dword ptr [
esp],
esi
039B5D85 03F5
add esi,
ebp
039B5D87 8B43 08
mov eax,
dword ptr [
ebx+8]
039B5D8A 3BC6
cmp eax,
esi
039B5D8C 7F 06
jg short 039B5D94
039B5D8E 2BF0
sub esi,
eax
039B5D90 3BC6
cmp eax,
esi
039B5D92 ^ 7E FA
jle short 039B5D8E
039B5D94 3B73 08
cmp esi,
dword ptr [
ebx+8]
039B5D97 0F83 C0010000
jnb 039B5F5D
039B5D9D 0FB74473 0C
movzx eax,
word ptr [
ebx+
esi*2+C]
;table1
039B5DA2 66:894424 04
mov word ptr [
esp+4],
ax
039B5DA7 0FB75424 04
movzx edx,
word ptr [
esp+4]
039B5DAC 6A 01
push 1
039B5DAE 33C9
xor ecx,
ecx
039B5DB0 E8 73DD4B76
call mscorwks.79E73B28
039B5DB5 8BD0
mov edx,
eax
039B5DB7 8BCF
mov ecx,
edi
039B5DB9 E8 F2DB72FF
call mscorlib.030E39B0
039B5DBE 8BF8
mov edi,
eax
039B5DC0 FF0424
inc dword ptr [
esp]
039B5DC3 833C24 14
cmp dword ptr [
esp], 14
039B5DC7 ^ 7C BC
jl short 039B5D85
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i++ )
{
temp = (sumName + temp) % table1.Length ;
result[i] = table1[temp] ;
}
039B5DC9 8B1D 4030C401
mov ebx,
dword ptr [1C43040]
039B5DCF 8B2D CC1EC401
mov ebp,
dword ptr [1C41ECC]
039B5DD5 8B45 08
mov eax,
dword ptr [
ebp+8]
039B5DD8 3B47 08
cmp eax,
dword ptr [
edi+8]
039B5DDB 7D 13
jge short 039B5DF0
039B5DDD 8BD5
mov edx,
ebp
039B5DDF 8BCD
mov ecx,
ebp
039B5DE1 E8 CADB72FF
call mscorlib.030E39B0
039B5DE6 8BE8
mov ebp,
eax
039B5DE8 8B45 08
mov eax,
dword ptr [
ebp+8]
039B5DEB 3B47 08
cmp eax,
dword ptr [
edi+8]
039B5DEE ^ 7C ED
jl short 039B5DDD
039B5DF0 33D2
xor edx,
edx
039B5DF2 895424 08
mov dword ptr [
esp+8],
edx
039B5DF6 837F 08 00
cmp dword ptr [
edi+8], 0
039B5DFA 7E 6D
jle short 039B5E69
039B5DFC 8B4424 18
mov eax,
dword ptr [
esp+18]
039B5E00 3940 08
cmp dword ptr [
eax+8],
eax
039B5E03 8B4424 08
mov eax,
dword ptr [
esp+8]
039B5E07 0FB74C47 0C
movzx ecx,
word ptr [
edi+
eax*2+C]
;result
039B5E0C 3B45 08
cmp eax,
dword ptr [
ebp+8]
039B5E0F 0F83 48010000
jnb 039B5F5D
039B5E15 0FB74445 0C
movzx eax,
word ptr [
ebp+
eax*2+C]
;table3
039B5E1A 0FAFC1
imul eax,
ecx
039B5E1D 8B5424 18
mov edx,
dword ptr [
esp+18]
039B5E21 8B4A 08
mov ecx,
dword ptr [
edx+8]
039B5E24 99
cdq
039B5E25 F7F9
idiv ecx
039B5E27 895424 0C
mov dword ptr [
esp+C],
edx
039B5E2B B9 FCBEE702
mov ecx, 2E7BEFC
039B5E30 E8 E7C1EEFC
call 008A201C
039B5E35 8BF0
mov esi,
eax
039B5E37 8B4424 0C
mov eax,
dword ptr [
esp+C]
039B5E3B 8B5424 18
mov edx,
dword ptr [
esp+18]
039B5E3F 3B42 08
cmp eax,
dword ptr [
edx+8]
039B5E42 0F83 15010000
jnb 039B5F5D
039B5E48 0FB75442 0C
movzx edx,
word ptr [
edx+
eax*2+C]
;table2
039B5E4D 66:8956 04
mov word ptr [
esi+4],
dx
039B5E51 8BD6
mov edx,
esi
039B5E53 8BCB
mov ecx,
ebx
039B5E55 E8 5EBA73FF
call mscorlib.030F18B8
039B5E5A 8BD8
mov ebx,
eax
039B5E5C FF4424 08
inc dword ptr [
esp+8]
039B5E60 8B47 08
mov eax,
dword ptr [
edi+8]
039B5E63 3B4424 08
cmp eax,
dword ptr [
esp+8]
039B5E67 ^ 7F 9A
jg short 039B5E03
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i++ )
{
temp = (table3[i] * result[i]) % table2.Length ;
result[i] = table2[temp];
}
039B5E69 8B2D 4030C401
mov ebp,
dword ptr [1C43040]
039B5E6F 8B3D D41EC401
mov edi,
dword ptr [1C41ED4]
039B5E75 8B47 08
mov eax,
dword ptr [
edi+8]
039B5E78 3B43 08
cmp eax,
dword ptr [
ebx+8]
039B5E7B 7D 13
jge short 039B5E90
039B5E7D 8BD7
mov edx,
edi
039B5E7F 8BCF
mov ecx,
edi
039B5E81 E8 2ADB72FF
call mscorlib.030E39B0
039B5E86 8BF8
mov edi,
eax
039B5E88 8B47 08
mov eax,
dword ptr [
edi+8]
039B5E8B 3B43 08
cmp eax,
dword ptr [
ebx+8]
039B5E8E ^ 7C ED
jl short 039B5E7D
[color=#0000D0]while[/color] ( sUserName.Length < 0x14 )
{
sUserName += sUserName ;
}
039B5E90 33D2
xor edx,
edx
039B5E92 895424 10
mov dword ptr [
esp+10],
edx
039B5E96 837B 08 00
cmp dword ptr [
ebx+8], 0
039B5E9A 7E 69
jle short 039B5F05
039B5E9C 8B4424 18
mov eax,
dword ptr [
esp+18]
039B5EA0 3940 08
cmp dword ptr [
eax+8],
eax
039B5EA3 8B4424 10
mov eax,
dword ptr [
esp+10]
039B5EA7 0FB74C43 0C
movzx ecx,
word ptr [
ebx+
eax*2+C]
;result
039B5EAC 3B47 08
cmp eax,
dword ptr [
edi+8]
039B5EAF 0F83 A8000000
jnb 039B5F5D
039B5EB5 0FB74447 0C
movzx eax,
word ptr [
edi+
eax*2+C]
;处理后UserName
039B5EBA 0FAFC1
imul eax,
ecx
039B5EBD 8B5424 18
mov edx,
dword ptr [
esp+18]
039B5EC1 8B4A 08
mov ecx,
dword ptr [
edx+8]
039B5EC4 99
cdq
039B5EC5 F7F9
idiv ecx
039B5EC7 895424 14
mov dword ptr [
esp+14],
edx
039B5ECB B9 FCBEE702
mov ecx, 2E7BEFC
039B5ED0 E8 47C1EEFC
call 008A201C
039B5ED5 8BF0
mov esi,
eax
039B5ED7 8B4424 14
mov eax,
dword ptr [
esp+14]
039B5EDB 8B5424 18
mov edx,
dword ptr [
esp+18]
039B5EDF 3B42 08
cmp eax,
dword ptr [
edx+8]
039B5EE2 73 79
jnb short 039B5F5D
039B5EE4 0FB75442 0C
movzx edx,
word ptr [
edx+
eax*2+C]
;table2
039B5EE9 66:8956 04
mov word ptr [
esi+4],
dx
039B5EED 8BD6
mov edx,
esi
039B5EEF 8BCD
mov ecx,
ebp
039B5EF1 E8 C2B973FF
call mscorlib.030F18B8
039B5EF6 8BE8
mov ebp,
eax
039B5EF8 FF4424 10
inc dword ptr [
esp+10]
039B5EFC 8B43 08
mov eax,
dword ptr [
ebx+8]
039B5EFF 3B4424 10
cmp eax,
dword ptr [
esp+10]
039B5F03 ^ 7F 9E
jg short 039B5EA3
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i++ )
{
temp = (sUserName.ToCharArray()[i] * result[i] ) % table2.Length ;
result[i] = table2[temp];
}
039B5F05 8B3D 4030C401
mov edi,
dword ptr [1C43040]
039B5F0B 33F6
xor esi,
esi
039B5F0D 3945 00
cmp dword ptr [
ebp],
eax
039B5F10 6A 05
push 5
039B5F12 6A 00
push 0
039B5F14 8D14B6
lea edx,
dword ptr [
esi+
esi*4]
039B5F17 8BCD
mov ecx,
ebp
039B5F19 E8 E24F71FF
call mscorlib.030CAF00
039B5F1E 8BD0
mov edx,
eax
039B5F20 8BCF
mov ecx,
edi
039B5F22 E8 89DA72FF
call mscorlib.030E39B0
039B5F27 8BF8
mov edi,
eax
039B5F29 83FE 03
cmp esi, 3
039B5F2C 7D 0F
jge short 039B5F3D
039B5F2E 8B15 A030C401
mov edx,
dword ptr [1C430A0]
039B5F34 8BCF
mov ecx,
edi
039B5F36 E8 75DA72FF
call mscorlib.030E39B0
039B5F3B 8BF8
mov edi,
eax
039B5F3D 46
inc esi
039B5F3E 83FE 04
cmp esi, 4
039B5F41 ^ 7C CA
jl short 039B5F0D
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i = i + 5 )
{
sPassword += System.Text.Encoding.Default.GetString(result,i,5);
sPassword += [color=#808080]"-"[/color];
}
sPassword = sPassword.TrimEnd('-');
039B5F43 8B15 D01EC401
mov edx,
dword ptr [1C41ED0]
039B5F49 8BCF
mov ecx,
edi
039B5F4B E8 A05971FF
call mscorlib.030CB8F0
;真假密码比较
039B5F50 0FB6D0
movzx edx,
al
039B5F53 8BC2
mov eax,
edx
039B5F55 83C4 1C
add esp, 1C
039B5F58 5D
pop ebp
039B5F59 5B
pop ebx
039B5F5A 5E
pop esi
039B5F5B 5F
pop edi
039B5F5C C3
retn
返回到这一段代码
039B5C75 0000
add byte ptr [
eax],
al
039B5C77 007423 AD
add byte ptr [
ebx-53],
dh
039B5C7B 0300
add eax,
dword ptr [
eax]
039B5C7D 0000
add byte ptr [
eax],
al
039B5C7F 0098 23AD03C8
add byte ptr [
eax+C803AD23],
bl
039B5C85 5B
pop ebx
039B5C86 8B00
mov eax,
dword ptr [
eax]
039B5C88 56
push esi
039B5C89 8BF1
mov esi,
ecx
039B5C8B FF15 84308B00
call dword ptr [8B3084]
;从这里返回
039B5C91 85C0
test eax,
eax
039B5C93 74 4E
je short 039B5CE3
;想爆破的看过来
039B5C95 8B0D 9030C401
mov ecx,
dword ptr [1C43090]
039B5C9B 8B15 D41EC401
mov edx,
dword ptr [1C41ED4]
039B5CA1 E8 0ADD72FF
call mscorlib.030E39B0
039B5CA6 8BD0
mov edx,
eax
039B5CA8 8BCE
mov ecx,
esi
039B5CAA 8B01
mov eax,
dword ptr [
ecx]
039B5CAC FF90 68010000
call dword ptr [
eax+168]
039B5CB2 8B8E 40010000
mov ecx,
dword ptr [
esi+140]
039B5CB8 33D2
xor edx,
edx
039B5CBA 3909
cmp dword ptr [
ecx],
ecx
039B5CBC E8 CFDEC977
call System_W.7B653B90
039B5CC1 8B8E 44010000
mov ecx,
dword ptr [
esi+144]
039B5CC7 33D2
xor edx,
edx
039B5CC9 3909
cmp dword ptr [
ecx],
ecx
039B5CCB E8 C0DEC977
call System_W.7B653B90
039B5CD0 8B8E 50010000
mov ecx,
dword ptr [
esi+150]
039B5CD6 33D2
xor edx,
edx
039B5CD8 3909
cmp dword ptr [
ecx],
ecx
039B5CDA E8 B1DEC977
call System_W.7B653B90
039B5CDF 5E
pop esi
039B5CE0 C2 0400
retn 4
039B5CE3 8BCE
mov ecx,
esi
039B5CE5 8B01
mov eax,
dword ptr [
ecx]
039B5CE7 FF90 64010000
call dword ptr [
eax+164]
039B5CED 8BC8
mov ecx,
eax
039B5CEF 8B15 9430C401
mov edx,
dword ptr [1C43094]
039B5CF5 E8 B6DC72FF
call mscorlib.030E39B0
039B5CFA 8BD0
mov edx,
eax
039B5CFC 8BCE
mov ecx,
esi
039B5CFE 8B01
mov eax,
dword ptr [
ecx]
039B5D00 FF90 68010000
call dword ptr [
eax+168]
039B5D06 5E
pop esi
039B5D07 C2 0400
retn 4
3 注册机(见附件)
byte[] table1 = System.Text.Encoding.Default.GetBytes([color=#808080]"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[/color]);
byte[] table2 = System.Text.Encoding.Default.GetBytes([color=#808080]"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[/color]);
byte[] table3 = System.Text.Encoding.Default.GetBytes([color=#808080]"13141598-5460-5421-1314-INRAINING520"[/color]);
byte[] buffer = System.Text.Encoding.Unicode.GetBytes(tUserName.Text);
byte[] result = [color=#0000D0]new[/color] byte[0x14];
[color=#0000D0]string[/color] sUserName = tUserName.Text;
[color=#0000D0]string[/color] sPassword = [color=#0000D0]string[/color].Empty;
[color=#0000D0]int[/color] sumName = 0 ;
[color=#0000D0]int[/color] temp = 0 ;
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < sUserName.Length ; i++)
{
sumName += buffer[2*i] + buffer[2*i+1] * 0x100 ;
}
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i++ )
{
temp = (sumName + temp) % table1.Length ;
result[i] = table1[temp] ;
}
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i++ )
{
temp = (table3[i] * result[i]) % table2.Length ;
result[i] = table2[temp];
}
[color=#0000D0]while[/color] ( sUserName.Length < 0x14 )
{
sUserName += sUserName ;
}
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i++ )
{
temp = (sUserName.ToCharArray()[i] * result[i] ) % table2.Length ;
result[i] = table2[temp];
}
[color=#0000D0]for[/color] ( [color=#0000D0]int[/color] i = 0 ; i < 0x14 ; i = i + 5 )
{
sPassword += System.Text.Encoding.Default.GetString(result,i,5);
sPassword += [color=#808080]"-"[/color];
}
[color=#0000D0]this[/color].tPassword.Text = sPassword.TrimEnd('-');
--------------------------------------------------------------------------------
【经验总结】
.Net程序使用Microsoft CLR调试器调试的话,可以直接调试IL代码,而不用像OD中调试本地代码这样不断地在mscorwks、
mscorlib等空间跳来跳去的,很不直观。可惜我不知道如何下断,以前调试了几个.Net程序,都是通过异常下断的,这个程
序好像没什么异常,断不下来,就不知道如何用Microsoft CLR调试器调试了。如果DRT(DST)的兄弟路过的话,还请不吝
赐教。
PEBrowse也可以动态调试.Net程序,可惜一直水土不服,不会用。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年03月02日 21:03:01
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课