您的位置:首页 > 其它

一个简单的CrackMe分析

2014-04-03 23:09 417 查看
有一段时间没分析过CrackMe了,是不敢去分析,因为破解这东西,耗时间,现在大学正是学东西的时候,不敢耗太多时间进去。

在csdn上写破文有种不伦不类的感觉,没办法,大牛都去看雪发帖了。

入门级别CrackMe开始,根据这个CrackMe的加密过程写了个注册码生成的程序。

CrackMe个人觉得就是个小程序,只有注册的过程,我们不好拿软件来破解,软件首先要安装,然后再注册,而CrackMe不安装,就相当于把软件的注册部分分出来,就是crackMe了。有点挑逗的意思,come on,CrackMe。

一般我是在http://crackmes.de/users/deurus/humanoid_asm_keygenme/上找CrackMe的。这次的CrackMe也不例外。

运行的界面如下



当点击check的时候,如果不正确会什么也不提示。所以就不用像从MessageBox入手了,不过像这种软件实在太简单了,我们自己都能写,一个对话框,我们要找的就是对话框回调函数。用OD载入

00401064     E8 40030000    CALL KeyGenMe.004013A9

00401069  |. 6A 00          PUSH 0                                   ; /pModule = NULL

0040106B  |. E8 90020000    CALL <JMP.&kernel32.GetModuleHandleA>    ; \GetModuleHandleA

00401070  |. A3 B0614000    MOV DWORD PTR DS:[4061B0],EAX

00401075  |. 6A 00          PUSH 0                                   ; /lParam = NULL

00401077  |. 68 91104000    PUSH KeyGenMe.00401091                   ; |DlgProc = KeyGenMe.00401091

0040107C  |. 6A 00          PUSH 0                                   ; |hOwner = NULL

0040107E  |. 6A 65          PUSH 65                                  ; |pTemplate = 65

00401080  |. FF35 B0614000  PUSH DWORD PTR DS:[4061B0]               ; |hInst = NULL

00401086  |. E8 BD020000    CALL <JMP.&user32.DialogBoxParamA>       ; \DialogBoxParamA

0040108B  |. 50             PUSH EAX                                 ; /ExitCode

0040108C  \. E8 5D020000    CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess

主程序就这样,再看看回调函数的反汇编代码

00401091   . 55             PUSH EBP

00401092   . 8BEC           MOV EBP,ESP

00401094   . 81C4 FCFCFFFF  ADD ESP,-304

0040109A   . 817D 0C 110100>CMP DWORD PTR SS:[EBP+C],111

004010A1   . 0F85 E4010000  JNZ KeyGenMe.0040128B

004010A7   . 817D 10 EB0300>CMP DWORD PTR SS:[EBP+10],3EB

004010AE   . 0F85 B0010000  JNZ KeyGenMe.00401264

004010B4   . C705 C4614000 >MOV DWORD PTR DS:[4061C4],0

004010BE   . C705 C8614000 >MOV DWORD PTR DS:[4061C8],1              ;  获取username

004010C8   > 68 00010000    PUSH 100                                 ; /Count = 100 (256.)

004010CD   . 8D85 00FFFFFF  LEA EAX,DWORD PTR SS:[EBP-100]           ; |

004010D3   . 50             PUSH EAX                                 ; |Buffer

004010D4   . 68 E9030000    PUSH 3E9                                 ; |ControlID = 3E9 (1001.)

004010D9   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd

004010DC   . E8 73020000    CALL <JMP.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA

004010E1   . 83F8 02        CMP EAX,2

004010E4   . 0F86 1A010000  JBE KeyGenMe.00401204                    ;  最少三个字符

004010EA   . 68 00010000    PUSH 100                                 ; /Length = 100 (256.)

004010EF   . 8D85 00FEFFFF  LEA EAX,DWORD PTR SS:[EBP-200]           ; |

004010F5   . 50             PUSH EAX                                 ; |Destination

