• 标 题:端口侦探(PortSpy)V3.8.28.06
  • 作 者:yesky1
  • 时 间:2003年9月21日 02:04
  • 链 接:http://bbs.pediy.com

端口侦探(PortSpy)V3.8.28.06


软件介绍:

软件名称:端口侦探(PortSpy)

软件版本:V3.8.28.06 增强版

运行平台:Win98、WinME、Win2000、WinXP、Win2003

软件性质:共享软件

软件作者:黄金龙(KimLon Huang)

作者联系方法:QQ:80215521 kimlon@163.com


【软件简介】:  本程序主要是针对电脑串口(COM)和并口(LPT)的调试与监测.是一款综合型调试软件。串口调试:跟市面上大多数软件一样,可以对串口的波特率,数据位,停止位,校验位等,可对串口进行读写数据。串口监试:可以不占用串口资源对串口的数据(发送和接收)进行捕获。并口操作:可以对并口进行读写数据,捕获数据。


【软件限制】:未注册只能使用30次

【作者声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!

【破解工具】:Ollydbg1.09、IDA、PEiD、DeDe、pe-scan 3.31


一、脱壳
用PEiD侦察得知壳为PEtite 2.1,壳虽然没怎么听说过,用pe-scan 3.31倒是很轻松的脱调了壳,再一看
Delphi程序。
  
二、自校验

双击运行无反映,估计有自校验存在,于是下断CreateFileA停在KIMLMON.dll中,清除断点,按Ctrl+F9回到PortSpy程序空间,停在0048C2AC,到IDA中看一下,还是比较清楚的阿,呵呵。主要验证函数都在KIMLON.DLL中,而且其倒出函数作用都一目了然。


FormCreate事件

