solly 发表于 2019-9-12 18:45

某内存 SPD 读取和烧录软件个人注册版脱壳和注册分析、注册机实现激活!

本帖最后由 solly 于 2019-9-18 03:50 编辑

我8月份在搬家,因此有一段时间没发贴了。


前几天录制了一个本论坛的参赛视频,针对的是一个内存 SPD 芯片的数据读取和烧录软件 Thaiphoon Burner,其版本是 16.0.0.6 Build 0818 免费版,没有注册算法,不需要注册。
这次是针对另一个老一点的版本,15.0.0.0 build 1126 个人版,这个版本需要注册激活,才可以使用烧录功能。


还是先查查壳吧:

再“Scan /t":

节的情况:

可以看出,主程序是通过 PECompact 加壳的,首先需要脱壳。


用 OD 载入主程序:

可以看到,一开始就是一段通过 SEH 异常处理机制的反调试的代码,防止单步跟踪。具体代码如下:
00401000 >B8 70A97300      mov   eax, 0073A970                  ; eax == 新的异常处理子例程地址
00401005    50               push    eax                              ; 保存新的异常处理子例程地址
00401006    64:FF35 00000000   push    dword ptr fs:               ; 保存老的SEH指针
0040100D    64:8925 00000000   mov   dword ptr fs:, esp            ; 保存新的SEH指针
00401014    33C0               xor   eax, eax                         ; 将 eax 清 0,将导致下一行指令出现非法地址异常
00401016    8908               mov   dword ptr , ecx             ; 因 eax == 0,这一行代码会产生异常

先 F8 执行第一行指令,使得 eax == 0x0073A970,这个地址就是异常处理子例程的地址。
Ctrl + G,输入 eax ,就可以跳转到这个异常处理子例程了:

上图所选的代码部分,就是整个异常处理子例程。其中第1、2、3行是对另一个子程序的入口(0x0073A993)代码进行参数修正。具体代码如下:
0073A970    B8 F59673F0      mov   eax, F07396F5
0073A975    8D88 9E120010      lea   ecx, dword ptr     ; eax == 0x0073A993,是这个异常处理子全程后面的第一条指令地址
0073A97B    8941 01            mov   dword ptr , eax         ; 修改 mov 指令中的立即数
0073A97E    8B5424 04          mov   edx, dword ptr
0073A982    8B52 0C            mov   edx, dword ptr
0073A985    C602 E9            mov   byte ptr , 0E9            ; 修正产生异常的指令
0073A988    83C2 05            add   edx, 5
0073A98B    2BCA               sub   ecx, edx
0073A98D    894A FC            mov   dword ptr , ecx         ; 修正产生异常的指令的参数
0073A990    33C0               xor   eax, eax
0073A992    C3               retn                                     ; 返回重新执行修改后的指令

另外的代码就是用来修正前面会产生异常的指令代码的。我们先在 0x0073A97B 处下一个断点,然后 F9 运行程序,如下图所示,会中断下来:

中断在我们刚下的断点处,开始进行代码修改,为了激活 OD 的 patch 记录功能(会使变动代码或数据变成红色),我们先把将要修改的代码改一改,如下图所示,先在数据区转移到修改处(ecx中保存的地址值):

然后随便改一下数据,再按”确定“。

这样操作后,修改处的数据会变成红色,便于区分程序改动了什么地方,如下图所示:

然后 F8 执行,可见,mov 指令的立即数参数已经修改了,如下图所示:

另一个指令的修改也一样进行操作,如下图所示,先跟随edx中的地址跳转到修改处:

数据区也跟随到这个地址,再手动在数据区随便修改一下(0x00401016 处)数据,如下图所示:

按 F8 执行,如下图,把几条修改异常指令的代码全执行完成:


再过去看一下刚才手动修改的地方,可以看到,如下图所示,指令变成了 "jmp 0x0073A993",不会再产生异常了。

上图具体代码如下:
00401000 >B8 70A97300      mov   eax, 0073A970                  ; eax == 新的异常处理子例程地址
00401005    50               push    eax                              ; 保存新的异常处理子例程地址
00401006    64:FF35 00000000   push    dword ptr fs:               ; 保存老的SEH指针
0040100D    64:8925 00000000   mov   dword ptr fs:, esp            ; 保存新的SEH指针
00401014    33C0               xor   eax, eax                         ; 将 eax 清 0,将导致下一行指令出现非法地址异常
00401016- E9 78993300      jmp   0073A993                         ; 通过异常处理子例程修正为可正常执行的指令了
我们再”跟随“刚才修正的 jmp 指令,转移到下图所示位置:


我们再在 ”0x0073A99F" 处下一个断点,然后直接 “F9" 运行程序,执行到下图所示位置:

正是我们才下的断点处,到了这里后,通过 SEH 异常处理机制反调试的代码就被破除了。下面继续 F8 执行:

来到一个调用处,这个调用是 VirtualAlloc() ,是一个分配内存的调用,我们F8 继续执行。

执行完后,数据区跟随 eax,就可以来到刚才申请的内存区,这片内存区已被初始化为全 0 了。

继续 F8 执行,当执行完上图所示的 call ecx 后,可以看到,数据区已经写入了数据,不过这还是壳的代码,并不是原始程序代码,这段代码会再对原始代码进行解码。

继续 F8 来到 0x0073AA0E call edi ,可以看到 edi 的值处在前面申请的内存的范围内,也就是去执行刚才解码的壳代码,因此这时按 F7 进入函数,来到下图所示位置:

可以看到,第1条指令是一个跳转指令,并且是跳转到两条指令的中间位置,因此,此跳转后含有花指令,只有一个字节的花指令,就是 0x25,在数据区改成 0x90 就可以正常显示了,如下图所示:

我们一路 F8 执行代码,来到下图位置:

这几条指令是修正刚才解码的代码的几个 API 调用地址,相当于 IAT 修正吧。具体代码如下:
00030A7A    03F2            add   esi, edx
00030A7C    8DBD 5D2F0010   lea   edi, dword ptr
00030A82    AD            lods    dword ptr                         ; LoadLibraryA()
00030A83    AB            stos    dword ptr es:
00030A84    AD            lods    dword ptr                         ; GetProcAddress()
00030A85    AB            stos    dword ptr es:
00030A86    AD            lods    dword ptr                         ; VirtualAlloc()
00030A87    AB            stos    dword ptr es:
00030A88    AD            lods    dword ptr                         ; VirtualFree()
00030A89    AB            stos    dword ptr es:

共更新了4个 API 函数。

上面数据区就是刚才修改的几个 API 地址,共 4 个 API 入口地址。


接下来就是几条指令对程序的入口代码进行破坏,如下图所示,这样程序的入口代码就不正确了,也算是一种反调试或反脱壳方法吧

上图具体代码如下:
00030A98    B9 23000000      mov   ecx, 23
00030A9D    03F2             add   esi, edx
00030A9F    8B7B 40          mov   edi, dword ptr
00030AA2    03FA             add   edi, edx
00030AA4    F3:A4            rep   movs byte ptr es:, byte ptr    ; 传输 ecx == 0x23 字节, edi==0x401000,破坏启动代码



一路 F8 往下走,执行完一堆 nop 指令后,又来到一个反调试代码处,如下图所示:


这次是调用 IsDebuggerPresent() ,这条 API 是通过 PEB+02 处的标志来确定程序是否处于调试状态的。
如果返回eax == 0x00000001,就表示程序处于调试状态,我们修改代码避开检测(也可以在函数返回后直接将 eax 置 0),如下图所示:

具体代码如下:
00030ACA    8B85 292F0010    mov   eax, dword ptr
00030AD0    85C0             test    eax, eax
00030AD2    74 07            je      short 00030ADB
00030AD4    FFD0             call    eax                                    ; call KERNELBA.IsDebuggerPresent, 检查调试状态
00030AD6    85C0             test    eax, eax                                 ; 上面调用后,需手动将 eax 清 0,或改成 xor eax, eax
00030AD8    74 01            je      short 00030ADB
00030ADA    4B               dec   ebx                                    ; 如果是处理调试状态,则 ebx 减 1,会导致后面程序出现异常。
00030ADB    8B4E 2C          mov   ecx, dword ptr
00030ADE    898D 592F0010    mov   dword ptr , ecx

将 test eax, eax 改成 xor eax, eax 就可以了,上图已改好了。


再次一路 F8 执行程序,来到下面位置:


又是一个调用,申请了一片内存,我们在数据区跟随到申请的内存区,也是初始化成全0状态。继续 F8 执行,来到下面位置:

具体代码如下:
00030ADB    8B4E 2C          mov   ecx, dword ptr
00030ADE    898D 592F0010    mov   dword ptr , ecx
00030AE4    6A 04            push    4
00030AE6    68 00100000      push    1000
00030AEB    51               push    ecx
00030AEC    6A 00            push    0
00030AEE    FF95 652F0010    call    dword ptr                ; call VirtualAlloc
00030AF4    8985 552F0010    mov   dword ptr , eax
00030AFA    56               push    esi
00030AFB    E8 F6030000      call    00030EF6                                 ; 释放程序原delphi代码
00030B00    8D8D D12D0010    lea   ecx, dword ptr             ; ecx ===> "Application corrupt."
00030B06    85C0             test    eax, eax
00030B08    0F85 94000000    jnz   00030BA2

执行完上面的调用后,数据区出现了 delphi 风格的代码头。表明原始程序应该是一个 delphi 编译的程序。继续 F8 往下走,执行完几个调用后,来到下图位置:


上面是释放刚才申请的内存的调用,表明代码已经完成解码并转移到可执行节区去了。
这里是清理现场并准备退出函数了。


一路 F8 退出当前函数,来到下图所示位置:

