-
-
[旧帖] [原创][申请激活码]某个crackme的详细分析 0.00雪花
-
2013-9-22 21:30 1696
-
对一个crackme的详细分析,该crackme 带有MD5算法,还有对Serial进行Base64Decode,大量的运算与比较。不知道有没有人分析过。好吧开始,我一直喜欢IDA,因为F8手指头会累
PS:你喷或者不喷,我就是菜鸟一个,经得起风雨。
IDA代码
对use_byarry_16进行大量的算法,最后赋值给use_key[] {第一位,第二位,第三位,第四位}
Use_byarry_16决定use_key[]的值。
到此已经把每个函数都分析完毕,不对的地方求指导。
代码量太大,总结一下吧
1、注册码 链接固定字符串-"-diablo2oo2” ,长度加0Bh
2、在NameFunc函数中运算得到 use_byarry_16数组
3、在GetNewUse_key函数中根据use_byarry_16数组获取use_key[]
4、ChangeArray函数use_key[]一系列运算结果给newarry
5、SerialFunc函数 serial base64运算,放在newarry1中
6、ChangeArray1函数中 对newarry[]进行运算赋值给newarry2[] 8为循环
7、MMXcode 函数中 浮点运算 对newarry1扩展结果放在newarry2[]
8、 ChangeArray2 函数中 对newarry1[]进行运算赋值给newarry3[] 80h为循环
9、 cmpArray 函数中 newarry[]与newarry3[]运算后的相比较,必须相等 不相等就over
A、 check_serialFunc 函数中 16+16+16 = 48 次 use_key[]验证,有一次不相等就Over
闲得无聊我把改程序还原了一下,不敢说是逆向,怕笑掉大家的大牙。注册机不会写,没有头绪,运算太多了。
附上还原的Radasm工程文件和源代码还有IDA分析的idb文件
PS其实不敢上传IDB文件因为变量写的太烂了,请不要喷的太厉害。
PS:你喷或者不喷,我就是菜鸟一个,经得起风雨。
IDA代码
.text:00401000 start proc near .text:00401000 call InitCommonControls .text:00401005 push 0 ; lpModuleName .text:00401007 call GetModuleHandleA .text:0040100C mov hInstance, eax .text:00401011 push 0 ; dwInitParam .text:00401013 push offset DialogFunc ; lpDialogFunc //这里没什么说的 .text:00401018 push 0 ; hWndParent .text:0040101A push offset TemplateName ; "MAIN_WINDOW" .text:0040101F push hInstance ; hInstance .text:00401025 call DialogBoxParamA .text:0040102A push 0 ; uExitCode .text:0040102C call ExitProcess .text:0040102C start endp .text:0040102C .text:00401040 ; INT_PTR __stdcall DialogFunc(HWND, UINT, WPARAM, LPARAM) .text:00401040 DialogFunc proc near ; DATA XREF: start+13o .text:00401040 .text:00401040 serial = dword ptr -800h .text:00401040 Name = byte ptr -400h .text:00401040 hWnd = dword ptr 8 .text:00401040 arg_4 = dword ptr 0Ch .text:00401040 arg_8 = dword ptr 10h .text:00401040 .text:00401040 push ebp .text:00401041 mov ebp, esp .text:00401043 add esp, 0FFFFF800h .text:00401049 push ebx .text:0040104A push esi .text:0040104B push edi .text:0040104C mov eax, [ebp+arg_4] .text:0040104F cmp eax, 110h .text:00401054 jnz short loc_40105B .text:00401056 jmp loc_4010FF .text:0040105B ; --------------------------------------------------------------------------- .text:0040105B loc_40105B: ; CODE XREF: DialogFunc+14j .text:0040105B cmp eax, 111h .text:00401060 jnz loc_4010F0 .text:00401066 mov eax, [ebp+arg_8] .text:00401069 cmp ax, 67h .text:0040106D jnz loc_4010FF .text:00401073 push 400h ; cchMax .text:00401078 lea eax, [ebp+Name] .text:0040106D jnz loc_4010FF .text:00401073 push 400h ; cchMax .text:00401078 lea eax, [ebp+Name] ;name .text:0040107E push eax ; lpString .text:0040107F push 65h ; nIDDlgItem .text:00401081 push [ebp+hWnd] ; hDlg .text:00401084 call GetDlgItemTextA .text:00401089 push 400h ; cchMax .text:0040108E lea eax, [ebp+serial] ;注册码 .text:00401094 push eax ; lpString .text:00401095 push 66h ; nIDDlgItem .text:00401097 push [ebp+hWnd] ; hDlg .text:0040109A call GetDlgItemTextA .text:0040109F lea eax, [ebp+serial] .text:004010A5 push eax ; serial .text:004010A6 lea eax, [ebp+Name] .text:004010AC push eax ; Name .text:004010AD push [ebp+hWnd] ; hWnd .text:004010B0 call CheckSerialFunc ;重要Call .text:004010B5 cmp eax, 1 ; 关键跳 爆破点 .text:004010B8 jnz short loc_4010C6 .text:004010BA mov edx, offset Text ; "Serial is OK!" .text:004010BF mov ecx, 40h .text:004010C4 jmp short loc_4010DF .text:004010C6 ; --------------------------------------------------------------------------- .text:004010C6 loc_4010C6: ; CODE XREF: DialogFunc+78j .text:004010C6 or eax, eax .text:004010C8 jnz short loc_4010D6 .text:004010CA mov edx, offset aWrongSerial ; "Wrong Serial" .text:004010CF mov ecx, 40h .text:004010D4 jmp short loc_4010DF .text:004010D6 ; --------------------------------------------------------------------------- .text:004010D6 loc_4010D6: ; CODE XREF: DialogFunc+88j .text:004010D6 xor eax, eax .text:004010D8 pop edi .text:004010D9 pop esi .text:004010DA pop ebx .text:004010DB leave .text:004010DC retn 10h .text:004010DF ; --------------------------------------------------------------------------- .text:004010DF loc_4010DF: ; CODE XREF: DialogFunc+84j .text:004010DF ; DialogFunc+94j .text:004010DF push ecx ; uType .text:004010E0 push offset Caption ; "Hey Cracker" .text:004010E5 push edx ; lpText .text:004010E6 push [ebp+hWnd] ; hWnd .text:004010E9 call MessageBoxA .text:004010EE jmp short loc_4010FF .text:004010F0 ; --------------------------------------------------------------------------- .text:004010F0 loc_4010F0: ; CODE XREF: DialogFunc+20j .text:004010F0 cmp eax, 10h .text:004010F3 jnz short loc_4010FF .text:004010F5 push 0 ; nResult .text:004010F7 push [ebp+hWnd] ; hDlg .text:004010FA call EndDialog .text:004010FF .text:004010FF loc_4010FF: ; CODE XREF: DialogFunc+16j .text:004010FF ; DialogFunc+2Dj ... .text:004010FF xor eax, eax .text:00401101 pop edi .text:00401102 pop esi .text:00401103 pop ebx .text:00401104 leave .text:00401105 retn 10h .text:00401105 DialogFunc endp 现在对CheckSerialFunc函数进行分析,如下(变量我都改了,大家就讲究的看吧,好吧): ; int __stdcall CheckSerialFunc(HWND hWnd, LPCSTR Name, int serial) .text:00401108 CheckSerialFunc proc near ; CODE XREF: DialogFunc+70p .text:00401108 .text:00401108 newarry1[] = byte ptr -21Ch .text:00401108 newarry3[] = byte ptr -11Ch .text:00401108 newarry2[] = byte ptr -1Ch .text:00401108 newarry[] = byte ptr -14h .text:00401108 len_name = dword ptr -4 .text:00401108 hWnd = dword ptr 8 .text:00401108 Name = dword ptr 0Ch .text:00401108 serial = dword ptr 10h .text:00401108 .text:00401108 push ebp .text:00401109 mov ebp, esp .text:0040110B add esp, 0FFFFFDE4h .text:00401111 push [ebp+Name] ; lpString .text:00401114 call lstrlenA .text:00401119 or eax, eax .text:0040111B jnz short loc_401137 .text:0040111D push 30h ; uType .text:0040111F push 0 ; lpCaption .text:00401121 push offset aNoNameEntered ; "no name entered" .text:00401126 push [ebp+hWnd] ; hWnd .text:00401129 call MessageBoxA .text:0040112E mov eax, 0FFFFFFFFh .text:00401133 leave .text:00401134 retn 0Ch .text:00401137 ; --------------------------------------------------------------------------- .text:00401137 loc_401137: ; CODE XREF: CheckSerialFunc+13j .text:00401137 mov [ebp+len_name], eax .text:0040113A push [ebp+serial] ; lpString .text:0040113D call lstrlenA .text:00401142 or eax, eax .text:00401144 jnz short loc_401160 .text:00401146 push 30h ; uType .text:00401148 push 0 ; lpCaption .text:0040114A push offset aNoSerialEntere ; "no serial entered" .text:0040114F push [ebp+hWnd] ; hWnd .text:00401152 call MessageBoxA .text:00401157 mov eax, 0FFFFFFFFh .text:0040115C leave .text:0040115D retn 0Ch .text:00401160 ; --------------------------------------------------------------------------- .text:00401160 loc_401160: ; CODE XREF: CheckSerialFunc+3Cj .text:00401160 call usefull_var_init ; 变量初始化 .text:00401165 push offset String2 ; "-diablo2oo2" .text:0040116A push [ebp+Name] ; lpString1 .text:0040116D call lstrcatA ; 链接固定字符串 .text:00401172 add [ebp+len_name], 0Bh ; len_name+固定字符串的长度,以后len_name就是加上0bh的长度 .text:00401176 push [ebp+len_name] ;len_name .text:00401179 push [ebp+Name] ;Name .text:0040117C call NameFunc ; 判断len_name 将name复制给数组 use_byarry_16 .text:00401181 call GetNewUse_key ; 获得新的use_key[] .text:00401186 mov ecx, eax ; ecx = eax = use_key[] .text:00401188 lea eax, [ebp+newarry[]] .text:0040118B push eax ; 新数组,用于接收新数据 .text:0040118C push ecx ; new_use_key[] .text:0040118D call ChangeArray ; 经过一系列运算,复制给新数组newarry[] .text:00401192 lea eax, [ebp+newarry1[]] ; 传递地址 newarry1[] = newarry[] .text:00401198 push eax ; 新数组newarry1[] .text:00401199 push [ebp+serial] ; serial .text:0040119C call SerialFunc ; 对serial进行运算 和base64运算很相似, .text:004011A1 push 8 .text:004011A3 lea eax, [ebp+newarry2[]] .text:004011A6 push eax .text:004011A7 lea eax, [ebp+newarry[]] .text:004011AA push eax .text:004011AB call ChangeArray1 ; 对newarry[]进行运算赋值给newarry2[] 8为循环数 .text:004011B0 lea eax, [ebp+newarry2[]] .text:004011B3 push eax .text:004011B4 lea eax, [ebp+newarry1[]] .text:004011BA push eax .text:004011BB call MMXcode ; 浮点运算 结果放在newarry2[] .text:004011C0 push 80h .text:004011C5 lea eax, [ebp+newarry3[]] .text:004011CB push eax .text:004011CC lea eax, [ebp+newarry1[]] .text:004011D2 push eax .text:004011D3 call ChangeArray2 ; 对newarry1[]进行运算赋值给newarry3[] 80h为循环数 .text:004011D8 lea eax, [ebp+newarry[]] .text:004011DB push eax .text:004011DC lea eax, [ebp+newarry3[]] .text:004011E2 push eax .text:004011E3 call cmpArray ; newarry[]与newarry3[]运算后的相比较,必须相等 eax = 0 证明不同,反之相等 .text:004011E8 or eax, eax .text:004011EA jnz short loc_4011F2 ; 不等于0跳走 .text:004011EC xor eax, eax ; 等于0 ,清空eax,就完蛋 .text:004011EE leave .text:004011EF retn 0Ch .text:004011F2 ; --------------------------------------------------------------------------- .text:004011F2 .text:004011F2 loc_4011F2: ; CODE XREF: CheckSerialFunc+E2j .text:004011F2 lea eax, [ebp+newarry3[]] .text:004011F8 push eax .text:004011F9 call check_serialFunc ; 再次验证一次 .text:004011FE or eax, eax ; eax == 0 ? .text:00401200 jnz short loc_401208 ; 不等于跳走 .text:00401202 xor eax, eax .text:00401204 leave .text:00401205 retn 0Ch .text:00401208 ; --------------------------------------------------------------------------- .text:00401208 .text:00401208 loc_401208: ; CODE XREF: CheckSerialFunc+F8j .text:00401208 mov eax, 1 ; 赋值eax = 1,就是成功 .text:0040120D leave .text:0040120E retn 0Ch .text:0040120E CheckSerialFunc endp 一、usefull_var_init函数进行分析,如下 .text:00404828 usefull_var_init proc near ; CODE XREF: CheckSerialFunc:loc_401160p .text:00404828 ; check_serialFunc+5Dp ... .text:00404828 push edi .text:00404829 xor eax, eax .text:0040482B mov dwFlag1, eax ;标志 后面会用到,赋值 0 .text:00404830 xor eax, eax .text:00404832 mov dwFlag2, eax ;标志 后面会用到,赋值 0 .text:00404837 mov edi, offset use_byarry_16_ .text:0040483C mov ecx, 10h .text:00404841 rep stosd ;将数组use_byarry_16初始化 .text:00404843 mov eax, offset use_key__ ;将use_key[]赋值{1,2,3,,,D,E,F} .text:00404848 mov dword ptr [eax], 67452301h .text:0040484E mov dword ptr [eax+4], 0EFCDAB89h .text:00404855 mov dword ptr [eax+8], 98BADCFEh .text:0040485C mov dword ptr [eax+0Ch], 10325476h .text:00404863 pop edi .text:00404864 retn .text:00404864 usefull_var_init endp C代码解释 { dwFlag1 = 0; dwFlag2 = 0; memset(&use_byarry_16_, 0, 0x40u); use_key__[0] = 67452301h; use_key__[1] = -0EFCDAB89h; use_key__[2] = -98BADCFEh; use_key__[3] = 10325476h; } 二、对NameFunc进行分析,分析如下 text:00404868 NameFunc proc near ; CODE XREF: CheckSerialFunc+74p .text:00404868 ; check_serialFunc+65p ... .text:00404868 .text:00404868 name = dword ptr 8 .text:00404868 len_name = dword ptr 0Ch .text:00404868 .text:00404868 push ebp .text:00404869 mov ebp, esp .text:0040486B push esi .text:0040486C push edi .text:0040486D push ebx .text:0040486E mov ebx, [ebp+len_name] .text:00404871 mov esi, [ebp+name] .text:00404874 add dwFlag1, ebx ; len_name .text:0040487A jmp short loc_4048BC ; len_name = 0? .text:0040487C ; --------------------------------------------------------------------------- .text:0040487C .text:0040487C loc_40487C: ; CODE XREF: NameFunc+56j .text:0040487C mov eax, dwFlag2 ; (dwFlag1 = 0初始化时)赋值给ecx .text:00404881 mov ecx, 40h .text:00404886 sub ecx, eax ; ecx = 40h - dwFlag2 .text:00404888 lea edi, use_byarry_16_[eax] ; 传递数组地址 .text:0040488E cmp ecx, ebx ; ecx值与len_name比较大于就跳走 .text:00404890 ja short loc_4048B0 ; ecx赋值给ecx .text:00404892 sub ebx, ecx ; 小于情况 len_name - ecx .text:00404894 rep movsb ; esi->edi esi为name 传递给use_byarry_16_数组 .text:00404896 call MD5_HashFunc ; 大于情况 MD5_hash 算法,利用新的use_byarry_16 获取新的use_key .text:0040489B xor eax, eax .text:0040489D mov dwFlag2, eax .text:004048A2 mov edi, offset use_byarry_16_ .text:004048A7 mov ecx, 10h .text:004048AC rep stosd ;; esi->edi esi为name 传递给use_byarry_16_数组 .text:004048AE jmp short loc_4048BC ; len_name = 0? .text:004048B0 ; --------------------------------------------------------------------------- .text:004048B0 .text:004048B0 loc_4048B0: ; CODE XREF: NameFunc+28j .text:004048B0 mov ecx, ebx ; ecx赋值给ecx .text:004048B2 rep movsb ; esi->edi esi为name 传递给use_byarry_16_数组 .text:004048B4 add dwFlag2, ebx ; dwFlag2+len_name .text:004048BA jmp short loc_4048C0 .text:004048BC ; --------------------------------------------------------------------------- .text:004048BC .text:004048BC loc_4048BC: ; CODE XREF: NameFunc+12j .text:004048BC ; NameFunc+46j .text:004048BC or ebx, ebx ; len_name = 0? .text:004048BE jnz short loc_40487C ; (dwFlag1 = 0初始化时)赋值给ecx .text:004048C0 .text:004048C0 loc_4048C0: ; CODE XREF: NameFunc+52j .text:004048C0 pop ebx .text:004048C1 pop edi .text:004048C2 pop esi .text:004048C3 leave .text:004048C4 retn 8 .text:004048C4 NameFunc endp 小于的时候,很简单就如下 If(40h - (dwFalg1+len_name) ) { Use_bayarry_16 = name dwFalg2+= len_name } IDA F5出来的好像很正确,嘿嘿 v2 = len_name; v3 = name; dwFlag1 += len_name; while ( v2 ) { result = dwFlag2; v5 = 64 - dwFlag2; v6 = &use_byarry_16_[dwFlag2]; if ( 64 - dwFlag2 > v2 ) { memcpy(v6, v3, v2); dwFlag2 += v2; return result; } v2 -= v5; memcpy(v6, v3, v5); v3 = (char *)v3 + v5; MD5_HashFunc(); result = 0; dwFlag2 = 0; memset(use_byarry_16_, 0, 0x40u); } return result; 三 、对GetNewUse_key 进行分析 .text:004048C8 GetNewUse_key proc near ; CODE XREF: CheckSerialFunc+79p .text:004048C8 ; check_serialFunc+6Ap ... .text:004048C8 push esi .text:004048C9 push edi .text:004048CA mov ecx, dwFlag2 ; Flag2 = len_name .text:004048D0 mov use_byarry_16_[ecx], 80h ; 数组最后一位 +1 赋值 80h 应该是标记 .text:004048D7 cmp ecx, 38h ; 再次判断len_name > 38h ?小于跳走 .text:004048DA jb short loc_4048F4 ; 此时Flag1 = len_name .text:004048DC call MD5_HashFunc ;MD5 .text:004048E1 xor eax, eax .text:004048E3 mov dwFlag2, eax .text:004048E8 mov edi, offset use_byarry_16_ .text:004048ED mov ecx, 10h .text:004048F2 rep stosd .text:004048F4 .text:004048F4 loc_4048F4: ; CODE XREF: GetNewUse_key+12j .text:004048F4 mov eax, dwFlag1 ; 此时Flag1 = len_name .text:004048F9 xor edx, edx ; 清空edx .text:004048FB shld edx, eax, 3 ; 双精度左移位指令 .text:004048FF shl eax, 3 ; 左移3 .text:00404902 mov dwVar1, eax ; 赋值给变量 .text:00404907 mov dwVar2, edx ; 赋值给变量 .text:0040490D call MD5_HashFunc ; MD5算法 得到新的use_key[] .text:00404912 mov eax, offset use_key__ ; 得到新的use_key 复制给 eax .text:00404917 pop edi .text:00404918 pop esi .text:00404919 retn .text:00404919 GetNewUse_key endp 上个函数 dwFlag2已将赋值 { unsigned __int64 v2; // kr08_8@3 use_byarry_16_[dwFlag2] = -128; if ( dwFlag2>= 0x38 ) { MD5_HashFunc(); dwFlag2 = 0; memset(use_byarry_16_, 0, 0x40u); } mov eax, dwFlag1 xor edx, edx shld edx, eax, 3 shl eax, 3 mov dwVar1, eax mov dwVar2, edx MD5_HashFunc(); mov eax, offset use_key__ } 最后返回的是改变后的use_key,use_key 是数组,返回的也就是首地址 四、ChangeArray函数进行分析 ..text:0040153B ChangeArray proc near ; CODE XREF: CheckSerialFunc+85p .text:0040153B .text:0040153B var_2 = byte ptr -2 .text:0040153B var_1 = byte ptr -1 .text:0040153B use_key[] = dword ptr 8 .text:0040153B newarry[] = dword ptr 0Ch .text:0040153B .text:0040153B push ebp .text:0040153C mov ebp, esp .text:0040153E add esp, 0FFFFFFFCh .text:00401541 push esi .text:00401542 push edi .text:00401543 push ebx .text:00401544 mov esi, [ebp+use_key[]] .text:00401547 mov edi, [ebp+newarry[]] .text:0040154A xor ecx, ecx ; 清空ecx .text:0040154C jmp short loc_401552 ; for(i = 0;i!= 16; ++i) .text:0040154E ; --------------------------------------------------------------------------- .text:0040154E .text:0040154E loc_40154E: ; CODE XREF: ChangeArray+1Aj .text:0040154E mov [ecx+edi], cl ;对newaarry进行赋值 .text:00401551 inc ecx .text:00401552 .text:00401552 loc_401552: ; CODE XREF: ChangeArray+11j .text:00401552 cmp ecx, 10h ; 循环控制 = 10h?? .text:00401555 jnz short loc_40154E ; 最后填充newarry[] = {1,2,3...D,E,F} .text:00401557 mov [ebp+var_2], 0 ; 赋值0 .text:0040155B jmp short loc_40158E .text:0040155D ; --------------------------------------------------------------------------- .text:0040155D .text:0040155D loc_40155D: ; CODE XREF: ChangeArray+57j .text:0040155D xor ecx, ecx ; ecx清零 .text:0040155F jmp short loc_401586 .text:00401561 ; --------------------------------------------------------------------------- .text:00401561 .text:00401561 loc_401561: ; CODE XREF: ChangeArray+4Ej .text:00401561 movzx eax, byte ptr [ecx+esi] ; 取每一位 .text:00401565 mov edx, eax .text:00401567 and al, 0Fh ; + 0Fh .text:00401569 shr dl, 4 ; 右移 4位 .text:0040156C mov bl, [eax+edi] .text:0040156F mov [ebp+var_1], bl .text:00401572 mov bl, [edx+edi] .text:00401575 mov [eax+edi], bl .text:00401578 mov bl, [ebp+var_1] .text:0040157B mov [edx+edi], bl .text:0040157E add [ecx+esi], bl .text:00401581 xor byte ptr [ecx+esi], 17h ; ^= 0x17u .text:00401585 inc ecx .text:00401586 .text:00401586 loc_401586: ; CODE XREF: ChangeArray+24j .text:00401586 cmp ecx, 10h .text:00401589 jnz short loc_401561 ; 取每一位 .text:0040158B inc [ebp+var_2] ; ++ .text:0040158E .text:0040158E loc_40158E: ; CODE XREF: ChangeArray+20j .text:0040158E cmp [ebp+var_2], 10h ; for(i = 0;i!= 16; ++i) .text:0040158E ; { .text:0040158E ; for(j = 0;j!= 16; ++j) .text:0040158E ; { .text:0040158E ; } .text:0040158E ; } .text:00401592 jnz short loc_40155D ; ecx清零 .text:00401594 pop ebx .text:00401595 pop edi .text:00401596 pop esi .text:00401597 leave .text:00401598 retn 8 .text:00401598 ChangeArray endp C代码解释 for ( i = 0; i != 16; ++i ) newarry[i])= i; for ( i = 0; i != 16; ++i) { for ( j= 0; j!= 16; ++j ) { var4 = use_key[i]; var6 = var4; result = v4 & 0xF; var6 = var6 >> 4; v7 = newarry[result ]; newarry[result ])= +newarry[var6]; newarry[v6] = v7; new_use_key[j] += v7; use_key[j] ^= 0x17u; } } 五、SerialFunc函数分析 serialFunc用是的Base64Decode运算,b64table 也就是byte_4060C0这个数组,网上资料应该也很多,这个就不做过多解释 text:00404920 SerialFunc proc near ; CODE XREF: CheckSerialFunc+94p .text:00404920 .text:00404920 serial = dword ptr 4 .text:00404920 newarry1[] = dword ptr 8 .text:00404920 .text:00404920 push ebp .text:00404921 push esi .text:00404922 push edi .text:00404923 push ebx .text:00404924 mov edi, [esp+10h+serial] .text:00404928 xor eax, eax ; 清零 .text:0040492A mov esi, edi ; esi = serial .text:0040492C .text:0040492C loc_40492C: ; CODE XREF: SerialFunc+13j .text:0040492C mov al, [edi] ; 每一位给al .text:0040492E add edi, 4 .text:00404931 test al, al ; 判断是否为0? .text:00404933 jnz short loc_40492C ; 等于O跳走 .text:00404935 lea ebp, [edi-4] ; 最后一位 .text:00404938 mov eax, 3Dh .text:0040493D sub ebp, esi ; 是否相等? .text:0040493F jz short loc_4049BF ; 等于跳走 .text:00404941 cmp al, [ebp+esi-1] ; 最后一位 == “=” ??? .text:00404945 setz dl ; 设置dl .text:00404948 jnz short loc_40494E ; 不等于就跳走 .text:0040494A mov [ebp+esi-1], ah ; 倒数第1位 = ah = 0 .text:0040494E .text:0040494E loc_40494E: ; CODE XREF: SerialFunc+28j .text:0040494E cmp al, [ebp+esi-2] ; 最后2位 == “=” ??? .text:00404952 setz al ; 设置al .text:00404955 jnz short loc_40495B ; 不等于跳走 .text:00404957 mov [ebp+esi-2], ah ; 倒数第2位 = ah = 0 .text:0040495B .text:0040495B loc_40495B: ; CODE XREF: SerialFunc+35j .text:0040495B add al, dl ; al+dl .text:0040495D mov edi, [esp+10h+newarry1[]] .text:00404961 shr ebp, 2 .text:00404964 lea edx, [ebp+ebp*2+0] .text:00404968 sub edx, eax .text:0040496A push edx .text:0040496B .text:0040496B loc_40496B: ; CODE XREF: SerialFunc+9Cj .text:0040496B mov ecx, [esi] .text:0040496D movzx edx, cl .text:00404970 movzx ebx, ch .text:00404973 mov al, byte_4060C0[edx] .text:00404979 mov ah, byte_4060C0[ebx] .text:0040497F shr ecx, 10h .text:00404982 add esi, 4 .text:00404985 movzx edx, cl .text:00404988 movzx ecx, ch .text:0040498B mov bl, byte_4060C0[edx] .text:00404991 mov bh, byte_4060C0[ecx] .text:00404997 mov dl, ah .text:00404999 mov dh, bl .text:0040499B shl al, 2 .text:0040499E shr bl, 2 .text:004049A1 shl dh, 6 .text:004049A4 shl ah, 4 .text:004049A7 shr dl, 4 .text:004049AA or bh, dh .text:004049AC or al, dl .text:004049AE or ah, bl .text:004049B0 mov [edi], al .text:004049B2 mov [edi+2], bh .text:004049B5 mov [edi+1], ah .text:004049B8 dec ebp .text:004049B9 lea edi, [edi+3] .text:004049BC jnz short loc_40496B .text:004049BE pop eax .text:004049BF .text:004049BF loc_4049BF: ; CODE XREF: SerialFunc+1Fj .text:004049BF pop ebx .text:004049C0 pop edi .text:004049C1 pop esi .text:004049C2 pop ebp .text:004049C3 retn 8 .text:004049C3 SerialFunc endp 六、 ChangeArray1 函数分析 text:004014E5 ChangeArray1 proc near ; CODE XREF: CheckSerialFunc+A3p .text:004014E5 .text:004014E5 newarry[] = dword ptr 8 .text:004014E5 newarry2[] = dword ptr 0Ch .text:004014E5 var_int8 = dword ptr 10h .text:004014E5 .text:004014E5 push ebp .text:004014E6 mov ebp, esp .text:004014E8 push esi .text:004014E9 push edi .text:004014EA mov esi, [ebp+newarry[]] .text:004014ED mov edi, [ebp+newarry2[]] .text:004014F0 xor ecx, ecx ; 清零 .text:004014F2 jmp short loc_401508 ; 参数8 .text:004014F4 ; --------------------------------------------------------------------------- .text:004014F4 .text:004014F4 loc_4014F4: ; CODE XREF: ChangeArray1+26j .text:004014F4 mov al, [esi] ; newarry[i]给al .text:004014F6 mov dl, [esi+1] ; newarry[i+1]给dl .text:004014F9 shl al, 4 ; 左移4位 .text:004014FC and dl, 0Fh ; 与0F异或 .text:004014FF add al, dl ; 相加 .text:00401501 mov [ecx+edi], al ; newarry2[i] .text:00401504 add esi, 2 ; newarry+2 .text:00401507 inc ecx ; ++ .text:00401508 .text:00401508 loc_401508: ; CODE XREF: ChangeArray1+Dj .text:00401508 cmp ecx, [ebp+var_int8] ; 参数8 .text:0040150B jnz short loc_4014F4 ; newarry[i]给al .text:0040150D pop edi .text:0040150E pop esi .text:0040150F leave .text:00401510 retn 0Ch .text:00401510 ChangeArray1 endp C代码解释: v4 = newarry[]; for ( i = 0; i != 8; ++i ) { result = (*(_BYTE *)(v4 + 1) & 0xF) + 16 * *(_BYTE *)v4; *(_BYTE *)(i + newarry2[]) = result; v4 += 2; } return result; 将运算的赋值给newarry2数组 MMXcode函数分析 MMXcode proc near ; CODE XREF: CheckSerialFunc+B3p .text:00401513 .text:00401513 newarry1[] = dword ptr 8 .text:00401513 newarry2[] = dword ptr 0Ch .text:00401513 .text:00401513 push ebp .text:00401514 mov ebp, esp .text:00401516 mov eax, [ebp+newarry2[]] .text:00401519 movq mm1, qword ptr [eax] .text:0040151C mov edx, [ebp+newarry1[]] .text:0040151F xor ecx, ecx .text:00401521 jmp short loc_401530 .text:00401523 ; --------------------------------------------------------------------------- .text:00401523 .text:00401523 loc_401523: ; CODE XREF: MMXcode+20j .text:00401523 movq mm0, qword ptr [edx] .text:00401526 pxor mm0, mm1 .text:00401529 movq qword ptr [edx], mm0 .text:0040152C add edx, 8 .text:0040152F inc ecx .text:00401530 .text:00401530 loc_401530: ; CODE XREF: MMXcode+Ej .text:00401530 cmp ecx, 10h .text:00401533 jnz short loc_401523 .text:00401535 emms .text:00401537 leave .text:00401538 retn 8 .text:00401538 MMXcode endp 对 newarry1[]进行浮点运算,扩展值放在newarry2里面 ChangeArray2 函数进行分析 text:004014B7 ChangeArray2 proc near ; CODE XREF: CheckSerialFunc+CBp .text:004014B7 .text:004014B7 newarry1[] = dword ptr 8 .text:004014B7 newarry3[] = dword ptr 0Ch .text:004014B7 var_int80h = dword ptr 10h .text:004014B7 .text:004014B7 push ebp .text:004014B8 mov ebp, esp .text:004014BA push esi .text:004014BB push edi .text:004014BC mov esi, [ebp+newarry1[]] ; 源地址 .text:004014BF mov edi, [ebp+newarry3[]] ; 目的地址 .text:004014C2 xor ecx, ecx .text:004014C4 jmp short loc_4014DA ; 参数三 80H次循环 .text:004014C6 ; --------------------------------------------------------------------------- .text:004014C6 .text:004014C6 loc_4014C6: ; CODE XREF: ChangeArray2+26j .text:004014C6 movzx eax, byte ptr [ecx+esi] ; newarry1[i] .text:004014CA mov edx, eax ; 给edx .text:004014CC and al, 0Fh ; al^0fh .text:004014CE shr dl, 4 ; 右移4位 .text:004014D1 mov [edi], dl ; 给newarry3 .text:004014D3 mov [edi+1], al ; 给newarry3[1] .text:004014D6 add edi, 2 ; +2 .text:004014D9 inc ecx .text:004014DA .text:004014DA loc_4014DA: ; CODE XREF: ChangeArray2+Dj .text:004014DA cmp ecx, [ebp+var_int80h] ; 参数三 80H次循环 .text:004014DD jnz short loc_4014C6 ; newarry1[i] .text:004014DF pop edi .text:004014E0 pop esi .text:004014E1 leave .text:004014E2 retn 0Ch .text:004014E2 ChangeArray2 endp C代码解释 F5就是强悍 v4 = newarry3[]; for ( i = 0; i != 80h; ++i ) { v6 = newarry1[i]; V5 = v6; *(_BYTE *)v4 = v6 >> 4; *(_BYTE *)(v4 + 1) = V5 & 0xF; v4 += 2; } cmpArray 函数分析 newarry和运算后的newarry3比较 .text:00401486 cmpArray proc near ; CODE XREF: CheckSerialFunc+DBp .text:00401486 .text:00401486 newarry3[] = dword ptr 8 .text:00401486 newarry[] = dword ptr 0Ch .text:00401486 .text:00401486 push ebp .text:00401487 mov ebp, esp .text:00401489 push edi .text:0040148A mov edi, [ebp+newarry[]] .text:0040148D xor ecx, ecx .text:0040148F jmp short loc_4014A8 ; 10h次循环 .text:00401491 ; --------------------------------------------------------------------------- .text:00401491 .text:00401491 loc_401491: ; CODE XREF: cmpArray+25j .text:00401491 push ecx .text:00401492 push ecx .text:00401493 push [ebp+newarry3[]] .text:00401496 call changevar ; 函数运算为 eax = newarry3[] + ecx + 16 * ecx .text:0040149B cmp al, [ecx+edi] ; 返回值放在eax里面 然后与newarry[]相比 .text:0040149E jz short loc_4014A7 ; 相等再继续 .text:004014A0 xor eax, eax ; 不等 清空eax .text:004014A2 pop edi .text:004014A3 leave .text:004014A4 retn 8 .text:004014A7 ; --------------------------------------------------------------------------- .text:004014A7 .text:004014A7 loc_4014A7: ; CODE XREF: cmpArray+18j .text:004014A7 inc ecx .text:004014A8 .text:004014A8 loc_4014A8: ; CODE XREF: cmpArray+9j .text:004014A8 cmp ecx, 10h ; 10h次循环 .text:004014AB jnz short loc_401491 .text:004014AD mov eax, 1 .text:004014B2 pop edi .text:004014B3 leave .text:004014B4 retn 8 .text:004014B4 cmpArray endp C代码解释 v3 = 0 for ( i = 0; i != 16; i = v3 + 1 ) { v4 = changevar(newarry3[], i, i); if ( v4 != *(_BYTE *)(v3 + newarry[]) ) return 0; } return 1; Changevar函数更简单 text:0040146E changevar proc near ; CODE XREF: check_serialFunc+42p .text:0040146E ; check_serialFunc+DEp ... .text:0040146E .text:0040146E newarry3[] = dword ptr 8 .text:0040146E arg_4 = dword ptr 0Ch .text:0040146E arg_8 = dword ptr 10h .text:0040146E .text:0040146E push ebp .text:0040146F mov ebp, esp .text:00401471 mov eax, 10h .text:00401476 mul [ebp+arg_8] .text:00401479 add eax, [ebp+arg_4] .text:0040147C add eax, [ebp+newarry3[]] ;eax = newarry3[] + ecx + 16 * ecx .text:0040147F movzx eax, byte ptr [eax] .text:00401482 leave .text:00401483 retn 0Ch .text:00401483 changevar endp 十 check_serialFunc进行分析此函数为重要call,前面的运算各种运算得到newarry3作为参数传入。 text:00401211 check_serialFunc proc near ; CODE XREF: CheckSerialFunc+F1p .text:00401211 .text:00401211 var_118 = dword ptr -118h .text:00401211 var_114 = dword ptr -114h .text:00401211 var_110 = dword ptr -110h .text:00401211 var_10C = dword ptr -10Ch .text:00401211 var_108 = dword ptr -108h .text:00401211 var_104 = dword ptr -104h .text:00401211 var_100 = byte ptr -100h .text:00401211 newarry3[] = dword ptr 8 .text:00401211 .text:00401211 push ebp .text:00401212 mov ebp, esp .text:00401214 add esp, 0FFFFFEE8h .text:0040121A push edi .text:0040121B lea edi, [ebp+var_100] .text:00401221 mov [ebp+var_108], 0 ; var_108 赋值 0 .text:0040122B jmp loc_4012B0 ; 10h 次循环 .text:00401230 ; --------------------------------------------------------------------------- .text:00401230 .text:00401230 loc_401230: ; CODE XREF: check_serialFunc+A6j .text:00401230 push 10h .text:00401232 push edi ; 清空var_100 .text:00401233 call RtlZeroMemory .text:00401238 mov [ebp+var_104], 0 ; var_104赋值 0 .text:00401242 jmp short loc_401265 ; 10h循环 .text:00401244 ; --------------------------------------------------------------------------- .text:00401244 .text:00401244 loc_401244: ; CODE XREF: check_serialFunc+5Bj .text:00401244 push [ebp+var_108] .text:0040124A push [ebp+var_104] .text:00401250 push [ebp+newarry3[]] .text:00401253 call changevar ; 函数运算为 eax = newarry3[] + var_104 + 16 * var_108 .text:00401258 cmp al, 0Fh ; al > 0Fh ??? .text:0040125A ja short loc_40125F ; 大于跳走 .text:0040125C mov [eax+edi], al ; 小于 将al给edi[eax] .text:0040125F .text:0040125F loc_40125F: ; CODE XREF: check_serialFunc+49j .text:0040125F inc [ebp+var_104] ; ++ .text:00401265 .text:00401265 loc_401265: ; CODE XREF: check_serialFunc+31j .text:00401265 cmp [ebp+var_104], 10h ; 10h循环 .text:0040126C jnz short loc_401244 .text:0040126E call usefull_var_init .text:00401273 push 10h .text:00401275 push edi ; 新的var_100[]数组 .text:00401276 call NameFunc .text:0040127B call GetNewUse_key .text:00401280 cmp dword ptr [eax], 1EFC11Ah ; 获得的新的key与这固定的数组比较不等于就跳走就over 了 .text:00401286 jnz short loc_4012A3 .text:00401288 cmp dword ptr [eax+4], 1BAF6CE9h .text:0040128F jnz short loc_4012A3 .text:00401291 cmp dword ptr [eax+8], 3329D3E0h .text:00401298 jnz short loc_4012A3 .text:0040129A cmp dword ptr [eax+0Ch], 0A8C24F1Ah .text:004012A1 jz short loc_4012AA ; ++ .text:004012A3 .text:004012A3 loc_4012A3: ; CODE XREF: check_serialFunc+75j .text:004012A3 ; check_serialFunc+7Ej ... .text:004012A3 xor eax, eax .text:004012A5 pop edi .text:004012A6 leave .text:004012A7 retn 4 .text:004012AA ; --------------------------------------------------------------------------- .text:004012AA .text:004012AA loc_4012AA: ; CODE XREF: check_serialFunc+90j .text:004012AA inc [ebp+var_108] ; ++ .text:004012B0 .text:004012B0 loc_4012B0: ; CODE XREF: check_serialFunc+1Aj .text:004012B0 cmp [ebp+var_108], 10h ; 10h 次循环 .text:004012B7 jnz loc_401230 .text:004012BD mov [ebp+var_104], 0 ; var_104 清零 .text:004012C7 jmp loc_40134C ; 再来一次和上面的一样 .text:004012CC ; --------------------------------------------------------------------------- .text:004012CC .text:004012CC loc_4012CC: ; CODE XREF: check_serialFunc+142j .text:004012CC push 10h .text:004012CE push edi .text:004012CF call RtlZeroMemory .text:004012D4 mov [ebp+var_108], 0 ; 清零 .text:004012DE jmp short loc_401301 ; 再来一次,和上面的一样 .text:004012E0 ; --------------------------------------------------------------------------- .text:004012E0 .text:004012E0 loc_4012E0: ; CODE XREF: check_serialFunc+F7j .text:004012E0 push [ebp+var_108] .text:004012E6 push [ebp+var_104] .text:004012EC push [ebp+newarry3[]] .text:004012EF call changevar ; 函数运算为 eax = newarry3[] + var_104 + 16 * var_108 .text:004012F4 cmp al, 0Fh .text:004012F6 ja short loc_4012FB .text:004012F8 mov [eax+edi], al .text:004012FB .text:004012FB loc_4012FB: ; CODE XREF: check_serialFunc+E5j .text:004012FB inc [ebp+var_108] .text:00401301 .text:00401301 loc_401301: ; CODE XREF: check_serialFunc+CDj .text:00401301 cmp [ebp+var_108], 10h .text:00401308 jnz short loc_4012E0 .text:0040130A call usefull_var_init .text:0040130F push 10h .text:00401311 push edi .text:00401312 call NameFunc .text:00401317 call GetNewUse_key .text:0040131C cmp dword ptr [eax], 1EFC11Ah .text:00401322 jnz short loc_40133F .text:00401324 cmp dword ptr [eax+4], 1BAF6CE9h .text:0040132B jnz short loc_40133F .text:0040132D cmp dword ptr [eax+8], 3329D3E0h .text:00401334 jnz short loc_40133F .text:00401336 cmp dword ptr [eax+0Ch], 0A8C24F1Ah .text:0040133D jz short loc_401346 .text:0040133F .text:0040133F loc_40133F: ; CODE XREF: check_serialFunc+111j .text:0040133F ; check_serialFunc+11Aj ... .text:0040133F xor eax, eax .text:00401341 pop edi .text:00401342 leave .text:00401343 retn 4 .text:00401346 ; --------------------------------------------------------------------------- .text:00401346 .text:00401346 loc_401346: ; CODE XREF: check_serialFunc+12Cj .text:00401346 inc [ebp+var_104] .text:0040134C .text:0040134C loc_40134C: ; CODE XREF: check_serialFunc+B6j .text:0040134C cmp [ebp+var_104], 10h ; 循环10h次 .text:00401353 jnz loc_4012CC .text:00401359 mov [ebp+var_110], 0 .text:00401363 jmp loc_401457 .text:00401368 ; --------------------------------------------------------------------------- .text:00401368 .text:00401368 loc_401368: ; CODE XREF: check_serialFunc+24Dj .text:00401368 mov [ebp+var_10C], 0 .text:00401372 jmp loc_401444 ; 这次是循环4次 .text:00401377 ; --------------------------------------------------------------------------- .text:00401377 .text:00401377 loc_401377: ; CODE XREF: check_serialFunc+23Aj .text:00401377 mov [ebp+var_118], 0 .text:00401381 push 10h .text:00401383 push edi .text:00401384 call RtlZeroMemory .text:00401389 jmp short loc_4013F9 ; 这次是循环4次 .text:0040138B ; --------------------------------------------------------------------------- .text:0040138B .text:0040138B loc_40138B: ; CODE XREF: check_serialFunc+1EFj .text:0040138B mov [ebp+var_114], 0 .text:00401395 jmp short loc_4013EA ; 循环 4 次 .text:00401397 ; --------------------------------------------------------------------------- .text:00401397 .text:00401397 loc_401397: ; CODE XREF: check_serialFunc+1E0j .text:00401397 mov eax, [ebp+var_10C] .text:0040139D mov ecx, 4 .text:004013A2 mul ecx .text:004013A4 add eax, [ebp+var_114] .text:004013AA mov [ebp+var_104], eax .text:004013B0 mov eax, [ebp+var_110] .text:004013B6 mov ecx, 4 .text:004013BB mul ecx .text:004013BD add eax, [ebp+var_118] .text:004013C3 mov [ebp+var_108], eax .text:004013C9 push [ebp+var_108] .text:004013CF push [ebp+var_104] .text:004013D5 push [ebp+newarry3[]] .text:004013D8 call changevar ; 函数运算为 eax = newarry3[] + var_104 + 16 * var_108 .text:004013DD cmp al, 0Fh .text:004013DF ja short loc_4013E4 .text:004013E1 mov [eax+edi], al .text:004013E4 .text:004013E4 loc_4013E4: ; CODE XREF: check_serialFunc+1CEj .text:004013E4 inc [ebp+var_114] .text:004013EA .text:004013EA loc_4013EA: ; CODE XREF: check_serialFunc+184j .text:004013EA cmp [ebp+var_114], 4 ; 循环 4 次 .text:004013F1 jnz short loc_401397 .text:004013F3 inc [ebp+var_118] .text:004013F9 .text:004013F9 loc_4013F9: ; CODE XREF: check_serialFunc+178j .text:004013F9 cmp [ebp+var_118], 4 ; 这次是循环4次 .text:00401400 jnz short loc_40138B .text:00401402 call usefull_var_init .text:00401407 push 10h .text:00401409 push edi .text:0040140A call NameFunc .text:0040140F call GetNewUse_key .text:00401414 cmp dword ptr [eax], 1EFC11Ah .text:0040141A jnz short loc_401437 .text:0040141C cmp dword ptr [eax+4], 1BAF6CE9h .text:00401423 jnz short loc_401437 .text:00401425 cmp dword ptr [eax+8], 3329D3E0h .text:0040142C jnz short loc_401437 .text:0040142E cmp dword ptr [eax+0Ch], 0A8C24F1Ah .text:00401435 jz short loc_40143E .text:00401437 .text:00401437 loc_401437: ; CODE XREF: check_serialFunc+209j .text:00401437 ; check_serialFunc+212j ... .text:00401437 xor eax, eax .text:00401439 pop edi .text:0040143A leave .text:0040143B retn 4 .text:0040143E ; --------------------------------------------------------------------------- .text:0040143E .text:0040143E loc_40143E: ; CODE XREF: check_serialFunc+224j .text:0040143E inc [ebp+var_10C] .text:00401444 .text:00401444 loc_401444: ; CODE XREF: check_serialFunc+161j .text:00401444 cmp [ebp+var_10C], 4 ; 这次是循环4次 .text:0040144B jnz loc_401377 .text:00401451 inc [ebp+var_110] .text:00401457 .text:00401457 loc_401457: ; CODE XREF: check_serialFunc+152j .text:00401457 cmp [ebp+var_110], 4 .text:0040145E jnz loc_401368 .text:00401464 mov eax, 1 .text:00401469 pop edi .text:0040146A leave .text:0040146B retn 4 .text:0040146B check_serialFunc endp 其实里面就是3个大循环,有规律,得到的use_key[]和固定的值相比较不相等就over,大量for循环 C源码看其真面目 char v16[256]; for ( i = 0; i != 16; ++i ) { RtlZeroMemory(v16, 16); for ( j = 0; j != 16; ++j ) { v1 = changevar(newarry3[], j, i); if ( (_BYTE)v1 <= 0xFu ) v16[v1] = v1; } usefull_var_init(); //初始化变量 NameFunc(v16, 0x10u); //获取 use_byarry_16数组 v2 = GetNewUse_key(); //根据use_byarry_16数组 得到的use_key 和这些比较不相等就失败 if ( *(_DWORD *)v2 != 1EFC11Ah || *(_DWORD *)(v2 + 4) != 1BAF6CE9h || *(_DWORD *)(v2 + 8) != 3329D3E0h || *(_DWORD *)(v2 + 12) != 0A8C24F1Ah ) return 0; } for ( k = 0; k != 16; ++k ) { RtlZeroMemory(v16, 16); for ( l = 0; l != 16; ++l ) { v4 = changevar(newarry3[], k, l); if ( (_BYTE)v4 <= 0xFu ) v16[v4] = v4; } usefull_var_init(); //初始化变量 NameFunc(v16, 0x10u); //获取 use_byarry_16数组 v5 = GetNewUse_key();//根据use_byarry_16数组 得到的use_key 和这些比较不相等就失败 if ( *(_DWORD *)v5 != 1EFC11Ah || *(_DWORD *)(v5 + 4) != 1BAF6CE9h || *(_DWORD *)(v5 + 8) != 3329D3E0h || *(_DWORD *)(v5 + 12) != 0A8C24F1Ah ) return 0; } for ( m = 0; m != 4; ++m ) { for ( n = 0; n != 4; ++n ) { v8 = 0; RtlZeroMemory(v16, 16); while ( v8 != 4 ) { for ( ii = 0; ii != 4; ++ii ) { v6 = changevar(newarry3[], ii + 4 * n, v8 + 4 * m); if ( (_BYTE)v6 <= 0xFu ) v16[v6] = v6; } ++v8; } usefull_var_init(); //初始化变量 NameFunc(v16, 0x10u); //获取 use_byarry_16数组 v7 = GetNewUse_key(); ////根据use_byarry_16数组 得到的use_key 和这些比较不相等就失败 if ( *(_DWORD *)v7 != 1EFC11Ah || *(_DWORD *)(v7 + 4) != 1BAF6CE9h || *(_DWORD *)(v7 + 8) != 3329D3E0h || *(_DWORD *)(v7 + 12) != 0A8C24F1Ah ) return 0; } } return 1; } 就剩下一个MD4_HASH函数了,其实很有规律,汇编代码就不写了,直接上C代码一目了然。 v0 = (int)use_key__; v1 = use_key__[1]; v2 = use_key__[2]; v3 = use_key__[3]; v4 = __ROL__(*(_DWORD *)use_byarry_16_ + use_key__[0] + (v3 ^ v1 & (v3 ^ use_key__[2])) - 680876936, 7); v5 = v1 + v4; v6 = __ROL__(*(_DWORD *)&use_byarry_16_[4] + v3 + (v2 ^ v5 & (v2 ^ use_key__[1])) - 389564586, 12); v7 = v5 + v6; v8 = __ROL__(*(_DWORD *)&use_byarry_16_[8] + v2 + (v1 ^ v7 & (v1 ^ v5)) + 606105819, 17); v9 = v7 + v8; v10 = __ROL__(*(_DWORD *)&use_byarry_16_[12] + v1 + (v5 ^ v9 & (v5 ^ v7)) - 1044525330, 22); v11 = v9 + v10; v12 = __ROL__(*(_DWORD *)&use_byarry_16_[16] + v5 + (v7 ^ v11 & (v7 ^ v9)) - 176418897, 7); v13 = v11 + v12; v14 = __ROL__(*(_DWORD *)&use_byarry_16_[20] + v7 + (v9 ^ v13 & (v9 ^ v11)) + 1200080426, 12); v15 = v13 + v14; v16 = __ROL__(*(_DWORD *)&use_byarry_16_[24] + v9 + (v11 ^ v15 & (v11 ^ v13)) - 1473231341, 17); v17 = v15 + v16; v18 = __ROL__(*(_DWORD *)&use_byarry_16_[28] + v11 + (v13 ^ v17 & (v13 ^ v15)) - 45705983, 22); v19 = v17 + v18; v20 = __ROL__(*(_DWORD *)&use_byarry_16_[32] + v13 + (v15 ^ v19 & (v15 ^ v17)) + 1770035416, 7); v21 = v19 + v20; v22 = __ROL__(*(_DWORD *)&use_byarry_16_[36] + v15 + (v17 ^ v21 & (v17 ^ v19)) - 1958414417, 12); v23 = v21 + v22; v24 = __ROL__(*(_DWORD *)&use_byarry_16_[40] + v17 + (v19 ^ v23 & (v19 ^ v21)) - 42063, 17); v25 = v23 + v24; v26 = __ROL__(*(_DWORD *)&use_byarry_16_[44] + v19 + (v21 ^ v25 & (v21 ^ v23)) - 1990404162, 22); v27 = v25 + v26; v28 = __ROL__(*(_DWORD *)&use_byarry_16_[48] + v21 + (v23 ^ v27 & (v23 ^ v25)) + 1804603682, 7); v29 = v27 + v28; v30 = __ROL__(*(_DWORD *)&use_byarry_16_[52] + v23 + (v25 ^ v29 & (v25 ^ v27)) - 40341101, 12); v31 = v29 + v30; v32 = __ROL__(*(_DWORD *)&use_byarry_16_[56] + v25 + (v27 ^ v31 & (v27 ^ v29)) - 1502002290, 17); v33 = v31 + v32; v34 = __ROL__(*(_DWORD *)&use_byarry_16_[60] + v27 + (v29 ^ v33 & (v29 ^ v31)) + 1236535329, 22); v35 = v33 + v34; v36 = __ROL__(*(_DWORD *)&use_byarry_16_[4] + v29 + (v33 ^ v31 & (v35 ^ v33)) - 165796510, 5); v37 = v35 + v36; v38 = __ROL__(*(_DWORD *)&use_byarry_16_[24] + v31 + (v35 ^ v33 & (v37 ^ v35)) - 1069501632, 9); v39 = v37 + v38; v40 = __ROL__(*(_DWORD *)&use_byarry_16_[44] + v33 + (v37 ^ v35 & (v39 ^ v37)) + 643717713, 14); v41 = v39 + v40; v42 = __ROL__(*(_DWORD *)use_byarry_16_ + v35 + (v39 ^ v37 & (v41 ^ v39)) - 373897302, 20); v43 = v41 + v42; v44 = __ROL__(*(_DWORD *)&use_byarry_16_[20] + v37 + (v41 ^ v39 & (v43 ^ v41)) - 701558691, 5); v45 = v43 + v44; v46 = __ROL__(*(_DWORD *)&use_byarry_16_[40] + v39 + (v43 ^ v41 & (v45 ^ v43)) + 38016083, 9); v47 = v45 + v46; v48 = __ROL__(*(_DWORD *)&use_byarry_16_[60] + v41 + (v45 ^ v43 & (v47 ^ v45)) - 660478335, 14); v49 = v47 + v48; v50 = __ROL__(*(_DWORD *)&use_byarry_16_[16] + v43 + (v47 ^ v45 & (v49 ^ v47)) - 405537848, 20); v51 = v49 + v50; v52 = __ROL__(*(_DWORD *)&use_byarry_16_[36] + v45 + (v49 ^ v47 & (v51 ^ v49)) + 568446438, 5); v53 = v51 + v52; v54 = __ROL__(*(_DWORD *)&use_byarry_16_[56] + v47 + (v51 ^ v49 & (v53 ^ v51)) - 1019803690, 9); v55 = v53 + v54; v56 = __ROL__(*(_DWORD *)&use_byarry_16_[12] + v49 + (v53 ^ v51 & (v55 ^ v53)) - 187363961, 14); v57 = v55 + v56; v58 = __ROL__(*(_DWORD *)&use_byarry_16_[32] + v51 + (v55 ^ v53 & (v57 ^ v55)) + 1163531501, 20); v59 = v57 + v58; v60 = __ROL__(*(_DWORD *)&use_byarry_16_[52] + v53 + (v57 ^ v55 & (v59 ^ v57)) - 1444681467, 5); v61 = v59 + v60; v62 = __ROL__(*(_DWORD *)&use_byarry_16_[8] + v55 + (v59 ^ v57 & (v61 ^ v59)) - 51403784, 9); v63 = v61 + v62; v64 = __ROL__(*(_DWORD *)&use_byarry_16_[28] + v57 + (v61 ^ v59 & (v63 ^ v61)) + 1735328473, 14); v65 = v63 + v64; v66 = __ROL__(*(_DWORD *)&use_byarry_16_[48] + v59 + (v63 ^ v61 & (v65 ^ v63)) - 1926607734, 20); v67 = v65 + v66; v68 = __ROL__((v67 ^ v63 ^ v65) + *(_DWORD *)&use_byarry_16_[20] + v61 - 378558, 4); v69 = v67 + v68; v70 = __ROL__((v69 ^ v65 ^ v67) + *(_DWORD *)&use_byarry_16_[32] + v63 - 2022574463, 11); v71 = v69 + v70; v72 = __ROL__((v71 ^ v67 ^ v69) + *(_DWORD *)&use_byarry_16_[44] + v65 + 1839030562, 16); v73 = v71 + v72; v74 = __ROL__((v73 ^ v69 ^ v71) + *(_DWORD *)&use_byarry_16_[56] + v67 - 35309556, 23); v75 = v73 + v74; v76 = __ROL__((v75 ^ v71 ^ v73) + *(_DWORD *)&use_byarry_16_[4] + v69 - 1530992060, 4); v77 = v75 + v76; v78 = __ROL__((v77 ^ v73 ^ v75) + *(_DWORD *)&use_byarry_16_[16] + v71 + 1272893353, 11); v79 = v77 + v78; v80 = __ROL__((v79 ^ v75 ^ v77) + *(_DWORD *)&use_byarry_16_[28] + v73 - 155497632, 16); v81 = v79 + v80; v82 = __ROL__((v81 ^ v77 ^ v79) + *(_DWORD *)&use_byarry_16_[40] + v75 - 1094730640, 23); v83 = v81 + v82; v84 = __ROL__((v83 ^ v79 ^ v81) + *(_DWORD *)&use_byarry_16_[52] + v77 + 681279174, 4); v85 = v83 + v84; v86 = __ROL__((v85 ^ v81 ^ v83) + *(_DWORD *)use_byarry_16_ + v79 - 358537222, 11); v87 = v85 + v86; v88 = __ROL__((v87 ^ v83 ^ v85) + *(_DWORD *)&use_byarry_16_[12] + v81 - 722521979, 16); v89 = v87 + v88; v90 = __ROL__((v89 ^ v85 ^ v87) + *(_DWORD *)&use_byarry_16_[24] + v83 + 76029189, 23); v91 = v89 + v90; v92 = __ROL__((v91 ^ v87 ^ v89) + *(_DWORD *)&use_byarry_16_[36] + v85 - 640364487, 4); v93 = v91 + v92; v94 = __ROL__((v93 ^ v89 ^ v91) + *(_DWORD *)&use_byarry_16_[48] + v87 - 421815835, 11); v95 = v93 + v94; v96 = __ROL__((v95 ^ v91 ^ v93) + *(_DWORD *)&use_byarry_16_[60] + v89 + 530742520, 16); v97 = v95 + v96; v98 = __ROL__((v97 ^ v93 ^ v95) + *(_DWORD *)&use_byarry_16_[8] + v91 - 995338651, 23); v99 = v97 + v98; v100 = __ROL__(*(_DWORD *)use_byarry_16_ + v93 + (v97 ^ (v99 | ~v95)) - 198630844, 6); v101 = v99 + v100; v102 = __ROL__(*(_DWORD *)&use_byarry_16_[28] + v95 + (v99 ^ (v101 | ~v97)) + 1126891415, 10); v103 = v101 + v102; v104 = __ROL__(*(_DWORD *)&use_byarry_16_[56] + v97 + (v101 ^ (v103 | ~v99)) - 1416354905, 15); v105 = v103 + v104; v106 = __ROL__(*(_DWORD *)&use_byarry_16_[20] + v99 + (v103 ^ (v105 | ~v101)) - 57434055, 21); v107 = v105 + v106; v108 = __ROL__(*(_DWORD *)&use_byarry_16_[48] + v101 + (v105 ^ (v107 | ~v103)) + 1700485571, 6); v109 = v107 + v108; v110 = __ROL__(*(_DWORD *)&use_byarry_16_[12] + v103 + (v107 ^ (v109 | ~v105)) - 1894986606, 10); v111 = v109 + v110; v112 = __ROL__(*(_DWORD *)&use_byarry_16_[40] + v105 + (v109 ^ (v111 | ~v107)) - 1051523, 15); v113 = v111 + v112; v114 = __ROL__(*(_DWORD *)&use_byarry_16_[4] + v107 + (v111 ^ (v113 | ~v109)) - 2054922799, 21); v115 = v113 + v114; v116 = __ROL__(*(_DWORD *)&use_byarry_16_[32] + v109 + (v113 ^ (v115 | ~v111)) + 1873313359, 6); v117 = v115 + v116; v118 = __ROL__(*(_DWORD *)&use_byarry_16_[60] + v111 + (v115 ^ (v117 | ~v113)) - 30611744, 10); v119 = v117 + v118; v120 = __ROL__(*(_DWORD *)&use_byarry_16_[24] + v113 + (v117 ^ (v119 | ~v115)) - 1560198380, 15); v121 = v119 + v120; v122 = __ROL__(*(_DWORD *)&use_byarry_16_[52] + v115 + (v119 ^ (v121 | ~v117)) + 1309151649, 21); v123 = v121 + v122; v124 = __ROL__(*(_DWORD *)&use_byarry_16_[16] + v117 + (v121 ^ (v123 | ~v119)) - 145523070, 6); v125 = v123 + v124; v126 = __ROL__(*(_DWORD *)&use_byarry_16_[44] + v119 + (v123 ^ (v125 | ~v121)) - 1120210379, 10); v127 = v125 + v126; v128 = __ROL__(*(_DWORD *)&use_byarry_16_[8] + v121 + (v125 ^ (v127 | ~v123)) + 718787259, 15); v129 = v127 + v128; v130 = __ROL__(*(_DWORD *)&use_byarry_16_[36] + v123 + (v127 ^ (v129 | ~v125)) - 343485551, 21); use_key__[0] += v125; *(_DWORD *)(v0 + 4) += v129 + v130; *(_DWORD *)(v0 + 8) += v129; *(_DWORD *)(v0 + 12) += v127; }
对use_byarry_16进行大量的算法,最后赋值给use_key[] {第一位,第二位,第三位,第四位}
Use_byarry_16决定use_key[]的值。
到此已经把每个函数都分析完毕,不对的地方求指导。
代码量太大,总结一下吧
1、注册码 链接固定字符串-"-diablo2oo2” ,长度加0Bh
2、在NameFunc函数中运算得到 use_byarry_16数组
3、在GetNewUse_key函数中根据use_byarry_16数组获取use_key[]
4、ChangeArray函数use_key[]一系列运算结果给newarry
5、SerialFunc函数 serial base64运算,放在newarry1中
6、ChangeArray1函数中 对newarry[]进行运算赋值给newarry2[] 8为循环
7、MMXcode 函数中 浮点运算 对newarry1扩展结果放在newarry2[]
8、 ChangeArray2 函数中 对newarry1[]进行运算赋值给newarry3[] 80h为循环
9、 cmpArray 函数中 newarry[]与newarry3[]运算后的相比较,必须相等 不相等就over
A、 check_serialFunc 函数中 16+16+16 = 48 次 use_key[]验证,有一次不相等就Over
闲得无聊我把改程序还原了一下,不敢说是逆向,怕笑掉大家的大牙。注册机不会写,没有头绪,运算太多了。
附上还原的Radasm工程文件和源代码还有IDA分析的idb文件
PS其实不敢上传IDB文件因为变量写的太烂了,请不要喷的太厉害。
【公告】 [2022大礼包]《看雪论坛精华22期》发布!收录近1000余篇精华优秀文章!