004010F6   . E8 23020000    CALL <JMP.&kernel32.RtlZeroMemory>       ; \RtlZeroMemory

004010FB   . 8DBD 00FFFFFF  LEA EDI,DWORD PTR SS:[EBP-100]

00401101   . EB 0E          JMP SHORT KeyGenMe.00401111

00401103   > 803F 61        CMP BYTE PTR DS:[EDI],61

00401106   . 72 08          JB SHORT KeyGenMe.00401110

00401108   . 803F 7A        CMP BYTE PTR DS:[EDI],7A

0040110B   . 77 03          JA SHORT KeyGenMe.00401110

0040110D   . 802F 20        SUB BYTE PTR DS:[EDI],20                 ;  将用户名中的小写字符转换成大写字符

00401110   > 47             INC EDI

00401111   > 803F 00        CMP BYTE PTR DS:[EDI],0

00401114   .^75 ED          JNZ SHORT KeyGenMe.00401103

00401116   . 33D2           XOR EDX,EDX

00401118   . 8DB5 00FFFFFF  LEA ESI,DWORD PTR SS:[EBP-100]

0040111E   . EB 49          JMP SHORT KeyGenMe.00401169

00401120   > 8D3D 8B604000  LEA EDI,DWORD PTR DS:[40608B]

00401126   . B9 FFFFFFFF    MOV ECX,-1

0040112B   . 0FB606         MOVZX EAX,BYTE PTR DS:[ESI]

0040112E   . F2:AE          REPNE SCAS BYTE PTR ES:[EDI]             ; 

00401130   . F7D1           NOT ECX                                  ;  ecx为扫描过后的字符数

00401132   . 49             DEC ECX

00401133   . 833D C4614000 >CMP DWORD PTR DS:[4061C4],1              ;

0040113A   . 74 13          JE SHORT KeyGenMe.0040114F               ; 

0040113C   . 0FB681 B060400>MOVZX EAX,BYTE PTR DS:[ECX+4060B0]       ; 

00401143   . C705 C4614000 >MOV DWORD PTR DS:[4061C4],1

0040114D   . EB 11          JMP SHORT KeyGenMe.00401160

0040114F   > 0FB681 D560400>MOVZX EAX,BYTE PTR DS:[ECX+4060D5]       ; 

00401156   . C705 C4614000 >MOV DWORD PTR DS:[4061C4],0

00401160   > 888415 00FEFFF>MOV BYTE PTR SS:[EBP+EDX-200],AL         ; 

00401167   . 42             INC EDX

00401168   . 46             INC ESI

00401169   > 803E 00        CMP BYTE PTR DS:[ESI],0

0040116C   .^75 B2          JNZ SHORT KeyGenMe.00401120

0040116E   . 8DB5 00FFFFFF  LEA ESI,DWORD PTR SS:[EBP-100]

00401174   . 8B15 C4614000  MOV EDX,DWORD PTR DS:[4061C4]

0040117A   . 33DB           XOR EBX,EBX

0040117C   . EB 15          JMP SHORT KeyGenMe.00401193

0040117E   > 0FB606         MOVZX EAX,BYTE PTR DS:[ESI]

00401181   . 33C2           XOR EAX,EDX

00401183   . C1E0 0A        SHL EAX,0A

00401186   . 35 F7D04E0A    XOR EAX,0A4ED0F7

0040118B   . 2D 9A020000    SUB EAX,29A

00401190   . 03D8           ADD EBX,EAX

00401192   . 46             INC ESI

00401193   > 803E 00        CMP BYTE PTR DS:[ESI],0

00401196   .^75 E6          JNZ SHORT KeyGenMe.0040117E

00401198   . 68 6F604000    PUSH KeyGenMe.0040606F                   ; /StringToAdd = "-%.d"

0040119D   . 8D85 00FEFFFF  LEA EAX,DWORD PTR SS:[EBP-200]           ; |

004011A3   . 50             PUSH EAX                                 ; |ConcatString

004011A4   . E8 81010000    CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA

004011A9   . 53             PUSH EBX