具体代码如下:
0073AA10    8985 3F130010   mov   dword ptr , eax             ; eax == OEP
0073AA16    8BF0            mov   esi, eax
0073AA18    8B4B 14         mov   ecx, dword ptr
0073AA1B    5A            pop   edx
0073AA1C    EB 0C         jmp   short 0073AA2A
0073AA1E    03CA            add   ecx, edx
0073AA20    68 00800000   push    8000
0073AA25    6A 00         push    0
0073AA27    57            push    edi
0073AA28    FF11            call    dword ptr
0073AA2A    8BC6            mov   eax, esi
0073AA2C    5A            pop   edx
0073AA2D    5E            pop   esi
0073AA2E    5F            pop   edi
0073AA2F    59            pop   ecx
0073AA30    5B            pop   ebx
0073AA31    5D            pop   ebp
0073AA32    FFE0            jmp   eax                                        ; goto OEP

可以看到,所选代码中,最后一个跳转 jmp eax 就是去 OEP 了,call edi 返回的 eax 值,就是 OEP 了。如下图所示,是壳代码最后一条指令了:

按 F8 来到 OEP,就可以开始脱壳了:

直接用 OD 的脱壳功能进行脱壳:

不修改任何内容,直接按 ”Dump" 即可,取一个名字并保存好脱壳文件。



下面,我们执行一下刚才脱壳的程序,不能正常运行,会弹出下面的错误:

这表示 API 函数导入不正确,还需要修复 IAT 才可以运行。


以“管理员身份运行 ”ImportREC"。如下图所示,选好进程,修改 OEP,并按 "IAT AutoSearch",再 ”Get Imports",但结果并不正确,如下图所示,没有取到所需的 IAT(在有些情况也可以取到IAT,就可以去后面的IAT修正步骤了)。


我们点"Clear Import“ 先清除不正确的 IAT,然后修改 OEP 为原始值 0x00001000,如下图所示,重新按 "IAT AutoSearch",再 ”Get Imports",如下图所示,取到了 IAT:

再按”Show Invalid",还是有一些无效的导入,如下图所示:

这个就是刚才执行时弹出的错误 API 导入。手动修改为 User32.dll 中的DefWindowProcA()即可,如下图所示:

修改后仍然按“Show Invalid”,找到其它无效导入,如下图所示:

改完那个 DefWindowProcA()后,还要修改几个 combase.dll 中的几个错误导入,如上图所示的一个,改成如下图所示 Ole32.dll 中的相应函数:


还有几个如下图所示,也一并要改掉:

全部改成 Ole32.dll 中的调用:

全部改完后,就可以修复刚才导出的程序了,如下图所示,点“ Fix Dump",弹出文件对话框,选中刚才的导出文件,点"打开”即可。

会重新生成一个已修复 IAT 的新的执行文件,带有下划线“_”的那个文件。

还有一个问题,刚才在 ImportREC 中并没有修复 OEP。我们还需要手动去修复 OEP。如下图示位置,现在 OEP 还是原来的入口:0x00001000。

我们将其改成 0x001BF1D0 后才能正常运行,如下图所示就是改好 OEP 了。

现在,我们可以正常运行程序了,先来看看程序是什么编译器生成的,便于后面的分析处理。如下图所示,重新查看文件信息:


显示程序由 Delphi 编译,因此,我们先用 DeDeDark 来反编译程序,便于查看资源、函数、表单、事件入口等。
如下图所示,正在反编译:


反编译后,先看看工程文件,也就是 Delphi 编译的程序入口,即 OEP 开始的代码。

再在 OD 中看一下这段代码,可以看到,有一段生成文件名:"C:\Windows\Debug\passwd.log"。这个在后面要用到,先不管。

还有这一段,读取文件“Regdata.rkf”的内容,这个就是注册文件,注册表单中按 "Accept"就会把注册信息存于此文件中。

在 DeDeDark 看就更明显了,如下图所示,拼成了一个文件路径:


如果文件存在,则读取文件内容:

下面是注册信息判断,最后的结果检测:


有关NAG 显示的配置读取和判断是否显示:

这里有一个判断,不为0则退出程序:

看到有对按钮的显示进行控制:

对按钮的启用和禁用状态进行设置:


一些不明标志的判断,后面可能会用到:

大概看了一下程序的启动代码,下面我们运行程序。


首先会弹出一个警告对话框,表示 BIOS 对芯片的写保护,需要到 BIOS 中去禁用写保护后方可进行烧录操作。


接着弹出注册的 NAG,不过可以通过其界面下面的 CheckBox 来禁止弹出这个 NAG。

最后,显示主界面,由于没有注册,看不到有写入的功能按钮。

退出程序。


用 OD 重新载入脱壳后的程序:


根据前面的 DeDeDark 中查得信息,我们在入口代码中处理注册文件前下一个断点。



还在主表单(TForm1)的 TForm1.FormCreate() 事件中也下一个断点。



F9 运行,还是先弹出这个警告框:


然后中断在第1个断点处,如下图所示,由于没有输入注册码,还是继续一路猛按 F8 往下运行。

泥煤,程序直接退出了,看来还是有暗桩,不仅是脱个壳就可以了的。


按”-“回退,退回到下面代码处,就是刚才退出的即方,这就是按 F8 的好处,可以退回看哪里脱靶的。。。。

根据地址,在 DeDeDark 中找到相应位置如下图所示:

这个就是创建注册 NAG 表单的方法,这是 Delphi 内置的方法,所以只要中断 NAG 表单的 FormCreate 事件即可,因为创建表单会自动执行这个事件,基本也应该是在这个事件中跑飞了。
注册 NAG 表单是 TForm2。因此我们看一下 TForm2.FormCreate事件:

从上图可以找到该事件入口地址。


重新在 OD 载入程序,直接在 OD 中转到该入口:

在事件中下一个断点即可,如上图所示位置下一个断点。


重新运行,然后在 TForm2.FormCreate() 中断下来,再一次猛按 F8 ,不一会程序又跑飞了,然后按”-“回退到如下位置,在此位置下一个断点。



再重新用 OD 载入程序并一路 F9 运行。在最后断点处(0x0050F1F9),如上图所示位置,我们按 F7 进入。


然后又一路 F8 ,又会退出。回退看到退出位置如下,再下一个断点(0x0050EF96处)。


退出的函数地址是 call 0050ED5C,我们到 DeDeDark 中看看这个函数。

如上图所示,找到了退出位置的代码了,Delphi 函数 Halt() 就是强行退出程序。具体代码如下:
0050ED83|.803D E8435C00 00   cmp   byte ptr , 0         ;如果 == 0x01,则退出程序,需要在这个地址(0x005C43E8)下硬件断点寻找赋值指令
0050ED8A|.74 05                je      short 0050ED91
0050ED8C|.E8 6B59EFFF          call    004046FC                     ;System.Halt(),退出程序
0050ED91|>A1 D0715C00          mov   eax, dword ptr

可以看出,是对一个标志进行判断,但该标志并没在此函数内赋值,所以,我们在 OD 中重新载入程序,并运行到这里(最后断点处 F7 进入,再运行到0x0050ED83处),然后在数据区转到此指令中的地址值(0x005C43E8),下一个硬件访问断点,如下图所示:

下断点后,我们还要把该标志值修改成 0x00,免得程序再次退出或其它地方退出。


跳过刚才的退出暗桩,程序继续运行,正常弹出注册对话框的 NAG:

我们输入注册信息(老版本的激活数据,并不适合当前版本,只是套用格式)

点”Accept" 按钮保存注册信息。

立即被前面的硬件访问中断下来了,也是对这个标志进行判断,如果为 0x01 则退出程序,不会保存注册信息。因为我们前面改了数据,所以现在不会退出程序。

保存完注册信息,弹出一个对话框,提示要重启才能生效,看来是一个重启验证的注册机制。
关闭对话框,又会被硬件中断下来,还是与前面一样的原因:


按 F9 续断运行,没有再中断了,弹出了主界面。如下图所示:

没有看到写入功能,表示还没有注册成功或还没进行验证。


退出程序,在 OD 中重新载入程序,检查硬件访问中断没有问题:

按 F9 运行,硬件中断了下来,是一个写入中断,在这里将 写入了 0x01。如下图所示:

具体代码如下:
0050FFDD|.3B0424          cmp   eax, dword ptr
0050FFE0|.0F92C0          setb    al                               ; 修改为 0F94C0seteal
0050FFE3|.EB 03         jmp   short 0050FFE8
0050FFE5|>0F9CC0          setl    al                               ; 修改为 0F94C0seteal
0050FFE8|>83C4 08         add   esp, 8
0050FFEB|.A2 E8435C00   mov   byte ptr , al            ; al == 0x01 由表示程序已脱壳

存入的是 al 的值,前面有两条指令对 al 赋值了。如下图所示,两条 set 指令:

再到 DeDeDark 中相应位置看看。可以看出,这是一个文件大小的检查,看来程序会检查文件大小,防止程序脱壳运行。


破解也很简单,如下图所示,直接修改两个 set 指令即可。


然后在文件中找到相应位置,修改脱壳后文件。

下图是改好了的:



破除了退出暗桩,下面进行注册算法的处理,在启动代码的如下位置,包含了注册算法:

具体代码如下:; start() 注册验证部分
005BF63E   > \8D95 8CFEFFFF       lea   edx, dword ptr
005BF644   .A1 EC715C00         mov   eax, dword ptr
005BF649   .8B00                mov   eax, dword ptr
005BF64B   .E8 C803EBFF         call    0046FA18                                          ;GetExeName()
005BF650   .8B85 8CFEFFFF       mov   eax, dword ptr
005BF656   .8D95 90FEFFFF       lea   edx, dword ptr
005BF65C   .E8 1FA8E4FF         call    00409E80                                          ;ExtractFilePath()
005BF661   .8B95 90FEFFFF       mov   edx, dword ptr
005BF667   .A1 6C715C00         mov   eax, dword ptr
005BF66C   .B9 34025C00         mov   ecx, 005C0234                                       ;ASCII "Regdata.rkf"
005BF671   .E8 FE54E4FF         call    00404B74                                          ;StrCat()
005BF676   .33D2                xor   edx, edx
005BF678   .55                  push    ebp
005BF679   .68 95FD5B00         push    005BFD95
005BF67E   .64:FF32             push    dword ptr fs:
005BF681   .64:8922             mov   dword ptr fs:, esp
005BF684   .A1 6C715C00         mov   eax, dword ptr
005BF689   .8B00                mov   eax, dword ptr
005BF68B   .E8 B8A4E4FF         call    00409B48                                          ;FileExists()
005BF690   .84C0                test    al, al
005BF692   .0F84 D0060000       je      005BFD68
005BF698   .6A 40               push    40
005BF69A   .8B0D 6C715C00       mov   ecx, dword ptr                            ;dumped_b.005C99A4
005BF6A0   .8B09                mov   ecx, dword ptr
005BF6A2   .B2 01               mov   dl, 1
005BF6A4   .A1 ACA64100         mov   eax, dword ptr
005BF6A9   .E8 0A05E6FF         call    0041FBB8                                          ;TFileStream.Create()
005BF6AE   .8BD8                mov   ebx, eax
005BF6B0   .BA 30A85C00         mov   edx, 005CA830                                       ;ASCII 05,"solly"
005BF6B5   .B9 3C010000         mov   ecx, 13C
005BF6BA   .8BC3                mov   eax, ebx
005BF6BC   .E8 1302E6FF         call    0041F8D4                                          ;TStream.ReadBuffer()
005BF6C1   .8BC3                mov   eax, ebx
005BF6C3   .E8 D842E4FF         call    004039A0                                          ;TObject.Free()
005BF6C8   .B8 95A85C00         mov   eax, 005CA895                                       ;ASCII 04,"THRK"
005BF6CD   .BA 40025C00         mov   edx, 005C0240                                       ;ASCII 04,"THRK"
005BF6D2   .33C9                xor   ecx, ecx
005BF6D4   .8A08                mov   cl, byte ptr
005BF6D6   .41                  inc   ecx
005BF6D7   .E8 D83AE4FF         call    004031B4                                          ;AStrCmp(), 检测注册文件的文件头
005BF6DC   .74 15               je      short 005BF6F3
005BF6DE   .A1 6C715C00         mov   eax, dword ptr
005BF6E3   .8B00                mov   eax, dword ptr
005BF6E5   .E8 6AA6E4FF         call    00409D54                                          ;DeleteFile()
005BF6EA   .B2 01               mov   dl, 1
005BF6EC   .B0 04               mov   al, 4
005BF6EE   .E8 95FBF4FF         call    0050F288                                          ;显示错误信息, eax == 4, 'The registration file has a corrupted header!'
005BF6F3   >8D85 C4FEFFFF       lea   eax, dword ptr
005BF6F9   .E8 5EF8F4FF         call    0050EF5C                                          ;生成ID
005BF6FE   .8D95 C4FEFFFF       lea   edx, dword ptr                             ;edx ===> ID
005BF704   .A1 2C6F5C00         mov   eax, dword ptr
005BF709   .E8 FA39E4FF         call    00403108                                          ;PStrCpy()
005BF70E   .B8 9AA85C00         mov   eax, 005CA89A                                       ;ASCII 21,"A1884D69D3C7F040-205D575B25207559"
005BF713   .8B15 2C6F5C00       mov   edx, dword ptr                            ;edx ===> ID
005BF719   .33C9                xor   ecx, ecx
005BF71B   .8A08                mov   cl, byte ptr                                   ;取得delphi短字符串的长度, cl == 0x21
005BF71D   .41                  inc   ecx                                                 ;将长度字节也计算在内进行比较
005BF71E   .E8 913AE4FF         call    004031B4                                          ;AStrCmp(), eax, edx 指向的两个ID比较
005BF723   .0F85 3F060000       jnz   005BFD68
005BF729   .B8 30A85C00         mov   eax, 005CA830                                       ;eax == 0x005CA830 ===> (ASCII 05,"solly")
005BF72E   .E8 85FFF4FF         call    0050F6B8                                          ;eax == 0x79, 最字符串最后一个字母(不超过48个)
005BF733   .3A05 69A95C00       cmp   al, byte ptr                                ;'y', 名字最后一个字母?或较验和
005BF739   .0F85 24060000       jnz   005BFD63
005BF73F   .B8 30A85C00         mov   eax, 005CA830                                       ;ASCII 05,"solly"
005BF744   .E8 C302F5FF         call    0050FA0C                                          ;al == 0x73, 's'
005BF749   .3A05 68A95C00       cmp   al, byte ptr                                ;'s',名字第一个字母?
005BF74F   .0F85 13060000       jnz   005BFD68
005BF755   .BA 48025C00         mov   edx, 005C0248
005BF75A   .8D85 20FEFFFF       lea   eax, dword ptr
005BF760   .E8 A339E4FF         call    00403108                                          ;PStrCpy(),生成delphi字符串 01,'$'
005BF765   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF76B   .50                  push    eax
005BF76C   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF771   .BA 01000000         mov   edx, 1                                              ;start = 1
005BF776   .B8 9AA85C00         mov   eax, 005CA89A                                       ;eax == 005CA89A ===> (ASCII 21,"A1884D69D3C7F040-205D575B25207559")
005BF77B   .E8 E431E4FF         call    00402964                                          ;System.Copy()
005BF780   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> "A1884D69"
005BF786   .8D85 20FEFFFF       lea   eax, dword ptr
005BF78C   .B1 65               mov   cl, 65
005BF78E   .E8 4539E4FF         call    004030D8                                          ;PStrNCat(),形成 "$A1884D69"
005BF793   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> "$A1884D69"
005BF799   .8D85 88FEFFFF       lea   eax, dword ptr
005BF79F   .E8 2853E4FF         call    00404ACC                                          ;LStrFromString(),生成 pchar 字符串 "$A1884D69"
005BF7A4   .8B85 88FEFFFF       mov   eax, dword ptr                             ;EAX ===> "$A1884D69"
005BF7AA   .E8 819FE4FF         call    00409730                                          ;StrToInt()
005BF7AF   .8BD8                mov   ebx, eax                                          ;ID 第 1 部分
005BF7B1   .BA 48025C00         mov   edx, 005C0248
005BF7B6   .8D85 20FEFFFF       lea   eax, dword ptr
005BF7BC   .E8 4739E4FF         call    00403108                                          ;PStrCpy(), 生成 01, '$'
005BF7C1   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF7C7   .50                  push    eax
005BF7C8   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF7CD   .BA 1A000000         mov   edx, 1A                                             ;start = 26
005BF7D2   .B8 9AA85C00         mov   eax, 005CA89A                                       ;ASCII 21,"A1884D69D3C7F040-205D575B25207559"
005BF7D7   .E8 8831E4FF         call    00402964                                          ;SubString(), get "25207559"
005BF7DC   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> "25207559"
005BF7E2   .8D85 20FEFFFF       lea   eax, dword ptr
005BF7E8   .B1 65               mov   cl, 65
005BF7EA   .E8 E938E4FF         call    004030D8                                          ;PStrNCat()
005BF7EF   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$25207559"
005BF7F5   .8D85 B4FDFFFF       lea   eax, dword ptr
005BF7FB   .E8 CC52E4FF         call    00404ACC                                          ;LStrFromString()
005BF800   .8B85 B4FDFFFF       mov   eax, dword ptr                             ;eax ===> "$25207559"
005BF806   .E8 259FE4FF         call    00409730                                          ;StrToInt()
005BF80B   .33D8                xor   ebx, eax                                          ;ID最后部分与第1部分xor运算,0xA1884D69 xor 0x25207559 == 0x84A83830,这是激活码的第1部分
005BF80D   .BA 48025C00         mov   edx, 005C0248
005BF812   .8D85 20FEFFFF       lea   eax, dword ptr
005BF818   .E8 EB38E4FF         call    00403108                                          ;PStrCpy(), 生成 01, '$'
005BF81D   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF823   .50                  push    eax
005BF824   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF829   .BA 12000000         mov   edx, 12                                             ;start = 18
005BF82E   .B8 9AA85C00         mov   eax, 005CA89A                                       ;ASCII 21,"A1884D69D3C7F040-205D575B25207559"
005BF833   .E8 2C31E4FF         call    00402964                                          ;System.Copy(), get "205D575B"
005BF838   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "205D575B"
005BF83E   .8D85 20FEFFFF       lea   eax, dword ptr
005BF844   .B1 65               mov   cl, 65
005BF846   .E8 8D38E4FF         call    004030D8                                          ;PStrNCat()
005BF84B   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$205D575B"
005BF851   .8D85 B0FDFFFF       lea   eax, dword ptr
005BF857   .E8 7052E4FF         call    00404ACC                                          ;LStrFromString()
005BF85C   .8B85 B0FDFFFF       mov   eax, dword ptr                             ;eax ===> "$205D575B"
005BF862   .E8 C99EE4FF         call    00409730                                          ;StrToInt()
005BF867   .8BF0                mov   esi, eax                                          ;ID 第3部分,0x205D575B
005BF869   .BA 48025C00         mov   edx, 005C0248
005BF86E   .8D85 20FEFFFF       lea   eax, dword ptr
005BF874   .E8 8F38E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BF879   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF87F   .50                  push    eax
005BF880   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF885   .BA 09000000         mov   edx, 9                                              ;start = 9
005BF88A   .B8 9AA85C00         mov   eax, 005CA89A                                       ;(ASCII 21,"A1884D69D3C7F040-205D575B25207559")
005BF88F   .E8 D030E4FF         call    00402964                                          ;System.Copy(), SubString(), get "D3C7F040"
005BF894   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "D3C7F040"
005BF89A   .8D85 20FEFFFF       lea   eax, dword ptr
005BF8A0   .B1 65               mov   cl, 65
005BF8A2   .E8 3138E4FF         call    004030D8                                          ;PStrNCat()
005BF8A7   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$D3C7F040"
005BF8AD   .8D85 ACFDFFFF       lea   eax, dword ptr
005BF8B3   .E8 1452E4FF         call    00404ACC                                          ;LStrFromString()
005BF8B8   .8B85 ACFDFFFF       mov   eax, dword ptr                             ;EAX ===> "$D3C7F040"
005BF8BE   .E8 6D9EE4FF         call    00409730                                          ;StrToInt()
005BF8C3   .33F0                xor   esi, eax                                          ;ID 第 3 部分与第 2 部分进行xor运算,0x205D575B xor 0xD3C7F040 == 0xF39AA71B,这是激活码的第2部分
005BF8C5   .BA 48025C00         mov   edx, 005C0248
005BF8CA   .8D85 20FEFFFF       lea   eax, dword ptr
005BF8D0   .E8 3338E4FF         call    00403108                                          ;PStrCpy()
005BF8D5   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF8DB   .50                  push    eax
005BF8DC   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF8E1   .BA 01000000         mov   edx, 1                                              ;start = 1
005BF8E6   .B8 FFA85C00         mov   eax, 005CA8FF                                       ;ASCII 28,"724FBD29057D22021234567807D10C7299022142"
005BF8EB   .E8 7430E4FF         call    00402964                                          ;System.Copy()
005BF8F0   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ==> 08, "724FBD29",激活码第1部分
005BF8F6   .8D85 20FEFFFF       lea   eax, dword ptr
005BF8FC   .B1 65               mov   cl, 65
005BF8FE   .E8 D537E4FF         call    004030D8                                          ;PStrNCat()
005BF903   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$724FBD29"
005BF909   .8D85 A8FDFFFF       lea   eax, dword ptr
005BF90F   .E8 B851E4FF         call    00404ACC                                          ;LStrFromString()
005BF914   .8B85 A8FDFFFF       mov   eax, dword ptr                             ;eax ===> "$724FBD29"
005BF91A   .E8 119EE4FF         call    00409730                                          ;StrToInt()
005BF91F   .3BD8                cmp   ebx, eax                                          ;激活码比较1,ID第1部分与第4部分的xor值
005BF921   .0F85 41040000       jnz   005BFD68
005BF927   .BA 48025C00         mov   edx, 005C0248
005BF92C   .8D85 20FEFFFF       lea   eax, dword ptr
005BF932   .E8 D137E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BF937   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF93D   .50                  push    eax
005BF93E   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF943   .BA 09000000         mov   edx, 9                                              ;start = 9
005BF948   .B8 FFA85C00         mov   eax, 005CA8FF                                       ;ASCII 28,"724FBD29057D22021234567807D10C7299022142"
005BF94D   .E8 1230E4FF         call    00402964                                          ;System.Copy(),取激活码第2部分 "057D2202"
005BF952   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "057D2202"
005BF958   .8D85 20FEFFFF       lea   eax, dword ptr
005BF95E   .B1 65               mov   cl, 65
005BF960   .E8 7337E4FF         call    004030D8                                          ;PStrNCat()
005BF965   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$057D2202"
005BF96B   .8D85 A4FDFFFF       lea   eax, dword ptr
005BF971   .E8 5651E4FF         call    00404ACC                                          ;LStrFromString()
005BF976   .8B85 A4FDFFFF       mov   eax, dword ptr                             ;eax ==> "$057D2202"
005BF97C   .E8 AF9DE4FF         call    00409730                                          ;StrToInt()
005BF981   .3BF0                cmp   esi, eax                                          ;激活码比较2,ID第3部分与第2部分的xor值
005BF983   .0F85 DF030000       jnz   005BFD68
005BF989   .BA 48025C00         mov   edx, 005C0248
005BF98E   .8D85 20FEFFFF       lea   eax, dword ptr
005BF994   .E8 6F37E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BF999   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF99F   .50                  push    eax
005BF9A0   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BF9A5   .BA 19000000         mov   edx, 19                                             ;start = 25
005BF9AA   .B8 FFA85C00         mov   eax, 005CA8FF                                       ;ASCII 28,"724FBD29057D22021234567807D10C7299022142"
005BF9AF   .E8 B02FE4FF         call    00402964                                          ;System.Copy(),取激活码第4部分 "07D10C72"
005BF9B4   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "07D10C72"
005BF9BA   .8D85 20FEFFFF       lea   eax, dword ptr
005BF9C0   .B1 65               mov   cl, 65
005BF9C2   .E8 1137E4FF         call    004030D8                                          ;PStrNCat()
005BF9C7   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$07D10C72"
005BF9CD   .8D85 A0FDFFFF       lea   eax, dword ptr
005BF9D3   .E8 F450E4FF         call    00404ACC                                          ;LStrFromString()
005BF9D8   .8B85 A0FDFFFF       mov   eax, dword ptr                             ;eax ===> "$07D10C72"
005BF9DE   .E8 4D9DE4FF         call    00409730                                          ;StrToInt()
005BF9E3   .8BD8                mov   ebx, eax                                          ;ebx == 0x07D10C72,激活码第4部分
005BF9E5   .BA 48025C00         mov   edx, 005C0248
005BF9EA   .8D85 20FEFFFF       lea   eax, dword ptr
005BF9F0   .E8 1337E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BF9F5   .8D85 B8FDFFFF       lea   eax, dword ptr
005BF9FB   .50                  push    eax
005BF9FC   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BFA01   .BA 11000000         mov   edx, 11                                             ;start = 17
005BFA06   .B8 FFA85C00         mov   eax, 005CA8FF                                       ;ASCII 28,"724FBD29057D22021234567807D10C7299022142"
005BFA0B   .E8 542FE4FF         call    00402964                                          ;System.Copy(),取激活码第3部分 "12345678"
005BFA10   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "12345678"
005BFA16   .8D85 20FEFFFF       lea   eax, dword ptr
005BFA1C   .B1 65               mov   cl, 65
005BFA1E   .E8 B536E4FF         call    004030D8                                          ;PStrNCat()
005BFA23   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "12345678"
005BFA29   .8D85 9CFDFFFF       lea   eax, dword ptr
005BFA2F   .E8 9850E4FF         call    00404ACC                                          ;LStrFromString()
005BFA34   .8B85 9CFDFFFF       mov   eax, dword ptr                             ;eax ===> "12345678"
005BFA3A   .E8 F19CE4FF         call    00409730                                          ;StrToInt()
005BFA3F   .35 45812700         xor   eax, 278145                                       ;激活码处理3
005BFA44   .33D8                xor   ebx, eax
005BFA46   .3B1D 64A95C00       cmp   ebx, dword ptr                            ; == 0x00000026,order_no = 38 = 0x26
005BFA4C   .0F85 16030000       jnz   005BFD68
005BFA52   .BB 04000000         mov   ebx, 4
005BFA57   .BE AC6C5C00         mov   esi, 005C6CAC                                       ;版本类型, == 0x11E768B7(个人版), xor 0x00278145 为激活码第三部分
005BFA5C   >BA 48025C00         mov   edx, 005C0248
005BFA61   .8D85 20FEFFFF       lea   eax, dword ptr
005BFA67   .E8 9C36E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BFA6C   .8D85 B8FDFFFF       lea   eax, dword ptr
005BFA72   .50                  push    eax
005BFA73   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BFA78   .BA 11000000         mov   edx, 11                                             ;start = 17
005BFA7D   .B8 FFA85C00         mov   eax, 005CA8FF                                       ;ASCII 28,"724FBD29057D22021234567807D10C7299022142"
005BFA82   .E8 DD2EE4FF         call    00402964                                          ;System.Copy(),取激活码第3部分 "12345678"
005BFA87   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "12345678"
005BFA8D   .8D85 20FEFFFF       lea   eax, dword ptr
005BFA93   .B1 65               mov   cl, 65
005BFA95   .E8 3E36E4FF         call    004030D8                                          ;PStrNCat()
005BFA9A   .8D95 20FEFFFF       lea   edx, dword ptr                             ;edx ===> 09, "$12345678"
005BFAA0   .8D85 98FDFFFF       lea   eax, dword ptr
005BFAA6   .E8 2150E4FF         call    00404ACC                                          ;LStrFromString()
005BFAAB   .8B85 98FDFFFF       mov   eax, dword ptr                             ;eax ===> "$12345678"
005BFAB1   .E8 7A9CE4FF         call    00409730
005BFAB6   .35 45812700         xor   eax, 278145                                       ;激活码处理4
005BFABB   .99                  cdq
005BFABC   .52                  push    edx
005BFABD   .50                  push    eax
005BFABE   .8B06                mov   eax, dword ptr                               ;激活码第3部分等于 0x11E768B7 xor 0x00278145,0x11E768B7 表示个人版
005BFAC0   .33D2                xor   edx, edx
005BFAC2   .3B5424 04         cmp   edx, dword ptr
005BFAC6   .75 03               jnz   short 005BFACB
005BFAC8   .3B0424            cmp   eax, dword ptr
005BFACB   >5A                  pop   edx
005BFACC   .58                  pop   eax
005BFACD   .0F85 84020000       jnz   005BFD57
005BFAD3   .8D85 B8FDFFFF       lea   eax, dword ptr
005BFAD9   .50                  push    eax
005BFADA   .B9 08000000         mov   ecx, 8                                              ;len = 8
005BFADF   .BA 21000000         mov   edx, 21                                             ;start = 33
005BFAE4   .B8 FFA85C00         mov   eax, 005CA8FF                                       ;ASCII 28,"724FBD29057D22021234567807D10C7299022142"
005BFAE9   .E8 762EE4FF         call    00402964                                          ;System.Copy(),取激活码第5部分 "99022142"
005BFAEE   .8D95 B8FDFFFF       lea   edx, dword ptr                             ;edx ===> 08, "99022142"
005BFAF4   .B8 74AB5C00         mov   eax, 005CAB74                                       ;ASCII 08,"99022142"
005BFAF9   .B1 0A               mov   cl, 0A                                              ;len = 10
005BFAFB   .E8 1436E4FF         call    00403114                                          ;PStrNCpy(), ==> 08, "99022142"
005BFB00   .BA 48025C00         mov   edx, 005C0248                                       ;edx ===> 01, "$"
005BFB05   .8D85 84FDFFFF       lea   eax, dword ptr
005BFB0B   .E8 F835E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BFB10   .8D85 78FDFFFF       lea   eax, dword ptr
005BFB16   .50                  push    eax
005BFB17   .B9 04000000         mov   ecx, 4                                              ;len == 4
005BFB1C   .BA 01000000         mov   edx, 1                                              ;start = 1
005BFB21   .B8 74AB5C00         mov   eax, 005CAB74                                       ;ASCII 08,"99022142"
005BFB26   .E8 392EE4FF         call    00402964                                          ;System.Copy(),从 "99022142" 中取前4个字符"9902"
005BFB2B   .8D95 78FDFFFF       lea   edx, dword ptr                             ;edx ===> 04, "9902"
005BFB31   .8D85 84FDFFFF       lea   eax, dword ptr
005BFB37   .B1 0B               mov   cl, 0B
005BFB39   .E8 9A35E4FF         call    004030D8                                          ;PStrNCat()
005BFB3E   .8D95 84FDFFFF       lea   edx, dword ptr                             ;edx ===> 05, "$9902"
005BFB44   .8D85 90FDFFFF       lea   eax, dword ptr
005BFB4A   .E8 7D4FE4FF         call    00404ACC                                          ;LStrFromString()
005BFB4F   .8B85 90FDFFFF       mov   eax, dword ptr                             ;eax ===> "$9902"
005BFB55   .E8 D69BE4FF         call    00409730                                          ;StrToInt()
005BFB5A   .35 F6EA0000         xor   eax, 0EAF6                                          ;激活码处理5, eax = 0x9902 xor 0xEAF6 = 0x73F4
005BFB5F   .8D95 94FDFFFF       lea   edx, dword ptr
005BFB65   .E8 E69AE4FF         call    00409650                                          ;IntToStr()
005BFB6A   .8D85 94FDFFFF       lea   eax, dword ptr                             ; ===> "29684"
005BFB70   .50                  push    eax
005BFB71   .8D85 74FDFFFF       lea   eax, dword ptr
005BFB77   .50                  push    eax
005BFB78   .BA 48025C00         mov   edx, 005C0248                                       ;edx ===> 01, "$"
005BFB7D   .8D85 84FDFFFF       lea   eax, dword ptr
005BFB83   .E8 8035E4FF         call    00403108                                          ;PStrCpy(), 生成 01, "$"
005BFB88   .8D85 78FDFFFF       lea   eax, dword ptr
005BFB8E   .50                  push    eax
005BFB8F   .B9 04000000         mov   ecx, 4                                              ;len = 4
005BFB94   .BA 05000000         mov   edx, 5                                              ;start = 5
005BFB99   .B8 74AB5C00         mov   eax, 005CAB74                                       ;ASCII 08,"99022142"
005BFB9E   .E8 C12DE4FF         call    00402964                                          ;System.Copy(),从 "99022142" 中取后4个字符"2142"
005BFBA3   .8D95 78FDFFFF       lea   edx, dword ptr                             ;edx ===> 04, "2142"
005BFBA9   .8D85 84FDFFFF       lea   eax, dword ptr
005BFBAF   .B1 0B               mov   cl, 0B
005BFBB1   .E8 2235E4FF         call    004030D8                                          ;PStrNCat()
005BFBB6   .8D95 84FDFFFF       lea   edx, dword ptr                             ;edx ===> 05, "$2142"
005BFBBC   .8D85 68FDFFFF       lea   eax, dword ptr
005BFBC2   .E8 054FE4FF         call    00404ACC                                          ;LStrFromString()
005BFBC7   .8B85 68FDFFFF       mov   eax, dword ptr                             ;eax ===> "$2142"
005BFBCD   .E8 5E9BE4FF         call    00409730                                          ;StrToInt()
005BFBD2   .35 F6EA0000         xor   eax, 0EAF6                                          ;激活码处理6, eax = 0x2142 xor 0xEAF6 = 0xCBB4
005BFBD7   .8985 6CFDFFFF       mov   dword ptr , eax                            ;低32位 == eax
005BFBDD   .C685 70FDFFFF 00    mov   byte ptr , 0                               ;高32位 == 0
005BFBE4   .8D95 6CFDFFFF       lea   edx, dword ptr
005BFBEA   .33C9                xor   ecx, ecx
005BFBEC   .B8 54025C00         mov   eax, 005C0254                                       ;ASCII "%.4d"
005BFBF1   .E8 AEABE4FF         call    0040A7A4                                          ;Format(), 格式化为10进制数字字符串, "52148"
005BFBF6   .8B95 74FDFFFF       mov   edx, dword ptr                             ;edx ===> "52148"
005BFBFC   .58                  pop   eax                                                 ;eax ===> "29684"
005BFBFD   .E8 2E4FE4FF         call    00404B30                                          ;LStrCat()
005BFC02   .8B95 94FDFFFF       mov   edx, dword ptr                             ;edx ===> "2968452148"
005BFC08   .8D85 C4FEFFFF       lea   eax, dword ptr
005BFC0E   .B9 FF000000         mov   ecx, 0FF
005BFC13   .E8 EC4EE4FF         call    00404B04                                          ;System.@LStrToString()
005BFC18   .8D95 C4FEFFFF       lea   edx, dword ptr                             ;edx ===> 0A, "2968452148"
005BFC1E   .B8 74AB5C00         mov   eax, 005CAB74                                       ;ASCII 08,"99022142"
005BFC23   .B1 0A               mov   cl, 0A
005BFC25   .E8 EA34E4FF         call    00403114                                          ;PStrNCpy()
005BFC2A   .8D85 60FDFFFF       lea   eax, dword ptr
005BFC30   .BA 74AB5C00         mov   edx, 005CAB74                                       ;ASCII 08,"99022142"
005BFC35   .E8 924EE4FF         call    00404ACC                                          ;LStrFromString(String;String;ShortString;ShortString);
005BFC3A   .8B85 60FDFFFF       mov   eax, dword ptr                             ;eax ===> "2968452148"
005BFC40   .8D95 64FDFFFF       lea   edx, dword ptr
005BFC46   .E8 6588E8FF         call    004484B0                                          ;ReverseString(),将10进制字符串反转, "2968452148" 变为 "8412548692"
005BFC4B   .8B95 64FDFFFF       mov   edx, dword ptr                             ;edx ===> "8412548692"
005BFC51   .8D85 C4FEFFFF       lea   eax, dword ptr
005BFC57   .B9 FF000000         mov   ecx, 0FF
005BFC5C   .E8 A34EE4FF         call    00404B04                                          ;System.LStrToString;
005BFC61   .8D95 C4FEFFFF       lea   edx, dword ptr                             ;edx ===> 0A, "8412548692"
005BFC67   .B8 74AB5C00         mov   eax, 005CAB74                                       ;全局变量, ASCII 0A, "8412548692", 长度 == 10
005BFC6C   .B1 0A               mov   cl, 0A                                              ;len == 10
005BFC6E   .E8 A134E4FF         call    00403114                                          ;PStrNCpy()
005BFC73   .8D85 58FDFFFF       lea   eax, dword ptr
005BFC79   .8A15 75AB5C00       mov   dl, byte ptr                                ;第1个字符, "8"
005BFC7F   .8850 01             mov   byte ptr , dl
005BFC82   .C600 01             mov   byte ptr , 1                                 ;生成delphi格式短字符串,01, "8"
005BFC85   .8D95 58FDFFFF       lea   edx, dword ptr
005BFC8B   .8D85 54FDFFFF       lea   eax, dword ptr
005BFC91   .E8 7234E4FF         call    00403108                                          ;PStrCpy()
005BFC96   .8D85 50FDFFFF       lea   eax, dword ptr
005BFC9C   .8A15 76AB5C00       mov   dl, byte ptr                                ;第2个字符 "4"
005BFCA2   .8850 01             mov   byte ptr , dl
005BFCA5   .C600 01             mov   byte ptr , 1                                 ;生成delphi格式短字符串,01, "4"
005BFCA8   .8D95 50FDFFFF       lea   edx, dword ptr                             ;edx ===> 01, "4"
005BFCAE   .8D85 54FDFFFF       lea   eax, dword ptr                             ;eax ===> 01, "8"
005BFCB4   .B1 02               mov   cl, 2                                             ;字符串个数 count = 2
005BFCB6   .E8 1D34E4FF         call    004030D8                                          ;PStrNCat()
005BFCBB   .8D95 54FDFFFF       lea   edx, dword ptr                             ;edx ===> 02, "84"
005BFCC1   .8D85 5CFDFFFF       lea   eax, dword ptr
005BFCC7   .E8 004EE4FF         call    00404ACC                                          ;System.LStrFromString(String;String;ShortString;ShortString);
005BFCCC   .8B85 5CFDFFFF       mov   eax, dword ptr                             ;eax ===> "84"
005BFCD2   .E8 599AE4FF         call    00409730                                          ;StrToInt()
005BFCD7   .48                  dec   eax                                                 ;第1,2位小于32, 取 0x1F, 31(每月天数检查,不超过31)
005BFCD8   .83E8 1F             sub   eax, 1F
005BFCDB   .73 6A               jnb   short 005BFD47
005BFCDD   .8D85 58FDFFFF       lea   eax, dword ptr
005BFCE3   .8A15 77AB5C00       mov   dl, byte ptr                                ;第3个字符 "1"
005BFCE9   .8850 01             mov   byte ptr , dl
005BFCEC   .C600 01             mov   byte ptr , 1                                 ;生成delphi格式短字符串,01, "1"
005BFCEF   .8D95 58FDFFFF       lea   edx, dword ptr
005BFCF5   .8D85 54FDFFFF       lea   eax, dword ptr
005BFCFB   .E8 0834E4FF         call    00403108                                          ;PStrCpy()
005BFD00   .8D85 50FDFFFF       lea   eax, dword ptr
005BFD06   .8A15 78AB5C00       mov   dl, byte ptr                                ;第4个字符 "2"
005BFD0C   .8850 01             mov   byte ptr , dl
005BFD0F   .C600 01             mov   byte ptr , 1                                 ;生成delphi格式短字符串,01, "2"
005BFD12   .8D95 50FDFFFF       lea   edx, dword ptr                             ;edx ===> 01, "2"
005BFD18   .8D85 54FDFFFF       lea   eax, dword ptr                             ;eax ===> 01, "1"
005BFD1E   .B1 02               mov   cl, 2                                             ;count = 2
005BFD20   .E8 B333E4FF         call    004030D8                                          ;PStrNCat()
005BFD25   .8D95 54FDFFFF       lea   edx, dword ptr                             ;edx ===> 02, "12"
005BFD2B   .8D85 4CFDFFFF       lea   eax, dword ptr
005BFD31   .E8 964DE4FF         call    00404ACC                                          ;System.LStrFromString(String;String;ShortString;ShortString);
005BFD36   .8B85 4CFDFFFF       mov   eax, dword ptr                             ;eax ===> "12"
005BFD3C   .E8 EF99E4FF         call    00409730                                          ;StrToInt()
005BFD41   .48                  dec   eax                                                 ;第3、4位小于12(月份检查,不超过12)
005BFD42   .83E8 0C             sub   eax, 0C
005BFD45   .72 04               jb      short 005BFD4B
005BFD47   >33C0                xor   eax, eax
005BFD49   .EB 02               jmp   short 005BFD4D
005BFD4B   >B0 01               mov   al, 1                                             ;注册成功标志 == 1
005BFD4D   >8B15 346E5C00       mov   edx, dword ptr                            ;注册成功标志 == 1
005BFD53   .8802                mov   byte ptr , al                                  ;注册成功标志 == 1
005BFD55   .EB 11               jmp   short 005BFD68
005BFD57   >83C6 04             add   esi, 4
005BFD5A   .4B                  dec   ebx
005BFD5B   .^ 0F85 FBFCFFFF       jnz   005BFA5C
005BFD61   .EB 05               jmp   short 005BFD68
005BFD63   >E8 9449E4FF         call    004046FC                                          ;System.halt0
005BFD68   >33C0                xor   eax, eax
005BFD6A   .5A                  pop   edx
005BFD6B   .59                  pop   ecx
005BFD6C   .59                  pop   ecx
005BFD6D   .64:8910             mov   dword ptr fs:, edx
005BFD70   .68 9CFD5B00         push    005BFD9C
005BFD75   >A1 346E5C00         mov   eax, dword ptr                            ;注册标志
005BFD7A   .8A00                mov   al, byte ptr
005BFD7C   .34 01               xor   al, 1                                             ;al == 0
005BFD7E   .8B15 A4725C00       mov   edx, dword ptr                            ;第2个注册成功标志 == 0
005BFD84   .8802                mov   byte ptr , al
005BFD86   .8B15 346E5C00       mov   edx, dword ptr                            ;dumped_b.005C43E4
005BFD8C   .8B15 C86E5C00       mov   edx, dword ptr                            ;第3个注册成功标志 == 0
005BFD92   .8802                mov   byte ptr , al
005BFD94   .C3                  retn                                                      ;RET 用作跳转到 005BFD9C
注册算法总结如下:
1、将硬件序列号去掉中间的"-"号,分成4部分,即4个16进制32位整数,即 ID, ID, ID, ID。
2、输入的激活码分成5部分,前面4个部分也是分成4个16进制32位整数,即 ACT, ACT, ACT, ACT,第5部分是一个时间字符串变形,表示成 ACT。
3、程序中有一个版本标识,共4个版本,本程序是个人版,VERTYPE = 0x0x11E768B7,这是一个常量。
4、还有在注册界面输入的 OrderNo,这是一个32位整数。
5、然后是计算:
    (1)如果 OrderNo<430000000,则将 OrderNo 改成 38,即 OrdrerNo = 0x26,否则不变。
    (2)ACT = ID xor ID
    (3)ACT = ID xor ID
    (4)ACT = VERTYPE xor 0x00278145
    (5)ACT = ACTxor 0x00278145 xor OrderNo,其实就是 VERTYPE xor OrderNo 吧。
