国外某软件 3.47 注册算法分析

来源:互联网 发布:知乎方糖 编辑:程序博客网 时间:2024/04/28 07:48

国外某软件3.47

XXX是一个16位的程序,ne结构,以前破解过3.41版本,在98下面用trw2000破解的,现在的Ollydbg不支持NE结构的程序。奈何?

好在他升级后,加密方式也有所升级,目录下面有个wsLicmgr.exe负责授权校验,是PE结构,于是打算做注册机。

这是个vc的程序,用mfcspy可以看到按钮的事件,

00407C3E    .  83C4 04        add esp,4

00407C41    .  50             push eax                                 ; |Arg1

00407C42    .  E8 83E40000    call WSLICMGR.004160CA   校验第一个key,里面可以写出注册机来。                ; /WSLICMGR.004160CA

 

 

 

 

 

 

 

 

00407C78    .  50             push eax                                 ;  key2:20c

00407C79    .  E8 1AE30000    call WSLICMGR.00415F98   ;  this call verify key2

这个call很关键,里面首先对key2进行检验是否合法,然后不停的test,结果影响eax,最终eax是返回值。

00407C7E    .  6A 00          push 0

00407C80    .  51             push ecx

00407C81    .  8D96 740A0000  lea edx,dword ptr ds:[esi+A74];  42042021

00407C87    .  8BF8           mov edi,eax              ;  return value

00407C89    .  8BCC           mov ecx,esp

00407C8B    .  896424 28      mov dword ptr ss:[esp+28],esp

00407C8F    .  52             push edx        ;  userid:

00407C90    .  897C24 20      mov dword ptr ss:[esp+20],edi   ;  Return value

00407C94    .  E8 85990100    call <jmp.&MFC42.#535>

00407C99    .  57             push edi      ;  前面一个函数的返回值 eax

00407C9A    .  8BCE           mov ecx,esi

00407C9C    .  E8 8F180000    call WSLICMGR.00409530;  this call verify key2 and setupcode 这个call里面对上面的call的返回值和setup code进行比较,应该是从这里推出key2的构成形式。

00407CA1    .  84C0           test al,al     ;  return value can't be zero

 

 

 

 

 

 

 

 

2个核心的地方,基本上在字符串比较里面,

 

 

 

 

00409B90   |> /8B5424 40      mov edx,dword ptr ss:[esp+40]

00409B94   |.  68 E4A04200    push WSLICMGR.0042A0E4                            ;  ASCII "AE1"

00409B99   |.  52             push edx

00409B9A   |.  FFD6           call esi

00409B9C   |.  83C4 08        add esp,8

00409B9F   |.  85C0           test eax,eax

 

 

 

 

00409FC2   |> /8B4424 40  mov eax,dword ptr ss:[esp+40]                     ;  Case C of switch 0040960F

 

 

 

 

12e954=结果?

 

 

 

 

004095F0   /$  6A FF                  push -1

004095F2   |.  68 B0344200            push WSLICMGR.004234B0                            ;  SE handler installation

004095F7   |.  64:A1 00000000         mov eax,dword ptr fs:[0]

004095FD   |.  50                     push eax

004095FE   |.  64:8925 00000000       mov dword ptr fs:[0],esp

00409605   |.  83EC 24                sub esp,24

00409608   |.  53                     push ebx

00409609   |.  56                     push esi

0040960A   |.  57                     push edi

0040960B   |.  8B4424 48      mov eax,dword ptr ss:[esp+48]   ;  12E92c

12E92C这个地址里存放着跳转的地址,应该是从key2转换得来的,现在是0,对于WDL应该是C

 

 

 

 

后来的f(key2)经过运算应该等于0

有两个小call

00414642   /$  B8 01000000            mov eax,1

00414647   |.  8B4C24 08              mov ecx,dword ptr ss:[esp+8]

0041464B   |.  FEC9                   dec cl

0041464D   |.  D3E0                   shl eax,cl

0041464F   |.  234424 04              and eax,dword ptr ss:[esp+4]

00414653   |.  83F8 01                cmp eax,1

00414656   |.  1BC0                   sbb eax,eax

00414658   |.  40                     inc eax

00414659   /.  C2 0800                retn 8

 

 

 

 

上面这个call好像没有用处,仅仅是判断返回值eax是否等于1。没有对key进行变换,继续看下面一个call

00414610   /$  B8 01000000            mov eax,1

00414615   |.  8B4C24 08              mov ecx,dword ptr ss:[esp+8]

00414619   |.  FEC9                   dec cl

0041461B   |.  D3E0                   shl eax,cl

0041461D   |.  8B4C24 04              mov ecx,dword ptr ss:[esp+4]

00414621   |.  F7D0                   not eax

00414623   |.  2301                   and eax,dword ptr ds:[ecx]

00414625   |.  8901                   mov dword ptr ds:[ecx],eax