004011AA   . 8D85 00FEFFFF  LEA EAX,DWORD PTR SS:[EBP-200]           ;  将用户名的字符用整数输出

004011B0   . 50             PUSH EAX                                 ; |Format

004011B1   . 8D85 00FFFFFF  LEA EAX,DWORD PTR SS:[EBP-100]           ; |

004011B7   . 50             PUSH EAX                                 ; |s

004011B8   . E8 85010000    CALL <JMP.&user32.wsprintfA>             ; \wsprintfA

004011BD   . 83C4 0C        ADD ESP,0C

004011C0   . 8D85 00FFFFFF  LEA EAX,DWORD PTR SS:[EBP-100]

004011C6   . 50             PUSH EAX                                 ; /String

004011C7   . E8 70010000    CALL <JMP.&kernel32.lstrlenA>            ; \lstrlenA

004011CC   . 83F8 18        CMP EAX,18

004011CF     76 11          JBE SHORT KeyGenMe.004011E2

004011D1   . 68 FA604000    PUSH KeyGenMe.004060FA                   ; /String2 = "Long Name"

004011D6   . 8D85 00FFFFFF  LEA EAX,DWORD PTR SS:[EBP-100]           ; |

004011DC   . 50             PUSH EAX                                 ; |String1

004011DD   . E8 54010000    CALL <JMP.&kernel32.lstrcpyA>            ; \lstrcpyA

004011E2   > 833D C8614000 >CMP DWORD PTR DS:[4061C8],0

004011E9   . 74 17          JE SHORT KeyGenMe.00401202               ;  只有这个跳转实现了才能获取密码

004011EB   . FF0D C8614000  DEC DWORD PTR DS:[4061C8]

004011F1   . C705 C4614000 >MOV DWORD PTR DS:[4061C4],1

004011FB   .^E9 C8FEFFFF    JMP KeyGenMe.004010C8

00401200   . EB 14          JMP SHORT KeyGenMe.00401216

00401202   > EB 12          JMP SHORT KeyGenMe.00401216

00401204   > 68 74604000    PUSH KeyGenMe.00406074                   ; /Text = "Min 3 charts!"

00401209   . 68 EA030000    PUSH 3EA                                 ; |ControlID = 3EA (1002.)

0040120E   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd

00401211   . E8 50010000    CALL <JMP.&user32.SetDlgItemTextA>       ; \SetDlgItemTextA

00401216   > 68 00010000    PUSH 100                                 ; /Count = 100 (256.)

0040121B   . 8D85 00FDFFFF  LEA EAX,DWORD PTR SS:[EBP-300]           ; |

00401221   . 50             PUSH EAX                                 ; |Buffer

00401222   . 68 EA030000    PUSH 3EA                                 ; |ControlID = 3EA (1002.)

00401227   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd

0040122A   . E8 25010000    CALL <JMP.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA

0040122F   . 8D85 00FDFFFF  LEA EAX,DWORD PTR SS:[EBP-300]           ;  获取密码

00401235   . 50             PUSH EAX                                 ; /String2

00401236   . 8D85 00FFFFFF  LEA EAX,DWORD PTR SS:[EBP-100]           ; |

0040123C   . 50             PUSH EAX                                 ; |String1

0040123D   . E8 EE000000    CALL <JMP.&kernel32.lstrcmpA>            ; \lstrcmpA

00401242   . 0BC0           OR EAX,EAX                               ;  判断是否是0

00401244   . 75 19          JNZ SHORT KeyGenMe.0040125F

00401246   . 6A 20          PUSH 20                                  ; /Style = MB_OK|MB_ICONQUESTION|MB_APPLMODAL

00401248   . 68 15614000    PUSH KeyGenMe.00406115                   ; |Title = "Info"

0040124D   . 68 0C614000    PUSH KeyGenMe.0040610C                   ; |Text = "Good boy"

00401252   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hOwner

00401255   . E8 00010000    CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA

0040125A   . E9 88000000    JMP KeyGenMe.004012E7

