SFV Checker 1.14

程序的算法部分比较隐蔽,藏的比较深,还好是用硬件访问断点,影响不是很大。不会编程,所以纯手工反推注册码。

Microsoft Visual C++ 6.0 [Debug]

1.订单号:
点击注册,输入用户名,然后又跳出提示框,输入订单code,输入后确认,错误提示:"Invalid Code!"

OD串参考:
地址=00411D0D 反汇编=push SFVCheck.0047B4E4 文本字符串=Invalid Code!

W32Dasm来到:
:00411CC0 56                      push esi
:00411CC1 8BF1                    mov esi, ecx
:00411CC3 6A01                    push 00000001
:00411CC5 E8277E0300              call 00449AF1
:00411CCA 8B465C                  mov eax, dword ptr [esi+5C]   ; 订单号的十六进制
:00411CCD 3D801A0600              cmp eax, 00061A80
:00411CD2 7E35                    jle 00411D09
:00411CD4 3DE9B00F00              cmp eax, 000FB0E9
:00411CD9 7D2E                    jge 00411D09
:00411CDB 3D44840600              cmp eax, 00068444
:00411CE0 7427                    je 00411D09
:00411CE2 3D40420F00              cmp eax, 000F4240
:00411CE7 7420                    je 00411D09
:00411CE9 3DF5340D00              cmp eax, 000D34F5
:00411CEE 7419                    je 00411D09
:00411CF0 3D2A830800              cmp eax, 0008832A
:00411CF5 7412                    je 00411D09
:00411CF7 3D40E20100              cmp eax, 0001E240
:00411CFC 740B                    je 00411D09
:00411CFE 6A01                    push 00000001
:00411D00 8BCE                    mov ecx, esi
:00411D02 E87D500300              call 00446D84
:00411D07 5E                      pop esi
:00411D08 C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00411CD2(C), :00411CD9(C), :00411CE0(C), :00411CE7(C), :00411CEE(C)
|:00411CF5(C), :00411CFC(C)
|
:00411D09 6A00                    push 00000000
:00411D0B 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"Invalid Code!"
                                  |
:00411D0D 68E4B44700              push 0047B4E4
:00411D12 8BCE                    mov ecx, esi
:00411D14 E8EF700300              call 00448E08
:00411D19 6A00                    push 00000000
:00411D1B 8BCE                    mov ecx, esi
:00411D1D E862500300              call 00446D84
:00411D22 5E                      pop esi
:00411D23 C3                      ret

输入的订单号转换成十六进制,范围要在:61A80-0FB0E9,即:400000-1028329,且不能等于好几个值。
修改为:654321,通过,然后又有提示框:输入key。

2.key:
OD串参考:
地址=004141B7 反汇编=push SFVCheck.0047B544 文本字符串=Invalid Key

2.1 W32Dasm来到:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004140EB(C)
|
:004140F9 57                      push edi                      // 从00411D08 ret可到达这里

* Possible StringData Ref from Data Obj ->"10134"
                                  |
:004140FA 6820A34700              push 0047A320  
:004140FF E82CDAFFFF              call 00411B30                 // 取得key,保存
:00414104 83C404                  add esp, 00000004
:00414107 8BCE                    mov ecx, esi
:00414109 8BF8                    mov edi, eax
:0041410B E810010000              call 00414220                 // 检查W32Dasm,SoftIce
:00414110 85FF                    test edi, edi
:00414112 5F                      pop edi
:00414113 0F84E0000000            je 004141F9

* Possible StringData Ref from Data Obj ->"SFV"
                                  |
:00414119 6828A34700              push 0047A328
:0041411E 8D542408                lea edx, dword ptr [esp+08]

* Possible StringData Ref from Data Obj ->"10134"
                                  |
:00414122 6820A34700              push 0047A320
:00414127 52                      push edx
:00414128 E883DAFFFF              call 00411BB0                 // 取出key,计算
:0041412D 8B442410                mov eax, dword ptr [esp+10]