6、授权时间 ACT:
    (1)时间数字需反序表示。
    (2)year = year xor 0xEAF6,如果 year = 9102, 是 2019年 的反序表示。
    (3)mon_day = mon_day xor 0xEAF6,如 mon_day = 9003,是09月30日反序表示。
      上面表示购买授权时间是 20190930。
    (4)ACT = (year << 16) or mon_day,生成激活码第5部分。

注意,上面OrderNo的计算是在输入注册信息的表单(TForm2)中保存注册信息的“Accept”按钮事件中计算的,并且计算结果保存到注册文件中了,后面是读出来直接使用的,具体代码如下:
0050FCEE|>817D F0 8047A119      cmp   dword ptr , 19A14780                        ;order_no >= 430000000
0050FCF5|.7D 07               jge   short 0050FCFE
0050FCF7|.C745 F0 26000000      mov   dword ptr , 26                              ;如果 order_no < 430000000,则将 order_no 改成 0x26




根据上面算法,计算正确的激活码,在注册界面重新输入:

可以看到,注册文件会更新,写入新的注册信息。




然后重启程序,这次又弹出一个对话框,大概是説安装版本过期,授权拒绝了:


这是另一个暗桩,大家还记得前面提到过的一个文件么:”C:\Windows\Debug\passwd.log“,就与这个文件的创建时间有关。