0040125F   > E9 83000000    JMP KeyGenMe.004012E7

00401264   > 817D 10 EC0300>CMP DWORD PTR SS:[EBP+10],3EC

0040126B   . 75 7A          JNZ SHORT KeyGenMe.004012E7

0040126D   . 6A 00          PUSH 0

0040126F   . E8 35010000    CALL KeyGenMe.004013A9

00401274   . FF35 D0614000  PUSH DWORD PTR DS:[4061D0]               ; /hMem = NULL

0040127A   . E8 8D000000    CALL <JMP.&kernel32.GlobalFree>          ; \GlobalFree

0040127F   . 6A 00          PUSH 0                                   ; /Result = 0

00401281   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd

00401284   . E8 C5000000    CALL <JMP.&user32.EndDialog>             ; \EndDialog

00401289   . EB 5C          JMP SHORT KeyGenMe.004012E7

0040128B   > 837D 0C 10     CMP DWORD PTR SS:[EBP+C],10

0040128F   . 75 0C          JNZ SHORT KeyGenMe.0040129D

00401291   . 6A 00          PUSH 0                                   ; /Result = 0

00401293   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd

00401296   . E8 B3000000    CALL <JMP.&user32.EndDialog>             ; \EndDialog

0040129B   . EB 4A          JMP SHORT KeyGenMe.004012E7

0040129D   > 817D 0C 100100>CMP DWORD PTR SS:[EBP+C],110

004012A4   . 75 25          JNZ SHORT KeyGenMe.004012CB

004012A6   . 68 B4614000    PUSH KeyGenMe.004061B4                   ; /pLocaltime = KeyGenMe.004061B4

004012AB   . E8 4A000000    CALL <JMP.&kernel32.GetLocalTime>        ; \GetLocalTime

004012B0   . A1 B4614000    MOV EAX,DWORD PTR DS:[4061B4]

004012B5   . A1 B6614000    MOV EAX,DWORD PTR DS:[4061B6]

004012BA   . A1 B8614000    MOV EAX,DWORD PTR DS:[4061B8]

004012BF   . A1 BA614000    MOV EAX,DWORD PTR DS:[4061BA]

004012C4   . A1 BC614000    MOV EAX,DWORD PTR DS:[4061BC]

004012C9   . EB 1C          JMP SHORT KeyGenMe.004012E7

004012CB   > 817D 0C 010200>CMP DWORD PTR SS:[EBP+C],201

004012D2   . 75 13          JNZ SHORT KeyGenMe.004012E7

004012D4   . 8B45 14        MOV EAX,DWORD PTR SS:[EBP+14]

004012D7   . 50             PUSH EAX                                 ; /lParam

004012D8   . 6A 02          PUSH 2                                   ; |wParam = 2

004012DA   . 68 A1000000    PUSH 0A1                                 ; |Message = WM_NCLBUTTONDOWN

004012DF   . FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd

004012E2   . E8 79000000    CALL <JMP.&user32.PostMessageA>          ; \PostMessageA

004012E7   > 33C0           XOR EAX,EAX

004012E9   . C9             LEAVE

004012EA   . C2 1000        RETN 10

暴力破解这东西就不要说了,我们要做的是找到加密过程,然后根据这个加密过程我们写个注册机

我们直接在回调函数下断点。然后跟着走,获取用户名,然后用户名叫经过一系列加密,然后得出一个字符串,,和序列号比较,相等就对。我们的肯定不等那,相等的几率是非常小的。

下面我将自己在跟踪的过程中遇到的加密过程写下,

①获取username

②将username中的字母转换成大写

③进行第一次加密。

对于username中的单号字符,在key1密文中找对应的字符,至于索引的过程,索引号是这样来生成的,

0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z在这串字符中扫描到相等,然后记录下下标比如说A,对应的下标是10,那我就把第Key1中的第十个找出来。

对于username中的双号字符,在key2密文中找对应的字符,跟上面的方法是一样的。