* Possible StringData Ref from Data Obj ->"SFV100-69"
                                  |
:00414131 6838B54700              push 0047B538
:00414136 50                      push eax
:00414137 C684248400000001        mov byte ptr [esp+00000084], 01
:0041413F E8D1370100              call 00427915                 // 比较
:00414144 83C414                  add esp, 00000014
:00414147 85C0                    test eax, eax
:00414149 0F94C0                  sete al
:0041414C 84C0                    test al, al
:0041414E 0F8497000000            je 004141EB
:00414154 8A86DC010000            mov al, byte ptr [esi+000001DC]
:0041415A 84C0                    test al, al
:0041415C 754B                    jne 004141A9
:0041415E 8BCE                    mov ecx, esi
:00414160 E81B090000              call 00414A80
:00414165 84C0                    test al, al
:00414167 7540                    jne 004141A9
:00414169 8BCE                    mov ecx, esi
:0041416B E8B0000000              call 00414220
:00414170 8BCE                    mov ecx, esi
:00414172 E819020000              call 00414390
:00414177 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"Reg Information"
                                  |
:00414179 6888B54700              push 0047B588

* Possible StringData Ref from Data Obj ->"Registered OK,Thank You!"
                                  |
:0041417E 686CB54700              push 0047B56C

...

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0041415C(C), :00414167(C)
|
:004141A9 8BCE                    mov ecx, esi
:004141AB E870000000              call 00414220
:004141B0 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"Try Again"
                                  |
:004141B2 6850B54700              push 0047B550

* Possible StringData Ref from Data Obj ->"Invalid Key"
                                  |
:004141B7 6844B54700              push 0047B544

2.2分解:
:004140FF E82CDAFFFF              call 00411B30                 // 取得key
00411B61      E8 3C980000     call <jmp.&OLCHK32.OLPromptLicense>
100013AB      E8 B0000000     call OLCHK32.OLStoreLicense
100014BA      FF15 30940110   call dword ptr ds:[10019430]         ; ADVAPI32.RegSetValueA
这几个call是层层进入的,取得key,并保存:
HKCR\O'License\Licenses\10134\(Default)  SUCCESS  "8765432112345678"  

:0041410B E810010000              call 00414220                 // 检查W32Dasm,SoftIce
0041429B      68 C4B54700        push SFVCheck.0047B5C4            ; ASCII "w32dasm"
004142B6      68 BCB54700        push SFVCheck.0047B5BC            ; ASCII "softice"

:00414128 E883DAFFFF              call 00411BB0                 // 取出key,计算
00411BFA      E8 AF970000       call <jmp.&OLCHK32.OLRetrieveKey>
1000156A      FF15 34940110   call dword ptr ds:[10019434]         ; ADVAPI32.RegQueryValueA
取出注册码后就开始进行计算,下面详细分解。

2.3进入计算call:00411BFA      E8 AF970000       call <jmp.&OLCHK32.OLRetrieveKey>
第一次计算:100015B9      E8 72020000     call OLCHK32.10001830           ; 计算
10001896      8A06            mov al,byte ptr ds:[esi]
10001898      8A4E 01         mov cl,byte ptr ds:[esi+1]
1000189B      83C6 02         add esi,2
1000189E      8845 F2         mov byte ptr ss:[ebp-E],al
100018A1      884D F3         mov byte ptr ss:[ebp-D],cl
100018A4      8B45 F2         mov eax,dword ptr ss:[ebp-E]
100018A7      50              push eax
100018A8      E8 D3FEFFFF     call OLCHK32.10001780                 ; 初步计算
100018AD      83C4 04         add esp,4
100018B0      8D4D EC         lea ecx,dword ptr ss:[ebp-14]
100018B3      50              push eax
100018B4      E8 019A0000     call OLCHK32.1000B2BA                  ; 保存计算值
100018B9      4F              dec edi
100018BA    ^ 75 DA           jnz short OLCHK32.10001896
100018BC      8D45 EC         lea eax,dword ptr ss:[ebp-14]          ; 值存放地址