00414627   /.  C2 0800                retn 8

 

 

 

 

E95c

 

 

 

 

UserKey1的码也不是固定的,根据lic种类不同有不同,影响返回值eax,然后根据eax进行跳转。

Eax=1的时候WB

 

 

 

 

Case eax of

1:WB

2:

3:default case

4:prx

5:prx

6:jmp 8196 contract service upgrade to 1.0

7:jmp 82c2 没反应?

8:WL

9:default

A:83e9 PP

B:default

C:84c1

Else

 

 

 

 

 

 

 

 

408b2f push 0ch

 

 

 

 

校验的路径基本清楚了。

Var


Var

  Idx : integer;

  Idx := VerifyKey1(0x5426,code1,code2,key1);

  Case idx of

  1: ;

  2:;

  Default: ;

  必须要跳到default

  ebx:= VerifyKey1(0x892D,Code1,Code2,key1);

  VerifyKey2(0xB5,key2);

0040867B    .  E8 18D90000  call <WSLICMGR.VerifyKey2>     ;  check key2

00408680    .  8BE8                   mov ebp,eax  ß----VerifyKey2的返回值

00408682    .  8BC3                   mov eax,ebx   ß-- VerifyKey1的返回值

00408684    .  48                     dec eax                 ;Switch (cases 1..2)

00408685    .  0F84 EE010000          je WSLICMGR.00408879 ß-不能跳

0040868B    .  48                     dec eax

0040868C    .  0F85 08040000          jnz WSLICMGR.00408A9Aß---必须要跳

在上面,VerifyKey1必须大于2

  Ret := VerifyKey1(0x4c50,Code1,Code2,Key1); ret=1

  VerifyKey2(0x6B,key2)

00408ABC    .  E8 09D60000            call <WSLICMGR.VerifyKey1>              ; /WSLICMGR.004160CA

00408AC1    .  8BE8                   mov ebp,eax

00408AC3    .  8B4424 1C              mov eax,dword ptr ss:[esp+1C]           ;  key1

00408AC7    .  6A 6B                  push 6B

00408AC9    .  50                     push eax

00408ACA    .  FFD7                   call edi

00408ACC    .  83C4 04                add esp,4

00408ACF    .  50                     push eax

00408AD0    .  E8 C3D40000            call <WSLICMGR.VerifyKey2>

00408AD5    .  8BF8                   mov edi,eax

00408AD7    .  8BC5                   mov eax,ebp  ß--verifyKey1的返回值,=1

00408AD9    .  48                     dec eax                                 ;  Switch (cases 1..3)

00408ADA    .  74 53                  je short WSLICMGR.00408B2F必须要跳转 里面出现push 0c,正确的地方。

 

 

 

 

00408ADC    .  83E8 02                sub eax,2

00408ADF    .  74 18                  je short WSLICMGR.00408AF9

 

 

 

 

 

 

 

 

00408B2F    > /6A 0C                  push 0C                                 ;  Case 1 of switch 00408AD9

00408B31    .  51                     push ecx

00408B32    .  8D96 740A0000          lea edx,dword ptr ds:[esi+A74]

00408B38    .  8BCC                   mov ecx,esp

00408B3A    .  896424 2C              mov dword ptr ss:[esp+2C],esp

00408B3E    .  52                     push edx

