【目 标】: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+Eo 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:004010E9j 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:004010DFj 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:004010E4j 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:004010CAj code:00401129 ; code:0040120Fj ... 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:004010EBj 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+47j 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_401163j code:00401152 cmp bl, 5Ah ; 如果用户名大于'Z'则跳去减20h,也就是uCASE code:00401155 jg short UPCASE code:00401157 code:00401157 loc_401157: ; CODE XREF: @UCASE:loc_401176j code:00401157 jmp short loc_401178 code:00401159 ; ---------------------------------------------------------------------------- code:00401159 code:00401159 ADD_20h: ; CODE XREF: @UCASE+13j 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+22j code:00401163 jmp short loc_401152 ; 如果用户名大于'Z'则跳去减20h,也就是uCASE code:00401165 ; ---------------------------------------------------------------------------- code:00401165 code:00401165 UPCASE: ; CODE XREF: @UCASE+18j 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+2Ej 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+35j code:00401176 jmp short loc_401157 code:00401178 ; ---------------------------------------------------------------------------- code:00401178 code:00401178 loc_401178: ; CODE XREF: @UCASE:loc_401157j 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:00401198j 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:004011DCj 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:004011CBj code:004011CF add bl, 11h ; 如果值小于':'则加11h code:004011D2 mov ds:sz_save_fmstr[ecx], bl code:004011D8 code:004011D8 loc_4011D8: ; CODE XREF: code:004011CDj 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:004011F7j 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:00401231j 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:004010FCj code:00401242 ; code:00401110j ... code:00401242 popa code:00401243 jmp short loc_401257 code:00401245 ; ----------------------------------------------------------------------------
算法总结: 又抓了个软杮子, 算法也是非常这简单的,先把注册名转为大写,然后替换固定字符串里奇数位的字符,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] Email:loveboom#163.com Date:2005-6-13 14:32
|