进入100018A8的call:call OLCHK32.10001780
10001780      83EC 04         sub esp,4
...
1000179F      50              push eax                             ; 参数一:低4位就是待转换的
100017A0      E8 ABFFFFFF     call OLCHK32.10001750                ; 转换成字节,注意eax
100017A5      8B15 38410110   mov edx,dword ptr ds:[10014138]
100017AB      83C4 04         add esp,4
100017AE      8B0D 805D0110   mov ecx,dword ptr ds:[10015D80]
100017B4      8A0C11          mov cl,byte ptr ds:[ecx+edx]         ; 顺取参数二
100017B7      33D2            xor edx,edx
100017B9      8AD9            mov bl,cl
100017BB      80E3 03         and bl,3
100017BE      8AD3            mov dl,bl
100017C0      83FA 03         cmp edx,3
100017C3      77 45           ja short OLCHK32.1000180A
100017C5      FF2495 1C180010 jmp dword ptr ds:[edx*4+1000181C]    ; 4种不同情况

100017CC      5B              pop ebx                              ; edx=0
100017CD      FF05 38410110   inc dword ptr ds:[10014138]
100017D3      F6D0            not al
100017D5      83C4 04         add esp,4
100017D8      C3              retn

100017D9      32C8            xor cl,al                              ; edx=1
100017DB      5B              pop ebx
100017DC      8AC1            mov al,cl
100017DE      83C4 04         add esp,4
100017E1      FF05 38410110   inc dword ptr ds:[10014138]
100017E7      C3              retn

100017E8      32C8            xor cl,al                              ; edx=2,即“F”,“V”
100017EA      5B              pop ebx
100017EB      83C4 04         add esp,4
100017EE      FF05 38410110   inc dword ptr ds:[10014138]
100017F4      F6D1            not cl
100017F6      8AC1            mov al,cl
100017F8      C3              retn

100017F9      32C8            xor cl,al                              ; edx=3,即“S”
100017FB      5B              pop ebx
100017FC      83C4 04         add esp,4
100017FF      FF05 38410110   inc dword ptr ds:[10014138]
10001805      F6D1            not cl
10001807      8AC1            mov al,cl
10001809      C3              retn

其中转换字节是这样转换的:
  10001720      8A4424 04       mov al,byte ptr ss:[esp+4]
  10001724      3C 30           cmp al,30
  10001726      72 07           jb short OLCHK32.1000172F
  10001728      3C 39           cmp al,39
  1000172A      77 03           ja short OLCHK32.1000172F
  1000172C      2C 30           sub al,30
  1000172E      C3              retn
  1000172F      3C 41           cmp al,41
  10001731      72 0D           jb short OLCHK32.10001740
  10001733      3C 5A           cmp al,5A
  10001735      77 09           ja short OLCHK32.10001740
  10001737      2A05 40410110   sub al,byte ptr ds:[10014140]
  1000173D      04 0A           add al,0A
  1000173F      C3              retn
如果是数字的话,不变,如果是字母的话+A-48。
比如B9=42 39,转换成字节就是42+A-48=4,39-30=9,就是49,对应关系:
A=48,B=49,...

这样计算的:
顺取参数一(这里是输入的注册码),2字节,转换成1字节=AL,然后根据顺取参数二(这里是“SFV”)=CL,与3的AND值判断计算,4种情况:
第一种:edx=0,NOT AL
第二种:edx=1,XOR CL,AL
第三种:edx=2,XOR CL,AL,NOT CL
第四种:edx=3,XOR CL,AL,NOT CL

