AJISky's CM_One详解

来源:互联网 发布:课外阅读训练软件 编辑:程序博客网 时间:2024/05/18 01:25

一、

PEID查看,是用汇编语言写的,所以直接看DialogBoxParamA的参数,找到消息循环。在消息循环里面找到0x111(WM_COMMAND),断下慢慢分析:

 

0040136A  |> \3D 11010000   cmp eax,0x1110040136F  |.  75 4D         jnz X004013BE00401371  |.  8B45 10       mov eax,[arg.3]                          ;  Case 111 (WM_COMMAND) of switch 0040134C00401374  |.  83F8 6A       cmp eax,0x6A00401377  |.  75 28         jnz X004013A100401379  |.  8D3D 7A324000 lea edi,dword ptr ds:[<K1>]0040137F  |.  33C0          xor eax,eax00401381  |.  B9 10000000   mov ecx,0x1000401386  |.  F3:AA         rep stos byte ptr es:[edi]               ;  清000401388  |.  8D3D 1E304000 lea edi,dword ptr ds:[<K2>]0040138E  |.  B9 10000000   mov ecx,0x1000401393  |.  F3:AA         rep stos byte ptr es:[edi]               ;  清000401395  |.  E8 A9FCFFFF   call 004010430040139A  |.  E8 97FDFFFF   call 00401136

0040139F  |. /EB 37         jmp X004013D8

 

二、分析:

call 00401043是取得用户名后,由它运算出一个长度最大为15的BYTE数组(K2),实际长度以用户名长度为准。

call 00401136比较复杂,先看前面:

00401136  /$  6A 10         push 0x10                                ; /Count = 10 (16.)00401138  |.  68 5F314000   push offset <sn>                         ; |Buffer = offset <CM_One.sn>0040113D  |.  6A 67         push 0x67                                ; |ControlID = 67 (103.)0040113F  |.  FF35 5E324000 push dword ptr ds:[0x40325E]             ; |hWnd = NULL00401145  |.  E8 E0020000   call <jmp.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA0040114A  |.  83F8 00       cmp eax,0x00040114D  |.  0F84 85010000 je <EXIT>00401153  |.  8BC8          mov ecx,eax                              ;  循环次数00401155  |.  8D3D 1E304000 lea edi,dword ptr ds:[<K2>]0040115B  |.  8D35 5F314000 lea esi,dword ptr ds:[<sn>]00401161  |>  8A06          /mov al,byte ptr ds:[esi]                ;  sn00401163  |.  8A1F          |mov bl,byte ptr ds:[edi]                ;  K200401165  |.  D0EB          |shr bl,100401167      02C3          add al,bl00401169      8807          mov byte ptr ds:[edi],al                 ;  K20040116B  |.  46            |inc esi0040116C  |.  47            |inc edi0040116D  |.^ E2 F2         \loopd X00401161                         ;  F(K2,sn)

 

这里,取注册码,最大15位,然后和K2运算并更新K2。

40116F到4011BE是分别打开Windows.iso和WinXP.iso。

 

004011C8  |.  B9 B2000000   mov ecx,0xB2                             ;  178004011CD  |.  8D3D 1E304000 lea edi,dword ptr ds:[<K2>]004011D3  |>  51            /push ecx004011D4  |.  6A 00         |push 0x0                                ; /pOverlapped = NULL004011D6  |.  68 76324000   |push offset <返回数据长度>                    ; |pBytesRead = offset <CM_One.返回数据长度>004011DB  |.  6A 01         |push 0x1                                ; |BytesToRead = 1004011DD  |.  68 16304000   |push offset <ReadBuff>                  ; |Buffer = offset <CM_One.ReadBuff>004011E2  |.  FF35 54304000 |push dword ptr ds:[<hFile1>]            ; |hFile = NULL004011E8  |.  E8 1F020000   |call <jmp.&kernel32.ReadFile>           ; \ReadFile读一个字节004011ED  |.  833D 76324000>|cmp dword ptr ds:[<返回数据长度>],0x0004011F4  |.  75 05         |jnz X004011FB                           ;  数据不为0004011F6  |.  E9 DD000000   |jmp <EXIT>004011FB  |>  8D35 16304000 |lea esi,dword ptr ds:[<ReadBuff>]00401201  |.  803F 00       |cmp byte ptr ds:[edi],0x0               ;  K2数据不为000401204  |.  75 06         |jnz X0040120C00401206  |.  8D3D 1E304000 |lea edi,dword ptr ds:[<K2>]             ;  如果为0,指针循环到[0]0040120C  |>  8A06          |mov al,byte ptr ds:[esi]                ;  ReadBuff win.iso0040120E  |.  3207          |xor al,byte ptr ds:[edi]                ;  K200401210  |.  A2 18304000   |mov byte ptr ds:[<WriteBuff>],al00401215  |.  47            |inc edi00401216  |.  6A 00         |push 0x0                                ; /pOverlapped = NULL00401218  |.  68 76324000   |push offset <返回数据长度>                    ; |pBytesWritten = offset <CM_One.返回数据长度>0040121D  |.  6A 01         |push 0x1                                ; |nBytesToWrite = 10040121F  |.  68 18304000   |push offset <WriteBuff>                 ; |Buffer = offset <CM_One.WriteBuff>00401224  |.  FF35 50304000 |push dword ptr ds:[<hFile2>]            ; |hFile = NULL0040122A  |.  E8 E3010000   |call <jmp.&kernel32.WriteFile>          ; \WriteFile0040122F  |.  59            |pop ecx00401230  |.^ E2 A1         \loopd X004011D3