④进行一系列的运算,其实也没几个运算,就像下面那样

00401174   . 8B15 C4614000  MOV EDX,DWORD PTR DS:[4061C4]

0040117A   . 33DB           XOR EBX,EBX

0040117C   . EB 15          JMP SHORT KeyGenMe.00401193

0040117E   > 0FB606         MOVZX EAX,BYTE PTR DS:[ESI]

00401181   . 33C2           XOR EAX,EDX

00401183   . C1E0 0A        SHL EAX,0A

00401186   . 35 F7D04E0A    XOR EAX,0A4ED0F7

0040118B   . 2D 9A020000    SUB EAX,29A

00401190   . 03D8           ADD EBX,EAX

00401192   . 46             INC ESI

00401193   > 803E 00        CMP BYTE PTR DS:[ESI],0

00401196   .^75 E6          JNZ SHORT KeyGenMe.0040117E

迭代求出一个和放进ebx里面,作者还进行了一个比较容易被忽视的处理,00401174   . 8B15 C4614000  MOV EDX,DWORD PTR DS:[4061C4]这一行,个人觉得是用来判断用户名的长度是奇数还是偶数的,因为奇数和偶数加密的过程是不一样的,具体表现在这行指令00401181   . 33C2           XOR EAX,EDX

奇数和偶数edx的值不一样,具体看用vc写的一个控制台的注册码生成的,也没测试几组数据。还望大神指点

#include <stdio.h>
#include <string.h>
//密文1,用于单号字符的加密
char Key1[] = { 'o', '3', 'z', 'Y', 'z', 'a', 'I', '1', '9', '8', '2', 'T', 'v', '2', 'F', 'a', 's', 'g',
'j', 'k', 'k', 'j', 'h', 'k', 'j', 'l', 'J', 't', '5', 'D', 'p', 'e', '3', '2', 'A', 'x' };
//密文2,用于双号密文的加密
char Key2[] = { 'A', 'H', 'y', 'u', 'k', 'j', 's', 'd', 'f', 'k', 'j', 's', 'd', 'f', 'n', 'P', 'Q', 'U',
'5', 'x', 'W', 'E', 'R', 'Y', '6', '7', '3', '4', '5', 'a', 'q', '9', 'n', 'F', 'y', 'R' };
//和用户名对比的表,用来索引密文中的字符
char source[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
int main()
{
char username[24];
int i = 0,length;
long result = 0;
long temp;
printf("输入用户名(只限于3~24个字符):");
scanf("%s",username);
length = strlen(username);
printf("对应的密码是:");
//接下来是运算过程,将用户名加密,在通过用户名的每个字节进行相关的异或运算从而得到一个数字,转换成十进制之后就是了
while(username[i]!='\0')
{
int j = 0;
if((i+1)%2 !=0)			//单号字符处理,从Key1中扫描对比
{

while( j<strlen(source) )
{
if( source[j] == username[i] )
{
//找Key[j]
printf("%c",Key1[j]);
break;
}
else
j++;

}
}
else		//双号字符处理
{
while( j<strlen(source) )
{
if( source[j] == username[i] )
{
//找Key[j]
printf("%c",Key2[j]);
break;
}
else
j++;
}
}
if(length%2 == 0)
username[i] = username[i]^1;
temp = username[i]<<0x0A	;		//左移十位
temp = temp^0xa4ed0f7;		//和0a4ed0f7进行异或运算
temp = temp - 0x29A;			//
result = result + temp;			//这里就是EBX迭代的 过程
i++;
}
printf("-%d\n",result);
return 0;
}
挺累的,破解这东西挺考验耐性和毅力,没耐性没毅力根本坚持不下来,我也只是偶尔练练而已。破文写的还真是破。思想在,表达出来有点问题,感觉代码表达出来的都比自己在这码字表达的清楚。跟我一样新手的朋友可以拿这个软件来玩玩,就觉得在反汇编里面走多了,慢慢路就好走了点
CrackMe可以去我的资源下载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  汇编 破解 加密