好友
阅读权限35
听众
最后登录1970-1-1
|
solly
发表于 2019-9-12 18:45
本帖最后由 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 异常处理机制的反调试的代码,防止单步跟踪。具体代码如下:
[Asm] 纯文本查看 复制代码 00401000 > B8 70A97300 mov eax, 0073A970 ; eax == 新的异常处理子例程地址
00401005 50 push eax ; 保存新的异常处理子例程地址
00401006 64:FF35 00000000 push dword ptr fs:[0] ; 保存老的SEH指针
0040100D 64:8925 00000000 mov dword ptr fs:[0], esp ; 保存新的SEH指针
00401014 33C0 xor eax, eax ; 将 eax 清 0,将导致下一行指令出现非法地址异常
00401016 8908 mov dword ptr [eax], ecx ; 因 eax == 0,这一行代码会产生异常
先 F8 执行第一行指令,使得 eax == 0x0073A970,这个地址就是异常处理子例程的地址。
Ctrl + G,输入 eax ,就可以跳转到这个异常处理子例程了:
上图所选的代码部分,就是整个异常处理子例程。其中第1、2、3行是对另一个子程序的入口(0x0073A993)代码进行参数修正。具体代码如下:
[Asm] 纯文本查看 复制代码 0073A970 B8 F59673F0 mov eax, F07396F5
0073A975 8D88 9E120010 lea ecx, dword ptr [eax+1000129E] ; eax == 0x0073A993,是这个异常处理子全程后面的第一条指令地址
0073A97B 8941 01 mov dword ptr [ecx+1], eax ; 修改 mov 指令中的立即数
0073A97E 8B5424 04 mov edx, dword ptr [esp+4]
0073A982 8B52 0C mov edx, dword ptr [edx+C]
0073A985 C602 E9 mov byte ptr [edx], 0E9 ; 修正产生异常的指令
0073A988 83C2 05 add edx, 5
0073A98B 2BCA sub ecx, edx
0073A98D 894A FC mov dword ptr [edx-4], ecx ; 修正产生异常的指令的参数
0073A990 33C0 xor eax, eax
0073A992 C3 retn ; 返回重新执行修改后的指令
另外的代码就是用来修正前面会产生异常的指令代码的。我们先在 0x0073A97B 处下一个断点,然后 F9 运行程序,如下图所示,会中断下来:
中断在我们刚下的断点处,开始进行代码修改,为了激活 OD 的 patch 记录功能(会使变动代码或数据变成红色),我们先把将要修改的代码改一改,如下图所示,先在数据区转移到修改处(ecx中保存的地址值):
然后随便改一下数据,再按”确定“。
这样操作后,修改处的数据会变成红色,便于区分程序改动了什么地方,如下图所示:
然后 F8 执行,可见,mov 指令的立即数参数已经修改了,如下图所示:
另一个指令的修改也一样进行操作,如下图所示,先跟随edx中的地址跳转到修改处:
数据区也跟随到这个地址,再手动在数据区随便修改一下(0x00401016 处)数据,如下图所示:
按 F8 执行,如下图,把几条修改异常指令的代码全执行完成:
再过去看一下刚才手动修改的地方,可以看到,如下图所示,指令变成了 "jmp 0x0073A993",不会再产生异常了。
上图具体代码如下:
[Asm] 纯文本查看 复制代码 00401000 > B8 70A97300 mov eax, 0073A970 ; eax == 新的异常处理子例程地址
00401005 50 push eax ; 保存新的异常处理子例程地址
00401006 64:FF35 00000000 push dword ptr fs:[0] ; 保存老的SEH指针
0040100D 64:8925 00000000 mov dword ptr fs:[0], 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 修正吧。具体代码如下:
[Asm] 纯文本查看 复制代码 00030A7A 03F2 add esi, edx
00030A7C 8DBD 5D2F0010 lea edi, dword ptr [ebp+10002F5D]
00030A82 AD lods dword ptr [esi] ; LoadLibraryA()
00030A83 AB stos dword ptr es:[edi]
00030A84 AD lods dword ptr [esi] ; GetProcAddress()
00030A85 AB stos dword ptr es:[edi]
00030A86 AD lods dword ptr [esi] ; VirtualAlloc()
00030A87 AB stos dword ptr es:[edi]
00030A88 AD lods dword ptr [esi] ; VirtualFree()
00030A89 AB stos dword ptr es:[edi]
共更新了4个 API 函数。
上面数据区就是刚才修改的几个 API 地址,共 4 个 API 入口地址。
接下来就是几条指令对程序的入口代码进行破坏,如下图所示,这样程序的入口代码就不正确了,也算是一种反调试或反脱壳方法吧
上图具体代码如下:
[Asm] 纯文本查看 复制代码 00030A98 B9 23000000 mov ecx, 23
00030A9D 03F2 add esi, edx
00030A9F 8B7B 40 mov edi, dword ptr [ebx+40]
00030AA2 03FA add edi, edx
00030AA4 F3:A4 rep movs byte ptr es:[edi], byte ptr [esi] ; 传输 ecx == 0x23 字节, edi==0x401000,破坏启动代码
一路 F8 往下走,执行完一堆 nop 指令后,又来到一个反调试代码处,如下图所示:
这次是调用 IsDebuggerPresent() ,这条 API 是通过 PEB+02 处的标志来确定程序是否处于调试状态的。
如果返回 eax == 0x00000001,就表示程序处于调试状态,我们修改代码避开检测(也可以在函数返回后直接将 eax 置 0),如下图所示:
具体代码如下:
[Asm] 纯文本查看 复制代码 00030ACA 8B85 292F0010 mov eax, dword ptr [ebp+10002F29]
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 [esi+2C]
00030ADE 898D 592F0010 mov dword ptr [ebp+10002F59], ecx
将 test eax, eax 改成 xor eax, eax 就可以了,上图已改好了。
再次一路 F8 执行程序,来到下面位置:
又是一个调用,申请了一片内存,我们在数据区跟随到申请的内存区,也是初始化成全0状态。继续 F8 执行,来到下面位置:
具体代码如下:
[Asm] 纯文本查看 复制代码 00030ADB 8B4E 2C mov ecx, dword ptr [esi+2C]
00030ADE 898D 592F0010 mov dword ptr [ebp+10002F59], 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 [ebp+10002F65] ; call VirtualAlloc
00030AF4 8985 552F0010 mov dword ptr [ebp+10002F55], eax
00030AFA 56 push esi
00030AFB E8 F6030000 call 00030EF6 ; 释放程序原delphi代码
00030B00 8D8D D12D0010 lea ecx, dword ptr [ebp+10002DD1] ; ecx ===> "Application corrupt."
00030B06 85C0 test eax, eax
00030B08 0F85 94000000 jnz 00030BA2
执行完上面的调用后,数据区出现了 delphi 风格的代码头。表明原始程序应该是一个 delphi 编译的程序。继续 F8 往下走,执行完几个调用后,来到下图位置:
上面是释放刚才申请的内存的调用,表明代码已经完成解码并转移到可执行节区去了。
这里是清理现场并准备退出函数了。
一路 F8 退出当前函数,来到下图所示位置:
具体代码如下:
[Asm] 纯文本查看 复制代码 0073AA10 8985 3F130010 mov dword ptr [ebp+1000133F], eax ; eax == OEP
0073AA16 8BF0 mov esi, eax
0073AA18 8B4B 14 mov ecx, dword ptr [ebx+14]
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 [ecx]
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() 就是强行退出程序。具体代码如下:
[Asm] 纯文本查看 复制代码 0050ED83 |. 803D E8435C00 00 cmp byte ptr [5C43E8], 0 ; 如果 [5C43E8] == 0x01,则退出程序,需要在这个地址(0x005C43E8)下硬件断点寻找赋值指令
0050ED8A |. 74 05 je short 0050ED91
0050ED8C |. E8 6B59EFFF call 004046FC ; System.Halt(),退出程序
0050ED91 |> A1 D0715C00 mov eax, dword ptr [5C71D0]
可以看出,是对一个标志进行判断,但该标志并没在此函数内赋值,所以,我们在 OD 中重新载入程序,并运行到这里(最后断点处 F7 进入,再运行到0x0050ED83处),然后在数据区转到此指令中的地址值(0x005C43E8),下一个硬件访问断点,如下图所示:
下断点后,我们还要把该标志值修改成 0x00,免得程序再次退出或其它地方退出。
跳过刚才的退出暗桩,程序继续运行,正常弹出注册对话框的 NAG:
我们输入注册信息(老版本的激活数据,并不适合当前版本,只是套用格式)
点”Accept" 按钮保存注册信息。
立即被前面的硬件访问中断下来了,也是对这个标志进行判断,如果为 0x01 则退出程序,不会保存注册信息。因为我们前面改了数据,所以现在不会退出程序。
保存完注册信息,弹出一个对话框,提示要重启才能生效,看来是一个重启验证的注册机制。
关闭对话框,又会被硬件中断下来,还是与前面一样的原因:
按 F9 续断运行,没有再中断了,弹出了主界面。如下图所示:
没有看到写入功能,表示还没有注册成功或还没进行验证。
退出程序,在 OD 中重新载入程序,检查硬件访问中断没有问题:
按 F9 运行,硬件中断了下来,是一个写入中断,在这里将 [0x005C43E8] 写入了 0x01。如下图所示:
具体代码如下:
[Asm] 纯文本查看 复制代码 0050FFDD |. 3B0424 cmp eax, dword ptr [esp]
0050FFE0 |. 0F92C0 setb al ; 修改为 0F94C0 sete al
0050FFE3 |. EB 03 jmp short 0050FFE8
0050FFE5 |> 0F9CC0 setl al ; 修改为 0F94C0 sete al
0050FFE8 |> 83C4 08 add esp, 8
0050FFEB |. A2 E8435C00 mov byte ptr [5C43E8], al ; al == 0x01 由表示程序已脱壳
存入的是 al 的值,前面有两条指令对 al 赋值了。如下图所示,两条 set 指令:
再到 DeDeDark 中相应位置看看。可以看出,这是一个文件大小的检查,看来程序会检查文件大小,防止程序脱壳运行。
破解也很简单,如下图所示,直接修改两个 set 指令即可。
然后在文件中找到相应位置,修改脱壳后文件。
下图是改好了的:
破除了退出暗桩,下面进行注册算法的处理,在启动代码的如下位置,包含了注册算法:
具体代码如下:[Asm] 纯文本查看 复制代码 ; start() 注册验证部分
005BF63E > \8D95 8CFEFFFF lea edx, dword ptr [ebp-174]
005BF644 . A1 EC715C00 mov eax, dword ptr [5C71EC]
005BF649 . 8B00 mov eax, dword ptr [eax]
005BF64B . E8 C803EBFF call 0046FA18 ; GetExeName()
005BF650 . 8B85 8CFEFFFF mov eax, dword ptr [ebp-174]
005BF656 . 8D95 90FEFFFF lea edx, dword ptr [ebp-170]
005BF65C . E8 1FA8E4FF call 00409E80 ; ExtractFilePath()
005BF661 . 8B95 90FEFFFF mov edx, dword ptr [ebp-170]
005BF667 . A1 6C715C00 mov eax, dword ptr [5C716C]
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:[edx]
005BF681 . 64:8922 mov dword ptr fs:[edx], esp
005BF684 . A1 6C715C00 mov eax, dword ptr [5C716C]
005BF689 . 8B00 mov eax, dword ptr [eax]
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 [5C716C] ; dumped_b.005C99A4
005BF6A0 . 8B09 mov ecx, dword ptr [ecx]
005BF6A2 . B2 01 mov dl, 1
005BF6A4 . A1 ACA64100 mov eax, dword ptr [41A6AC]
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 [eax]
005BF6D6 . 41 inc ecx
005BF6D7 . E8 D83AE4FF call 004031B4 ; AStrCmp(), 检测注册文件的文件头
005BF6DC . 74 15 je short 005BF6F3
005BF6DE . A1 6C715C00 mov eax, dword ptr [5C716C]
005BF6E3 . 8B00 mov eax, dword ptr [eax]
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 [ebp-13C]
005BF6F9 . E8 5EF8F4FF call 0050EF5C ; 生成ID
005BF6FE . 8D95 C4FEFFFF lea edx, dword ptr [ebp-13C] ; edx ===> ID
005BF704 . A1 2C6F5C00 mov eax, dword ptr [5C6F2C]
005BF709 . E8 FA39E4FF call 00403108 ; PStrCpy()
005BF70E . B8 9AA85C00 mov eax, 005CA89A ; ASCII 21,"A1884D69D3C7F040-205D575B25207559"
005BF713 . 8B15 2C6F5C00 mov edx, dword ptr [5C6F2C] ; edx ===> ID
005BF719 . 33C9 xor ecx, ecx
005BF71B . 8A08 mov cl, byte ptr [eax] ; 取得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 [5CA969] ; '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 [5CA968] ; 's',名字第一个字母?
005BF74F . 0F85 13060000 jnz 005BFD68
005BF755 . BA 48025C00 mov edx, 005C0248
005BF75A . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF760 . E8 A339E4FF call 00403108 ; PStrCpy(),生成delphi字符串 01,'$'
005BF765 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> "A1884D69"
005BF786 . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF78C . B1 65 mov cl, 65
005BF78E . E8 4539E4FF call 004030D8 ; PStrNCat(),形成 "$A1884D69"
005BF793 . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> "$A1884D69"
005BF799 . 8D85 88FEFFFF lea eax, dword ptr [ebp-178]
005BF79F . E8 2853E4FF call 00404ACC ; LStrFromString(),生成 pchar 字符串 "$A1884D69"
005BF7A4 . 8B85 88FEFFFF mov eax, dword ptr [ebp-178] ; 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 [ebp-1E0]
005BF7BC . E8 4739E4FF call 00403108 ; PStrCpy(), 生成 01, '$'
005BF7C1 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> "25207559"
005BF7E2 . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF7E8 . B1 65 mov cl, 65
005BF7EA . E8 E938E4FF call 004030D8 ; PStrNCat()
005BF7EF . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$25207559"
005BF7F5 . 8D85 B4FDFFFF lea eax, dword ptr [ebp-24C]
005BF7FB . E8 CC52E4FF call 00404ACC ; LStrFromString()
005BF800 . 8B85 B4FDFFFF mov eax, dword ptr [ebp-24C] ; 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 [ebp-1E0]
005BF818 . E8 EB38E4FF call 00403108 ; PStrCpy(), 生成 01, '$'
005BF81D . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> 08, "205D575B"
005BF83E . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF844 . B1 65 mov cl, 65
005BF846 . E8 8D38E4FF call 004030D8 ; PStrNCat()
005BF84B . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$205D575B"
005BF851 . 8D85 B0FDFFFF lea eax, dword ptr [ebp-250]
005BF857 . E8 7052E4FF call 00404ACC ; LStrFromString()
005BF85C . 8B85 B0FDFFFF mov eax, dword ptr [ebp-250] ; 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 [ebp-1E0]
005BF874 . E8 8F38E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BF879 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> 08, "D3C7F040"
005BF89A . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF8A0 . B1 65 mov cl, 65
005BF8A2 . E8 3138E4FF call 004030D8 ; PStrNCat()
005BF8A7 . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$D3C7F040"
005BF8AD . 8D85 ACFDFFFF lea eax, dword ptr [ebp-254]
005BF8B3 . E8 1452E4FF call 00404ACC ; LStrFromString()
005BF8B8 . 8B85 ACFDFFFF mov eax, dword ptr [ebp-254] ; 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 [ebp-1E0]
005BF8D0 . E8 3338E4FF call 00403108 ; PStrCpy()
005BF8D5 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ==> 08, "724FBD29",激活码第1部分
005BF8F6 . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF8FC . B1 65 mov cl, 65
005BF8FE . E8 D537E4FF call 004030D8 ; PStrNCat()
005BF903 . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$724FBD29"
005BF909 . 8D85 A8FDFFFF lea eax, dword ptr [ebp-258]
005BF90F . E8 B851E4FF call 00404ACC ; LStrFromString()
005BF914 . 8B85 A8FDFFFF mov eax, dword ptr [ebp-258] ; 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 [ebp-1E0]
005BF932 . E8 D137E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BF937 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> 08, "057D2202"
005BF958 . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF95E . B1 65 mov cl, 65
005BF960 . E8 7337E4FF call 004030D8 ; PStrNCat()
005BF965 . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$057D2202"
005BF96B . 8D85 A4FDFFFF lea eax, dword ptr [ebp-25C]
005BF971 . E8 5651E4FF call 00404ACC ; LStrFromString()
005BF976 . 8B85 A4FDFFFF mov eax, dword ptr [ebp-25C] ; 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 [ebp-1E0]
005BF994 . E8 6F37E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BF999 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> 08, "07D10C72"
005BF9BA . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BF9C0 . B1 65 mov cl, 65
005BF9C2 . E8 1137E4FF call 004030D8 ; PStrNCat()
005BF9C7 . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$07D10C72"
005BF9CD . 8D85 A0FDFFFF lea eax, dword ptr [ebp-260]
005BF9D3 . E8 F450E4FF call 00404ACC ; LStrFromString()
005BF9D8 . 8B85 A0FDFFFF mov eax, dword ptr [ebp-260] ; 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 [ebp-1E0]
005BF9F0 . E8 1337E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BF9F5 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> 08, "12345678"
005BFA16 . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BFA1C . B1 65 mov cl, 65
005BFA1E . E8 B536E4FF call 004030D8 ; PStrNCat()
005BFA23 . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "12345678"
005BFA29 . 8D85 9CFDFFFF lea eax, dword ptr [ebp-264]
005BFA2F . E8 9850E4FF call 00404ACC ; LStrFromString()
005BFA34 . 8B85 9CFDFFFF mov eax, dword ptr [ebp-264] ; 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 [5CA964] ; [0x005CA964] == 0x00000026,order_no = 38 = 0x26
005BFA4C . 0F85 16030000 jnz 005BFD68
005BFA52 . BB 04000000 mov ebx, 4
005BFA57 . BE AC6C5C00 mov esi, 005C6CAC ; 版本类型,[esi] == 0x11E768B7(个人版), [esi] xor 0x00278145 为激活码第三部分
005BFA5C > BA 48025C00 mov edx, 005C0248
005BFA61 . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BFA67 . E8 9C36E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BFA6C . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; edx ===> 08, "12345678"
005BFA8D . 8D85 20FEFFFF lea eax, dword ptr [ebp-1E0]
005BFA93 . B1 65 mov cl, 65
005BFA95 . E8 3E36E4FF call 004030D8 ; PStrNCat()
005BFA9A . 8D95 20FEFFFF lea edx, dword ptr [ebp-1E0] ; edx ===> 09, "$12345678"
005BFAA0 . 8D85 98FDFFFF lea eax, dword ptr [ebp-268]
005BFAA6 . E8 2150E4FF call 00404ACC ; LStrFromString()
005BFAAB . 8B85 98FDFFFF mov eax, dword ptr [ebp-268] ; 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 [esi] ; 激活码第3部分等于 0x11E768B7 xor 0x00278145,0x11E768B7 表示个人版
005BFAC0 . 33D2 xor edx, edx
005BFAC2 . 3B5424 04 cmp edx, dword ptr [esp+4]
005BFAC6 . 75 03 jnz short 005BFACB
005BFAC8 . 3B0424 cmp eax, dword ptr [esp]
005BFACB > 5A pop edx
005BFACC . 58 pop eax
005BFACD . 0F85 84020000 jnz 005BFD57
005BFAD3 . 8D85 B8FDFFFF lea eax, dword ptr [ebp-248]
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 [ebp-248] ; 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(), [005CAB74] ==> 08, "99022142"
005BFB00 . BA 48025C00 mov edx, 005C0248 ; edx ===> 01, "$"
005BFB05 . 8D85 84FDFFFF lea eax, dword ptr [ebp-27C]
005BFB0B . E8 F835E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BFB10 . 8D85 78FDFFFF lea eax, dword ptr [ebp-288]
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 [ebp-288] ; edx ===> 04, "9902"
005BFB31 . 8D85 84FDFFFF lea eax, dword ptr [ebp-27C]
005BFB37 . B1 0B mov cl, 0B
005BFB39 . E8 9A35E4FF call 004030D8 ; PStrNCat()
005BFB3E . 8D95 84FDFFFF lea edx, dword ptr [ebp-27C] ; edx ===> 05, "$9902"
005BFB44 . 8D85 90FDFFFF lea eax, dword ptr [ebp-270]
005BFB4A . E8 7D4FE4FF call 00404ACC ; LStrFromString()
005BFB4F . 8B85 90FDFFFF mov eax, dword ptr [ebp-270] ; 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 [ebp-26C]
005BFB65 . E8 E69AE4FF call 00409650 ; IntToStr()
005BFB6A . 8D85 94FDFFFF lea eax, dword ptr [ebp-26C] ; [eax] ===> "29684"
005BFB70 . 50 push eax
005BFB71 . 8D85 74FDFFFF lea eax, dword ptr [ebp-28C]
005BFB77 . 50 push eax
005BFB78 . BA 48025C00 mov edx, 005C0248 ; edx ===> 01, "$"
005BFB7D . 8D85 84FDFFFF lea eax, dword ptr [ebp-27C]
005BFB83 . E8 8035E4FF call 00403108 ; PStrCpy(), 生成 01, "$"
005BFB88 . 8D85 78FDFFFF lea eax, dword ptr [ebp-288]
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 [ebp-288] ; edx ===> 04, "2142"
005BFBA9 . 8D85 84FDFFFF lea eax, dword ptr [ebp-27C]
005BFBAF . B1 0B mov cl, 0B
005BFBB1 . E8 2235E4FF call 004030D8 ; PStrNCat()
005BFBB6 . 8D95 84FDFFFF lea edx, dword ptr [ebp-27C] ; edx ===> 05, "$2142"
005BFBBC . 8D85 68FDFFFF lea eax, dword ptr [ebp-298]
005BFBC2 . E8 054FE4FF call 00404ACC ; LStrFromString()
005BFBC7 . 8B85 68FDFFFF mov eax, dword ptr [ebp-298] ; 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 [ebp-294], eax ; 低32位 == eax
005BFBDD . C685 70FDFFFF 00 mov byte ptr [ebp-290], 0 ; 高32位 == 0
005BFBE4 . 8D95 6CFDFFFF lea edx, dword ptr [ebp-294]
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 [ebp-28C] ; edx ===> "52148"
005BFBFC . 58 pop eax ; eax ===> "29684"
005BFBFD . E8 2E4FE4FF call 00404B30 ; LStrCat()
005BFC02 . 8B95 94FDFFFF mov edx, dword ptr [ebp-26C] ; edx ===> "2968452148"
005BFC08 . 8D85 C4FEFFFF lea eax, dword ptr [ebp-13C]
005BFC0E . B9 FF000000 mov ecx, 0FF
005BFC13 . E8 EC4EE4FF call 00404B04 ; System.@LStrToString()
005BFC18 . 8D95 C4FEFFFF lea edx, dword ptr [ebp-13C] ; 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 [ebp-2A0]
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 [ebp-2A0] ; eax ===> "2968452148"
005BFC40 . 8D95 64FDFFFF lea edx, dword ptr [ebp-29C]
005BFC46 . E8 6588E8FF call 004484B0 ; ReverseString(),将10进制字符串反转, "2968452148" 变为 "8412548692"
005BFC4B . 8B95 64FDFFFF mov edx, dword ptr [ebp-29C] ; edx ===> "8412548692"
005BFC51 . 8D85 C4FEFFFF lea eax, dword ptr [ebp-13C]
005BFC57 . B9 FF000000 mov ecx, 0FF
005BFC5C . E8 A34EE4FF call 00404B04 ; System.LStrToString;
005BFC61 . 8D95 C4FEFFFF lea edx, dword ptr [ebp-13C] ; edx ===> 0A, "8412548692"
005BFC67 . B8 74AB5C00 mov eax, 005CAB74 ; 全局变量[0x005CAB74], 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 [ebp-2A8]
005BFC79 . 8A15 75AB5C00 mov dl, byte ptr [5CAB75] ; 第1个字符, "8"
005BFC7F . 8850 01 mov byte ptr [eax+1], dl
005BFC82 . C600 01 mov byte ptr [eax], 1 ; 生成delphi格式短字符串,01, "8"
005BFC85 . 8D95 58FDFFFF lea edx, dword ptr [ebp-2A8]
005BFC8B . 8D85 54FDFFFF lea eax, dword ptr [ebp-2AC]
005BFC91 . E8 7234E4FF call 00403108 ; PStrCpy()
005BFC96 . 8D85 50FDFFFF lea eax, dword ptr [ebp-2B0]
005BFC9C . 8A15 76AB5C00 mov dl, byte ptr [5CAB76] ; 第2个字符 "4"
005BFCA2 . 8850 01 mov byte ptr [eax+1], dl
005BFCA5 . C600 01 mov byte ptr [eax], 1 ; 生成delphi格式短字符串,01, "4"
005BFCA8 . 8D95 50FDFFFF lea edx, dword ptr [ebp-2B0] ; edx ===> 01, "4"
005BFCAE . 8D85 54FDFFFF lea eax, dword ptr [ebp-2AC] ; eax ===> 01, "8"
005BFCB4 . B1 02 mov cl, 2 ; 字符串个数 count = 2
005BFCB6 . E8 1D34E4FF call 004030D8 ; PStrNCat()
005BFCBB . 8D95 54FDFFFF lea edx, dword ptr [ebp-2AC] ; edx ===> 02, "84"
005BFCC1 . 8D85 5CFDFFFF lea eax, dword ptr [ebp-2A4]
005BFCC7 . E8 004EE4FF call 00404ACC ; System.LStrFromString(String;String;ShortString;ShortString);
005BFCCC . 8B85 5CFDFFFF mov eax, dword ptr [ebp-2A4] ; 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 [ebp-2A8]
005BFCE3 . 8A15 77AB5C00 mov dl, byte ptr [5CAB77] ; 第3个字符 "1"
005BFCE9 . 8850 01 mov byte ptr [eax+1], dl
005BFCEC . C600 01 mov byte ptr [eax], 1 ; 生成delphi格式短字符串,01, "1"
005BFCEF . 8D95 58FDFFFF lea edx, dword ptr [ebp-2A8]
005BFCF5 . 8D85 54FDFFFF lea eax, dword ptr [ebp-2AC]
005BFCFB . E8 0834E4FF call 00403108 ; PStrCpy()
005BFD00 . 8D85 50FDFFFF lea eax, dword ptr [ebp-2B0]
005BFD06 . 8A15 78AB5C00 mov dl, byte ptr [5CAB78] ; 第4个字符 "2"
005BFD0C . 8850 01 mov byte ptr [eax+1], dl
005BFD0F . C600 01 mov byte ptr [eax], 1 ; 生成delphi格式短字符串,01, "2"
005BFD12 . 8D95 50FDFFFF lea edx, dword ptr [ebp-2B0] ; edx ===> 01, "2"
005BFD18 . 8D85 54FDFFFF lea eax, dword ptr [ebp-2AC] ; eax ===> 01, "1"
005BFD1E . B1 02 mov cl, 2 ; count = 2
005BFD20 . E8 B333E4FF call 004030D8 ; PStrNCat()
005BFD25 . 8D95 54FDFFFF lea edx, dword ptr [ebp-2AC] ; edx ===> 02, "12"
005BFD2B . 8D85 4CFDFFFF lea eax, dword ptr [ebp-2B4]
005BFD31 . E8 964DE4FF call 00404ACC ; System.LStrFromString(String;String;ShortString;ShortString);
005BFD36 . 8B85 4CFDFFFF mov eax, dword ptr [ebp-2B4] ; 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 [5C6E34] ; 注册成功标志 == 1
005BFD53 . 8802 mov byte ptr [edx], 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:[eax], edx
005BFD70 . 68 9CFD5B00 push 005BFD9C
005BFD75 > A1 346E5C00 mov eax, dword ptr [5C6E34] ; 注册标志
005BFD7A . 8A00 mov al, byte ptr [eax]
005BFD7C . 34 01 xor al, 1 ; al == 0
005BFD7E . 8B15 A4725C00 mov edx, dword ptr [5C72A4] ; 第2个注册成功标志 == 0
005BFD84 . 8802 mov byte ptr [edx], al
005BFD86 . 8B15 346E5C00 mov edx, dword ptr [5C6E34] ; dumped_b.005C43E4
005BFD8C . 8B15 C86E5C00 mov edx, dword ptr [5C6EC8] ; 第3个注册成功标志 == 0
005BFD92 . 8802 mov byte ptr [edx], al
005BFD94 . C3 retn ; RET 用作跳转到 005BFD9C
注册算法总结如下:
1、将硬件序列号去掉中间的"-"号,分成4部分,即4个16进制32位整数,即 ID[1], ID[2], ID[3], ID[4]。
2、输入的激活码分成5部分,前面4个部分也是分成4个16进制32位整数,即 ACT[1], ACT[2], ACT[3], ACT[4],第5部分是一个时间字符串变形,表示成 ACT[5]。
3、程序中有一个版本标识,共4个版本,本程序是个人版,VERTYPE = 0x0x11E768B7,这是一个常量。
4、还有在注册界面输入的 OrderNo,这是一个32位整数。
5、然后是计算:
(1)如果 OrderNo<430000000,则将 OrderNo 改成 38,即 OrdrerNo = 0x26,否则不变。
(2)ACT[1] = ID[1] xor ID[4]
(3)ACT[2] = ID[2] xor ID[3]
(4)ACT[3] = VERTYPE xor 0x00278145
(5)ACT[4] = ACT[3] xor 0x00278145 xor OrderNo,其实就是 VERTYPE xor OrderNo 吧。
6、授权时间 ACT[5]:
(1)时间数字需反序表示。
(2)year = year xor 0xEAF6,如果 year = 9102, 是 2019年 的反序表示。
(3)mon_day = mon_day xor 0xEAF6,如 mon_day = 9003,是09月30日反序表示。
上面表示购买授权时间是 20190930。
(4)ACT[5] = (year << 16) or mon_day,生成激活码第5部分。
注意,上面OrderNo的计算是在输入注册信息的表单(TForm2)中保存注册信息的“Accept”按钮事件中计算的,并且计算结果保存到注册文件中了,后面是读出来直接使用的,具体代码如下:
[Asm] 纯文本查看 复制代码 0050FCEE |> 817D F0 8047A119 cmp dword ptr [ebp-10], 19A14780 ; order_no >= 430000000
0050FCF5 |. 7D 07 jge short 0050FCFE
0050FCF7 |. C745 F0 26000000 mov dword ptr [ebp-10], 26 ; 如果 order_no < 430000000,则将 order_no 改成 0x26
根据上面算法,计算正确的激活码,在注册界面重新输入:
可以看到,注册文件会更新,写入新的注册信息。
然后重启程序,这次又弹出一个对话框,大概是説安装版本过期,授权拒绝了:
这是另一个暗桩,大家还记得前面提到过的一个文件么:”C:\Windows\Debug\passwd.log“,就与这个文件的创建时间有关。
在注册码算法代码后,通过 F8 单步,很快确定是下面函数弹出的对话框:
具体代码如下:
[Asm] 纯文本查看 复制代码 005BFEA7 > \A1 A4725C00 mov eax, dword ptr [5C72A4]
005BFEAC . 8038 00 cmp byte ptr [eax], 0
005BFEAF . 75 11 jnz short 005BFEC2
005BFEB1 . A1 C86E5C00 mov eax, dword ptr [5C6EC8]
005BFEB6 . 8038 00 cmp byte ptr [eax], 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 [5C6CBC], 1
005BFEC9 > A1 38745C00 mov eax, dword ptr [5C7438]
005BFECE . 8038 00 cmp byte ptr [eax], 0
005BFED1 . 74 0C je short 005BFEDF
在 DeDeDark 中相应函数内可以查得就是判断上面那个文件的创建时间来判定的,并且是在程序中硬编码,这个版本的passwd.log的创建时间不能大于 2019/03/27 这个时间。
函数代码如下:
[Asm] 纯文本查看 复制代码 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 [ebp-34], eax
005BEA98 |. 8945 D0 mov dword ptr [ebp-30], eax
005BEA9B |. 8945 EC mov dword ptr [ebp-14], eax
005BEA9E |. 8945 F0 mov dword ptr [ebp-10], eax
005BEAA1 |. 8945 F4 mov dword ptr [ebp-C], eax
005BEAA4 |. 33C0 xor eax, eax
005BEAA6 |. 55 push ebp
005BEAA7 |. 68 37EC5B00 push 005BEC37
005BEAAC |. 64:FF30 push dword ptr fs:[eax]
005BEAAF |. 64:8920 mov dword ptr fs:[eax], esp
005BEAB2 |. A1 EC715C00 mov eax, dword ptr [5C71EC]
005BEAB7 |. 8B00 mov eax, dword ptr [eax]
005BEAB9 |. BA FFE99100 mov edx, 91E9FF
005BEABE |. E8 B50FEBFF call 0046FA78
005BEAC3 |. 8B1D 946E5C00 mov ebx, dword ptr [5C6E94] ; Thaiphoo.005C8739
005BEAC9 |. 8A1B mov bl, byte ptr [ebx]
005BEACB |. 8D45 F4 lea eax, dword ptr [ebp-C]
005BEACE |. 8B15 7C6F5C00 mov edx, dword ptr [5C6F7C] ; Thaiphoo.005C873C
005BEAD4 |. 8B12 mov edx, dword ptr [edx]
005BEAD6 |. E8 2D5EE4FF call 00404908
005BEADB |. 8D55 F0 lea edx, dword ptr [ebp-10]
005BEADE |. B8 4CEC5B00 mov eax, 005BEC4C ; ASCII "{-o-f"
005BEAE3 |. E8 ECFFF4FF call 0050EAD4
005BEAE8 |. 8B55 F0 mov edx, dword ptr [ebp-10]
005BEAEB |. A1 7C6F5C00 mov eax, dword ptr [5C6F7C]
005BEAF0 |. E8 CF5DE4FF call 004048C4
005BEAF5 |. A1 946E5C00 mov eax, dword ptr [5C6E94]
005BEAFA |. C600 5F mov byte ptr [eax], 5F
005BEAFD |. 8D45 EC lea eax, dword ptr [ebp-14]
005BEB00 |. 50 push eax
005BEB01 |. C745 D4 1B000000 mov dword ptr [ebp-2C], 1B ; 27 日 ===> 31 (0x1F)
005BEB08 |. C645 D8 00 mov byte ptr [ebp-28], 0
005BEB0C |. C745 DC 03000000 mov dword ptr [ebp-24], 3 ; 03 月 ===> 12 (0x0C)
005BEB13 |. C645 E0 00 mov byte ptr [ebp-20], 0
005BEB17 |. C745 E4 E3070000 mov dword ptr [ebp-1C], 7E3 ; 2019 年 ===> 9999 (0x270F)
005BEB1E |. C645 E8 00 mov byte ptr [ebp-18], 0
005BEB22 |. 8D55 D4 lea edx, dword ptr [ebp-2C]
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 [ebp-14]
005BEB37 |. E8 68DEE4FF call 0040C9A4
005BEB3C |. DD5D F8 fstp qword ptr [ebp-8]
005BEB3F |. 9B wait
005BEB40 |. 8D45 D0 lea eax, dword ptr [ebp-30]
005BEB43 |. BA 74AA5C00 mov edx, 005CAA74 ; 检查文件 "C:\WINDOWS\Debug\passwd.log" 的创建时间
005BEB48 |. E8 7F5FE4FF call 00404ACC
005BEB4D |. 8B45 D0 mov eax, dword ptr [ebp-30]
005BEB50 |. E8 8BAFE4FF call 00409AE0 ; SysUtils.FileAge(AnsiString):Integer;
005BEB55 |. E8 4EB4E4FF call 00409FA8
005BEB5A |. DD1D 6CA95C00 fstp qword ptr [5CA96C]
005BEB60 |. 9B wait
005BEB61 |. DD45 F8 fld qword ptr [ebp-8]
005BEB64 |. DC1D 6CA95C00 fcomp qword ptr [5CA96C]
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 [5C6E34]
005BEB7D |. 8038 00 cmp byte ptr [eax], 0
005BEB80 |. 74 72 je short 005BEBF4
005BEB82 |. 803D 74AB5C00 08 cmp byte ptr [5CAB74], 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 [ebp-34]
005BEBBA |. BA 74AB5C00 mov edx, 005CAB74 ; ASCII 08,"31129102"
005BEBBF |. E8 085FE4FF call 00404ACC
005BEBC4 |. 8B45 CC mov eax, dword ptr [ebp-34]
005BEBC7 |. E8 D8DDE4FF call 0040C9A4
005BEBCC |. DD5D F8 fstp qword ptr [ebp-8]
005BEBCF |. 9B wait
005BEBD0 |. DD45 F8 fld qword ptr [ebp-8]
005BEBD3 |. D805 6CEC5B00 fadd dword ptr [5BEC6C]
005BEBD9 |. DC1D 6CA95C00 fcomp qword ptr [5CA96C]
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 [5C6CBC], 1
005BEBFB |. A1 946E5C00 mov eax, dword ptr [5C6E94]
005BEC00 |. 8818 mov byte ptr [eax], bl
005BEC02 |. A1 7C6F5C00 mov eax, dword ptr [5C6F7C]
005BEC07 |. 8B55 F4 mov edx, dword ptr [ebp-C]
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:[eax], edx
005BEC17 |. 68 3EEC5B00 push 005BEC3E
005BEC1C |> 8D45 CC lea eax, dword ptr [ebp-34]
005BEC1F |. BA 02000000 mov edx, 2
005BEC24 |. E8 6B5CE4FF call 00404894
005BEC29 |. 8D45 EC lea eax, dword ptr [ebp-14]
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 目录下的任何文件的属性。
注册机源码如下:
[C++] 纯文本查看 复制代码 #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[4] = {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[256];
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[12];
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], 8);
id2 = strtoul(tmp, &endptr, 16);
strncpy(tmp, &ID[17], 8);
id3 = strtoul(tmp, &endptr, 16);
strncpy(tmp, &ID[25], 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[0] ^ 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
谢谢!!!
|
免费评分
-
查看全部评分
|