-
-
[原创]对一个crackme详细分析
-
发表于: 2010-11-6 17:42 6048
-
标 题: 【原创】我也来谈谈消息断点二(有新内容)
作 者: icefisher
时 间: 2008-08-13,13:30:52
链 接: http://bbs.pediy.com/showthread.php?t=70619
本文对 【原创】我也来谈谈消息断点二(有新内容) 这篇贴子中的crackme进行了后续的分析...
附件请看原贴.....
书接上文,上文中icefisher已经带我们领略了下消息断点的魅力,理解了消息断点后,我简单分析了下程序算法。。。。与众人分享一下...
004015A1 /. 55 push ebp ; 处理函数
004015A2 |. 89E5 mov ebp,esp
004015A4 |. 83EC 3C sub esp,0x3C
004015A7 |. 53 push ebx
004015A8 |. 56 push esi
004015A9 |. 57 push edi
004015AA |. 8B45 0C mov eax,[arg.2]
004015AD |. 83F8 10 cmp eax,0x10 ; Switch (cases 10..111)
004015B0 |. 0F84 BB000000 je unpacked.00401671
004015B6 |. 0F8C C4000000 jl unpacked.00401680
004015BC |. 3D 10010000 cmp eax,0x110
004015C1 |. 74 0C je short unpacked.004015CF
004015C3 |. 3D 11010000 cmp eax,0x111
004015C8 |. 74 1E je short unpacked.004015E8 ; 根据上面下的条件断点,这里应该跳了
004015CA |. E9 B1000000 jmp unpacked.00401680
004015CF |> FF75 14 push [arg.4] ; Case 110 (WM_INITDIALOG) of switch 004015AD
004015D2 |. FF75 10 push [arg.3]
004015D5 |. FF75 08 push [arg.1]
004015D8 |. E8 C0FFFFFF call unpacked.0040159D
004015DD |. 83C4 0C add esp,0xC
004015E0 |. 31C0 xor eax,eax
004015E2 |. 40 inc eax
004015E3 |. E9 9A000000 jmp unpacked.00401682
004015E8 |> 0FB745 10 movzx eax,word ptr ss:[ebp+0x10] ; Case 111 (WM_COMMAND) of switch 004015AD
004015EC |. 25 FFFF0000 and eax,0xFFFF
004015F1 |. 83F8 01 cmp eax,0x1 ; Switch (cases 1..3)
004015F4 |. 74 0C je short unpacked.00401602 ; 同样根据上面下的条件断点,这里应该跳了
004015F6 |. 83F8 02 cmp eax,0x2
004015F9 |. 74 6A je short unpacked.00401665
004015FB |. 83F8 03 cmp eax,0x3
004015FE |. 74 43 je short unpacked.00401643
00401600 |. EB 7E jmp short unpacked.00401680
00401602 |> 8D7D D3 lea edi,dword ptr ss:[ebp-0x2D] ; Case 1 of switch 004015F1
00401605 |. 8D35 5E254000 lea esi,dword ptr ds:[0x40255E] ; 这里是check按钮的处理
0040160B |. B9 29000000 mov ecx,0x29
00401610 |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi] ; 将一些注册成功的提示文字复制到相应的内存中
00401612 |. 8D7D C7 lea edi,dword ptr ss:[ebp-0x39]
00401615 |. 8D35 87254000 lea esi,dword ptr ds:[0x402587]
0040161B |. B9 03000000 mov ecx,0x3
00401620 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi] ; 这也是复制注册成功的提示文字
00401622 |. FF75 08 push [arg.1]
00401625 |. E8 DFFEFFFF call unpacked.00401509 ; 这是关键CALL,
0040162A |. 59 pop ecx
0040162B |. 09C0 or eax,eax
0040162D |. 74 53 je short unpacked.00401682 ; 上面的CALL返回的是0的话就跳走,失败了。。如果上面CALL返回不为0,下面的MessageBoxA就弹出成功的对话框了..
0040162F |. 6A 40 push 0x40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401631 |. 8D45 C7 lea eax,dword ptr ss:[ebp-0x39] ; |
00401634 |. 50 push eax ; |Title
00401635 |. 8D45 D3 lea eax,dword ptr ss:[ebp-0x2D] ; |
00401638 |. 50 push eax ; |Text
00401639 |. FF75 08 push [arg.1] ; |hOwner
0040163C |. E8 1B010000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401641 |. EB 3D jmp short unpacked.00401680
----------------------------------------------------------------------------------
进入00401625 位置处的关键CALL:
00401509 /$ 55 push ebp
0040150A |. 89E5 mov ebp,esp
0040150C |. 81EC 00010000 sub esp,0x100
00401512 |. 53 push ebx
00401513 |. 56 push esi
00401514 |. 57 push edi
00401515 |. 8DBD 00FFFFFF lea edi,[local.64]
0040151B |. 8D35 5E244000 lea esi,dword ptr ds:[0x40245E]
00401521 |. B9 40000000 mov ecx,0x40
00401526 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]
00401528 |. 68 00010000 push 0x100 ; /Count = 100 (256.)
0040152D |. 8D85 00FFFFFF lea eax,[local.64] ; |
00401533 |. 50 push eax ; |Buffer
00401534 |. 6A 65 push 0x65 ; |ControlID = 65 (101.)
00401536 |. FF75 08 push [arg.1] ; |hWnd
00401539 |. E8 FA010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
0040153E |. 89C3 mov ebx,eax ; 得到用户名
00401540 |. 09DB or ebx,ebx ; (Initial CPU selection)
00401542 |. 75 04 jnz short unpacked.00401548 ; 用户名长度不能为0,否则跳向失败
00401544 |. 31C0 xor eax,eax
00401546 |. EB 50 jmp short unpacked.00401598
00401548 |> BF BC020000 mov edi,0x2BC ; 下面进行一系列运算
0040154D |. BE 30000000 mov esi,0x30
00401552 |. B8 48000000 mov eax,0x48
00401557 |. 99 cdq
00401558 |. F7FB idiv ebx
0040155A |. 29C6 sub esi,eax
0040155C |. 8D34B6 lea esi,dword ptr ds:[esi+esi*4]
0040155F |. 29F7 sub edi,esi
00401561 |. 6BFF 6B imul edi,edi,0x6B
00401564 |. 81EF 6CCF0000 sub edi,0xCF6C
0040156A |. 81FF 00230000 cmp edi,0x2300
00401570 |. 7F 08 jg short unpacked.0040157A ; edi的值介于190和2300之间,才通往成功。。否则,失败
00401572 |. 81FF 90010000 cmp edi,0x190
00401578 |. 7D 04 jge short unpacked.0040157E
0040157A |> 31C0 xor eax,eax
0040157C |. EB 1A jmp short unpacked.00401598
0040157E |> 8D85 00FFFFFF lea eax,[local.64]
00401584 |. 50 push eax ; name
00401585 |. 53 push ebx ; nameLength
00401586 |. FF75 08 push [arg.1] ; 0016034A
00401589 |. E8 77FDFFFF call unpacked.00401305
0040158E |. 83C4 0C add esp,0xC
00401591 |. 09C0 or eax,eax
00401593 |. 74 03 je short unpacked.00401598
00401595 |. 31C0 xor eax,eax
00401597 |. 40 inc eax
00401598 |> 5F pop edi
00401599 |. 5E pop esi
0040159A |. 5B pop ebx
0040159B |. C9 leave
0040159C \. C3 retn
此处计算edi的值的算法如下:
char name[256];
int nNameLength = GetDlgItemTextA(hDlg,101,&name,256);
if(nNameLength)
{
int edi;
edi = 0x6B * (0x2BC - 5 * (0x30 - 0x48u / nNameLength)) - 0xCF6C;
if ( edi <= 0x2300 && edi >= 0x190 )
{
;通过第一关,通往成功之路进行后续验证
;call unpacked.00401305
}
else
{
;失败
}
}
else
{
;失败
}
在00401589处调用call unpacked.00401305,此处为关键,进入分析
**********************************************************************************
从上面传递进来的参数可以看出,这个函数接收3个参数,分别为:hDlg,nNameLength,name;
其中: hDlg为窗口句柄
nNameLength为输入的用户名的长度
name为输入的用户名的地址
00401305 /$ 55 push ebp
00401306 |. 89E5 mov ebp,esp
00401308 |. 81EC 2C040000 sub esp,0x42C
0040130E |. 53 push ebx
0040130F |. 56 push esi
00401310 |. 57 push edi
00401311 |. 8DBD FCFEFFFF lea edi,[local.65]
00401317 |. 8D35 38204000 lea esi,dword ptr ds:[0x402038]
0040131D |. B9 40000000 mov ecx,0x40
00401322 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds>; 把edi开始的40大小位置初始化为0
00401324 |. 8DBD E1FBFFFF lea edi,dword ptr ss:[ebp-0x41F]
0040132A |. 8D35 38214000 lea esi,dword ptr ds:[0x402138]
00401330 |. B9 40000000 mov ecx,0x40
00401335 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds>; 把edi开始的40大小位置初始化为0
00401337 |. 8DBD E1FDFFFF lea edi,dword ptr ss:[ebp-0x21F]
0040133D |. 8D35 38224000 lea esi,dword ptr ds:[0x402238]
00401343 |. B9 40000000 mov ecx,0x40
00401348 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds>; 也是初始化为0
0040134A |. 8DBD E1FCFFFF lea edi,dword ptr ss:[ebp-0x31F]
00401350 |. 8D35 38234000 lea esi,dword ptr ds:[0x402338]
00401356 |. B9 40000000 mov ecx,0x40
0040135B |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds>; 还是初始化为0
0040135D |. 8DBD DCFBFFFF lea edi,[local.265]
00401363 |. 8D35 38244000 lea esi,dword ptr ds:[0x402438]
00401369 |. B9 05000000 mov ecx,0x5
0040136E |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[>; 把%c%s拷贝到edi中,以后格式化时用到
00401370 |. 8DBD D6FBFFFF lea edi,dword ptr ss:[ebp-0x42A]
00401376 |. 8D35 3D244000 lea esi,dword ptr ds:[0x40243D]
0040137C |. B9 03000000 mov ecx,0x3
00401381 |. F3:66:A5 rep movs word ptr es:[edi],word ptr ds:[>; 也是拷贝以后用到的格式化字符串
00401384 |. 8DBD E1FEFFFF lea edi,dword ptr ss:[ebp-0x11F]
0040138A |. 8D35 43244000 lea esi,dword ptr ds:[0x402443]
00401390 |. B9 1B000000 mov ecx,0x1B
00401395 |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[>; 拷贝table数据到edi中,算法中使用了这张表
00401397 |. C745 FC 00000>mov [local.1],0x0
0040139E |. 68 00010000 push 0x100 ; /Count = 100 (256.)
004013A3 |. 8D85 E1FCFFFF lea eax,dword ptr ss:[ebp-0x31F] ; |
004013A9 |. 50 push eax ; |Buffer
004013AA |. 6A 66 push 0x66 ; |ControlID = 66 (102.)
004013AC |. FF75 08 push [arg.1] ; |hWnd
004013AF |. E8 84030000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004013B4 |. 09C0 or eax,eax ; 得到注册码
004013B6 |. 0F84 48010000 je unpacked.00401504 ; 注册码长度不为0
004013BC |. B8 CF110000 mov eax,0x11CF
004013C1 |. 0FB68D E1FCFF>movzx ecx,byte ptr ss:[ebp-0x31F] ; ecx=code
004013C8 |. 99 cdq
004013C9 |. F7F9 idiv ecx ; edx=0xFFCF%code[0]
004013CB |. 83FA 17 cmp edx,0x17 ; 必须为17,否则失败
004013CE 74 07 je short unpacked.004013D7
004013D0 31C0 xor eax,eax
004013D2 E9 2D010000 jmp unpacked.00401504
004013D7 |> 31DB xor ebx,ebx
004013D9 |. EB 0B jmp short unpacked.004013E6
004013DB |> 8B45 10 /mov eax,[arg.3] ; 循环,取出用户名ASCII和,放在local.1中
004013DE |. 0FBE0418 |movsx eax,byte ptr ds:[eax+ebx]
004013E2 |. 0145 FC |add [local.1],eax
004013E5 |. 43 |inc ebx
004013E6 |> 3B5D 0C cmp ebx,[arg.2]
004013E9 |.^ 7C F0 \jl short unpacked.004013DB
004013EB |. 31DB xor ebx,ebx
004013ED |. E9 83000000 jmp unpacked.00401475
004013F2 |> 8B55 10 /mov edx,[arg.3] ; 此处又是一个运算过程
004013F5 |. 0FBE3C1A |movsx edi,byte ptr ds:[edx+ebx]
004013F9 |. 8B75 FC |mov esi,[local.1]
004013FC |. 89D9 |mov ecx,ebx
004013FE |. C1E1 02 |shl ecx,0x2
00401401 |. 89DA |mov edx,ebx
00401403 |. 42 |inc edx
00401404 |. 29D1 |sub ecx,edx
00401406 |. 0FB68C0D E1FE>|movzx ecx,byte ptr ss:[ebp+ecx-0x11F]
0040140E |. 89FA |mov edx,edi
00401410 |. 31CA |xor edx,ecx
00401412 |. 89F1 |mov ecx,esi
00401414 |. 0FAFCB |imul ecx,ebx
00401417 |. 29F1 |sub ecx,esi
00401419 |. 89CE |mov esi,ecx
0040141B |. 83F6 FF |xor esi,-0x1
0040141E |. 8DB432 4D0100>|lea esi,dword ptr ds:[edx+esi+0x14D]
00401425 |. 8B4D 0C |mov ecx,[arg.2]
00401428 |. 89DA |mov edx,ebx
0040142A |. 83C2 03 |add edx,0x3
0040142D |. 0FAFCA |imul ecx,edx
00401430 |. 0FAFCF |imul ecx,edi
00401433 |. 89F0 |mov eax,esi
00401435 |. 01C8 |add eax,ecx
00401437 |. B9 0A000000 |mov ecx,0xA
0040143C |. 31D2 |xor edx,edx
0040143E |. F7F1 |div ecx
00401440 |. 83C2 30 |add edx,0x30
00401443 |. 88941D FCFEFF>|mov byte ptr ss:[ebp+ebx-0x104],dl
0040144A |. 0FB6BC1D FCFE>|movzx edi,byte ptr ss:[ebp+ebx-0x104]
00401452 |. 81F7 ACAD0000 |xor edi,0xADAC
00401458 |. 89DE |mov esi,ebx
0040145A |. 83C6 02 |add esi,0x2
0040145D |. 89F8 |mov eax,edi
0040145F |. 0FAFC6 |imul eax,esi
00401462 |. B9 0A000000 |mov ecx,0xA
00401467 |. 99 |cdq
00401468 |. F7F9 |idiv ecx
0040146A |. 83C2 30 |add edx,0x30
0040146D |. 88941D FCFEFF>|mov byte ptr ss:[ebp+ebx-0x104],dl
00401474 |. 43 |inc ebx
00401475 |> 3B5D 0C cmp ebx,[arg.2]
00401478 |.^ 0F8C 74FFFFFF \jl unpacked.004013F2
0040147E |. 8D85 FCFEFFFF lea eax,[local.65]
00401484 |. 50 push eax
00401485 |. 6A 54 push 0x54
00401487 |. 8D85 DCFBFFFF lea eax,[local.265]
0040148D |. 50 push eax ; |Format
0040148E |. 8D85 E1FBFFFF lea eax,dword ptr ss:[ebp-0x41F] ; |
00401494 |. 50 push eax ; |s
00401495 |. E8 CE020000 call <jmp.&USER32.wsprintfA> ; \wsprintfA
0040149A |. 8B7D 0C mov edi,[arg.2]
0040149D |. 89F8 mov eax,edi
0040149F |. 0FAF45 FC imul eax,[local.1]
004014A3 |. B9 64000000 mov ecx,0x64
004014A8 |. 99 cdq
004014A9 |. F7F9 idiv ecx
004014AB |. 89D7 mov edi,edx
004014AD |. 83C7 30 add edi,0x30
004014B0 |. 57 push edi
004014B1 |. 8DBD E1FBFFFF lea edi,dword ptr ss:[ebp-0x41F]
004014B7 |. 57 push edi
004014B8 |. 8DBD D6FBFFFF lea edi,dword ptr ss:[ebp-0x42A]
004014BE |. 57 push edi ; |Format
004014BF |. 8DBD E1FDFFFF lea edi,dword ptr ss:[ebp-0x21F] ; |
004014C5 |. 57 push edi ; |s
004014C6 |. E8 9D020000 call <jmp.&USER32.wsprintfA> ; \wsprintfA
004014CB |. 83C4 20 add esp,0x20
004014CE |. 8D8D E1FDFFFF lea ecx,dword ptr ss:[ebp-0x21F]
004014D4 |. 83C8 FF or eax,-0x1
004014D7 |> 40 /inc eax
004014D8 |. 803C01 00 |cmp byte ptr ds:[ecx+eax],0x0
004014DC |.^ 75 F9 \jnz short unpacked.004014D7
004014DE |. 50 push eax
004014DF |. 8D85 E1FCFFFF lea eax,dword ptr ss:[ebp-0x31F]
004014E5 |. 50 push eax
004014E6 |. 8D85 E1FDFFFF lea eax,dword ptr ss:[ebp-0x21F]
004014EC |. 50 push eax
004014ED |. E8 D0FDFFFF call unpacked.004012C2
004014F2 |. 83C4 0C add esp,0xC
004014F5 |. 83F8 00 cmp eax,0x0
004014F8 |. 75 07 jnz short unpacked.00401501 ; 必须跳
004014FA |. B8 00000000 mov eax,0x0 ; 失败
004014FF |. EB 03 jmp short unpacked.00401504
00401501 |> 31C0 xor eax,eax
00401503 |. 40 inc eax
00401504 |> 5F pop edi
00401505 |. 5E pop esi
00401506 |. 5B pop ebx
00401507 |. C9 leave
00401508 \. C3 retn
循环计算name,ASCII和的算法如下:
int i = 0;
while ( v7 < nNameLength )
nameSum += *(_BYTE *)(name + i++);
计算中间注册码的算法如下:
i = 0;
while ( i < nLength )
{
tempResult[i] = (unsigned __int8)(*(_BYTE *)(name + i) * ((_BYTE)i + 3) * (_BYTE)nLength
+ (table[4 * i - (i + 1)] ^ *(_BYTE *)(name + i))
+ ~((_BYTE)i * (_BYTE)nameSum - (_BYTE)nameSum)
+ 0x4D)
% 0xAu
+ 0x30;
tempResult[i] = (i + 2) * (tempResult[i] ^ 0xADAC) % (signed int)0xAu + 0x30;
++i;
}
生成的中间注册码如上图
然后两次调用wsprintf进行格式化,第一次格式化所用参数如下图所示..
wsprintfa(&v11,"%c%s",'T',v10)
第二次调用的参数为:同样,有图为证,呵呵~
wsprintfa(v12,"%s-%d",tempResult,(nameSum*nLength)%100+48)
下面开始计算生成的中间注册码的长度:
004014CB |. 83C4 20 add esp,0x20
004014CE |. 8D8D E1FDFFFF lea ecx,dword ptr ss:[ebp-0x21F]
004014D4 |. 83C8 FF or eax,-0x1
004014D7 |> 40 /inc eax
004014D8 |. 803C01 00 |cmp byte ptr ds:[ecx+eax],0x0
004014DC |.^ 75 F9 \jnz short unpacked.004014D7
最后又调用函数,此函数将中间注册码与用户输入的注册码作为参数
004014DE |. 50 push eax
004014DF |. 8D85 E1FCFFFF lea eax,dword ptr ss:[ebp-0x31F]
004014E5 |. 50 push eax
004014E6 |. 8D85 E1FDFFFF lea eax,dword ptr ss:[ebp-0x21F]
004014EC |. 50 push eax
004014ED |. E8 D0FDFFFF call unpacked.004012C2
此处004014ED |. E8 D0FDFFFF call unpacked.004012C2为关键,还得进入分析...
**********************************************************************************
这个函数全是干货,一点水分没有,就是一个算法进行比较。。
此函数的三个参数为:
中间注册码
用户输入的假码:code
中间注册码的长度nLengthTemp
004012C2 /$ 55 push ebp
004012C3 |. 89E5 mov ebp,esp
004012C5 |. 53 push ebx
004012C6 |. 56 push esi
004012C7 |. 57 push edi
004012C8 |. 8B5D 10 mov ebx,[arg.3]
004012CB |. 31F6 xor esi,esi
004012CD |. 46 inc esi
004012CE |. EB 29 jmp short unpacked.004012F9
004012D0 |> 8B55 08 /mov edx,[arg.1]
004012D3 |. 0FBE3C32 |movsx edi,byte ptr ds:[edx+esi]
004012D7 |. 89F8 |mov eax,edi
004012D9 |. 83F0 20 |xor eax,0x20
004012DC |. B9 0A000000 |mov ecx,0xA
004012E1 |. 99 |cdq
004012E2 |. F7F9 |idiv ecx
004012E4 |. 89D7 |mov edi,edx
004012E6 |. 83C7 30 |add edi,0x30
004012E9 |. 8B55 0C |mov edx,[arg.2]
004012EC |. 0FBE1432 |movsx edx,byte ptr ds:[edx+esi]
004012F0 |. 39D7 |cmp edi,edx
004012F2 |. 74 04 |je short unpacked.004012F8
004012F4 |. 31C0 |xor eax,eax
004012F6 |. EB 08 |jmp short unpacked.00401300
004012F8 |> 46 |inc esi
004012F9 |> 39DE cmp esi,ebx
004012FB |.^ 7C D3 \jl short unpacked.004012D0
004012FD |. 31C0 xor eax,eax
004012FF |. 40 inc eax
00401300 |> 5F pop edi
00401301 |. 5E pop esi
00401302 |. 5B pop ebx
00401303 |. 5D pop ebp
00401304 \. C3 retn
算法伪代码如下:
int i;
i = 1;
while ( i < nLengthOfTempCode )
{
if ( (*(_BYTE *)(TempCode + i) ^ 0x20) % 0x0A + 0x30 != *(_BYTE *)(UserCode + i) )
return 0;
++i;
}
return 1;
}
通过此处若返回的是1,刚会验证成功...
给出一组注册码:
name:xiaoju
code:T860668940
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
- [讨论]apLib的使用 11561
- [原创]对一个crackme详细分析 6049
- [原创]一个盗号木马的不完全分析 10968
- [原创]一个简单病毒的分析 14339