• 标 题:SPQuery v4.2 build 4237 (22千字)
  • 作 者:Blowfish
  • 时 间:2001-3-12 17:46:37
  • 链 接:http://bbs.pediy.com

SPQuery v4.2 build 4237

http://www.stbernard.com

如果你是WinNT/2K的系统管理员,这个工具是非常有用的。

用isDcc反编译setup.ins脚本,得到脚本源码。显然是调用sbssetup.dll来判断安装序列号的。关键的是下面这几个:

    prototype SBSSETUP.VerifySN(string);
    prototype SBSSETUP.GetModeCode(string);
    prototype SBSSETUP.GetLicenseLevel(string);

判断序列号的部分如下(string7就是序列号):

label18: //Ref: 001428 

00143F:00B4:        SBSSETUP.VerifySN(string7);        //判断序列号
001447:0021:        lNumber0 = LAST_RESULT;
00144F:0128:        lNumber3 = lNumber0 < 0;
001461:0022:        if (lNumber3 = 0) then
                        goto label19;
                    endif;
00146F:0112:        StrLoadString("", "INVALID_SN", lString0);
001484:002A:        MessageBox(lString0, -65535);
00148E:002C:        goto label17;

label19: //Ref: 001461 
001497:00B4:        SBSSETUP.GetModeCode(string7);    //这里
00149F:0021:        lNumber2 = LAST_RESULT;
0014A7:0128:        lNumber3 = lNumber2 < 0;
0014B9:0022:        if (lNumber3 = 0) then
                        goto label20;
                    endif;
0014C7:0112:        StrLoadString("", "INVALID_SN", lString0);
0014DC:002A:        MessageBox(lString0, -65535);
0014E6:002C:        goto label17;

label20: //Ref: 0014B9 
0014EF:00B4:        SBSSETUP.GetLicenseLevel(string7);  //这里
0014F7:0021:        lNumber1 = LAST_RESULT;
0014FF:0128:        lNumber3 = lNumber1 < 0;
001511:0022:        if (lNumber3 = 0) then
                        goto label21;
                    endif;
00151F:0112:        StrLoadString("", "INVALID_SN", lString0);
001534:002A:        MessageBox(lString0, -65535);
00153E:002C:        goto label17;

label21: //Ref: 001511 
001547:0128:        lNumber3 = MODE = 0;
001559:0022:        if (lNumber3 = 0) then
                        goto label26;
                    endif;
001567:0128:        lNumber3 = lNumber2 > 1;
001579:0022:        if (lNumber3 = 0) then
                        goto label24;
                    endif;
001587:0128:        lNumber3 = lNumber1 = 0;
001599:0022:        if (lNumber3 = 0) then
                        goto label22;
                    endif;
0015A7:0112:        StrLoadString("", "LICENSE_EXPLANATION", lString0);
0015C5:0112:        StrLoadString("", "LIVE_TRIAL_UNLIMITED", lString1);
0015E4:0104:        SprintfBox(-65535, lString0, lString1);
0015F4:002C:        goto label23;

label22: //Ref: 001599 
0015FD:0112:        StrLoadString("", "LICENSE_EXPLANATION", lString0);
00161B:0112:        StrLoadString("", "LIVE_TRIAL_LIMITED", lString1);
001638:0104:        SprintfBox(-65535, lString0, lString1, lNumber1, lNumber1);

label23: //Ref: 0015F4 
001652:002C:        goto label26;

label24: //Ref: 001579 
00165B:0128:        lNumber3 = lNumber1 = 0;
00166D:0022:        if (lNumber3 = 0) then
                        goto label25;
                    endif;
00167B:0112:        StrLoadString("", "LICENSE_EXPLANATION", lString0);
001699:0112:        StrLoadString("", "MACHINE_UNLIMITED", lString1);
0016B5:0104:        SprintfBox(-65535, lString0, lString1);
0016C5:002C:        goto label26;

label25: //Ref: 00166D 
0016CE:0112:        StrLoadString("", "LICENSE_EXPLANATION", lString0);
0016EC:0112:        StrLoadString("", "MACHINE_LIMITED", lString1);
001706:0104:        SprintfBox(-65535, lString0, lString1, lNumber1, lNumber1);

察看文本文件value.shl,得到字符串宏定义如下:

INVALID_SN=Invalid Serial Number.
LIVE_TRIAL_LIMITED=You have installed a license allowing you to evaluate SPQuery on %d machines for 15 days.  Once %d machines have been queried, any remaining machines will become inaccessible via SPQuery.
SERIAL_NUMBER=Serial Number:
MACHINE_UNLIMITED=You have installed a license allowing you to use SPQuery at one physical site.
LIVE_TRIAL_UNLIMITED=You have installed a license allowing you to evaluate SPQuery on any number of machines for 15 days.
MACHINE_LIMITED=You have installed a license allowing you to use SPQuery on %d machines.  Once %d machines have been queried, any remaining machines will become inaccessible via SPQuery.
LICENSE_EXPLANATION=License Explanation

显然它有多种序列号,不同的序列号对应不同的license类型。最完美的当然是MACHINE_UNLIMITED,没有时间和机器数目的限制。
那就看看如何才能让程序流程走到MACHINE_UNLIMITED这里来。

lNumber0 = SBSSETUP.VerifySN(string7);        //lNumber0 应大于等于0
lNumber2 = SBSSETUP.GetModeCode(string7);    //lNumber2应大于等于0,且小于等于1
lNumber1 = SBSSETUP.GetLicenseLevel(string7); //lNumber1应等于0

得到上述条件之后启动SoftICE针对DLL中的函数设断点进行跟踪,使用其默认的序列号01-0184-4174-0909。
发现它是把注册码的后两部分4174和0909用同一个函数进行变换,分别得到0B26和5005,lNumber0就等于0B26的高两位即0B,
而lNumber2则等于0B26中的2,lNumber1则为5005的低三位即005。它还会取出0B26中的低位(即6),和5005的高位(即5)
凑成一个字节0x65,并将该字节与另外一个字节(此字节是根据注册码其它部分计算出来的)进行比较,比较的地方如下:

001B:01972307  CALL      01971FE0
001B:0197230C  MOV      DL,[ESP+32]
001B:01972310  MOV      AL,[ESP+33] 
001B:01972314  ADD      ESP,20
001B:01972317  CMP      DL,AL        //比较
001B:01972319  JNZ      01972368

再结合上面得出的lNumber0,lNumber1,lNumber2所要满足的条件,就可以知道变换后的两个数所要满足的条件。
现在的问题就是根据变换后的数如何反推出变换前的数(即注册码的后两部分)来,从而写出keymaker。看一下变换函数,
该函数只是对一个16-bit整数的16个bit进行调换位置的操作,从而得到一个新的16-bit数,这个换位变换显然是可逆的。
假定变换前的整数的16个bit依次为15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,则变换得到的新的整数16个bit依次为
15,11,7,3,14,10,6,2,13,9,5,1,12,8,4,0。即变换后的整数的第15 bit等于变换前的整数的第15 bit,变换后的整数的第14 bit
等于变换前的整数的第11 bit···依次类推。如下:

* Referenced by a CALL at Addresses:
|:10002200  , :1000220A 
|
:10001D50 8B4C2404                mov ecx, dword ptr [esp+04]
:10001D54 83EC08                  sub esp, 00000008
:10001D57 8D442400                lea eax, dword ptr [esp]
:10001D5B 53                      push ebx
:10001D5C 55                      push ebp
:10001D5D 56                      push esi
:10001D5E 57                      push edi
:10001D5F 50                      push eax
:10001D60 51                      push ecx
:10001D61 E84AFFFFFF              call 10001CB0                //atol( )或sscanf( )
:10001D66 8B442418                mov eax, dword ptr [esp+18]  //变换前的16-bit整数
:10001D6A 8BC8                    mov ecx, eax
:10001D6C 81E10F000080            and ecx, 8000000F        //ecx中存放该数的3~0 bit
:10001D72 7905                    jns 10001D79
:10001D74 49                      dec ecx
:10001D75 83C9F0                  or ecx, FFFFFFF0
:10001D78 41                      inc ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001D72(C)
|
:10001D79 99                      cdq
:10001D7A 83E20F                  and edx, 0000000F
:10001D7D 03C2                    add eax, edx
:10001D7F C1F804                  sar eax, 04
:10001D82 8BF0                    mov esi, eax
:10001D84 81E60F000080            and esi, 8000000F        //esi中存放该数的7~4 bit
:10001D8A 7905                    jns 10001D91
:10001D8C 4E                      dec esi
:10001D8D 83CEF0                  or esi, FFFFFFF0
:10001D90 46                      inc esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001D8A(C)
|
:10001D91 99                      cdq
:10001D92 83E20F                  and edx, 0000000F
:10001D95 03C2                    add eax, edx
:10001D97 C1F804                  sar eax, 04
:10001D9A 8BF8                    mov edi, eax
:10001D9C 81E70F000080            and edi, 8000000F        //edi中存放该数的11~8 bit
:10001DA2 7905                    jns 10001DA9
:10001DA4 4F                      dec edi
:10001DA5 83CFF0                  or edi, FFFFFFF0
:10001DA8 47                      inc edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001DA2(C)
|
:10001DA9 99                      cdq
:10001DAA 83E20F                  and edx, 0000000F
:10001DAD 03C2                    add eax, edx
:10001DAF C1F804                  sar eax, 04
:10001DB2 8BD8                    mov ebx, eax
:10001DB4 81E30F000080            and ebx, 8000000F      //ebx中存放该数的15~12 bit
:10001DBA 7905                    jns 10001DC1
:10001DBC 4B                      dec ebx
:10001DBD 83CBF0                  or ebx, FFFFFFF0
:10001DC0 43                      inc ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001DBA(C)
|
:10001DC1 8BC3                    mov eax, ebx
:10001DC3 99                      cdq
:10001DC4 83E207                  and edx, 00000007
:10001DC7 03C2                    add eax, edx
:10001DC9 C1F803                  sar eax, 03
:10001DCC 8BE8                    mov ebp, eax
:10001DCE 81E501000080            and ebp, 80000001      //用掩码取出该数的第15 bit
:10001DD4 7905                    jns 10001DDB
:10001DD6 4D                      dec ebp
:10001DD7 83CDFE                  or ebp, FFFFFFFE
:10001DDA 45                      inc ebp

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001DD4(C)
|
:10001DDB 8BC7                    mov eax, edi
:10001DDD 99                      cdq
:10001DDE 83E207                  and edx, 00000007
:10001DE1 03C2                    add eax, edx
:10001DE3 C1F803                  sar eax, 03
:10001DE6 2501000080              and eax, 80000001    //用掩码取出该数的第11 bit
:10001DEB 7905                    jns 10001DF2
:10001DED 48                      dec eax
:10001DEE 83C8FE                  or eax, FFFFFFFE
:10001DF1 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001DEB(C)
|
:10001DF2 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001DF5 8BC6                    mov eax, esi
:10001DF7 99                      cdq
:10001DF8 83E207                  and edx, 00000007
:10001DFB 03C2                    add eax, edx
:10001DFD C1F803                  sar eax, 03
:10001E00 2501000080              and eax, 80000001  //用掩码取出该数的第7 bit
:10001E05 7905                    jns 10001E0C
:10001E07 48                      dec eax
:10001E08 83C8FE                  or eax, FFFFFFFE
:10001E0B 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E05(C)
|
:10001E0C 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001E0F 8BC1                    mov eax, ecx
:10001E11 99                      cdq
:10001E12 83E207                  and edx, 00000007
:10001E15 03C2                    add eax, edx
:10001E17 C1F803                  sar eax, 03
:10001E1A 2501000080              and eax, 80000001      //用掩码取出该数的第3 bit
:10001E1F 7905                    jns 10001E26
:10001E21 48                      dec eax
:10001E22 83C8FE                  or eax, FFFFFFFE
:10001E25 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E1F(C)
|
:10001E26 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001E29 8BC3                    mov eax, ebx
:10001E2B 99                      cdq
:10001E2C 83E203                  and edx, 00000003
:10001E2F 03C2                    add eax, edx
:10001E31 C1F802                  sar eax, 02
:10001E34 2501000080              and eax, 80000001    //用掩码取出该数的第14 bit
:10001E39 7905                    jns 10001E40
:10001E3B 48                      dec eax
:10001E3C 83C8FE                  or eax, FFFFFFFE
:10001E3F 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E39(C)
|
:10001E40 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001E43 8BC7                    mov eax, edi
:10001E45 99                      cdq
:10001E46 83E203                  and edx, 00000003
:10001E49 03C2                    add eax, edx
:10001E4B C1F802                  sar eax, 02
:10001E4E 2501000080              and eax, 80000001  //用掩码取出该数的第10 bit
:10001E53 7905                    jns 10001E5A
:10001E55 48                      dec eax
:10001E56 83C8FE                  or eax, FFFFFFFE
:10001E59 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E53(C)
|
:10001E5A 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001E5D 8BC6                    mov eax, esi
:10001E5F 99                      cdq
:10001E60 83E203                  and edx, 00000003
:10001E63 03C2                    add eax, edx
:10001E65 C1F802                  sar eax, 02
:10001E68 2501000080              and eax, 80000001 //用掩码取出该数的第6 bit
:10001E6D 7905                    jns 10001E74
:10001E6F 48                      dec eax
:10001E70 83C8FE                  or eax, FFFFFFFE
:10001E73 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E6D(C)
|
:10001E74 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001E77 8BC1                    mov eax, ecx
:10001E79 99                      cdq
:10001E7A 83E203                  and edx, 00000003
:10001E7D 03C2                    add eax, edx
:10001E7F C1F802                  sar eax, 02
:10001E82 2501000080              and eax, 80000001  //用掩码取出该数的第2 bit
:10001E87 7905                    jns 10001E8E
:10001E89 48                      dec eax
:10001E8A 83C8FE                  or eax, FFFFFFFE
:10001E8D 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E87(C)
|
:10001E8E 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001E91 8BC3                    mov eax, ebx
:10001E93 99                      cdq
:10001E94 2BC2                    sub eax, edx
:10001E96 D1F8                    sar eax, 1
:10001E98 2501000080              and eax, 80000001  //用掩码取出该数的第13 bit
:10001E9D 7905                    jns 10001EA4
:10001E9F 48                      dec eax
:10001EA0 83C8FE                  or eax, FFFFFFFE
:10001EA3 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001E9D(C)
|
:10001EA4 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001EA7 8BC7                    mov eax, edi
:10001EA9 99                      cdq
:10001EAA 2BC2                    sub eax, edx
:10001EAC D1F8                    sar eax, 1
:10001EAE 2501000080              and eax, 80000001  //用掩码取出该数的第9 bit
:10001EB3 7905                    jns 10001EBA
:10001EB5 48                      dec eax
:10001EB6 83C8FE                  or eax, FFFFFFFE
:10001EB9 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001EB3(C)
|

