首页
社区
课程
招聘
[原创]分析一个简单的crackme算法,请多多指教!!
发表于: 2010-3-27 19:32 3405

[原创]分析一个简单的crackme算法,请多多指教!!

2010-3-27 19:32
3405
本人刚学crack,水平十分有限.不足之处,还请大虾多多指教!
由于经常熬夜,今天早上起床喉咙特别不舒服,头晕的厉害,感冒了.外面烈日灼烧,给人一种懒洋洋的状态,但想到"革命尚未成功,同志仍需努力" <^.^ 呵呵~开个玩笑> 于是马上开机,起来搞学习.下载了一个crackme,想分析其算法,搞了一上午,才写下这篇文章.

好了,闲话不多说了.下面切入正题!

查找字符串,根据提示成功信息下断
输入用户名:abcdef 假码:abcdefghij12345678.<为什么写这么长,就要看后面的限制>
运行程序,被断在这里:
004011BD    |.  66:A5              movs    word ptr es:[edi], word ptr [esi]
004011BF    |.  6A 45              push    45                                 ; /Count = 45 (69.)
004011C1    |.  50                 push    eax                                ; |Buffer = 0012F984
004011C2    |.  A4                 movs    byte ptr es:[edi], byte ptr [esi]  ; |
004011C3    |.  8B3D A8404000      mov     edi, dword ptr [<&USER32.GetDlgIte>; |USER32.GetDlgItemTextA
004011C9    |.  68 E8030000        push    3E8                                ; |ControlID = 3E8 (1000.)
004011CE    |.  51                 push    ecx                                ; |hWnd
004011CF    |.  FFD7               call    edi                                ; \GetDlgItemTextA
004011D1    |.  8BF0               mov     esi, eax
004011D3    |.  85F6               test    esi, esi
004011D5    |.  0F84 4B010000      je      00401326
004011DB    |.  83FE 40            cmp     esi, 40                            ;  用户名长度在1-64之间
004011DE    |.  0F87 42010000      ja      00401326
004011E4    |.  8B45 08            mov     eax, dword ptr [ebp+8]
004011E7    |.  8D55 94            lea     edx, dword ptr [ebp-6C]
004011EA    |.  6A 13              push    13                                 ; /Count = 13 (19.)
004011EC    |.  52                 push    edx                                ; |Buffer
004011ED    |.  68 E9030000        push    3E9                                ; |ControlID = 3E9 (1001.)
004011F2    |.  50                 push    eax                                ; |hWnd
004011F3    |.  FFD7               call    edi                                ; \GetDlgItemTextA
004011F5    |.  6BC0 03            imul    eax, eax, 3
004011F8    |.  C1E0 02            shl     eax, 2
004011FB    |.  05 CD000000        add     eax, 0CD
00401200    |.  8945 FC            mov     dword ptr [ebp-4], eax
00401203    |.  817D FC A5010000   cmp     dword ptr [ebp-4], 1A5             ;  假码的长度必须等于18
0040120A    |.  0F85 BC000000      jnz     004012CC
00401210    |.  33C0               xor     eax, eax
00401212    |.  8A45 94            mov     al, byte ptr [ebp-6C]              ;  假码字符依次入al
00401215    |.  84C0               test    al, al
00401217    |.  74 13              je      short 0040122C
00401219    |.  8D4D 94            lea     ecx, dword ptr [ebp-6C]
0040121C    |>  3C 30              /cmp     al, 30                            ;  检查是否有特殊字符
0040121E    |.  0F82 C6000000      |jb      004012EA
00401224    |.  8A41 01            |mov     al, byte ptr [ecx+1]
00401227    |.  41                 |inc     ecx
00401228    |.  84C0               |test    al, al
0040122A    |.^ 75 F0              \jnz     short 0040121C
0040122C    |> \E8 CFFDFFFF        call    00401000
00401231    |.  8D85 2CFFFFFF      lea     eax, dword ptr [ebp-D4]            ;  用户名存入eax
00401237    |.  50                 push    eax
00401238    |.  E8 43FEFFFF        call    00401080                           ;  关键call<1>
0040123D    |.  8945 FC            mov     dword ptr [ebp-4], eax
00401240    |.  E8 BBFDFFFF        call    00401000                          
00401245    |.  8D8D 2CFFFFFF      lea     ecx, dword ptr [ebp-D4]
0040124B    |.  56                 push    esi
0040124C    |.  51                 push    ecx
0040124D    |.  E8 BEFDFFFF        call    00401010                           ; 关键call<2>
00401252    |.  83C4 0C            add     esp, 0C
00401255    |.  33C9               xor     ecx, ecx

关键call<1>:

00401080    /$  55                 push    ebp
00401081    |.  8BEC               mov     ebp, esp
00401083    |.  51                 push    ecx
00401084    |.  53                 push    ebx
00401085    |.  56                 push    esi
00401086    |.  57                 push    edi
00401087    |.  68 80504000        push    00405080                           ;  字符串1 "eheh"
0040108C    |.  6A 00              push    0
0040108E    |.  E8 ADFFFFFF        call    00401040                           ;  关键call<3> 设此方法为T计算
00401093    |.  83C4 08            add     esp, 8
00401096    |.  8BD8               mov     ebx, eax                           ;  "eheh"经过T计算后结果ZX

继续跟进call<3>:

00401040    /$  8B4C24 04          mov     ecx, dword ptr [esp+4]             ;  设此计算方法为 T
00401044    |.  56                 push    esi
00401045    |.  8B7424 0C          mov     esi, dword ptr [esp+C]             ;  "eheh"
00401049    |.  33C0               xor     eax, eax
0040104B    |.  33D2               xor     edx, edx
0040104D    |.  8A4431 03          mov     al, byte ptr [ecx+esi+3]           ;  取最后一个字符"h"
00401051    |.  8A5431 02          mov     dl, byte ptr [ecx+esi+2]           ;  取"e"
00401055    |.  C1E0 08            shl     eax, 8
00401058    |.  03C2               add     eax, edx                           ;  结果记为x1
0040105A    |.  33D2               xor     edx, edx
0040105C    |.  8A5431 01          mov     dl, byte ptr [ecx+esi+1]           ;  第二个"h"
00401060    |.  C1E0 08            shl     eax, 8                             ;  x1右移8位
00401063    |.  03C2               add     eax, edx                           ;  x1右移8位+"h"asc值结果为x2
00401065    |.  33D2               xor     edx, edx
00401067    |.  8A1431             mov     dl, byte ptr [ecx+esi]
0040106A    |.  5E                 pop     esi
0040106B    |.  C1E0 08            shl     eax, 8
0040106E    |.  03C2               add     eax, edx                           ;  x2右移8位+"e"的asc码结果记为ZX
00401070    \.  C3                 retn

返回至这里:
00401093    |.  83C4 08            add     esp, 8
00401096    |.  8BD8               mov     ebx, eax                           ;  "eheh"经过T计算后结果ZX
00401098    |.  E8 63FFFFFF        call    00401000
0040109D        BF 70504000        mov     edi, 00405070                      ;  字符串2 " is a whore."
004010A2    |.  83C9 FF            or      ecx, FFFFFFFF
004010A5    |.  33C0               xor     eax, eax
004010A7    |.  F2:AE              repne   scas byte ptr es:[edi]
004010A9    |.  F7D1               not     ecx
004010AB    |.  2BF9               sub     edi, ecx
004010AD    |.  8BF7               mov     esi, edi
004010AF    |.  8B7D 08            mov     edi, dword ptr [ebp+8]
004010B2    |.  8BD1               mov     edx, ecx
004010B4    |.  83C9 FF            or      ecx, FFFFFFFF
004010B7    |.  F2:AE              repne   scas byte ptr es:[edi]
004010B9    |.  8BCA               mov     ecx, edx
004010BB    |.  4F                 dec     edi
004010BC    |.  C1E9 02            shr     ecx, 2
004010BF    |.  F3:A5              rep     movs dword ptr es:[edi], dword ptr [esi];  取字符串2.四字节的倍数长度存入地址12F98A处
004010C1    |.  8BCA               mov     ecx, edx
004010C3    |.  83E1 03            and     ecx, 3
004010C6    |.  F3:A4              rep     movs byte ptr es:[edi], byte ptr [esi];  未取完的字符加载
004010C8    |.  33FF               xor     edi, edi
004010CA    |.  33F6               xor     esi, esi
004010CC    |>  8B45 08            /mov     eax, dword ptr [ebp+8]            ;  上面是把字符串2连接到用户名的后面,字符串3
004010CF    |.  50                 |push    eax
004010D0    |.  56                 |push    esi

执行完了返回这里:
004010D1    |.  E8 6AFFFFFF        |call    00401040                               ;  关键call<4>

跟进去:
00401040    /$  8B4C24 04          mov     ecx, dword ptr [esp+4]                  ;  此计算方法为 T   
00401044    |.  56                 push    esi
00401045    |.  8B7424 0C          mov     esi, dword ptr [esp+C]                  ;  "abcdef is a whore"
00401049    |.  33C0               xor     eax, eax
0040104B    |.  33D2               xor     edx, edx
0040104D    |.  8A4431 03          mov     al, byte ptr [ecx+esi+3]                ;  倒序取字符
00401051    |.  8A5431 02          mov     dl, byte ptr [ecx+esi+2]               
00401055    |.  C1E0 08            shl     eax, 8
00401058    |.  03C2               add     eax, edx                        
0040105A    |.  33D2               xor     edx, edx
0040105C    |.  8A5431 01          mov     dl, byte ptr [ecx+esi+1]             
00401060    |.  C1E0 08            shl     eax, 8                                  
00401063    |.  03C2               add     eax, edx                                
00401065    |.  33D2               xor     edx, edx
00401067    |.  8A1431             mov     dl, byte ptr [ecx+esi]
0040106A    |.  5E                 pop     esi
0040106B    |.  C1E0 08            shl     eax, 8
0040106E    |.  03C2               add     eax, edx                        
00401070    \.  C3                 retn

004010D1    |.  E8 6AFFFFFF        |call    00401040                               ;  这个就是call<4>    T计算  计算15次
004010D6    |.  8B8E 30504000      |mov     ecx, dword ptr [esi+405030]
004010DC    |.  83C4 08            |add     esp, 8
004010DF    |.  33CF               |xor     ecx, edi
004010E1    |.  03C1               |add     eax, ecx
004010E3    |.  8945 FC            |mov     dword ptr [ebp-4], eax
004010E6    |.  C145 FC 07         |rol     dword ptr [ebp-4], 7
004010EA    |.  8B45 FC            |mov     eax, dword ptr [ebp-4]                 ;  此时eax中的值设为Dn(n=1,2,3..)
004010ED    |.  83C6 04            |add     esi, 4                                 ;  An为异或后的值
004010F0    |.  33D8               |xor     ebx, eax                               ;  An(n=2,3,4..)与Dn(b=2,3,4..)的值异或15次后值设为AT
004010F2    |.  47                 |inc     edi
004010F3    |.  83FE 40            |cmp     esi, 40
004010F6    |.^ 7C D4              \jl      short 004010CC
004010F8    |.  5F                 pop     edi
004010F9    |.  8BC3               mov     eax, ebx
004010FB    |.  5E                 pop     esi
004010FC    |.  5B                 pop     ebx
004010FD    |.  8BE5               mov     esp, ebp
004010FF    |.  5D                 pop     ebp
00401100    \.  C3                 retn

返回来到这里:

0040123D    |.  8945 FC            mov     dword ptr [ebp-4], eax
00401240    |.  E8 BBFDFFFF        call    00401000                             
00401245    |.  8D8D 2CFFFFFF      lea     ecx, dword ptr [ebp-D4]
0040124B    |.  56                 push    esi
0040124C    |.  51                 push    ecx
0040124D    |.  E8 BEFDFFFF        call    00401010                                ;  去掉用户名后缀" is a whore"
00401252    |.  83C4 0C            add     esp, 0C
00401255    |.  33C9               xor     ecx, ecx
00401257    |> /8B45 FC            /mov     eax, dword ptr [ebp-4]                 ;  上次计算出来的结果AT参与生成表的计算
0040125A    |. |33D2               |xor     edx, edx
0040125C    |. |BE 1A000000        |mov     esi, 1A
00401261    |. |F7F6               |div     esi                                    ;  设ATsn除以1A后的余数为bn(n=1,2,3...)
00401263    |. |8A9415 10FFFFFF    |mov     dl, byte ptr [ebp+edx-F0]
0040126A    |. |88540D C8          |mov     byte ptr [ebp+ecx-38], dl              ;  从表1取第bn位数值
0040126E    |. |8B45 FC            |mov     eax, dword ptr [ebp-4]
00401271    |. |C1E0 03            |shl     eax, 3                                 ;  AT左移3位后的值 ATn(n=1,2,3,..)
00401274    |. |BA 45230100        |mov     edx, 12345
00401279    |. |F7E8               |imul    eax                                    ;  ATn*12345+12345的值设为ATsn(n=1,2,3..)
0040127B    |. |03C2               |add     eax, edx
0040127D    |. |8945 FC            |mov     dword ptr [ebp-4], eax
00401280    |. |41                 |inc     ecx
00401281    |. |83F9 12            |cmp     ecx, 12                                ;  一系列复杂的运算只为生成一张新表  记为BD2
00401284    |.^\72 D1              \jb      short 00401257
00401286    |.  E8 75FDFFFF        call    00401000                                
0040128B    |.  33C0               xor     eax, eax
0040128D    |>  8A4C05 94          /mov     cl, byte ptr [ebp+eax-6C]              ;  假码字符依次入cl
00401291    |.  8A5405 C8          |mov     dl, byte ptr [ebp+eax-38]              ;  表BD2对应字符依次入dl
00401295    |.  80E9 30            |sub     cl, 30
00401298    |.  32D1               |xor     dl, cl
0040129A    |.  885405 C8          |mov     byte ptr [ebp+eax-38], dl
0040129E    |.  40                 |inc     eax
0040129F    |.  83F8 12            |cmp     eax, 12
004012A2    |.^ 72 E9              \jb      short 0040128D                         ;  假码与表BD2进行计算生成表BD3
004012A4    |.  E8 57FDFFFF        call    00401000                            
004012A9    |.  8D55 C8            lea     edx, dword ptr [ebp-38]
004012AC    |.  52                 push    edx
004012AD    |.  E8 5EFEFFFF        call    00401110                                ;  关键call <5>
004012B2    |.  E8 49FDFFFF        call    00401000                               
004012B7    |.  8D45 C8            lea     eax, dword ptr [ebp-38]
004012BA    |.  68 14514000        push    00405114                                ;  真码压栈
004012BF    |.  50                 push    eax                                     ;  表BD4
004012C0    |.  E8 6BFEFFFF        call    00401130                                ;  逐位进行比较
004012C5    |.  83C4 0C            add     esp, 0C
004012C8    |.  85C0               test    eax, eax
004012CA    |.  75 3C              jnz     short 00401308
004012CC    |>  8B4D 08            mov     ecx, dword ptr [ebp+8]
004012CF    |.  6A 10              push    10                                      ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004012D1    |.  68 0C514000        push    0040510C                                ; |Title = "Error"
004012D6    |.  68 FC504000        push    004050FC                                ; |Text = "Bad Serial :o("
004012DB    |.  51                 push    ecx                                     ; |hOwner
004012DC    |.  FF15 AC404000      call    dword ptr [<&USER32.MessageBoxA>]       ; \MessageBoxA
004012E2    |.  5F                 pop     edi
004012E3    |.  33C0               xor     eax, eax
004012E5    |.  5E                 pop     esi
004012E6    |.  8BE5               mov     esp, ebp
004012E8    |.  5D                 pop     ebp
004012E9    |.  C3                 retn
004012EA    |>  8B55 08            mov     edx, dword ptr [ebp+8]
004012ED    |.  6A 10              push    10                                      ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004012EF    |.  68 0C514000        push    0040510C                                ; |Title = "Error"
004012F4    |.  68 FC504000        push    004050FC                                ; |Text = "Bad Serial :o("
004012F9    |.  52                 push    edx                                     ; |hOwner
004012FA    |.  FF15 AC404000      call    dword ptr [<&USER32.MessageBoxA>]       ; \MessageBoxA
00401300    |.  5F                 pop     edi
00401301    |.  33C0               xor     eax, eax
00401303    |.  5E                 pop     esi
00401304    |.  8BE5               mov     esp, ebp
00401306    |.  5D                 pop     ebp
00401307    |.  C3                 retn

跟进call<5>:

00401110    /$  8B4C24 04          mov     ecx, dword ptr [esp+4]
00401114    |.  33C0               xor     eax, eax
00401116    |>  8A1408             /mov     dl, byte ptr [eax+ecx]
00401119    |.  32D0               |xor     dl, al
0040111B    |.  881408             |mov     byte ptr [eax+ecx], dl
0040111E    |.  40                 |inc     eax
0040111F    |.  83F8 12            |cmp     eax, 12                                ;  由BD3建立一张新表BD4
00401122    |.^ 72 F2              \jb      short 00401116
00401124    \.  C3                 retn

执行完了之后返回至地址00401000

到这里为止,我们对该crackme得算法已经分析完了,大致过程是这样的:

0>表BD1是固定的:KEYGENNING4NEWBIES
1>用户名长度L,0<L<=64 假码长度必须18位.
2>倒序取字符"eheh"进行转换[("h"*2^8+"e")*2^8+"h"]*2^8+"e"  "h","e"为对应的ASC码的值  结果设为 ZX
3>把字符串" is a whore."连接到用户名的后面组成字符串3
4>字符串3经过T运算15次,An(n=2,3,4...) xor Dn(n=2,3,4...) 异或10次后的值设为AT
5>AT左移3位得到AT1,AT1左移3位得到AT2,以此类推...ATn(n=1,2,3...)
ATn*12345+12345后的值设为ATSn(n=1,2,3..)
ATSn 除以 1A 得到的余数为bn(n=1,2,3...)
6>从表1取第bn位的数值,依次排列生成表单BD2
7>设假码每一位的字符的ASC码对应Jn(n=1,2,3...) 表单BD2每一位对应的ASC码Bn(n=1,2,3...)  (Jn-30) xor Bn=CMn(n=1,2,3...),把CMn的值转换成字符,依次连接起来,建立BD3 
8>表单BD3每位字符与它的数位减一的值进行异或得到结果,转换成字符,依次排列于是 表单BD4建成了
9>把BD4与BD1进行比较 相等就成功!

要想BD4=BD1,就需要逆推注册码! 假设BD1=BD4,往上逆推,BD4每位字符的ASC码与(0,1,2,3...17)异或,得到BD3
<输入注册码的每位字符-30> xor <BD2中对应字符> =<BD3中对应字符> 因为BD3逆推出来了,BD2也算出来了 所以
<BD3中对应字符> xor <BD2对应字符> +30 后 把对应ASC码转换成字符就是真的注册码了!
计算过程有点复杂,所以在逆推注册码的时候要用到指令计算器,OD命令行.不能错掉一个字符,因为是逐位进行比较了.

注册名:abcdef
注册码:2<O9:A6L=8?:N=6:DM

注:算法分析完了,但是发现一个bug,24 xor 55 +30 =A1 在ASC码表找不到相应的字符.(就是注册码中的"?").

由于本人经验不足,文中有些地方让你感到很别扭,造成你阅读上的不便.请原谅!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
2
附件呢?
你昨天发的那个cm真麻烦,不过还是干掉了
今天这个不知道怎么样
2010-3-27 20:18
0
雪    币: 48
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
忘了上传附件,感谢提醒!
上传的附件:
2010-3-27 20:22
0
雪    币: 78
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
顶!你的进步真快!
2010-3-27 20:26
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
5
今晚就算了,困的 不行,明天看看
2010-3-27 20:40
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
6
注册机来了
累,cm作者够缺德的,里面有骂人的话
不过加密思路很清晰
可惜最后还是在和一个常量作比较,xor可逆
所以此注册算法也是可逆的

/*如果你的serial有?表示是不可视字符,请更换注册名*/
/*不要相信自己的眼睛,尽量复制粘贴*/

#include	"stdafx.h"
#include	<string.h>
unsigned int h=0,i,j,k;
int const1[18]={0x12,0x5c,0x34,0x22,0xab,0x9d,0x54,0x00,0xdd,0x84,0xae,0x66,0x31,0x78,0x73,0xcf};//405030处的常量数组
char const2[19]="KD[DAKHNFN>EIZLFUB";  //最后的常量字符串,和自己下标异或后的结果
unsigned int hehe=0x68656865;
char name[80],serial[18],sub[18];
void imul(int x)
{
	__asm mov eax,x
	__asm imul eax
	__asm mov hehe,eax
	__asm mov k,edx
}
int getint(int i)
{
	int p=0;
	p=name[i+3];
	p=p<<8;
	p=p+name[i+2];
	p=p<<8;
	p=p+name[i+1];
	p=p<<8;
	p=p+name[i];
	return p;
}
int main(int argc, char* argv[])
{
	memset(name,'\0',80);
	printf("Plz input your name:\n");
	scanf("%s",name);
	strcat(name," is a whore.");
	for(i=0;h<0x40;i++)
	{
		j=getint(h)+(const1[i]^i);
		__asm mov eax,j
		__asm rol eax,7
		__asm mov j,eax
		h+=4;
		hehe=j^hehe;
	}
	for(i=0;i<18;i++)
	{
		serial[i]=(hehe%26)+65;
		hehe=hehe<<3;
		imul(hehe);
		hehe=hehe+k;
	}
	for(i=0;i<18;i++)
	{
		sub[i]=serial[i]^const2[i];
		serial[i]=sub[i]+0x30;
	}
	printf("This is your serial:\n%s\n",serial);
	return 0;
}
2010-3-28 14:00
0
游客
登录 | 注册 方可回帖
返回
//