snyped:0048C264                 push    ebp
snyped:0048C265                 mov     ebpesp
snyped:0048C267                 mov     ecx, 1Eh
snyped:0048C26C 
snyped:0048C26C loc_48C26C:                             ; CODE XREF: snyped:0048C271j
snyped:0048C26C                 push    0
snyped:0048C26E                 push    0
snyped:0048C270                 dec     ecx
snyped:0048C271                 jnz     short loc_48C26C
snyped:0048C273                 push    ebx
snyped:0048C274                 push    esi
snyped:0048C275                 mov     ebxeax
snyped:0048C277                 xor     eaxeax
snyped:0048C279                 push    ebp
snyped:0048C27A                 push    offset loc_48CB3F
snyped:0048C27F                 push    dword ptr fs:[eax]
snyped:0048C282                 mov     fs:[eax], esp
snyped:0048C285                 lea     eax, [ebp-30h]
snyped:0048C288                 push    eax
snyped:0048C289                 lea     edx, [ebp-7Ch]
snyped:0048C28C                 mov     eaxds:dword_493020
snyped:0048C291                 mov     eax, [eax]
snyped:0048C293                 call    unknown_libname_311
snyped:0048C298                 mov     edx, [ebp-7Ch]
snyped:0048C29B                 lea     eax, [ebp-78h]
snyped:0048C29E                 call    unknown_libname_21
snyped:0048C2A3                 mov     eax, [ebp-78h]
snyped:0048C2A6                 push    eax
snyped:0048C2A7                 call    GetCheckSum    ; 调用KIMLON.DLL! GetCheckSum 函数,计算文件校验码
snyped:0048C2AC                 lea     edx, [ebp-84h] ; <======= 停到此处
snyped:0048C2B2                 mov     eaxds:dword_493020
snyped:0048C2B7                 mov     eax, [eax]
snyped:0048C2B9                 call    unknown_libname_311
snyped:0048C2BE                 mov     edx, [ebp-84h]
snyped:0048C2C4                 lea     eax, [ebp-80h]
snyped:0048C2C7                 call    unknown_libname_21
snyped:0048C2CC                 mov     eax, [ebp-80h]
snyped:0048C2CF                 push    eax
snyped:0048C2D0                 lea     eax, [ebp-10h]
snyped:0048C2D3                 push    eax
snyped:0048C2D4                 call    FileDateTime ;调用KIMLON.DLL! FileDateTime 函数,获取文件日期
snyped:0048C2D9                 lea     edx, [ebp-8Ch]
snyped:0048C2DF                 mov     eaxds:dword_493020
snyped:0048C2E4                 mov     eax, [eax]
snyped:0048C2E6                 call    unknown_libname_311
snyped:0048C2EB                 mov     edx, [ebp-8Ch]
snyped:0048C2F1                 lea     eax, [ebp-88h]
snyped:0048C2F7                 call    unknown_libname_21
snyped:0048C2FC                 mov     eax, [ebp-88h]
snyped:0048C302                 push    eax
snyped:0048C303                 call    FileSizeX  ;调用KIMLON.DLL! FileSizeX 函数,获取文件大小
snyped:0048C308                 mov     esieax
snyped:0048C30A                 call    SumText  ;调用KIMLON.DLL! SumText 函数,获取保存在KIMLON.DLL内的PortSpy.exe的校验码
snyped:0048C30F                 cmp     eax, [ebp-30h]
snyped:0048C312                 jnz     short loc_48C36F
snyped:0048C314                 lea     eax, [ebp-90h]
snyped:0048C31A                 push    eax
snyped:0048C31B                 call    FileDTText  ;调用KIMLON.DLL! FileDTText 函数,获取保存在KIMLON.DLL内的PortSpy.exe文件创建
snyped:0048C320                 mov     edx, [ebp-90h]
snyped:0048C326                 mov     eax, [ebp-10h]
snyped:0048C329                 call    @System@@WStrCmp$qqrv ; System::__linkproc__ WStrCmp(void) 比较文件日期是否相同
snyped:0048C32E                 jnz     short loc_48C36F
snyped:0048C330                 call    FileSizeText  ;调用KIMLON.DLL! FileSizeText 函数,获取保存在KIMLON.DLL内的PortSpy.exe的文件大小
snyped:0048C335                 cmp     esieax      ;比较文件大小是否相同
snyped:0048C337                 jnz     short loc_48C36F
snyped:0048C339                 call    FILEVXD       ;调用KIMLON.DLL! FILEVXD用CreateFileA()来判断是否有调试器,下同
snyped:0048C33E                 test    alal
snyped:0048C340                 jnz     short loc_48C36F
snyped:0048C342                 call    portmvxd
snyped:0048C347                 test    alal
snyped:0048C349                 jnz     short loc_48C36F
snyped:0048C34B                 call    REGVXD
snyped:0048C350                 test    alal
snyped:0048C352                 jnz     short loc_48C36F
snyped:0048C354                 call    checkoutsoft  ;调用KIMLON.DLL! checkoutsoft通过FindWindow()来判断是否有softice,ida等在后台,留待待会处理
snyped:0048C359                 test    alal
snyped:0048C35B                 jnz     short loc_48C36F
snyped:0048C35D                 call    SoftIceNT
snyped:0048C362                 test    alal
snyped:0048C364                 jnz     short loc_48C36F
snyped:0048C366                 call    SoftIce95
snyped:0048C36B                 test    alal
snyped:0048C36D                 jz      short loc_48C38B
snyped:0048C36F 
snyped:0048C36F loc_48C36F:                             ; CODE XREF: snyped:0048C312j
snyped:0048C36F                                         ; snyped:0048C32Ej ...
snyped:0048C36F                 call    @Sysutils@Beep$qqrv ; Sysutils::Beep(void)
snyped:0048C374                 mov     eaxds:dword_493020 snyped:0048C379                 mov     eax, [eax]
snyped:0048C37B                 mov     byte ptr [eax+5Bh], 0
snyped:0048C37F                 mov     eaxds:dword_493020
snyped:0048C384                 mov     eax, [eax]
snyped:0048C386                 call    @Forms@TApplication@Terminate$qqrv ; Forms::TApplication::Terminate(void)
snyped:0048C38B 
snyped:0048C38B 
snyped:0048C38B loc_48C38B:                             ; CODE XREF: snyped:0048C36Dj
snyped:0048C38B                 push    ebx
snyped:0048C38C                 push    offset loc_48F474 ; ; 定时器触发函数调用KIMLON.DLL! closeout关闭黑名单中软件事件
snyped:0048C391                 mov     eax, [ebx+450h]
snyped:0048C397                 call    @Extctrls@TTimer@SetOnTimer$qqrynpqqrp14System@TObject$v ; Extctrls::TTimer::SetOnTimer(void (*)(System::TObject *))
snyped:0048C39C                 mov     edx, 0C8h  ; 间隔200毫秒
snyped:0048C3A1                 mov     eax, [ebx+450h]
snyped:0048C3A7                 call    @Extctrls@TTimer@SetInterval$qqrui ; Extctrls::TTimer::SetInterval(uint)


上面还有一些代码是调用KPSDisk.dll! DiskID32得到硬盘序列号




三、判断是否注册