:10001EBA 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001EBD 8BC6                    mov eax, esi
:10001EBF 99                      cdq
:10001EC0 2BC2                    sub eax, edx
:10001EC2 D1F8                    sar eax, 1
:10001EC4 2501000080              and eax, 80000001  //用掩码取出该数的第5 bit
:10001EC9 7905                    jns 10001ED0
:10001ECB 48                      dec eax
:10001ECC 83C8FE                  or eax, FFFFFFFE
:10001ECF 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001EC9(C)
|
:10001ED0 8D2C68                  lea ebp, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001ED3 8BC1                    mov eax, ecx
:10001ED5 99                      cdq
:10001ED6 2BC2                    sub eax, edx
:10001ED8 D1F8                    sar eax, 1
:10001EDA 2501000080              and eax, 80000001 //用掩码取出该数的第1 bit
:10001EDF 7905                    jns 10001EE6
:10001EE1 48                      dec eax
:10001EE2 83C8FE                  or eax, FFFFFFFE
:10001EE5 40                      inc eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001EDF(C)
|
:10001EE6 81E301000080            and ebx, 80000001  //用掩码取出该数的第12 bit
:10001EEC 8D1468                  lea edx, dword ptr [eax+2*ebp] //乘以2(二进制)再加上新的bit
:10001EEF 7905                    jns 10001EF6
:10001EF1 4B                      dec ebx
:10001EF2 83CBFE                  or ebx, FFFFFFFE
:10001EF5 43                      inc ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001EEF(C)
|
:10001EF6 81E701000080            and edi, 80000001    //用掩码取出该数的第8 bit
:10001EFC 8D0453                  lea eax, dword ptr [ebx+2*edx] //乘以2(二进制)再加上新的bit
:10001EFF 7905                    jns 10001F06
:10001F01 4F                      dec edi
:10001F02 83CFFE                  or edi, FFFFFFFE
:10001F05 47                      inc edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001EFF(C)
|
:10001F06 81E601000080            and esi, 80000001    //用掩码取出该数的第4 bit
:10001F0C 8D1447                  lea edx, dword ptr [edi+2*eax] //乘以2(二进制)再加上新的bit
:10001F0F 7905                    jns 10001F16
:10001F11 4E                      dec esi
:10001F12 83CEFE                  or esi, FFFFFFFE
:10001F15 46                      inc esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001F0F(C)
|
:10001F16 81E101000080            and ecx, 80000001      //用掩码取出该数的第0 bit
:10001F1C 8D0456                  lea eax, dword ptr [esi+2*edx] //乘以2(二进制)再加上新的bit
:10001F1F 7905                    jns 10001F26
:10001F21 49                      dec ecx
:10001F22 83C9FE                  or ecx, FFFFFFFE
:10001F25 41                      inc ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001F1F(C)
|
:10001F26 8B5C2424                mov ebx, dword ptr [esp+24]
:10001F2A 8D0441                  lea eax, dword ptr [ecx+2*eax] //乘以2(二进制)再加上新的bit
:10001F2D 6A10                    push 00000010
:10001F2F 53                      push ebx                      //ebx中存放变换后的整数
:10001F30 50                      push eax
:10001F31 89442424                mov dword ptr [esp+24], eax
:10001F35 E812060000              call 1000254C                //sprintf( )