参数一:87654321123456788765432112345678,
参数二:“SFV”=53 46 56
得到的edx=2或3,都是一样的计算:XOR CL,AL,NOT CL
参数一转换后:87 65 43 21 12 34 56 78 87 65 43 21 12 34 56 78,
运算值:
009221C4  2B DC EA 8D AB 9D FA C1  +荜崼濟
009221CC  2E C9 FA 88 BE 8D FF D4  .生埦?

然后又计算了一次,不过运算参数不同,是第一次运算后的值:
100015F5      E8 36020000     call OLCHK32.10001830                      ; 又计算了一次
参数一:009221CC  2E C9 FA 88 BE 8D FF D4  .生埦?
参数二:009221C4  2B DC EA 8D AB 9D FA C1  +荜崼濟

顺取参数一,2个字节转换成1个字节,如果不能得到字符,就变为00,
比如:2E C9 FA 88 BE 8D FF D4转换成:00 00 00 00,
再顺取参数二:00921F3C  2B DC EA 8D AB 9D FA C1,  
根据AND 3结果进行运算,
值:009236EC  D4 FF 15 8D              ??

比较:
00427944      66:0FB60F       movzx cx,byte ptr ds:[edi]           ; 顺取最后的运算值
00427948      0FB6C1          movzx eax,cl
0042794B      47              inc edi
0042794C      894D 0C         mov dword ptr ss:[ebp+C],ecx
0042794F      F680 E1494900 0>test byte ptr ds:[eax+4949E1],4      ; 这个要相等
00427956      74 16           je short SFVCheck.0042796E           ; 跳

0042796E      66:0FB61E       movzx bx,byte ptr ds:[esi]           ; 顺取待比较的值
00427972      0FB6C3          movzx eax,bl
00427975      46              inc esi
00427976      F680 E1494900 0>test byte ptr ds:[eax+4949E1],4      ; 这个相等
0042797D      74 13           je short SFVCheck.00427992           ; 跳

00427992      66:395D 0C      cmp word ptr ss:[ebp+C],bx           ; 
00427996      75 09           jnz short SFVCheck.004279A1
00427998      66:837D 0C 00   cmp word ptr ss:[ebp+C],0
0042799D      74 16           je short SFVCheck.004279B5
0042799F    ^ EB A3           jmp short SFVCheck.00427944

这个比较有讲究,因为要比较的值为:SFV100-69,它跳的要跟着跳,否则比较的东西就变样。
比如最后计算值: D4 FF 15 8D,因为不跳,最后比较的是FFD4与0053比较,
如果修改让其跳转,比较的是:00D4与0053。
不管如何,只要最后的计算值=SFV100-69就肯定没问题。

然后程序金蝉脱壳:
00414190      68 5CB54700     push SFVCheck.0047B55C                         ; ASCII "SFVChecker.exe"
00414195      68 F4A04700     push SFVCheck.0047A0F4                         ; ASCII "open"
0041419A      6A 00           push 0
0041419C      FF15 2C454600   call dword ptr ds:[<&SHELL32.ShellExecuteA>]   ; SHELL32.ShellExecuteA

3.反推注册码:
SFV100-69=53,46,56,31,30,30,2D,36,39,
总共9位,×2×2=36位,×2=72位,注册码需要72位
假设练码为:876543211234567887654321123456788765 432112345678876543211234567887654321

第一次计算后得到:
009221C4  2B DC EA 8D AB 9D FA C1 2E C9 FA 88 BE 8D FF D4  +荜崼濟?生埦?
009221D4  3E CC EF 98 BB 98 EF D1 2B DC EA 8D AB 9D FA C1  >田樆橈?荜崼濟
009221E4  2E C9 FA 88                                      .生?

这里又发现,程序只是取第1次运算值前8字节作为参数二:2B DC EA 8D AB 9D FA C1 
剩下的为参数一:2E C9 FA 88 BE 8D FF D4 3E CC EF 98 BB 98 EF D1 2B DC EA 8D AB 9D FA C1 2E C9 FA 88

