首页
社区
课程
招聘
[原创][原创]分析一个crackme的算法,菜鸟必看!!大侠也来指教!
发表于: 2010-3-26 01:16 3879

[原创][原创]分析一个crackme的算法,菜鸟必看!!大侠也来指教!

2010-3-26 01:16
3879
本人刚学cracke,水平很菜.今下午琢磨了一下午才写了这篇破文~,这也是我第一次写的破文,不足之处还请各位大侠指教.

在逆推注册码和用户名的时候,我把计算关系列了出来,可搞了3小时还是不能算出来,试了很多次,计算器都点的手疼了.代码看了一遍又一遍还是不能成功,差点放弃.最后狠下心来,仔仔细细看了一遍,终

于发现了一个地方是我算错了.于是惊喜万分,马上逆推出来注册名和注册码.
那时的心情好激动!所以我劝大家要是认真坚持一下,就可以成功!

好了,切入正题:
字符串查找,看到注册成功信息后,下断.运行crackme,输入注册名:bzceff 注册码:aBbcdX 程序被断在这里:

0040137B  |.  6A 40         push    40                               ; /Count = 40 (64.)
0040137D  |.  68 20334000   push    00403320                         ; |Buffer = cztria~1.00403320
00401382  |.  FF35 66324000 push    dword ptr [403266]               ; |hWnd = 00080262 (class='Edit',parent=0008025A)
00401388  |.  E8 A3080000   call    <jmp.&USER32.GetWindowTextA>     ; \GetWindowTextA
0040138D  |.  83F8 04       cmp     eax, 4
00401390  |.  0F8E 9F000000 jle     00401435
00401396  |.  6A 40         push    40                               ; /Count = 40 (64.)
00401398  |.  68 60334000   push    00403360                         ; |Buffer = cztria~1.00403360
0040139D  |.  68 B90B0000   push    0BB9                             ; |ControlID = BB9 (3001.)
004013A2  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004013A5  |.  E8 6E080000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA
004013AA  |.  83F8 04       cmp     eax, 4                           ;  用户名注册码长度大于4位
004013AD  |.  0F8E 82000000 jle     00401435
004013B3  |.  A3 62324000   mov     dword ptr [403262], eax
004013B8  |.  FF35 66324000 push    dword ptr [403266]               ; /hWnd = 00080262 (class='Edit',parent=0008025A)
004013BE  |.  E8 AF080000   call    <jmp.&USER32.SetFocus>           ; \SetFocus
004013C3  |.  BF 20334000   mov     edi, 00403320                    ;  ASCII "bzceff"
004013C8  |.  BE 20334000   mov     esi, 00403320                    ;  ASCII "bzceff"
004013CD  |>  AC            /lods    byte ptr [esi]
004013CE  |.  0C 00         |or      al, 0
004013D0  |.  74 05         |je      short 004013D7
004013D2  |.  0C 20         |or      al, 20                          ;  大写转换成小写
004013D4  |.  AA            |stos    byte ptr es:[edi]               ;  存入→地址403320
004013D5  |.^ EB F6         \jmp     short 004013CD
004013D7  |>  BF A0324000   mov     edi, 004032A0
004013DC  |.  BE 60334000   mov     esi, 00403360                    ;  输入的假码存放esi
004013E1  |.  8D1D 20334000 lea     ebx, dword ptr [403320]          ;  ebx指向403320,即用户名的地址
004013E7  |.  33C9          xor     ecx, ecx                         ;  ecx清零
004013E9  |>  AC            /lods    byte ptr [esi]                  ;  al依次存放假码的ASC码
004013EA  |.  0C 00         |or      al, 0                           ;  取完了么?
004013EC  |.  74 17         |je      short 00401405
004013EE  |.  8A13          |mov     dl, byte ptr [ebx]              ;  用户名字符依次存入dl
004013F0  |.  2AD0          |sub     dl, al                          ;  用户名每一位asc码-对应假码字符的asc码存入dl
004013F2  |.  80CA 00       |or      dl, 0
004013F5  |.  74 3E         |je      short 00401435                  ;  判断输入的假码是否有空格字符
004013F7  |.  8AC2          |mov     al, dl
004013F9  |.  24 0F         |and     al, 0F                          ;  al的取值如果高于0F就取al-0f的值
004013FB  |.  0C 00         |or      al, 0
004013FD      74 36         je      short 00401435
004013FF  |.  AA            |stos    byte ptr es:[edi]               ;  把al中的值存入地址004032A0处
00401400  |.  02C8          |add     cl, al                          ;  依次把计算出的al累加放入cl中
00401402  |.  43            |inc     ebx                             ;  循环次数为假码的位数
00401403  |.^ EB E4         \jmp     short 004013E9
00401405  |>  890D 6A324000 mov     dword ptr [40326A], ecx          ;  cl中的结果存入地址40326A处
0040140B  |.  E8 27020000   call    00401637                         ;  关键call
00401410  |.  BE A0324000   mov     esi, 004032A0