下面是读取注册表保存的注册码。

snyped:0048C4F2                 mov     dl, 1
snyped:0048C4F4                 mov     eaxds:dword_4621A0
snyped:0048C4F9                 call    @Registry@TRegistry@$bctr$qqrv ; Registry::TRegistry::TRegistry(void)
snyped:0048C4FE                 mov     esieax
snyped:0048C500                 mov     edx, 80000002h
snyped:0048C505                 mov     eaxesi
snyped:0048C507                 call    @Registry@TRegistry@SetRootKey$qqrui ; Registry::TRegistry::SetRootKey(uint)
snyped:0048C50C                 mov     cl, 1
snyped:0048C50E                 mov     edx, offset aSoftwareMicr_0 ; "Software\Microsoft\Windows\PortReg"
snyped:0048C513                 mov     eaxesi
snyped:0048C515                 call    @Registry@TRegistry@OpenKey$qqrx17System@AnsiStringo ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
snyped:0048C51A                 test    alal
snyped:0048C51C                 jz      loc_48C6E8
snyped:0048C522                 lea     ecx, [ebp-14h]
snyped:0048C525                 mov     edx, offset dword_48CBE4  ; "tag"
snyped:0048C52A                 mov     eaxesi
snyped:0048C52C                 call    @TRegistry@ReadString$qqrx10AnsiString ; TRegistry::ReadString(AnsiString)
snyped:0048C531                 lea     ecx, [ebp-1Ch]
snyped:0048C534                 mov     edx, offset dword_48CBF0  ; "XX"
snyped:0048C539                 mov     eax, [ebp-14h]
snyped:0048C53C                 call    sub_4767F4  ; sub_4767F4([tag],"XX",返回值) 对注册tag项中保存值进行解码,对注册码多一层保护,解出值应为"TRY"
snyped:0048C541                 lea     ecx, [ebp-18h]
snyped:0048C544                 mov     edx, offset dword_48CBFC  ; "!!!!" 该注册项保存着注册码
snyped:0048C549                 mov     eaxesi
snyped:0048C54B                 call    @TRegistry@ReadString$qqrx10AnsiString ; TRegistry::ReadString(AnsiString)
snyped:0048C550                 lea     edx, [ebp-0BCh]
snyped:0048C556                 mov     eax, [ebx+494h]
snyped:0048C55C                 call    @TControl@GetText$qqrv ; TControl::GetText(void)
snyped:0048C561                 mov     eax, [ebp-0BCh]
snyped:0048C567                 lea     ecx, [ebp-0B8h]
snyped:0048C56D                 mov     edx, offset dword_48CC0C  ; "3!a@c"
snyped:0048C572                 call    sub_476548    ; 注册码=sub_4767F4("CP"+硬盘卷标,"3!a@c",返回值)"3!a@c"
snyped:0048C577                 mov     ecx, [ebp-0B8h]
snyped:0048C57D                 lea     eax, [ebp-20h]
snyped:0048C580                 mov     edx, offset dword_48CC1C ;  "KC" 注册码以"KC"开头 
snyped:0048C585                 call    @System@@LStrCat3$qqrv ;  注册码="KC" + 注册码
snyped:0048C58A                 mov     eax, [ebp-1Ch]
snyped:0048C58D                 mov     edx, offset dword_48CC28  ; "TRY"
snyped:0048C592                 call    @System@@LStrCmp$qqrv  ; [tag]项解出是否为"TRY"
snyped:0048C597                 jnz     short loc_48C5D5
snyped:0048C599                 mov     eax, [ebp-18h]
snyped:0048C59C                 mov     edx, [ebp-20h]
snyped:0048C59F                 call    @System@@LStrCmp$qqrv ;   *****关键! 注册码明码比较*****
snyped:0048C5A4                 jnz     short loc_48C5D5
snyped:0048C5A6                 mov     edx, offset dword_48CC34 ;  ->"感谢您的注册! (^_^)"
snyped:0048C5AB                 mov     eax, [ebx+4A0h]
snyped:0048C5B1                 call    @Controls@TControl@SetText$qqrx17System@AnsiString ; Controls::TControl::SetText(System::AnsiString)
snyped:0048C5B6                 mov     dl, 1
snyped:0048C5B8                 mov     eax, [ebx+4A0h]
snyped:0048C5BE                 call    @Stdctrls@TCustomEdit@SetReadOnly$qqro ; Stdctrls::TCustomEdit::SetReadOnly(bool)
snyped:0048C5C3                 xor     edxedx
snyped:0048C5C5                 mov     eax, [ebx+498h]
snyped:0048C5CB                 mov     ecx, [eax]
snyped:0048C5CD                 call    dword ptr [ecx+64h]
snyped:0048C5D0                 jmp     loc_48C6E8
snyped:0048C5D5 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
snyped:0048C5D5 
snyped:0048C5D5 loc_48C5D5:                             ; CODE XREF: snyped:0048C597j
snyped:0048C5D5                                         ; snyped:0048C5A4j
snyped:0048C5D5                 mov     edx, 80000001h
snyped:0048C5DA                 mov     eaxesi
snyped:0048C5DC                 call    @Registry@TRegistry@SetRootKey$qqrui ; Registry::TRegistry::SetRootKey(uint)
snyped:0048C5E1                 mov     cl, 1
snyped:0048C5E3                 mov     edx, offset aSoftwareMicr_1 ; "Software\Microsoft"
snyped:0048C5E8                 mov     eaxesi
snyped:0048C5EA                 call    @Registry@TRegistry@OpenKey$qqrx17System@AnsiStringo ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
snyped:0048C5EF                 test    alal
snyped:0048C5F1                 jz      loc_48C6E8
snyped:0048C5F7                 mov     edx, offset dword_48CC6C
snyped:0048C5FC                 mov     eaxesi
snyped:0048C5FE                 call    @Registry@TRegistry@ValueExists$qqrx17System@AnsiString ; Registry::TRegistry::ValueExists(System::AnsiString)
snyped:0048C603                 test    alal
snyped:0048C605                 jz      loc_48C6C1
snyped:0048C60B                 lea     ecx, [ebp-24h]
snyped:0048C60E                 mov     edx, offset dword_48CC6C
snyped:0048C613                 mov     eaxesi
snyped:0048C615                 call    @TRegistry@ReadString$qqrx10AnsiString ; TRegistry::ReadString(AnsiString)
snyped:0048C61A                 lea     ecx, [ebp-2Ch]
snyped:0048C61D                 mov     edx, offset aKimlon_0 ; "kimlon"
snyped:0048C622                 mov     eax, [ebp-24h]
snyped:0048C625                 call    sub_4767F4            ; 使用信息保存在Software\Microsoft下,kao(??!!!, faint)项中,
                                                              ; 过期后如果删除此项,即可重新使用。sub_4767F4为解码函数,解出用户使用次数