因此注册码不需要那么多位,只要:9×2×2+8×2=36+16=52位
8765432112345678 876543211234567887654321123456788765
第一次运算后:
2B DC EA 8D AB 9D FA C1 
2E C9 FA 88 BE 8D FF D4 3E CC EF 98 BB 98 EF D1 2B DC 00

反推第二次运算:
前8字节可以不动,也就是注册码前16位不动,那么它们AND 3后结果(8+1次):
3,0,2,1,3,1,2,1,3
第一种:edx=0,NOT AL
第二种:edx=1,XOR CL,AL
第三种:edx=2,XOR CL,AL,NOT CL
第四种:edx=3,XOR CL,AL,NOT CL

转换字节的逆转换:数值+30,字母+48-A。

参数二:2B DC EA 8D AB 9D FA C1 

要让最后值=SFV100-69=53,46,56,31,30,30,2D,36,39,
那么逆推:
53,2B,3,NOT 53=AC,XOR 2B=87        38,37
46,DC,0,NOT 46=B9                  49,39
56,EA,2,NOT 56=A9,XOR EA=43        34,33   
31,8D,1,XOR 8D=BC                  49,4A         
30,AB,3,NOT 30=CF,XOR AB=64        36,34     
30,9D,1,XOR 9D=AD                  48,4B        
2D,FA,2,NOT 2D=D2,XOR FA=28        32,38       
36,C1,1,XOR C1=F7                  4D,37     
39,2B,3,NOT 39=C6,XOR 2B=ED        4C,4B         

第一次运算后结果要为:
2B DC EA 8D AB 9D FA C1 
38 37 49 39 34 33 49 4A 36 34 48 4B 32 38 4D 37 4C 4B
初步验证ok。

再反推第一次运算:
参数二:SFV=53 46 56 
它们AND 3的结果为edx=2或者3,都是一样的运算:XOR CL,AL,NOT CL
结果要=2B DC EA 8D AB 9D FA C1 38 37 49 39 34 33 49 4A 36 34 48 4B 32 38 4D 37 4C 4B
前面8个字节对应8765432112345678,因为没动,所以不用反推。
只要反推后面的: 38 37 49 39 34 33 49 4A 36 34 48 4B 32 38 4D 37 4C 4B
     NOT后的值: C7 C8 B6 C6 CB CC B6 B5 C9 CB B7 B4 CD C7 B2 C8 B3 B4
           XOR: V  S  F  V  S  F  V  S  F  V  S  F  V  S  F  V  S  F
            即: 56 53 46 56 53 46 56 53 46 56 53 46 56 53 46 56 53 46 
      得到的值: 91 9B F0 90 98 8A E0 E6 8F 9D E4 F2 9B 94 F4 9E E0 F2   

对应关系:数字+30,字母:A=48,B=49,C=4A,D=4B,E=4C,F=4D
逆运算后:
91   9B   F0   90   98   8A   E0   E6   8F   9D   E4   F2   9B   94   F4   9E   E0   F2
3931 3949 4D30 3930 3938 3848 4C30 4C36 384D 394B 4C34 4D32 3949 3934 4D34 394C 4C30 4D32                                                              
9 1  9 I  M 0  9 0  9 8  8 H  L 0  L 6  8 M  9 K  L 4  M 2  9 I  9 4  M 4  9 L  L 0  M 2                                                                                                      

即后部分为:919IM090988HL0L68M9KL4M29I94M49LL0M2                                                                                          
连接2部分的注册码:8765432112345678919IM090988HL0L68M9KL4M29I94M49LL0M2

呵呵注册成功!
用户名:cyto
订单号:654321
注册码:8765432112345678919IM090988HL0L68M9KL4M29I94M49LL0M2

注册表相关:
HKCR\O'License\Licenses\10134\(Default)  SUCCESS  "8765432112345678919IM090988HL0L68M9KL4M29I94M49LL0M2"