上面的变换看似复杂,实际上可以简化为一个循环,其逆运算就是把各个bit调换回去,如下:

    int a = 0x0B26;      //变换后的
    int b = 0;          //变换前的
    int index[] = {15,11,7,3,14,10,6,2,13,9,5,1,12,8,4,0};

    for(int k = 0; k < 16; k++)
    {
        b <<= 1;
        b |=  (a >> index[k]) & 1;
    }

这样就可以写出keymaker来,一个注册码是01-0184-4056-8888。注意VerifySN( )函数实际上应该返回0x0B,这点在安装时
不判断,但是其主程序在运行时会判断,若不等于0x0B则无法运行,主要是因为它用这个返回值来区分该公司的不同软件。

* Possible StringData Ref from Data Obj ->"CSPQueryApp::InitInstance - About "
                                        ->"to validate SN"
                                  |
:00498348 689C305200              push 0052309C
:0049834D E8FE08F7FF              call 00408C50
:00498352 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00498346(C)
|
:00498355 51                      push ecx
:00498356 8BCC                    mov ecx, esp
:00498358 89642418                mov dword ptr [esp+18], esp
:0049835C 51                      push ecx
:0049835D 8BCD                    mov ecx, ebp
:0049835F E88C270000              call 0049AAF0
:00498364 8BCD                    mov ecx, ebp
:00498366 E815280000              call 0049AB80
:0049836B 8BF0                    mov esi, eax
:0049836D 3BF3                    cmp esi, ebx
:0049836F 7423                    je 00498394
:00498371 F6054078520002          test byte ptr [00527840], 02
:00498378 740D                    je 00498387

* Possible StringData Ref from Data Obj ->"CSPQueryApp::InitInstance - Invalid "
                                        ->"SN"
                                  |
:0049837A 6874305200              push 00523074
:0049837F E8CC08F7FF              call 00408C50
:00498384 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00498378(C)
|
:00498387 56                      push esi
:00498388 8BCD                    mov ecx, ebp
:0049838A E8312B0000              call 0049AEC0
:0049838F E939060000              jmp 004989CD

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0049836F(C)
|
:00498394 8B8504020000            mov eax, dword ptr [ebp+00000204]
:0049839A 83F80A                  cmp eax, 0000000A
:0049839D 7511                    jne 004983B0
:0049839F 53                      push ebx
:004983A0 53                      push ebx

* Possible StringData Ref from Data Obj ->"Domain license is detected for "
                                        ->"this current version of SPQuery. "
                                        ->" Please contact St. Bernard Software "
                                        ->"for a new license."
                                  |
:004983A1 68FC2F5200              push 00522FFC

* Reference To: MFC42.Ordinal:04B0, Ord:04B0h
                                  |
:004983A6 E849950400              Call 004E18F4
:004983AB E91D060000              jmp 004989CD

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0049839D(C)
|
:004983B0 83F80B                  cmp eax, 0000000B    //VerifySN( )的返回值
:004983B3 740C                    je 004983C1
:004983B5 8BCD                    mov ecx, ebp
:004983B7 E8D42B0000              call 0049AF90        //出错MessageBox
:004983BC E90C060000              jmp 004989CD


BF