在注册码算法代码后,通过 F8 单步,很快确定是下面函数弹出的对话框:

具体代码如下:
005BFEA7   > \A1 A4725C00          mov   eax, dword ptr
005BFEAC   .8038 00            cmp   byte ptr , 0
005BFEAF   .75 11                jnz   short 005BFEC2
005BFEB1   .A1 C86E5C00          mov   eax, dword ptr
005BFEB6   .8038 00            cmp   byte ptr , 0
005BFEB9   .75 07                jnz   short 005BFEC2
005BFEBB   .E8 CCEBFFFF          call    005BEA8C                     ;程序版本过期判断
005BFEC0   .EB 07                jmp   short 005BFEC9
005BFEC2   >C605 BC6C5C00 01   mov   byte ptr , 1
005BFEC9   >A1 38745C00          mov   eax, dword ptr
005BFECE   .8038 00            cmp   byte ptr , 0
005BFED1   .74 0C                je      short 005BFEDF


在 DeDeDark 中相应函数内可以查得就是判断上面那个文件的创建时间来判定的,并且是在程序中硬编码,这个版本的passwd.log的创建时间不能大于2019/03/27 这个时间。
函数代码如下:
005BEA8C/$55                   push    ebp
005BEA8D|.8BEC               mov   ebp, esp
005BEA8F|.83C4 CC            add   esp, -34
005BEA92|.53                   push    ebx
005BEA93|.33C0               xor   eax, eax
005BEA95|.8945 CC            mov   dword ptr , eax
005BEA98|.8945 D0            mov   dword ptr , eax
005BEA9B|.8945 EC            mov   dword ptr , eax
005BEA9E|.8945 F0            mov   dword ptr , eax
005BEAA1|.8945 F4            mov   dword ptr , eax
005BEAA4|.33C0               xor   eax, eax
005BEAA6|.55                   push    ebp
005BEAA7|.68 37EC5B00          push    005BEC37
005BEAAC|.64:FF30            push    dword ptr fs:
005BEAAF|.64:8920            mov   dword ptr fs:, esp
005BEAB2|.A1 EC715C00          mov   eax, dword ptr
005BEAB7|.8B00               mov   eax, dword ptr
005BEAB9|.BA FFE99100          mov   edx, 91E9FF
005BEABE|.E8 B50FEBFF          call    0046FA78
005BEAC3|.8B1D 946E5C00      mov   ebx, dword ptr       ;Thaiphoo.005C8739
005BEAC9|.8A1B               mov   bl, byte ptr
005BEACB|.8D45 F4            lea   eax, dword ptr
005BEACE|.8B15 7C6F5C00      mov   edx, dword ptr       ;Thaiphoo.005C873C
005BEAD4|.8B12               mov   edx, dword ptr
005BEAD6|.E8 2D5EE4FF          call    00404908
005BEADB|.8D55 F0            lea   edx, dword ptr
005BEADE|.B8 4CEC5B00          mov   eax, 005BEC4C                  ;ASCII "{-o-f"
005BEAE3|.E8 ECFFF4FF          call    0050EAD4
005BEAE8|.8B55 F0            mov   edx, dword ptr
005BEAEB|.A1 7C6F5C00          mov   eax, dword ptr
005BEAF0|.E8 CF5DE4FF          call    004048C4
005BEAF5|.A1 946E5C00          mov   eax, dword ptr
005BEAFA|.C600 5F            mov   byte ptr , 5F
005BEAFD|.8D45 EC            lea   eax, dword ptr
005BEB00|.50                   push    eax
005BEB01|.C745 D4 1B000000   mov   dword ptr , 1B         ;27 日    ===> 31   (0x1F)
005BEB08|.C645 D8 00         mov   byte ptr , 0
005BEB0C|.C745 DC 03000000   mov   dword ptr , 3          ;03 月    ===> 12   (0x0C)
005BEB13|.C645 E0 00         mov   byte ptr , 0
005BEB17|.C745 E4 E3070000   mov   dword ptr , 7E3      ;2019 年===> 9999 (0x270F)
005BEB1E|.C645 E8 00         mov   byte ptr , 0
005BEB22|.8D55 D4            lea   edx, dword ptr
005BEB25|.B9 02000000          mov   ecx, 2
005BEB2A|.B8 5CEC5B00          mov   eax, 005BEC5C                  ;ASCII "%d_%d_%d"
005BEB2F|.E8 70BCE4FF          call    0040A7A4
005BEB34|.8B45 EC            mov   eax, dword ptr
005BEB37|.E8 68DEE4FF          call    0040C9A4
005BEB3C|.DD5D F8            fstp    qword ptr
005BEB3F|.9B                   wait
005BEB40|.8D45 D0            lea   eax, dword ptr
005BEB43|.BA 74AA5C00          mov   edx, 005CAA74                  ;检查文件 "C:\WINDOWS\Debug\passwd.log" 的创建时间
005BEB48|.E8 7F5FE4FF          call    00404ACC
005BEB4D|.8B45 D0            mov   eax, dword ptr
005BEB50|.E8 8BAFE4FF          call    00409AE0                     ;SysUtils.FileAge(AnsiString):Integer;
005BEB55|.E8 4EB4E4FF          call    00409FA8
005BEB5A|.DD1D 6CA95C00      fstp    qword ptr
005BEB60|.9B                   wait
005BEB61|.DD45 F8            fld   qword ptr
005BEB64|.DC1D 6CA95C00      fcomp   qword ptr
005BEB6A|.DFE0               fstsw   ax
005BEB6C|.9E                   sahf
005BEB6D|.73 09                jnb   short 005BEB78               ;如果文件过期,则不会跳转,否则跳转去检查授权文件内的时间是否过期
005BEB6F|.B0 01                mov   al, 1
005BEB71|.E8 52FDFFFF          call    005BE8C8
005BEB76|.EB 7C                jmp   short 005BEBF4
005BEB78|>A1 346E5C00          mov   eax, dword ptr
005BEB7D|.8038 00            cmp   byte ptr , 0
005BEB80|.74 72                je      short 005BEBF4
005BEB82|.803D 74AB5C00 08   cmp   byte ptr , 8
005BEB89|.75 62                jnz   short 005BEBED
005BEB8B|.6A 03                push    3
005BEB8D|.BA 74AB5C00          mov   edx, 005CAB74                  ;授权文件中激活码内的过期时间 (ASCII 08,"31129102"),日/月/年
005BEB92|.B9 0A000000          mov   ecx, 0A
005BEB97|.B8 68EC5B00          mov   eax, 005BEC68
005BEB9C|.E8 373EE4FF          call    004029D8
005BEBA1|.6A 06                push    6
005BEBA3|.BA 74AB5C00          mov   edx, 005CAB74                  ;ASCII 08,"31129102"
005BEBA8|.B9 0A000000          mov   ecx, 0A
005BEBAD|.B8 68EC5B00          mov   eax, 005BEC68
005BEBB2|.E8 213EE4FF          call    004029D8
005BEBB7|.8D45 CC            lea   eax, dword ptr
005BEBBA|.BA 74AB5C00          mov   edx, 005CAB74                  ;ASCII 08,"31129102"
005BEBBF|.E8 085FE4FF          call    00404ACC
005BEBC4|.8B45 CC            mov   eax, dword ptr
005BEBC7|.E8 D8DDE4FF          call    0040C9A4
005BEBCC|.DD5D F8            fstp    qword ptr
005BEBCF|.9B                   wait
005BEBD0|.DD45 F8            fld   qword ptr
005BEBD3|.D805 6CEC5B00      fadd    dword ptr
005BEBD9|.DC1D 6CA95C00      fcomp   qword ptr
005BEBDF|.DFE0               fstsw   ax
005BEBE1|.9E                   sahf
005BEBE2|.73 10                jnb   short 005BEBF4
005BEBE4|.B0 01                mov   al, 1
005BEBE6|.E8 DDFCFFFF          call    005BE8C8
005BEBEB|.EB 07                jmp   short 005BEBF4
005BEBED|>33C0               xor   eax, eax
005BEBEF|.E8 D4FCFFFF          call    005BE8C8
005BEBF4|>C605 BC6C5C00 01   mov   byte ptr , 1
005BEBFB|.A1 946E5C00          mov   eax, dword ptr
005BEC00|.8818               mov   byte ptr , bl
005BEC02|.A1 7C6F5C00          mov   eax, dword ptr
005BEC07|.8B55 F4            mov   edx, dword ptr
005BEC0A|.E8 B55CE4FF          call    004048C4
005BEC0F|.33C0               xor   eax, eax
005BEC11|.5A                   pop   edx
005BEC12|.59                   pop   ecx
005BEC13|.59                   pop   ecx
005BEC14|.64:8910            mov   dword ptr fs:, edx
005BEC17|.68 3EEC5B00          push    005BEC3E
005BEC1C|>8D45 CC            lea   eax, dword ptr
005BEC1F|.BA 02000000          mov   edx, 2
005BEC24|.E8 6B5CE4FF          call    00404894
005BEC29|.8D45 EC            lea   eax, dword ptr
005BEC2C|.BA 03000000          mov   edx, 3
005BEC31|.E8 5E5CE4FF          call    00404894
005BEC36\.C3                   retn
005BEC37   .^ E9 F854E4FF          jmp   00404134
005BEC3C   .^ EB DE                jmp   short 005BEC1C
005BEC3E   .5B                   pop   ebx
005BEC3F   .8BE5               mov   esp, ebp
005BEC41   .5D                   pop   ebp
005BEC42   .C3                   retn

