端口侦探(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 ebp, esp
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 ebx, eax
snyped:0048C277 xor eax, eax
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 eax, ds: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 eax, ds: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 eax, ds: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 esi, eax
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 esi, eax ;比较文件大小是否相同
snyped:0048C337 jnz short loc_48C36F
snyped:0048C339 call FILEVXD ;调用KIMLON.DLL! FILEVXD用CreateFileA()来判断是否有调试器,下同
snyped:0048C33E test al, al
snyped:0048C340 jnz short loc_48C36F
snyped:0048C342 call portmvxd
snyped:0048C347 test al, al
snyped:0048C349 jnz short loc_48C36F
snyped:0048C34B call REGVXD
snyped:0048C350 test al, al
snyped:0048C352 jnz short loc_48C36F
snyped:0048C354 call checkoutsoft ;调用KIMLON.DLL! checkoutsoft通过FindWindow()来判断是否有softice,ida等在后台,留待待会处理
snyped:0048C359 test al, al
snyped:0048C35B jnz short loc_48C36F
snyped:0048C35D call SoftIceNT
snyped:0048C362 test al, al
snyped:0048C364 jnz short loc_48C36F
snyped:0048C366 call SoftIce95
snyped:0048C36B test al, al
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 eax, ds:dword_493020 snyped:0048C379 mov eax, [eax]
snyped:0048C37B mov byte ptr [eax+5Bh], 0
snyped:0048C37F mov eax, ds: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 eax, ds:dword_4621A0
snyped:0048C4F9 call @Registry@TRegistry@$bctr$qqrv ; Registry::TRegistry::TRegistry(void)
snyped:0048C4FE mov esi, eax
snyped:0048C500 mov edx, 80000002h
snyped:0048C505 mov eax, esi
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 eax, esi
snyped:0048C515 call @Registry@TRegistry@OpenKey$qqrx17System@AnsiStringo ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
snyped:0048C51A test al, al
snyped:0048C51C jz loc_48C6E8
snyped:0048C522 lea ecx, [ebp-14h]
snyped:0048C525 mov edx, offset dword_48CBE4 ; "tag"
snyped:0048C52A mov eax, esi
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 eax, esi
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 edx, edx
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 eax, esi
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 eax, esi
snyped:0048C5EA call @Registry@TRegistry@OpenKey$qqrx17System@AnsiStringo ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
snyped:0048C5EF test al, al
snyped:0048C5F1 jz loc_48C6E8
snyped:0048C5F7 mov edx, offset dword_48CC6C
snyped:0048C5FC mov eax, esi
snyped:0048C5FE call @Registry@TRegistry@ValueExists$qqrx17System@AnsiString ; Registry::TRegistry::ValueExists(System::AnsiString)
snyped:0048C603 test al, al
snyped:0048C605 jz loc_48C6C1
snyped:0048C60B lea ecx, [ebp-24h]
snyped:0048C60E mov edx, offset dword_48CC6C
snyped:0048C613 mov eax, esi
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 eax, ds:dword_493020
snyped:0048C635 mov eax, [eax]
snyped:0048C637 mov byte ptr [eax+5Bh], 0
snyped:0048C63B mov eax, ds: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 eax, ds:dword_493020
snyped:0048C668 mov eax, [eax]
snyped:0048C66A mov byte ptr [eax+5Bh], 0
snyped:0048C66E mov eax, ds: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 eax, esi
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 eax, edx
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 EAX, DWORD PTR SS:[EBP-20]
0048F00C . 8D4D F4 LEA ECX, DWORD 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 ESI, DWORD 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 ebp, esp
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强大查找功能可以找到一些隐含属性或事件读写之处,方便破解。
初学破解,破文写的有些混乱,见谅。