00408B3F    .  E8 DA8A0100            call <WSLICMGR.CString::CString(CString>;  jmp to MFC42.#535

00408B44    .  57                     push edi

00408B45    .  8BCE                   mov ecx,esi

00408B47    .  E8 E4090000            call <WSLICMGR.VerifySetupCode>

这个call校验SetupCode,”WDL”,成功返回1,也就是这里最终跳到成功的地方。

00408B4C    .  84C0                   test al,al

00408B4E    .^ 0F84 46FDFFFF          je WSLICMGR.0040889Aß-----成功了!!!!!

跟进00408B47处的call

这个函数应该有三个参数,第二个参数应该是setupCode:’WDL’,最后一个参数表示跳转的位置,也就是根据它判断去什么地方跳转,这个参数是很核心的,我也大部分是根据这个参数倒退得到的解法,因为只有这个参数=C才有可能跳转到比较WDL的地方,否则是别的类型,比如WB1,WB2等。现在有点奇怪的是第二个参数居然得不到。难道是key2还有问题?

00409530 <>/$  6A FF                  push -1

00409532   |.  68 48344200 push WSLICMGR.00423448 ;  SE handler installation

00409537   |.  64:A1 00000000         mov eax,dword ptr fs:[0]

0040953D   |.  50                     push eax

0040953E   |.  64:8925 00000000       mov dword ptr fs:[0],esp

00409545   |.  51                     push ecx    

00409546   |.  53                     push ebx

00409547   |.  55                     push ebp

00409548   |.  56                     push esi      ;  "haB"

00409549   |.  57                     push edi     ;  f(key2)

0040954A   |.  8BF1                   mov esi,ecx

0040954C   |.  8B4424 28              mov eax,dword ptr ss:[esp+28] ;  "WDL"

00409550   |.  C74424 1C 00000000     mov dword ptr ss:[esp+1C],0

00409558   |.  50                     push eax         ; /s

00409559   |.  B3 01                  mov bl,1         ; |here, assign bl=1

0040955B   |.  FF15 4C544200          call dword ptr ds:[<&MSVCRT._strdup>]; /_strdup

00409561   |.  8B3D 00544200          mov edi,dword ptr ds:[<&MSVCRT.strtok>] ;  MSVCRT.strtok

00409567   |.  8BE8                   mov ebp,eax

00409569   |.  68 54A94200    push WSLICMGR.0042A954  ; /s2 = "-"

0040956E   |.  55                     push ebp          ; |s1

0040956F   |.  896C24 1C              mov dword ptr ss:[esp+1C],ebp     ; |

00409573   |.  FFD7                   call edi                                ; /strtok

00409575   |.  83C4 0C                add esp,0C

00409578   |.  85C0                   test eax,eax

0040957A   |.  74 38                  je short WSLICMGR.004095B4 ----jmp

0040957C   |.  8B6C24 2C              mov ebp,dword ptr ss:[esp+2C] ;  case code

00409580   |>  8D4C24 24              /lea ecx,dword ptr ss:[esp+24]  ;  f(key2)

00409584   |.  55                     |push ebp

00409585   |.  51                     |push ecx

00409586   |.  51                     |push ecx

00409587   |.  8BCC                   |mov ecx,esp

00409589   |.  896424 38              |mov dword ptr ss:[esp+38],esp

0040958D   |.  50                     |push eax

0040958E   |.  E8 2D7E0100            |call <WSLICMGR.CString::CString(char c>;  jmp to MFC42.#537

00409593   |.  8BCE                   |mov ecx,esi   ; |

00409595   |.  E8 56000000            |call <WSLICMGR.GetSetupCodeType> ; /check userid in this call

0040959A   |.  84C0                   |test al,al

0040959C   |.  75 02                  |jnz short WSLICMGR.004095A0

0040959E   |.  32DB                   |xor bl,bl    ;  fail

004095A0   |>  68 54A94200 |push WSLICMGR.0042A954   ;  setup code

004095A5   |.  6A 00                  |push 0

004095A7   |.  FFD7                   |call edi

004095A9   |.  83C4 08                |add esp,8

004095AC   |.  85C0                   |test eax,eax

004095AE   |.^ 75 D0                  /jnz short WSLICMGR.00409580

004095B0   |.  8B6C24 10              mov ebp,dword ptr ss:[esp+10];  "WDL"

004095B4   |>  8B4424 24              mov eax,dword ptr ss:[esp+24]           ;  f(key2)12E954,very important address

004095B8   |.  85C0                   test eax,eax  这个地方有点奇怪,如果前面的GetSetupType没有正确执行的话,那么这个地方eaxf(key2)一定是非零。

004095BA   |.  74 02                  je short WSLICMGR.004095BE

004095BC   |.  32DB                   xor bl,bl    ;  fail

004095BE   |>  55                     push ebp                                ; /block

004095BF   |.  FF15 08544200          call dword ptr ds:[<&MSVCRT.free>]      ; /free

004095C5   |.  83C4 04                add esp,4

004095C8   |.  8D4C24 28              lea ecx,dword ptr ss:[esp+28]

004095CC   |.  C74424 1C FFFFFFFF     mov dword ptr ss:[esp+1C],-1

004095D4   |.  E8 CF7D0100            call <WSLICMGR.CString::~CString(void)> ;  jmp to MFC42.#800

004095D9   |.  8B4C24 14              mov ecx,dword ptr ss:[esp+14]

004095DD   |.  5F                     pop edi

004095DE   |.  5E                     pop esi

004095DF   |.  8AC3                   mov al,bl

004095E1   |.  5D                     pop ebp

004095E2   |.  64:890D 00000000       mov dword ptr fs:[0],ecx

004095E9   |.  5B                     pop ebx

004095EA   |.  83C4 10                add esp,10

004095ED   /.  C2 0C00                retn 0C

 

 

 

 

Key1=5270131 (根据第三次的verifyKey1必须=1得到)

Key2=0x52343023 or 0x20000 = 52363023 ->1379282979

(key2 and C284249=42042021) and (key2 and 10311282=111280) and (key2 and 10311282=10301002)

后面2个条件好像没法同时成立,所以取第一个和第三个,因为第三个校验有用。

整理:

根据VerifyKey1写出key1的算法

根据Verifykey2写出key2的算法。

修改VerifySetupCode里面见上