我们直接可以在程序文件中找到这个位置,如下图所示:


将上图位置的硬编码“年/月/日”修改一下即可,上面改成了 9999/12/31,够大的了。


保存修改结果,重新运行,正常进入程序,界面如下:

这次可以看到了 "Write" 按钮,并且是可用状态,注册成功了!!!


前面对时间限制的破除还有一个方法,就是修改文件”C:\Windows\Debug\passwd.log“ 的创建时间早于 2019-03-27 即可。
下面的注册机就实现了这个方法,不过需要”以管理员身份运行“注册机,不然不能修改 C:\Windows 目录下的任何文件的属性。


注册机源码如下:
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <string.h>

/// char v[][] = {"Personal Edition", "Personal Lifetime Edition", "Professional Edition", "Engineering Edition"};
unsigned long version_type_id = {0x11E768B7, 0x11E89D96, 0x11E7A00A, 0x11E8788D};


int GetSN(char * ID, unsigned long order_no);
int showFileTime(LPSTR szFile);
int modifyFileTime(LPSTR szFile, int year, int mon, int day);

int main(int argc, char** argv) {
      
      //char ID[] = "A1884D69D3C7F040-205D575B25207559";   //// 根据本机软件显示的ID修正
      char ID[] = "8C894D69D387F000-4351525542445F5F";
      unsigned long order_no = 430000000;                  //// 32位整数, 定单号,可随意填
      
      /// generate activation code
      GetSN(ID, order_no);
      
      LPSTR szFilePath = new char;
      strcpy(szFilePath, "c:\\Windows\\Debug\\PASSWD.LOG");
      
      printf("\nFile Time Check patching...\n");
      
      showFileTime(szFilePath); //// before of 2019-03-27
      //// 修改文件时间需要“以管理员身份运行”本注册程序
      //modifyFileTime(szFilePath, 2019, 3, 28); //// 无效
      modifyFileTime(szFilePath, 2019, 3, 26); //// before of 2019-03-27,有效
      
      delete szFilePath;

      printf("\nFile Time Check patched.\n");
      
      return 0;
}