00401637  /$  BE A0324000   mov     esi, 004032A0
0040163C  |.  8B15 62324000 mov     edx, dword ptr [403262]          ;  假码的位数存入edx
00401642  |.  52            push    edx
00401643  |.  33C0          xor     eax, eax
00401645  |.  83EA 01       sub     edx, 1                           ;  edx=edx-1   结果记为L
00401648  |.  03F2          add     esi, edx
0040164A  |.  8A06          mov     al, byte ptr [esi]               ;  4032A5的值存入al
0040164C  |.  F7E0          mul     eax                              ;  eax=al^2        记为x1
0040164E  |.  5A            pop     edx
0040164F  |.  83EA 01       sub     edx, 1
00401652  |.  F7E2          mul     edx                              ;  eax=x1*L        记为x2
00401654  |.  B9 01000000   mov     ecx, 1
00401659  |>  2BC1          /sub     eax, ecx                        ;  x2=x2-1-3-5-7-...
0040165B  |.  83F8 00       |cmp     eax, 0                          ;  x2<=0 退出循环
0040165E  |.  7E 08         |jle     short 00401668
00401660  |.  83C2 01       |add     edx, 1                          ;  循环次数存入edx  记为CS1
00401663  |.  83C1 02       |add     ecx, 2
00401666  |.^ EB F1         \jmp     short 00401659
00401668  |>  52            push    edx
00401669  |.  BE A0324000   mov     esi, 004032A0
0040166E  |.  8BFE          mov     edi, esi
00401670  |.  8B15 62324000 mov     edx, dword ptr [403262]
00401676  |.  33C0          xor     eax, eax
00401678  |.  83EA 01       sub     edx, 1
0040167B  |.  03F2          add     esi, edx
0040167D  |.  8A06          mov     al, byte ptr [esi]               ;  4032A5的值存入al
0040167F  |.  83C0 01       add     eax, 1
00401682  |.  5A            pop     edx                              ;  edx=CS1   即上次循环次数出栈
00401683  |.  03C2          add     eax, edx
00401685  |.  D1E8          shr     eax, 1                           ;  右移1位后的结果记为x3
00401687  |.  8B15 62324000 mov     edx, dword ptr [403262]
0040168D  |.  03FA          add     edi, edx
0040168F  |.  AA            stos    byte ptr es:[edi]                ;  x3  存入4032A6处
00401690  |.  F7E0          mul     eax
00401692  |.  8B15 62324000 mov     edx, dword ptr [403262]
00401698  |.  83EA 01       sub     edx, 1
0040169B  |.  F7E2          mul     edx                              ;  x3*x3*L的值记为   x4
0040169D  |.  B9 01000000   mov     ecx, 1
004016A2  |>  2BC1          /sub     eax, ecx
004016A4  |.  83F8 00       |cmp     eax, 0
004016A7  |.  7E 08         |jle     short 004016B1
004016A9  |.  83C2 01       |add     edx, 1                          ;  edx等于循环的次数记为  CS2
004016AC  |.  83C1 02       |add     ecx, 2
004016AF  |.^ EB F1         \jmp     short 004016A2
004016B1  |>  52            push    edx
004016B2  |.  BE A0324000   mov     esi, 004032A0
004016B7  |.  8B15 62324000 mov     edx, dword ptr [403262]
004016BD  |.  33C0          xor     eax, eax
004016BF  |.  03F2          add     esi, edx
004016C1  |.  8A06          mov     al, byte ptr [esi]               ;  4032A6处的值入al
004016C3  |.  83C0 01       add     eax, 1                           ;  eax=x3+1
004016C6  |.  5A            pop     edx
004016C7  |.  03C2          add     eax, edx
004016C9  |.  D1E8          shr     eax, 1                           ;  (x3+1+CS2)右移一位后结果记为 x5
004016CB  |.  A3 6E324000   mov     dword ptr [40326E], eax          ;  x5存入地址40326E处
004016D0  \.  C3            retn

跳转至这里:

00401410  |.  BE A0324000   mov     esi, 004032A0
00401415  |.  8B15 62324000 mov     edx, dword ptr [403262]
0040141B  |.  C1EA 02       shr     edx, 2                           ;  假码位数右移2位 记为L0
0040141E  |.  03F2          add     esi, edx
00401420  |.  8A06          mov     al, byte ptr [esi]               ;  [4032A0+L0]的值存入al
00401422  |.  33D2          xor     edx, edx
00401424  |.  8B15 6E324000 mov     edx, dword ptr [40326E]          ;  x5的值存入 edx
0040142A  |.  2BD0          sub     edx, eax                         ;  edx=x5-eax  记为x6
0040142C  |.  A1 6A324000   mov     eax, dword ptr [40326A]          ;  40326A的值为原来累加在cl中的值
00401431  |.  3BC2          cmp     eax, edx                         ;  x6与40326A处数值进行比较
00401433  |.  74 31         je      short 00401466                   ;  相等就注册成功!
00401435      68 00200000   push    2000
0040143A  |.  68 D1314000   push    004031D1                         ; |Title = "              Error"
0040143F  |.  68 F9314000   push    004031F9                         ; |Text = " Sorry Cracker, wrong."
00401444  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
00401447  |.  E8 02080000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
0040144C  |.  6A 40         push    40                               ; /Length = 40 (64.)
0040144E  |.  68 E0324000   push    004032E0                         ; |Destination = cztria~1.004032E0
00401453  |.  E8 56080000   call    <jmp.&KERNEL32.RtlZeroMemory>    ; \RtlZeroMemory
00401458  |.  6A 40         push    40                               ; /Length = 40 (64.)
0040145A  |.  68 A0334000   push    004033A0                         ; |Destination = cztria~1.004033A0
0040145F  |.  E8 4A080000   call    <jmp.&KERNEL32.RtlZeroMemory>    ; \RtlZeroMemory
00401464  |.  EB 2F         jmp     short 00401495
00401466  |>  68 00200000   push    2000                             ; /Style = MB_OK|MB_TASKMODAL
0040146B  |.  68 E5314000   push    004031E5                         ; |Title = "       <Registered>"
00401470  |.  68 10324000   push    00403210                         ; |Text = "            You did it!"
00401475  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
00401478  |.  E8 D1070000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
0040147D  |.  6A 40         push    40                               ; /Length = 40 (64.)

用户名只能是字母不能为数字,或其他字符!
设用户名第一位字符的ASC码为A1,以此类推...最后一位字符记为AT;
设假码第一位字符ASC码为B1,以此类推...    最后一位字符记为BT;
An-Bn的值存放于004032A0处;
到这里为止,可以知道用户名多出的字符不参与计算!x6的值由(AT-BT),[4032A0+L0]经过一系列的转换得来的
x6=(A1-B1)+(A2-B2)+....(AT-BT)才能注册成功!
只要保证每次输入的AT,BT保持不变,x5的值是不会变化的;
设[4032A0+L0]处对应的用户名,假码字符分别为 AR,BR;
x5-(AR-BR)=(AR-BR)+(AT-BT)+W
这个W就是剩下(L-1)位对应的(AN-Bn)ASC码之和 
到这一步很好算了,x5定值,W是可以随便假设的只要符合上面算法的条件,所以得到4032A0+L0]的假设值也就不难了!

第一次写破文,没有经验,很多地方看起来特别别扭.请大侠指出错误,造成你阅读上困扰,请原谅!
 

一组可用的字符:
注册名:bjcdef
注册码:aaacdx

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 33
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
很不错,....
2010-3-26 09:12
0
雪    币: 727
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
来顶下.......
2010-3-26 09:40
0
雪    币: 273
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习了!!
2010-3-26 11:44
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
很详细!谢谢分享!
2010-3-26 13:30
0
雪    币: 132
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
来学习一下,很详细的内容,谢谢
2010-3-26 14:16
0
雪    币: 435
活跃值: (1277)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
7
不知道为什么,昨天下午突然登不上,知道现在,
很麻烦的一个cm,佩服lz的耐心
运算过程中有好几个shr
所以应该是不可逆的,不过
因为只有serial最后一位和name对应位的差值会对比较结果产生影响
所以可以对这个差值进行枚举,很快就能找到可用的serial

我的注册名是bittz,最简单的serial就是ahssv
下面是个注册算法,有点投机取巧的意思,不过能生成一个可用的serial
/*一个投机取巧的注册算法*/
#include	"stdafx.h"
#include	<string.h>

int main(int argc, char* argv[])
{
	char name[10],serial[10];
	printf("Plz input your name:\n");
	scanf("%s",name);
	for(int i=0;i<=3;i++)
		serial[i]=name[i]-1;
	serial[4]=name[4]-4;
	serial[5]='\0';
	printf("This is an available serial:\n%s\n",serial);
	return 0;
}
2010-3-27 20:15
0
雪    币: 78
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
顶!你的进步真快!
2010-3-27 20:25
0
雪    币: 48
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
呵呵...楼上强大~
2010-3-27 20:31
0
游客
登录 | 注册 方可回帖
返回
//