snyped:0048C62A                 cmp     dword ptr [ebp-2Ch], 0
snyped:0048C62E                 jnz     short loc_48C647
snyped:0048C630                 mov     eaxds:dword_493020
snyped:0048C635                 mov     eax, [eax]
snyped:0048C637                 mov     byte ptr [eax+5Bh], 0
snyped:0048C63B                 mov     eaxds:dword_493020
snyped:0048C640                 mov     eax, [eax]
snyped:0048C642                 call    @Forms@TApplication@Terminate$qqrv ; Forms::TApplication::Terminate(void)
snyped:0048C647 
snyped:0048C647 loc_48C647:                             ; CODE XREF: snyped:0048C62Ej
snyped:0048C647                 mov     eax, [ebp-2Ch]
snyped:0048C64A                 mov     edx, offset dword_48CC88
snyped:0048C64F                 call    @System@@LStrCmp$qqrv ; System::__linkproc__ LStrCmp(void)
snyped:0048C654                 jz      short loc_48C663
snyped:0048C656                 mov     eax, [ebp-2Ch]
snyped:0048C659                 call    @Sysutils@StrToInt$qqrx17System@AnsiString ; Sysutils::StrToInt(System::AnsiString)
snyped:0048C65E                 cmp     eax, 5Ah     ; 关键! *******每次使用值+3,编码后保存在注册表中,故为30×3=90******
snyped:0048C661                 jle     short loc_48C67C ; 如果使用次数<30则跳
snyped:0048C663 
snyped:0048C663 loc_48C663:                             ; CODE XREF: snyped:0048C654j
snyped:0048C663                 mov     eaxds:dword_493020
snyped:0048C668                 mov     eax, [eax]
snyped:0048C66A                 mov     byte ptr [eax+5Bh], 0
snyped:0048C66E                 mov     eaxds:dword_493020
snyped:0048C673                 mov     eax, [eax]
snyped:0048C675                 call    @Forms@TApplication@Terminate$qqrv ; Forms::TApplication::Terminate(void)
snyped:0048C67A                 jmp     short loc_48C6E8
snyped:0048C67C ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
snyped:0048C67C 
snyped:0048C67C loc_48C67C:                             ; CODE XREF: snyped:0048C661j
snyped:0048C67C                 mov     eax, [ebp-2Ch]
snyped:0048C67F                 call    @Sysutils@StrToInt$qqrx17System@AnsiString ; Sysutils::StrToInt(System::AnsiString)
snyped:0048C684                 add     eax, 3         ; 每次使用值+3,编码后保存在注册表中
snyped:0048C687                 lea     edx, [ebp-0C0h]
snyped:0048C68D                 call    @Sysutils@IntToStr$qqri ; Sysutils::IntToStr(int)
snyped:0048C692                 mov     edx, [ebp-0C0h]
snyped:0048C698                 lea     eax, [ebp-2Ch]
snyped:0048C69B                 call    @System@@LStrLAsg$qqrv ; System::__linkproc__ LStrLAsg(void)
snyped:0048C6A0                 lea     ecx, [ebp-28h]
snyped:0048C6A3                 mov     edx, offset aKimlon_0 ; "kimlon"
snyped:0048C6A8                 mov     eax, [ebp-2Ch]
snyped:0048C6AB                 call    sub_476548  ; 编码函数,编码后保存在注册表中
snyped:0048C6B0                 mov     ecx, [ebp-28h]
snyped:0048C6B3                 mov     edx, offset dword_48CC6C
snyped:0048C6B8                 mov     eaxesi
snyped:0048C6BA                 call    @TRegistry@WriteString ; TRegistry::WriteString
snyped:0048C6BF                 jmp     short loc_48C6E8
...




