发新话题
打印

[转载]Diablo 2oo2's CrackMe 2算法分析

[转载]Diablo 2oo2's CrackMe 2算法分析

作者:loveboom[DFCG][FCG][US]
信息来源:看雪技术论坛

【目    标】:Diablo 2oo2’s CrackMe 2
【工    具】:IDA 4.7
【任    务】:算法分析
【操作平台】:Windows 2003 server
【作    者】: LOVEBOOM[DFCG][FCG][US]
【相关链接】: 见附件
【简要说明】: 用IDA再分析一篇简单的算法。
【详细过程】:
因为CRACKME是用masm写的,所以非常方便分析的。这次目标用yoda加了壳,怎么脱壳我就不说了,很简单的。脱壳后,用IDA分析一下结果就出来了:
code:00401028 DialogFunc:                          ; DATA XREF: start+E o
code:00401028            push   ebp
code:00401029            mov    ebp, esp
code:0040102B            cmp    dword ptr [ebp+0Ch], 111h
code:00401032            jnz    loc_401245
code:00401038            mov    eax, [ebp+10h]        ; CASE EAX==WM_COMMAND
code:0040103B            cmp    ax, 65h
code:0040103F            jnz    loc_40125D
code:00401045            pusha                    ; CASE AX==IDC_BTN_CHECKREG
code:00401046            mov    byte ptr ds:UCASE_Buffer, 53h ; "SJKAZBVTECGIDFNG"
code:0040104D            mov    byte ptr ds:UCASE_Buffer+1, 4Ah
code:00401054            mov    byte ptr ds:UCASE_Buffer+2, 4Bh
code:0040105B            mov    byte ptr ds:UCASE_Buffer+3, 41h
code:00401062            mov    byte ptr ds:UCASE_Buffer+4, 5Ah
code:00401069            mov    byte ptr ds:UCASE_Buffer+5, 42h
code:00401070            mov    byte ptr ds:UCASE_Buffer+6, 56h
code:00401077            mov    byte ptr ds:UCASE_Buffer+7, 54h
code:0040107E            mov    byte ptr ds:UCASE_Buffer+8, 45h
code:00401085            mov    byte ptr ds:UCASE_Buffer+9, 43h
code:0040108C            mov    byte ptr ds:UCASE_Buffer+0Ah, 47h
code:00401093            mov    byte ptr ds:UCASE_Buffer+0Bh, 49h
code:0040109A            mov    byte ptr ds:UCASE_Buffer+0Ch, 44h
code:004010A1            mov    byte ptr ds:UCASE_Buffer+0Dh, 46h
code:004010A8            mov    byte ptr ds:UCASE_Buffer+0Eh, 4Eh
code:004010AF            mov    byte ptr ds:UCASE_Buffer+0Fh, 47h ; 准备获取注册码
code:004010B6            push   28h                ; nMaxCount
code:004010B8            push   offset SN_Buffer       ; lpString
code:004010BD            push   68h                ; nIDDlgItem
code:004010BF            push   dword ptr [ebp+8]      ; hDlg
code:004010C2            call   GetDlgItemTextA        ; 获取注册码
code:004010C7            cmp    eax, 10h
code:004010CA            jnz    short Reg_Failed       ; 比较注册码,如果注册码长度不是10h则over
code:004010CC            push   28h                ; nMaxCount
code:004010CE            push   offset SzName_Buffer    ; lpString
code:004010D3            push   67h                ; nIDDlgItem
code:004010D5            push   dword ptr [ebp+8]      ; hDlg
code:004010D8            call   GetDlgItemTextA        ; 获取用户名
code:004010DD            test   eax, eax
code:004010DF            jz    short loc_401101
code:004010E1            cmp    eax, 8              ; 用户名长度不能大于8
code:004010E4            jg    short loc_401115
code:004010E6            cmp    eax, 1              ; 如果用户名小于1则提示,问题提示,后面的提示最少2位,这里判断却是不为空就算过关了
code:004010E9            jl    short loc_4010ED
code:004010EB            jmp    short @UCASE          ; 这里实际就是一个转为大写的函数。
code:004010EB                                  ; 如果小于'A'则加20h,相加后值还是小于'A'则把字符转为'F'
code:004010EB                                  ; 如果大于'Z'则减20h(就是转为大写),运算值大于'Z'则字符转为'G'
code:004010EB                                  ; 运算值小于'A',则把字符转为'S'
code:004010ED ; ----------------------------------------------------------------------------
code:004010ED
code:004010ED loc_4010ED:                          ; CODE XREF: code:004010E9 j
code:004010ED            push   offset aNameMustBeAtLe   ; lpString
code:004010F2            push   68h                ; nIDDlgItem
code:004010F4            push   dword ptr [ebp+8]      ; hDlg
code:004010F7            call   SetDlgItemTextA        ; 显示错误信息 
code:004010FC            jmp    loc_401242
code:00401101 ; ----------------------------------------------------------------------------
code:00401101
code:00401101 loc_401101:                          ; CODE XREF: code:004010DF j
code:00401101            push   offset aEnterAName      ; lpString
code:00401106            push   68h                ; nIDDlgItem
code:00401108            push   dword ptr [ebp+8]      ; hDlg
code:0040110B            call   SetDlgItemTextA
code:00401110            jmp    loc_401242
code:00401115 ; ----------------------------------------------------------------------------
code:00401115
code:00401115 loc_401115:                          ; CODE XREF: code:004010E4 j
code:00401115            push   offset aNameIsTooLong    ; lpString
code:0040111A            push   68h                ; nIDDlgItem
code:0040111C            push   dword ptr [ebp+8]      ; hDlg
code:0040111F            call   SetDlgItemTextA
code:00401124            jmp    loc_401242
code:00401129 ; ----------------------------------------------------------------------------
code:00401129
code:00401129 Reg_Failed:                          ; CODE XREF: code:004010CA j
code:00401129                                  ; code:0040120F j ...
code:00401129            push   offset String         ; lpString
code:0040112E            push   68h                ; nIDDlgItem
code:00401130            push   dword ptr [ebp+8]      ; hDlg
code:00401133            call   SetDlgItemTextA
code:00401138            jmp    loc_401242
code:0040113D
code:0040113D ; ************** S U B R O U T I N E *****************************************
code:0040113D
code:0040113D ; 这里实际就是一个转为大写的函数。
code:0040113D ; 如果小于'A'则加20h,相加后值还是小于'A'则把字符转为'F'
code:0040113D ; 如果大于'Z'则减20h(就是转为大写),运算值大于'Z'则字符转为'G'
code:0040113D ; 运算值小于'A',则把字符转为'S'
code:0040113D
code:0040113D @UCASE       proc near                 ; CODE XREF: code:004010EB j
code:0040113D            xor    ebx, ebx
code:0040113F            xor    ecx, ecx            ; 初始化相关寄存器
code:00401141            xor    edx, edx
code:00401143            xor    edi, edi
code:00401145            xor    esi, esi
code:00401147
code:00401147 loc_401147:                          ; CODE XREF: @UCASE+47 j
code:00401147            mov    bl, ds:SzName_Buffer[ecx]
code:0040114D            cmp    bl, 41h             ; 如果用户名小于'A'则跳去加20h
code:00401150            jl    short ADD_20h
code:00401152
code:00401152 loc_401152:                          ; CODE XREF: @UCASE:loc_401163 j
code:00401152            cmp    bl, 5Ah             ; 如果用户名大于'Z'则跳去减20h,也就是uCASE
code:00401155            jg    short UPCASE
code:00401157
code:00401157 loc_401157:                          ; CODE XREF: @UCASE:loc_401176 j
code:00401157            jmp    short loc_401178
code:00401159 ; ----------------------------------------------------------------------------
code:00401159
code:00401159 ADD_20h:                            ; CODE XREF: @UCASE+13 j
code:00401159            add    bl, 20h
code:0040115C            cmp    bl, 41h             ; 如果+20后还是小于41则直接置BL为46H('F')
code:0040115F            jge    short loc_401163
code:00401161            mov    bl, 46h
code:00401163
code:00401163 loc_401163:                          ; CODE XREF: @UCASE+22 j
code:00401163            jmp    short loc_401152       ; 如果用户名大于'Z'则跳去减20h,也就是uCASE
code:00401165 ; ----------------------------------------------------------------------------
code:00401165
code:00401165 UPCASE:                             ; CODE XREF: @UCASE+18 j
code:00401165            sub    bl, 20h
code:00401168            cmp    bl, 5Ah             ; 如果-20小于或等于则跳
code:0040116B            jle    short loc_40116F       ; 如果减后小于'A'则改为'S'
code:0040116D            mov    bl, 47h             ; 如果-20后还是大于'Z'则把BL改为'D'
code:0040116F
code:0040116F loc_40116F:                          ; CODE XREF: @UCASE+2E j
code:0040116F            cmp    bl, 41h             ; 如果减后小于'A'则改为'S'
code:00401172            jge    short loc_401176
code:00401174            mov    bl, 53h
code:00401176
code:00401176 loc_401176:                          ; CODE XREF: @UCASE+35 j
code:00401176            jmp    short loc_401157
code:00401178 ; ----------------------------------------------------------------------------
code:00401178
code:00401178 loc_401178:                          ; CODE XREF: @UCASE:loc_401157 j
code:00401178            mov    byte ptr ds:UCASE_Buffer[edx], bl ; "SJKAZBVTECGIDFNG"
code:0040117E            add    edx, 2              ; 每次加2,替换原有的数据,偶数替换
code:00401181            inc    ecx
code:00401182            cmp    ecx, eax
code:00401184            jnz    short loc_401147
code:00401184 @UCASE       endp
code:00401184
code:00401186            xor    ecx, ecx            ; 初始化相关寄存器
code:00401188            xor    edx, edx
code:0040118A            xor    ebx, ebx
code:0040118C
code:0040118C Lp_Sum_value:                         ; CODE XREF: code:00401198 j
code:0040118C            mov    bl, byte ptr ds:UCASE_Buffer[ecx] ; 取出转为大写后字符
code:00401192            add    edx, ebx            ; 计算大写替换后字符串的和sumValue
code:00401194            inc    ecx
code:00401195            cmp    ecx, 10h
code:00401198            jnz    short Lp_Sum_value      ; 取出转为大写后字符
code:0040119A            imul   eax, 0FFh            ; 用户名长度乘以0FFh的值key1
code:004011A0            imul   edx, eax            ; 再用key1乘以sumValue,设为imulvalue
code:004011A3            xor    edx, 0ACEBDFABh        ; 用imulValue 异或常数0ACEBDFABH的值设为XorValue
code:004011A9            bswap  edx                ; 计算出的xorValue反转
code:004011AB            push   edx
code:004011AC            push   offset szLx          ; "%lX"
code:004011B1            push   offset sz_save_fmstr    ; 转换后的十六进制值输出为字符串
code:004011B6            call   wsprintfA
code:004011BB            add    esp, 0Ch
code:004011BE            xor    ebx, ebx
code:004011C0            xor    ecx, ecx
code:004011C2
code:004011C2 loc_4011C2:                          ; CODE XREF: code:004011DC j
code:004011C2            mov    bl, ds:sz_save_fmstr[ecx]
code:004011C8            cmp    bl, 3Ah             ; 比较值是否小于':'
code:004011CB            jl    short jl3a           ; 如果值小于':'则加11h
code:004011CD            jmp    short loc_4011D8
code:004011CF ; ----------------------------------------------------------------------------
code:004011CF
code:004011CF jl3a:                              ; CODE XREF: code:004011CB j
code:004011CF            add    bl, 11h             ; 如果值小于':'则加11h
code:004011D2            mov    ds:sz_save_fmstr[ecx], bl
code:004011D8
code:004011D8 loc_4011D8:                          ; CODE XREF: code:004011CD j
code:004011D8            inc    ecx
code:004011D9            cmp    ecx, 8
code:004011DC            jnz    short loc_4011C2       ; 循环判断替换
code:004011DE            xor    ebx, ebx
code:004011E0            xor    ecx, ecx
code:004011E2            xor    edx, edx
code:004011E4
code:004011E4 loc_4011E4:                          ; CODE XREF: code:004011F7 j
code:004011E4            mov    bl, ds:sz_save_fmstr[ecx] ; 再次取出运算后的值
code:004011EA            mov    byte ptr ds:(UCASE_Buffer+1)[edx], bl ; 奇数替换字符
code:004011F0            add    edx, 2
code:004011F3            inc    ecx
code:004011F4            cmp    edx, 10h
code:004011F7            jnz    short loc_4011E4       ; 再次取出运算后的值
code:004011F9            xor    ebx, ebx
code:004011FB            xor    ecx, ecx
code:004011FD            xor    edx, edx
code:004011FF            xor    eax, eax
code:00401201
code:00401201 Loop_Compare_Data:                      ; CODE XREF: code:00401231 j
code:00401201            mov    bl, ds:SN_Buffer[edx]    ; 取出假码
code:00401207            mov    al, byte ptr ds:UCASE_Buffer[edx] ; 取出真码
code:0040120D            xor    eax, ebx
code:0040120F            jnz    Reg_Failed           ; 如果不相等则over
code:00401215            mov    bl, ds:byte_4030C9[edx]
code:0040121B            mov    al, byte ptr ds:(UCASE_Buffer+1)[edx]
code:00401221            add    al, 5              ; 比较真注册码的偶数位-5是否等于假码的偶数位
code:00401223            cmp    bl, al
code:00401225            jnz    Reg_Failed
code:0040122B            add    edx, 2
code:0040122E            cmp    edx, 10h
code:00401231            jnz    short Loop_Compare_Data  ; 取出假码
code:00401233            push   offset aThankYouForYou   ; lpString
code:00401238            push   68h                ; nIDDlgItem
code:0040123A            push   dword ptr [ebp+8]      ; hDlg
code:0040123D            call   SetDlgItemTextA        ; 显示正确信息
code:00401242
code:00401242 loc_401242:                          ; CODE XREF: code:004010FC j
code:00401242                                  ; code:00401110 j ...
code:00401242            popa
code:00401243            jmp    short loc_401257
code:00401245 ; ----------------------------------------------------------------------------


算法总结:
   又抓了个软?#123;子, 算法也是非常这简单的,先把注册名转为大写,然后替换固定字符串里奇数位的字符,s1,然后把s1的值累加s2,s2*0ff*用户名长度key1,key1再异或固定值0ACEBDFABh结果保存为key2,key2的每一位比较是否小于’:’,小于则加上11h,然后再加上5,结果替换固定字符串里偶数位的字符。

Greetz:
Fly.Jingulong,yock,tDasm.David.hexer,hmimys,ahao.UFO(brother).alan(sister).all of my friends and you!

                   By loveboom[DFCG][FCG][US]
                   http://blog.csdn.net/bmd2chen
                   Email:loveboom#163.com
                   Date:2005-6-13 14:32

附件:cme2.rar
http://bbs.pediy.com/upload/2005/4/files/cme2.rar
没有被评为38组织一员感到十分遗憾! 原因是我现在没有签名,我没有签名的原因是我没有想出很好的签名来,所以我的签名现在还没有签名,你说我把这段话作为签名算不算签名?

TOP

发新话题