int GetSN(char * ID, unsigned long order_no) {
      
      char tmp;
      unsigned long id1, id2, id3, id4;
      unsigned long act1, act2, act3, act4, act5;
      
      char * endptr;
      
      memset(tmp, 0, 12);
      strncpy(tmp, ID, 8);
      id1 = strtoul(tmp, &endptr, 16);
      
      strncpy(tmp, &ID, 8);
      id2 = strtoul(tmp, &endptr, 16);

      strncpy(tmp, &ID, 8);
      id3 = strtoul(tmp, &endptr, 16);

      strncpy(tmp, &ID, 8);
      id4 = strtoul(tmp, &endptr, 16);
      
      printf(" ID: %08X%08X-%08X%08X\n", id1, id2, id3, id4);
      printf("Order Number: %u\n", order_no);
      
      act1 = id1 ^ id4;
      act2 = id2 ^ id3;
      
      if(order_no < 430000000) {
                order_no = 38;   //// 0x26
      }
      
      act3 = version_type_id ^ 0x00278145; //0x11C0E9F2; /// Person Version
      act4 = act3 ^ 0x00278145 ^ order_no;
      
      //long dmy = 31129998;/// reverse to 89992113
      unsigned long y= 2019;// reverse from "9102"   /// year: 9102
      unsigned long md = 2113;// reverse from "1231";/// month and day

      y^= 0xEAF6;
      md ^= 0xEAF6;
      
      //printf("YMD: %X%X\n",y, md);
      
      act5 = (y << 16) | md;
      
      printf("Activation Code: %08X%08X%08X%08X%08X\n", act1, act2, act3, act4, act5);
      
      return 0;
}