snyped:0048C354                 call    checkoutsoft  ;调用KIMLON.DLL! checkoutsoft通过FindWindow()来判断是否有softice,ida等
这个函数通过使用FindWindowA来查找是否有黑名单上的软件在运行,这技法不怎么新鲜阿,黑名单中都是些耳熟能详的软件了呵呵,用HexWorkShop看看有
^[.OWL_Window..TIdaWindow..OLLYDBG.NuMega SoftICE Symbol Loader....TMainForm...TRW2000.#32770..TRW2000 for Windows 9x..-=CHiNA CrACKiNG GrOUp=-....TDeDeMainForm...18467-41....RegmonClass.FileMonClass....PortmonClass....Registry Shot for Win9X,WinNT...TSpyWindow..APIMonitor By Rohitab...WFS_Frame

.WFS_Frame...OWL_Window..TIdaWindow..OLLYDBG.TRW2000.TRW2000 for Windows 9x..#32770..TDeDeMainForm...FileMonClass....RegmonClass.PortmonClass....18467-41

不过程序并不立即进行比较,只是将这些找到的列表保存下来,待会会向这些程序挨个发退出消息,还好没让你重起,^_^
可以将这些名字胡改一下,或者在更改主程序中判断语句。



四、输入注册码

当你在0048C59F看到了注册码,可是当想用这个注册码在注册页面输入时却发现点击注册按钮没有反映,why??难道注册码不正确吗?开始让我很疑惑,以为这是个试用版不能注册。
用DEDE载入,看看注册按钮响应事件指向0048EF50,看了看这个事件判断大致判断即为注册事件。设置断点,却没能断下来。

这就是此软件有意思的地方---- 注册按钮响应事件指向并不正确,指向一个垃圾事件,非真正的响应.
等一下,整理思路,首先我们找到的注册码应该是正确的,输入不正确代表里面有判断事件

还是在FormCreate事件
...
snyped:0048CA6B                 mov     eax, [ebx+498h] ;获取"注册"按钮 指针
snyped:0048CA71                 mov     [eax+124h], ebx
snyped:0048CA77                 mov     dword ptr [eax+120h], offset sub_48DE70  ; 设置注册按钮事件(垃圾事件,非真正的响应)
...

这是Delphi获取控件指针的惯用手法mov     eax, [ebx+498h]
处498h为"注册"按钮控件offset值,可在dede中查看到,
所以可以通过在IDA中查找[ebx+498h] or [eax+498h]来找到使用"注册"按钮指针的引用之处


找到了这里,在DEDE中一看是"g" lable(即"注册码"label)的双击事件,
当双击"注册码"Label后才挂接正确注册按钮响应事件,作者还真用心良苦阿,:)