这里是一个循环,次数为0xB2。读Windows.iso的字节,异或K2后,WinXP.iso。

 

00401232  |.  8D3D 40304000 lea edi,dword ptr ds:[<conKEY>]00401238  |.  8D35 16304000 lea esi,dword ptr ds:[<ReadBuff>]0040123E  |.  8D1D 1E304000 lea ebx,dword ptr ds:[<K2>]00401244  |.  EB 59         jmp X0040129F00401246  |>  6A 00         /push 0x0                                ; /pOverlapped = NULL00401248  |.  68 76324000   |push offset <返回数据长度>                    ; |pBytesRead = offset <CM_One.返回数据长度>0040124D  |.  6A 01         |push 0x1                                ; |BytesToRead = 10040124F  |.  68 16304000   |push offset <ReadBuff>                  ; |Buffer = offset <CM_One.ReadBuff>00401254  |.  FF35 54304000 |push dword ptr ds:[<hFile1>]            ; |hFile = NULL0040125A  |.  E8 AD010000   |call <jmp.&kernel32.ReadFile>           ; \ReadFile0040125F  |.  833D 76324000>|cmp dword ptr ds:[<返回数据长度>],0x000401266  |.  74 37         |je X0040129F00401268  |.  803F 00       |cmp byte ptr ds:[edi],0x00040126B  |.  75 0C         |jnz X004012790040126D  |.  8D1D 1E304000 |lea ebx,dword ptr ds:[<K2>]00401273  |.  8D3D 40304000 |lea edi,dword ptr ds:[<conKEY>]00401279  |>  8A06          |mov al,byte ptr ds:[esi]                ;  ReadBuff0040127B  |.  3207          |xor al,byte ptr ds:[edi]                ;  conKEY0040127D  |.  3203          |xor al,byte ptr ds:[ebx]                ;  K20040127F  |.  A2 16304000   |mov byte ptr ds:[<ReadBuff>],al00401284  |.  47            |inc edi00401285  |.  43            |inc ebx00401286  |.  6A 00         |push 0x0                                ; /pOverlapped = NULL00401288  |.  68 76324000   |push offset <返回数据长度>                    ; |pBytesWritten = offset <CM_One.返回数据长度>0040128D  |.  6A 01         |push 0x1                                ; |nBytesToWrite = 10040128F  |.  68 16304000   |push offset <ReadBuff>                  ; |Buffer = offset <CM_One.ReadBuff>00401294  |.  FF35 50304000 |push dword ptr ds:[<hFile2>]            ; |hFile = NULL0040129A  |.  E8 73010000   |call <jmp.&kernel32.WriteFile>          ; \WriteFile0040129F  |>  833D 76324000> cmp dword ptr ds:[<返回数据长度>],0x0004012A6  |.^ 75 9E         \jnz X00401246


这里是读Windows.iso的字节,异或K2,异或一个常量(conKEY)后,写入WinXP.iso。

 

004012A8  |.  FF35 50304000 push dword ptr ds:[<hFile2>]             ; /hObject = NULL004012AE  |.  E8 2F010000   call <jmp.&kernel32.CloseHandle>         ; \CloseHandle004012B3  |.  FF35 54304000 push dword ptr ds:[<hFile1>]             ; /hObject = NULL004012B9  |.  E8 24010000   call <jmp.&kernel32.CloseHandle>         ; \CloseHandle004012BE  |.  68 00304000   push 00403000                            ; /FileName = "WinXP.iso"004012C3  |.  E8 3E010000   call <jmp.&kernel32.LoadLibraryA>        ; \LoadLibraryA004012C8  |.  50            push eax                                 ; /hLibModule004012C9  |.  E8 2C010000   call <jmp.&kernel32.FreeLibrary>         ; \FreeLibrary004012CE  |.  68 00304000   push 00403000                            ; /FileName = "WinXP.iso"004012D3  |.  E8 16010000   call <jmp.&kernel32.DeleteFileA>         ; \DeleteFileA004012D8 >\>  C3            retn

 

这里关闭文件句柄,用LoadLibraryA打开WinXP.iso,然后关闭并删除它。可见WinXP.iso应该是一个DLL。DLL是PE格式,根据PE格式头部都是固定的原理,得出公式:

N1=F1(name);

K2=F2(name,N1);

K2=sn+(K2>>1);

PE=K2^iWindows.iso;

以上PE和Windows.iso已知,所以可得K2,把K2代入K2=sn+(K2>>1);就可以得SN了。

K=PE^Windows.iso;

sn=K-(K2>>1);

 

三、实际问题

PE文件在格式上是统一的,但格式内的数据略有不同来看看两个PE文件:

00000000h: 4D 5A 50 00 02 00 00 00 04 00 0F 00 FF FF 00 00 ; MZP...........00000010h: B8 00 00 00 00 00 00 00 40 00 1A 00 00 00 00 00 ; ?......@.......00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 ; ................00000040h: BA 10 00 0E 1F B4 09 CD 21 B8 01 4C CD 21 90 90 ; ?...???L?悙00000050h: 54 68 69 73 20 70 72 6F 67 72 61 6D 20 6D 75 73 ; This program mus00000060h: 74 20 62 65 20 72 75 6E 20 75 6E 64 65 72 20 57 ; t be run under W00000070h: 69 6E 33 32 0D 0A 24 37 00 00 00 00 00 00 00 00 ; in32..$7........

 

00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 ; MZ?..........00000010h: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ; ?......@.......00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00 ; ............?..00000040h: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ; ..?.???L?Th00000050h: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F ; is program canno00000060h: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 ; t be run in DOS 00000070h: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 ; mode....$.......

 

以上两个PE文件就差哪么一点,特别是IMAGE_DOS_HEADER的e_cblp(第3,4个字节)。如果用前16位来异或Windows.iso可能会出现错误。注意观察会发现“50h”这一行16位基本不变。所以就好以这16个字节进行异或,得出K。

         PE-50h:  69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F

Windows.iso-50h:  25 E2 7D 26 F9 C6 04 27 2D FC 7D 35 EA C7 0D 3A   异或运算

           结果:  4C 91 5D 56 8B A9 63 55 4D 91 5D 56 8B A9 63 55

可见,K为8位,所以sn也为8位。

 

四、注册机源码:

// CM_One_REG.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <wtypes.h>DWORD g_N1=0;BYTE g_K1[16],g_K2[16];const int g_KEY1LEN=16;const BYTE g_KEY1[8]={0x4C,0x91,0x5D,0x56,0x8B,0xA9,0x63,0x55};const BYTE g_KEY2[8]={0x26, 0x32, 0x43, 0x1A, 0x2C, 0xB3, 0x5F, 0x42};void call_0040104390(char *name){g_N1=0;ZeroMemory(g_K1,16);ZeroMemory(g_K2,16);int len=strlen(name),loop=0xf,i=0,temp=0;// g_N1=(name[0]%name[1]);// g_N1*=name[2];// g_N1++;// g_N1=0xFFFFFFFF/g_N1;g_N1=0xFFFFFFFF/((name[0]%name[1])*name[2]+1);while(loop--){g_N1*=0x342ab;g_N1+=0x269EC3;g_K1[i]=(char)(((g_N1>>0x10)&0x7FFF)%0x10)+0x4b;i++;}loop=len;i=0;while(loop--){temp=(name[i]>>5)*0x7B;if (temp>0){while(temp--){g_N1=(g_N1*0x123CD)+0x775851;}}g_N1=(g_N1*0x123CD)+0x269EC3;g_K2[i]=(char)(g_N1>>0x10)&0x7FFF;//i++;}}void call_00401136(char *sn){int len=strlen(sn),loop=0,i=0,temp=0;if (len>8){printf("sn Error!");return;}loop=len;i=0;while(loop--){g_K2[i]=(g_K2[i]>>1)+sn[i];i++;}}BYTE *GetSN(char *name){call_0040104390(name);BYTE out[10]={0};BYTE j=0;printf("SN:");for (int i=0;i<8;i++){//j=((BYTE)g_K2[i])>>1;out[i]=g_KEY1[i]-(g_K2[i]>>1);//printf("%d:%d - %02X\n",i+1,out[i],out[i],out[i]);printf("%02X ",out[i]);}return out;}// BYTE *GetN1(char *sn)// {// if (strlen(sn)!=8)// {// return NULL;// }// BYTE out[8]={0};// int i=0,j=0,k=0;// for(i=0;i<8;i++)// {// k=g_KEY1[i]-sn[1];// for (j=0;j<0x100;j++)// {// if ((j>>1)==k)// {// break;// }// }// out[i]=j;// }// return out;// }int main(int argc, char* argv[]){//printf("SN:");IMAGE_DOS_HEADERGetSN("lili");return 0;}


五、总结

1.了解PE文件格式是关键

2.算出来的sn有时为不可见字符,要怎样输入呢?我只知道用UltraEdit输入16进制数值后,转换成字符模式再复制粘贴。

 

原创粉丝点击