目标软件:OJOsoft系列
语言:VC
工具:OD
软件是VC写的,用PEID显示为:Microsoft Visual C++ 7.0 Method2 [调试]
二话不说,直接到OD载入,然后输入假的激活码,很快就能找到关键点:
代码:
00401D6D . C74424 1C 00000>mov dword ptr ss:[esp+1C],0 00401D75 . E8 96E80100 call <jmp.&MFC71.#3761> 00401D7A . 51 push ecx 00401D7B . 8D5424 08 lea edx,dword ptr ss:[esp+8] 00401D7F . 8BCC mov ecx,esp 00401D81 . 896424 10 mov dword ptr ss:[esp+10],esp 00401D85 . 52 push edx 00401D86 . FF15 E4514200 call dword ptr ds:[<&MFC71.#297>] ; MFC71.7C14E575 00401D8C . 8B8E C8000000 mov ecx,dword ptr ds:[esi+C8] 00401D92 . FF15 30504200 call dword ptr ds:[<&Control.AVProxy::Reg>; Control.AVProxy::RegisteProduct
显然是通过专用的DLL来验证注册的。
跟进后,来到这里:
代码:
003A6C49 C64424 4C 01 mov byte ptr ss:[esp+4C],1 003A6C4E FF15 94803B00 call dword ptr ds:[<&MFC71.#297>] ; MFC71.7C14E575 003A6C54 8D4C24 0C lea ecx,dword ptr ss:[esp+C] 003A6C58 E8 03DB0000 call Control.003B4760 //这里同样为关键CALL,跟进继续分析 003A6C5D 8BF0 mov esi,eax 003A6C5F 85F6 test esi,esi 003A6C61 75 76 jnz short Control.003A6CD9 003A6C63 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
代码:
003B485D 8BCE mov ecx,esi 003B485F 885C24 3C mov byte ptr ss:[esp+3C],bl 003B4863 E8 38F5FFFF call Control.003B3DA0 003B4868 0FB6C0 movzx eax,al 003B486B 85C0 test eax,eax 003B486D 74 69 je short Control.003B48D8
代码:
003B3DE7 8BCE mov ecx,esi 003B3DE9 E8 12FAFFFF call Control.003B3800 003B3DEE 84C0 test al,al 003B3DF0 0F84 49010000 je Control.003B3F3F
代码:
003B3837 2BC2 sub eax,edx 003B3839 83F8 18 cmp eax,18 //比较激活码的长度是否为0x18,不是则失败 ………………………… 003B3850 > 56 push esi 003B3851 . |8D4C24 20 lea ecx,dword ptr ss:[esp+20] 003B3855 . |FF15 20813B00 call dword ptr ds:[<&MFC71.#865>] ; MFC71.7C1894E7 003B385B . |0FBEC0 movsx eax,al 003B385E . |50 push eax 003B385F . |FFD3 call ebx 003B3861 . |83C4 04 add esp,4 003B3864 . |83FF 04 cmp edi,4 003B3867 . |75 08 jnz short Control.003B3871 003B3869 . |3C 2D cmp al,2D 003B386B . |75 33 jnz short Control.003B38A0 003B386D . |33FF xor edi,edi 003B386F . |EB 09 jmp short Control.003B387A 003B3871 > |3C 41 cmp al,41 003B3873 . |7C 2B jl short Control.003B38A0 003B3875 . |3C 5A cmp al,5A 003B3877 . |7F 27 jg short Control.003B38A0 003B3879 . |47 inc edi 003B387A > |46 inc esi 003B387B . |83FE 18 cmp esi,18 003B387E .^\7C D0 jl short Control.003B3850
而且应该是全为字母,不能为数字!
好了,我们重新输入来过,路跳过上面的分析,来到:
代码:
003B3960 |> /8D4424 14 /lea eax,dword ptr ss:[esp+14] 003B3964 |. |33ED |xor ebp,ebp 003B3966 |. |8D50 01 |lea edx,dword ptr ds:[eax+1] 003B3969 |. |8DA424 00000000 |lea esp,dword ptr ss:[esp] 003B3970 |> |8A08 |/mov cl,byte ptr ds:[eax] 003B3972 |. |40 ||inc eax 003B3973 |. |84C9 ||test cl,cl 003B3975 |.^|75 F9 |\jnz short Control.003B3970 003B3977 |. |2BC2 |sub eax,edx ; 取软件名长度-EBX 003B3979 |. |8BF8 |mov edi,eax 003B397B |. |33C9 |xor ecx,ecx 003B397D |. |85FF |test edi,edi 003B397F |. |7E 18 |jle short Control.003B3999 003B3981 |> |0FBE740C 14 |/movsx esi,byte ptr ss:[esp+ecx+1> 003B3986 |. |8BC3 ||mov eax,ebx 003B3988 |. |0FAFC6 ||imul eax,esi 003B398B |. |99 ||cdq 003B398C |. |2BC2 ||sub eax,edx 003B398E |. |D1F8 ||sar eax,1 003B3990 |. |03C6 ||add eax,esi 003B3992 |. |03E8 ||add ebp,eax 003B3994 |. |41 ||inc ecx 003B3995 |. |3BCF ||cmp ecx,edi 003B3997 |.^|7C E8 |\jl short Control.003B3981 003B3999 |> |8BC5 |mov eax,ebp 003B399B |. |99 |cdq 003B399C |. |B9 1A000000 |mov ecx,1A 003B39A1 |. |F7F9 |idiv ecx 003B39A3 |. |8B4424 10 |mov eax,dword ptr ss:[esp+10] ; 除以常量0x1A 003B39A7 |. |83C3 06 |add ebx,6 ; EB+=6 003B39AA |. |83C0 04 |add eax,4 003B39AD |. |83FB 19 |cmp ebx,19 ; 与0x19比较,大于则结束循环 003B39B0 |. |894424 10 |mov dword ptr ss:[esp+10],eax 003B39B4 |. |8950 FC |mov dword ptr ds:[eax-4],edx ; 将上面的相除所得余数保存到下来 003B39B7 |.^\7C A7 \jl short Control.003B3960
这里将之记为modNum[4],代码的流程用C++转述如下(注:name记为软件名):
代码:
int modNum[4]={0}; int k=0; for(int i=1;i<0x19;i+=6){ int len=strlen(name); int sum=0; for(int j=0;j<len;j++){ int tmpSum=name[j]*i; tmpSum=(tmpSum>>1); sum=sum+tmpSum+name[j]; } modNum[k]=sum % 0x1A; k++; }
代码:
003B3E02 |> /83FF 04 /cmp edi,4 003B3E05 |. |75 04 |jnz short Control.003B3E0B 003B3E07 |. |33FF |xor edi,edi 003B3E09 |. |EB 23 |jmp short Control.003B3E2E 003B3E0B |> |53 |push ebx 003B3E0C |. |8D8C24 E0000000 |lea ecx,dword ptr ss:[esp+E0] 003B3E13 |. |FF15 20813B00 |call dword ptr ds:[<&MFC71.#865>] ; MFC71.7C1894E7 003B3E19 |. |0FBEC8 |movsx ecx,al 003B3E1C |. |51 |push ecx 003B3E1D |. |FFD5 |call ebp 003B3E1F |. |0FBED0 |movsx edx,al 003B3E22 |. |83EA 41 |sub edx,41 003B3E25 |. |83C4 04 |add esp,4 003B3E28 |. |8916 |mov dword ptr ds:[esi],edx 003B3E2A |. |47 |inc edi 003B3E2B |. |83C6 04 |add esi,4 003B3E2E |> |43 |inc ebx 003B3E2F |. |83FB 18 |cmp ebx,18 003B3E32 |.^\7C CE \jl short Control.003B3E02
然后我们就来到了关键的比较点了:
代码:
003B3F01 |> /8B6C0C 18 /mov ebp,dword ptr ss:[esp+ecx+18] ; 按位取第1组 003B3F05 |. |8B840C B8000000 |mov eax,dword ptr ss:[esp+ecx+B8] ; 按位取上面所得余数 003B3F0C |. |8B7C0C 28 |mov edi,dword ptr ss:[esp+ecx+28] ; 按位取第2组 003B3F10 |. |8B740C 48 |mov esi,dword ptr ss:[esp+ecx+48] ; 按位取第4组 003B3F14 |. |8B540C 38 |mov edx,dword ptr ss:[esp+ecx+38] ; 按位取第3组 003B3F18 |. |03C5 |add eax,ebp 003B3F1A |. |03C7 |add eax,edi 003B3F1C |. |03C6 |add eax,esi 003B3F1E |. |03C2 |add eax,edx 003B3F20 |. |99 |cdq 003B3F21 |. |BE 1A000000 |mov esi,1A 003B3F26 |. |F7FE |idiv esi 003B3F28 |. |3B940C A8000000 |cmp edx,dword ptr ss:[esp+ecx+A8] ; 按位与第5组相比 003B3F2F |. |89540C 58 |mov dword ptr ss:[esp+ecx+58],edx 003B3F33 |. |75 0A |jnz short Control.003B3F3F 003B3F35 |. |83C1 04 |add ecx,4 003B3F38 |. |83F9 10 |cmp ecx,10 003B3F3B |.^\7C C4 \jl short Control.003B3F01 003B3F3D |. EB 02 jmp short Control.003B3F41 003B3F3F |> 32DB xor bl,bl 003B3F41 |> 8D8C24 D8000000 lea ecx,dword ptr ss:[esp+D8]
代码:
#include<stdio.h> #include<time.h> #include<iostream> using namespace std; int main() { char name[32]={0}; cout<<"lease Enter SoftName)\n"; cin.getline(name,31); //cout<<name<<endl; int modNum[4]={0}; int k=0; for(int i=1;i<0x19;i+=6){ int len=strlen(name); int sum=0; for(int j=0;j<len;j++){ int tmpSum=name[j]*i; tmpSum=(tmpSum>>1); sum=sum+tmpSum+name[j]; } modNum[k]=sum % 0x1A; k++; } srand(time(NULL)); char code[32]={0}; for(int i=0;i<4;i++){ int n1,n2,n3,n4,n5; while(1){ n1=((double)rand()/(double)RAND_MAX)*0x19+0; n2=((double)rand()/(double)RAND_MAX)*0x19+0; n3=((double)rand()/(double)RAND_MAX)*0x19+0; n4=((double)rand()/(double)RAND_MAX)*0x19+0; n5=((double)rand()/(double)RAND_MAX)*0x19+0; int tmp=n1+n2+n3+n4+modNum; if((tmp %0x1A)==n5) break; } code=0x41+n1; code[i+5]=0x41+n2; code[i+5*2]=0x41+n3; code[i+5*3]=0x41+n4; code[i+5*4]=0x41+n5; } code[4]='-'; code[9]='-'; code[14]='-'; code[19]='-'; cout<<"Your RegCode is: "; cout<<code<<endl;; cout<<"lease Enter a Key to Exit…………\n"; getchar(); getchar(); return 0; }