...
snyped:0048FED8                 mov     edx, [eax+498h]
snyped:0048FEDE                 mov     [edx+124h], eax
snyped:0048FEE4                 mov     dword ptr [edx+120h], offset sub_48EF50 ; 挂接"注册"按钮正确得响应事件
snyped:0048FEEE                 mov     eaxedx
snyped:0048FEF0                 mov     edx, offset dword_48FF04
snyped:0048FEF5                 call    @Controls@TControl@SetText$qqrx17System@AnsiString ; Controls::TControl::SetText(System::AnsiString)
snyped:0048FEFA                 retn
...

再试一次,输入注册码还是不管用,晕~~~,不过不要气馁,cracker最需要的就是耐心了 :)
于是ollydbg载入设断0048EF50,果然停在这里了,:)
单步走来到这里

0048F009   .  8B45 E0       MOV     EAXDWORD PTR SS:[EBP-20]
0048F00C   .  8D4D F4       LEA     ECXDWORD PTR SS:[EBP-C]
0048F00F   .  BA 74F14800   MOV     EDX, <PortSpy3.dword_48F174>    ;  ASCII "3!a@c"
0048F014   .  E8 2F75FEFF   CALL    <PortSpy3.sub_476548>  ; 计算注册码,若要得到算法,可研究一下此call,我粗略看了一下,好像不怎么复杂,可是吾汇编太差了,还是不懂,:(。有一点奇怪的就是此函数在dede中显示为TRichEditStrings类的一个函数??
0048F019   .  8BB3 A0040000 MOV     ESIDWORD PTR DS:[EBX+4A0] ; 获取"注册码"Label 指针 
0048F01F   .  837E 0C 01    CMP     DWORD PTR DS:[ESI+C], 1  ; 判断是否注册使能,TEdit.Tag=1?
0048F023   .  0F85 CC000000 JNZ     <PortSpy3.loc_48F0F5>

这里一跳走就没戏了,看来这是"注册码"Label的一个属性,标志注册使能。看来还没有完,继续IDA中查找[ebx+4A0h] or [eax+4A0h]
找到这里:
注册码输入框okeditKeyDown事件

snyped:0048F820 sub_48F820      proc near               ; DATA XREF: snyped:0048CA3Ao
snyped:0048F820 
snyped:0048F820 arg_0           = byte ptr  8
snyped:0048F820 
snyped:0048F820                 push    ebp
snyped:0048F821                 mov     ebpesp
snyped:0048F823                 test    [ebp+arg_0], 4       ;按下Ctrl,可以从
snyped:0048F827                 jz      short loc_48F853
snyped:0048F829                 mov     dx, [ecx]
snyped:0048F82C                 sub     dl, 41h              ;键盘扫描码 'a'
snyped:0048F82F                 jz      short loc_48F836
snyped:0048F831                 sub     dl, 20h              ; or 'A'
snyped:0048F834                 jnz     short loc_48F853
snyped:0048F836 
snyped:0048F836 loc_48F836:                             ; CODE XREF: sub_48F820+Fj
snyped:0048F836                 mov     edx, [eax+4A0h] ; 指向注册码输入框okedit
snyped:0048F83C                 mov     dword ptr [edx+0Ch], 1  ; <==== 注册使能,TEdit.Tag=1,Tag属性是程序员自己定义意义得属性
snyped:0048F843                 mov     edx, offset dword_48F860
snyped:0048F848                 mov     eax, [eax+498h]
snyped:0048F84E                 call    @Controls@TControl@SetText$qqrx17System@AnsiString ; Controls::TControl::SetText(System::AnsiString)
snyped:0048F853 
snyped:0048F853 loc_48F853:                             ; CODE XREF: sub_48F820+7j
snyped:0048F853                                         ; sub_48F820+14j
snyped:0048F853                 pop     ebp
snyped:0048F854                 retn    4
snyped:0048F854 sub_48F820      endp


也就是在注册码输入框输入Ctrl+A(a)方能开启,再次输入注册码,注册码输入框变为 "感谢您的注册! (^_^)"
怎么看这小脸笑得这么甜,:)


总结一下注册过程,首先双击"注册码" Label,然后在注册码输入框按Ctrl+A,使能注册事件。Delphi中获取控件指针好像有固定模式,

snyped:0048CA6B                 mov     eax, [ebx+498h] ; 获取控件指针,498h为控件偏移,有时是[eax+498h]
snyped:0048CA71                 mov     [eax+124h], ebx
snyped:0048CA77                 mov     dword ptr [eax+120h], offset sub_48DE70  ;  写控件属性

再通过IDA强大查找功能可以找到一些隐含属性或事件读写之处,方便破解。

初学破解,破文写的有些混乱,见谅。