int modifyFileTime(LPSTR szFile, int year, int mon, int day) {
      FILETIME CTime, LATime, LWTime;
      FILETIME CTime1, LATime1, LWTime1;
      SYSTEMTIME CTime2, LATime2, LWTime2;

      /// Creation Time
      CTime2.wYear   = year;
      CTime2.wMonth= mon;
      CTime2.wDay    = day;
      CTime2.wHour   = 0;
      CTime2.wMinute = 0;
      CTime2.wSecond = 0;
      
      /// Last accessed time
      LATime2.wYear   = year;
      LATime2.wMonth= mon;
      LATime2.wDay    = day;
      LATime2.wHour   = 0;
      LATime2.wMinute = 0;
      LATime2.wSecond = 0;
      
      /// Last modified time
      LWTime2.wYear   = year;
      LWTime2.wMonth= mon;
      LWTime2.wDay    = day;
      LWTime2.wHour   = 0;
      LWTime2.wMinute = 0;
      LWTime2.wSecond = 0;

      //// convert to local file time      
      SystemTimeToFileTime(&CTime2, &CTime1);
      SystemTimeToFileTime(&LATime2, &LATime1);
      SystemTimeToFileTime(&LWTime2, &LWTime1);

      /// convert to file time
      LocalFileTimeToFileTime(&CTime1, &CTime);
      LocalFileTimeToFileTime(&LATime1, &LATime);
      LocalFileTimeToFileTime(&LWTime1, &LWTime);
      
      HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
      bool bSetFile = SetFileTime(hFile, &CTime, &LATime, &LWTime); //// run as administrator
      CloseHandle(hFile);
      if(bSetFile) {
                printf("Set File time successed.\n");
      } else {
                printf("Set File time failured. error code: 0x%X\n", GetLastError());
      }
}

int showFileTime(LPSTR szFile) {
    //文件时间结构
    FILETIME ftLocal;
    //系统时间结构
    SYSTEMTIME st;
    //文件属性结构
    WIN32_FILE_ATTRIBUTE_DATA wfad;

    printf("File: %s\n", szFile);
    //获取文件属性
    if(!GetFileAttributesExA(szFile, GetFileExInfoStandard, &wfad)) {
      printf("GetFileAttr Error:%d\n", GetLastError());
      return -1;
    }
    //显示相关时间
    PFILETIME lptime = &(wfad.ftCreationTime);
    //调整为系统所在时区的时间
    FileTimeToLocalFileTime(lptime, &ftLocal);
    //将文件时间转换为SYSTEMTIME格式,便于显示。
    FileTimeToSystemTime(&ftLocal, &st);
    //显示时间信息字符串
    printf("Creation Time:\t%4d-%.2d-%#02d, %.2d:%.2d:%.2d\n",
      st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

    return 0;
}



分析完毕。

本程序的最新版本为 16.0.0.8 build 0818 版,我录制了这个新版本的视频破解教程,参加本论坛的动画比赛,请各位朋友多多支持,连接如下:


https://www.52pojie.cn/thread-1021707-1-1.html

谢谢!!!


chen4321 发表于 2019-9-13 11:15

哇真是精彩,分析的非常好{:1_927:}

solly 发表于 2019-9-21 04:08

本帖最后由 solly 于 2019-9-21 22:48 编辑

dsanke 发表于 2019-9-17 22:19
感谢楼主,依葫芦画瓢处理好了
16 版的个人注册版的注册算法相比15版有了一点变化:

注册算法如下:

#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <string.h>

/// char v[][] = {"Personal Edition", "Personal Lifetime Edition", "Professional Edition", "Engineering Edition"};
unsigned long version_type_id = {0x11E768B7, 0x11E89D96, 0x11E7A00A, 0x11E8788D};
      
int GetSN(char * ID, unsigned long order_no);
int showFileTime(LPSTR szFile);
int modifyFileTime(LPSTR szFile, int year, int mon, int day);

int main(int argc, char** argv) {
      
      char ID[] = "A1884D69D3C7F040-205D575B25207559";   //// 根据本机软件显示的ID修正
      unsigned long order_no = 450000000;                  //// 32位整数, 定单号,可随意填,但不能小于 440000000
      
      /// generate activation code
      GetSN(ID, order_no);
      
      LPSTR szFilePath = new char;
      strcpy(szFilePath, "c:\\Windows\\Debug\\PASSWD.LOG");
      
      printf("\nFile Time Check patching...\n");
      
      showFileTime(szFilePath); //// before of 2020-01-30
      ////
      modifyFileTime(szFilePath, 2019, 3, 26); //// before of 2020-01-30, 版本失效日期
      
      delete szFilePath;

      printf("\nFile Time Check patched.\n");
      
      return 0;
}

int GetSN(char * ID, unsigned long order_no) {
      
      char tmp;
      unsigned long id1, id2, id3, id4;
      unsigned long act1, act2, act3, act4, act5;
      
      char * endptr;
      
      memset(tmp, 0, 12);
      strncpy(tmp, ID, 8);
      id1 = strtoul(tmp, &endptr, 16);
      
      strncpy(tmp, &ID, 8);
      id2 = strtoul(tmp, &endptr, 16);

      strncpy(tmp, &ID, 8);
      id3 = strtoul(tmp, &endptr, 16);

      strncpy(tmp, &ID, 8);
      id4 = strtoul(tmp, &endptr, 16);

      if(order_no < 440000000) {
                order_no = 440000000;   //// OrderNo < 440000000 时,注册失效
      }
      
      printf(" ID: %08X%08X-%08X%08X\n", id1, id2, id3, id4);
      printf("Order Number: %u\n", order_no);
      
      act1 = id1 ^ id4;
      act2 = id2 ^ id3;
      
      //act3 = version_type_id ^ 0x002B884A; ///// Person Version
      act3 = version_type_id ^ 0x002B884A; ///// Engineering Edition
      act4 = act3 ^ 0x2B884A ^ order_no;
      
      //long dmy = 31129998;/// reverse to 89992113
      unsigned long y= 9102;// reverse from "2019"   /// year: 9102
      unsigned long md = 9061;// reverse from "0916";/// month and day

      y^= 0xEAF6;
      md ^= 0xEAF6;
      
      //printf("YMD: %X%X\n",y, md);
      
      act5 = (y << 16) | md;
      
      printf("Activation Code: %08X%08X%08X%08X%08X\n", act1, act2, act3, act4, act5);
      
      return 0;
}

int modifyFileTime(LPSTR szFile, int year, int mon, int day) {
      FILETIME CTime, LATime, LWTime;
      FILETIME CTime1, LATime1, LWTime1;
      SYSTEMTIME CTime2, LATime2, LWTime2;

      /// Creation Time
      CTime2.wYear   = year;
      CTime2.wMonth= mon;
      CTime2.wDay    = day;
      CTime2.wHour   = 0;
      CTime2.wMinute = 0;
      CTime2.wSecond = 0;
      
      /// Last accessed time
      LATime2.wYear   = year;
      LATime2.wMonth= mon;
      LATime2.wDay    = day;
      LATime2.wHour   = 0;
      LATime2.wMinute = 0;
      LATime2.wSecond = 0;
      
      /// Last modified time
      LWTime2.wYear   = year;
      LWTime2.wMonth= mon;
      LWTime2.wDay    = day;
      LWTime2.wHour   = 0;
      LWTime2.wMinute = 0;
      LWTime2.wSecond = 0;

      //// convert to local file time      
      SystemTimeToFileTime(&CTime2, &CTime1);
      SystemTimeToFileTime(&LATime2, &LATime1);
      SystemTimeToFileTime(&LWTime2, &LWTime1);

      /// convert to file time
      LocalFileTimeToFileTime(&CTime1, &CTime);
      LocalFileTimeToFileTime(&LATime1, &LATime);
      LocalFileTimeToFileTime(&LWTime1, &LWTime);
      
      HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
      bool bSetFile = SetFileTime(hFile, &CTime, &LATime, &LWTime); //// run as administrator
      CloseHandle(hFile);
      if(bSetFile) {
                printf("Set File time successed.\n");
      } else {
                printf("Set File time failured. error code: 0x%X\n", GetLastError());
      }
}

int showFileTime(LPSTR szFile) {
    //文件时间结构
    FILETIME ftLocal;
    //系统时间结构
    SYSTEMTIME st;
    //文件属性结构
    WIN32_FILE_ATTRIBUTE_DATA wfad;

    printf("File: %s\n", szFile);
    //获取文件属性
    if(!GetFileAttributesExA(szFile, GetFileExInfoStandard, &wfad)) {
      printf("GetFileAttr Error:%d\n", GetLastError());
      return -1;
    }
    //显示相关时间
    PFILETIME lptime = &(wfad.ftCreationTime);
    //调整为系统所在时区的时间
    FileTimeToLocalFileTime(lptime, &ftLocal);
    //将文件时间转换为SYSTEMTIME格式,便于显示。
    FileTimeToSystemTime(&ftLocal, &st);
    //显示时间信息字符串
    printf("Creation Time:\t%4d-%.2d-%#02d, %.2d:%.2d:%.2d\n",
      st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

    return 0;
}




download url:

http://softnology.biz/files/thphn_16010_spblsk_build_0916.zip

xcuuwww 发表于 2019-9-12 19:49

先坐个沙发

IsMe9666 发表于 2019-9-12 19:51

大佬就是大佬,膜拜,顺便问一句 干嘛用的??

熊熊 发表于 2019-9-12 20:05

膜拜大神,精彩

solly 发表于 2019-9-12 22:52

yu17863200980 发表于 2019-9-12 19:51
大佬就是大佬,膜拜,顺便问一句 干嘛用的??

查看内存 SPD 芯片信息的,并可以烧录 XMP Profile 到内存的 SPD 芯片中。

fnp902003 发表于 2019-9-13 00:24

某些奸商就是用这个工具修改内存条信息的~~~~

solly 发表于 2019-9-13 00:38

fnp902003 发表于 2019-9-13 00:24
某些奸商就是用这个工具修改内存条信息的~~~~

JEDEC标准部分改不了,只是增加超频部分 XMP Profile 之类的。

duduhao 发表于 2019-9-13 02:54

谢谢楼主的分享

pepete 发表于 2019-9-13 05:17

学习了, 谢谢楼主分享
页: [1] 2 3 4 5 6 7 8
查看完整版本: 某内存 SPD 读取和烧录软件个人注册版脱壳和注册分析、注册机实现激活!