首页
社区
课程
招聘
[原创]疱丁解牛两层Nag窗体:FrameMaster.exe相框专家共享版和补丁源码(C#)
2006-9-14 20:07 8613

[原创]疱丁解牛两层Nag窗体:FrameMaster.exe相框专家共享版和补丁源码(C#)

2006-9-14 20:07
8613
软件英文名字叫:FrameMaster.exe,有两个版本的中文名字.4.58版本的FrameMaster.exe叫相框专家共享版,4.88版本的FrameMaster.exe快乐大头贴共享版.
Borland Delphi 6.0 - 7.0编译.4.58版本的FrameMaster.exe中有两个Nag(讨厌窗体提示注册)窗体,一个是启动主程序的时候加载第一个NAG窗体并延迟几分钟,然后方可点击button控件进入主界面.第二个NAG出现在软件上功能中,你选择其他共享相框的时候,它会加载阻止!
4.88版本的FrameMaster.exe只有第一个启动Nag窗体,并且与4.58版本相同.
本文章针对4.58版本二个Nag的窗口的,对4.88版本也适用的..4.58版本的FrameMaster.exe相框专家共享版软件在华军下载!
soft down url=http://www.onlinedown.net/soft/47141.htm
中文名字:EPC相框专家
---qiweixue
Borland Delphi的DFM资源是续列化到Exe的Resouse DATA节中其中关键的事件如OnClick,OnClose,OnCreate等窗体和控件事件也以这样的字符串命名进入节中并且都赋了事件名,所以要定位这些事件与类很容易一般索引资源就就ok,也可以用dede反编译.
如果程序对资源节做个手脚,屏蔽了事件名资源那就不爽了,那就需要对delphi消息事件分派有所了解,即使不使用dede这类反编译,自己也可以根据VCL类库定位到想要的事件.
分析第一个启动NAG窗体:窗体上有四个控件:两个Button,一个Timer控件,一个webBorwse控件.先来破除第一个NAG,方法大概有两种,
先用delphi模拟给大家看看
program NAG;
uses
  Forms,TRegForm,TMainForm

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TRegForm, RegForm);----->创建第一个Neg启动窗体
  RegForm.ShowModal-------------->显示模式窗体RegForm
  Application.CreateForm(TMainForm, MainForm);-------->启动主窗体TMainForm
  Application.Run;-->启动消息分派
end.
看玩以上大体明白了它启动原理,来看FrameMaster.exe启动汇编码:
00567E12      A1 8C755600   mov     eax, [56758C]----->[56758C]是TRegForm类模版
00567E17   .  E8 A45AF0FF   call    0046D8C0--------->Application.CreateForm(TRegForm, RegForm);
00567E1C   .  8B15 D8665700 mov     edx, [5766D8]---------->[5766D8]是TRegForm类对象RegForm的引用堆地址               
00567E22   .  8902          mov     [edx], eax
00567E24   .  A1 D8665700   mov     eax, [5766D8]
00567E29   .  8B00          mov     eax, [eax]
00567E2B   .  8B10          mov     edx, [eax]----->虚表给edx
00567E2D   .  FF92 EC000000 call    [edx+EC]------>RegForm.ShowModal
00567E33   .  A1 38695700   mov     eax, [576938]----->以后加载TMainForm窗体
00567E38   .  8B00          mov     eax, [eax]

方法一:直接从TRegForm直接补丁个跳转指令躲避开RegForm的实例化,直接到加载TMainForm窗体的加载地址.分析在上边给出了!

第二中方法是:
原理是NAG窗体启动的时候,修改NAG窗体控件的响应时间(1毫秒够快北)与修改Timer控件的事件方法,直接让它跳到主程序界面.自己并没有销毁且还在内存中.

NAG窗体设置了一个15000ms的记数器如下:
00432F2E  |.  6A 00         push    0    ----> imerproc = NULL
00432F30  |.  56            push    esi   --->Timeout=15000ms
00432F31  |.  6A 01         push    1  --->TimerID = 1
00432F33  |.  8B43 34       mov     eax, [ebx+34]
00432F36  |.  50            push    eax  --->hWnd
00432F37  |.  E8 1048FDFF   call    0040774 --->SetTimer

OnTimer事件响应方法:
00567830 > .  53            push    ebx                              
00567831   .  8BD8          mov     ebx, eax
00567833   .  C605 702B5800>mov     byte ptr [582B70], 1
0056783A   .  B2 01         mov     dl, 1-------->设置Boolean dl 为真,下边要回复Button的Enabled=true;
0056783C > .  8B83 00030000 mov     eax, [ebx+300]  ----->定位到Button控件地址
00567842   .  8B08          mov     ecx, [eax]---->给虚表ecx
00567844 > .  FF51 64       call    [ecx+64] -------> 调用虚方法TButton.SetEnabled(Boolean dl)
00567847   .  33D2          xor     edx, edx----->又一个Boolean 变量dl,给TTimer的Enable=false
00567849 > .  8B83 FC020000 mov     eax, [ebx+2FC] --->定位到Timer1控件
0056784F > .  E8 30B7ECFF   call    00432F84 --->TTimer.SetEnabled(TTimer;Boolean),自我销毁.
00567854   .  5B            pop     ebx
00567855   .  C3            retn
方法二,你可以在OnTimer事件里补丁个跳转指令直接跳到TMainForm窗体并且修改时间为极短.
我用的是第一种绿色方法.
定位OnTimer事件地址可以用dede来反编译.也可以用VCL类库固定模式来分析:
StdWndProc-->TTimer.WndProc(var Msg: TMessage)->procedure TTimer.Timer->FOnTimer(Self)->FOnTimer(Self)--->终点程序事件响应.详细看下边的流程图和代码分析.
TMessage = packed record
      Msg: Cardinal;
  case Integer of
      0: (
        WParam: Longint;
        LParam: Longint;
        Result: Longint);
      1: (
        WParamLo: Word;
        WParamHi: Word;
        LParamLo: Word;
        LParamHi: Word;
        ResultLo: Word;
        ResultHi: Word);
end;

StdWndProc 这里不做解释,下边有,它直接TTimer.WndPorc如下:
TTimer.WndProc(var Msg: TMessage);
00432E84   .  55            push    ebp                             
00432E85   .  8BEC          mov     ebp, esp
00432E87   .  51            push    ecx
00432E88   .  53            push    ebx
00432E89   .  56            push    esi
00432E8A   .  57            push    edi
00432E8B   .  8BDA          mov     ebx, edx
00432E8D   .  8945 FC       mov     [ebp-4], eax--------->eax是VCL中的TTimer类
00432E90   .  8B33          mov     esi, [ebx]----->[ebx]是TTMessage类对象 以上两个寄存器参数是由StdWndProc函数传进来的.
00432E92   .  81FE 13010000 cmp     esi, 113---------------->WM_Timer消息
00432E98   .  75 3F         jnz     short 00432ED9--->不是WM_Timer跳
00432E9A   .  33C0          xor     eax, eax
00432E9C   .  55            push    ebp
00432E9D   .  68 BE2E4300   push    00432EBE
00432EA2   .  64:FF30       push    dword ptr fs:[eax]
00432EA5   .  64:8920       mov     fs:[eax], esp
00432EA8   .  8B45 FC       mov     eax, [ebp-4]
00432EAB   .  66:BE EFFF    mov     si, 0FFEF->注意很关键动态方法索引值:EF是动态发法TTimer.Timer动态表占位偏移.
00432EAF   .  E8 A80CFDFF   call    00403B5C   -----> CallDynaInst 最终它找到动态方法TTimer.Timer,
00432EF6   .  C3            retn

mov si ,0Fxx
Call 403B5C
这中动态消息分派方法在delphi大量常见,几乎所有的消息事件都是由这种固定模式分派寻找末端的事件方法
从上边的 _CallDynaInst中它内部又调用GetDynaMethod(vmt: TClass; selector: Smallint) : Pointer,这一点与TObject.Dispatch(var Message)内部雷同,
它们共同约定的寄存器:eax是对象地址,si是动态方法索引值,[eax+vmtDynamicTable]动态方法表,这比C++等其他面向对象多了一个动态函数表格,最终找到事件句柄然后jmp进去.
比如:TButton.Click,EB是它的索引值.用这些索引值找方法是个不错的方式.

procedure TTimer.Timer;
if Assigned(FOnTimer) then FOnTimer(Self);
00432FBC   .  53            push    ebx
00432FBD   .  66:8378 3A 00 cmp     word ptr [eax+3A], 0---->这也是VCL固定模式比较onTimer事件指针高两位字节是否为空
00432FC2   .  74 0A         je      short 00432FCE--->为空就跳
00432FC4   .  8BD8          mov     ebx, eax
00432FC6   .  8BD0          mov     edx, eax----->Timer对象地址
00432FC8   .  8B43 3C       mov     eax, [ebx+3C]---->这是什么东东,只是个self指针,TObject类型在这里当然是我们的TRegFrom类了.
00432FCB   .  FF53 38       call    [ebx+38]--------->FOnTimer(self)最终跳转到最末端事件方法.就是上边给出那个OnTimer事件方法,往上看.
00432FCE   >  5B            pop     ebx
00432FCF   .  C3            retn

第一个Neg窗体就over,空掉了.
第二个Neg登场子了...先说一原由为什么这样分析:第二个NAG是功能限制NAG,也就是点击窗体的应用功能Button(应该是SpeedButton,下文的Buttno和SpeedButton是一个东东)的时候,它会跳出来阻止你到官方网站去注册.
这个关键事件就是Button(SpeedButton)类响应的通知单击(WM_COMMAND消息0+)Click事件,在用dede的时候没有分析出它们的事件地址,怀疑它对dede做了手脚.正是这样的原因才详细分析VCL消息分派模型,看看它到底搞了什么东东在里边了.
开始吧。
以下1-20个步骤是在分析弹出第二个Neg窗口WM_Command消息在VCL类库中的分派流程,T1-T2-T3-T4步骤是第一个Neg窗体触发的WM_Timer消息在VCL类库中的分派流程.当然这个框架也是其他消息在VCL类库中分派的流程.

进入第二个Neg分析流程,根据流程图中的WM_Comamnd消息在VCL中分派走.为什么这样做呢?因为开始用Dede等反编译的时候,分析不出那两个关键Button按钮的事件地址,但是点击它们都有事件响应的,怀疑它反dede,所以才
才大废脑细胞分析一二,看看它到底做了什么.开始吧!

WM_Command消息分派流程:
StdWndProc-->TWinControl.MainWndProc--->TCustomForm.WndProc--->TWinControl.WndProc->TControl.WndProc-----
--->TObject.Dispatch--->TCustomForm.WMCommand--->TWinControl.WMCommand-->DoControlMsg(父窗体不理会并把控件通知码发向子控件回调函数)--->TControl.Perform---
--->TButtonControl.WndProc-->TWinControl.WndProc--->TControl.WndProc--->TObject.Dispatch--->TButton.CNCommand---
--->TButton.Click--->TControl.Click--->TButton.CNCommand--->TButton.Click--->TControl.Click;            

注意在跟入分析的时候是逆向反跟踪分析,我这里写出的分析文章是从起点开始分析.
classes.pas.10958:StdWndProc(Window: HWND; Message, WParam: Longint; LParam: Longint): Longint; stdcall;
经典的Stdcall到register调用转化.
004201CC  /.  55            push    ebp
004201CD  |.  8BEC          mov     ebp, esp
004201CF  |.  31C0          xor     eax, eax
004201D1  |.  50            push    eax
004201D2  |.  FF75 14       push    dword ptr [ebp+14]--->LParam
004201D5  |.  FF75 10       push    dword ptr [ebp+10]----> WParam
004201D8  |.  FF75 0C       push    dword ptr [ebp+C]------>Message
004201DB  |.  89E2          mov     edx, esp--->把当前堆栈地址esp传给edx????好奇怪为什么这么做请看下一个函数
004201DD  |.  8B41 04       mov     eax, [ecx+4]--->窗口对象指针[ecx+4]给eax
004201E0  |.  FF11          call    [ecx]---->TWinControl.MainWndProc(var Message: TMessage);
004201E2  |.  83C4 0C       add     esp, 0C----->Object Pascal经典register调用约定
004201E5  |.  58            pop     eax---->返回值放到eax
004201E6  |.  5D            pop     ebp
004201E7  \.  C2 1000       retn    10

Controls.pas.6234:TWinControl.MainWndProc(var Message: TMessage);
TMessage = packed record
      Msg: Cardinal;
  case Integer of
      0: (
        WParam: Longint;
        LParam: Longint;
        Result: Longint);
      1: (
        WParamLo: Word;
        WParamHi: Word;
        LParamLo: Word;
        LParamHi: Word;
        ResultLo: Word;
        ResultHi: Word);
end;
这个函数中加了两个SEH异常处理句柄然后跳到各个窗体类重载的WndProc

00458BCC  /.  55            push    ebp
00458BCD  |.  8BEC          mov     ebp, esp
00458BCF  |.  51            push    ecx
00458BD0  |.  53            push    ebx
00458BD1  |.  56            push    esi
00458BD2  |.  57            push    edi
00458BD3  |.  8945 FC       mov     [ebp-4], eax---->TfrmMain对象地址,这里跟踪的是TfrmMain父窗口类对象
00458BD6  |.  33C0          xor     eax, eax
00458BD8  |.  55            push    ebp
00458BD9  |.  68 248C4500   push    00458C24------> 新SEH处理句柄
00458BDE  |.  64:FF30       push    dword ptr fs:[eax]
00458BE1  |.  64:8920       mov     fs:[eax], esp----->SEH构造完毕
00458BE4  |.  33C0          xor     eax, eax
00458BE6  |.  55            push    ebp
00458BE7  |.  68 138C4500   push    00458C13---->新SEH处理句柄
00458BEC  |.  64:FF30       push    dword ptr fs:[eax]
00458BEF  |.  64:8920       mov     fs:[eax], esp--->新SEH构造完毕
00458BF2  |.  8B5D FC       mov     ebx, [ebp-4]--->TfrmMain类对象地址给ebx
00458BF5  |.  8B43 3C       mov     eax, [ebx+3C]->又把TfrmMain类对象地址[epx+3C]传给eax,下边与很多这样相同的约定.
00458BF8  |.  FF53 38       call    [ebx+38]---->TCustomForm.WndProc(var Message: TMessage)
00458BFB  |.  33C0          xor     eax, eax
00458BFD  |.  5A            pop     edx
00458BFE  |.  59            pop     ecx
00458BFF  |.  59            pop     ecx
00458C00  |.  64:8910       mov     fs:[eax], edx------------>这就是上边函数传递过来的edx堆栈指针,原来是构造SEH
00458C03  |.  68 1A8C4500   push    00458C1A
00458C08  |>  E8 CFA8FFFF   call    004534DC--->Controls.pas.6239:FreeDeviceContexts
00458C0D  |.  E8 76E1FCFF   call    00426D88------>Controls.pas.6240:FreeMemoryContexts
00458C12  \.  C3            retn

TCustomForm.WndProc(var Message: TMessage)
没有可处理的消息,把消息分派给父类TWinControl.WndProc(var Message: TMessage);
eax传对象指针,edx传数据消息指针
0046EC44   > \8BD3          mov     edx, ebx----->Message参数
0046EC46   .  8B45 FC       mov     eax, [ebp-4]--->[ebp-4]把TfrmMain父窗口对象地址给eax往下传参数
0046EC49   .  E8 D6A1FEFF   call    00458E24-------->TWinControl.WndProc(var Message: TMessage);
0046EC4E   >  5F            pop     edi
0046EC4F   .  5E            pop     esi
0046EC50   .  5B            pop     ebx
0046EC51   .  8BE5          mov     esp, ebp
0046EC53   .  5D            pop     ebp
0046EC54   .  C3            retn

Controls.pas.6309:TWinControl.WndProc(var Message: TMessage);
没有可处理的消息,把消息分派给父类TControl.WndProc(TControl;TMessage;TMessage);   
eax传对象指针,edx传数据消息指针
00458F77  |> \8BD6          mov     edx, esi  ----->Message                          
00458F79  |.  8BC3          mov     eax, ebx--------->把TfrmMain父窗口对象指针给eax往下传参数
00458F7B  |.  E8 14CEFFFF   call    00455D94---->TControl.WndProc(TControl;TMessage;TMessage);     
00458F80  |>  83C4 10       add     esp, 10
00458F83  |.  5F            pop     edi
00458F84  |.  5E            pop     esi
00458F85  |.  5B            pop     ebx
00458F86  \.  C3            retn

TControl.WndProc(TControl;TMessage;TMessage);  
同样也没有可处理的消息,把消息再分派给父类TObject.Dispatch(var Message);
约定与前几个消息分派函数一样,都是eax传对象指针,edx传数据消息指针
00455F16  |> \8BD3          mov     edx, ebx-------->消息指针edx存放Message地址
00455F18  |.  8BC6          mov     eax, esi----->对象地址给eax
00455F1A  |.  8B08          mov     ecx, [eax]----->虚拟表首地址给ecx
00455F1C  |.  FF51 EC       call    [ecx-14]----->虚函数:TObject.Dispatch(var Message);
00455F1F  |>  5F            pop     edi
00455F20  |.  5E            pop     esi
00455F21  |.  5B            pop     ebx
00455F22  |.  8BE5          mov     esp, ebp
00455F24  |.  5D            pop     ebp

TObject.Dispatch(var Message);
TObject.Dispatch负责所有的事件方法(在delphi IDE 对象属性面版中的所有事件方法)的分派和动态方法的调用,它是对虚拟方法调用的一种内存资源优化.
00403BBC   .  56            push    esi
00403BBD   .  66:8B32       mov     si, [edx]----->从edx消息指针中取走消息给si
00403BC0   .  66:09F6       or      si, si
00403BC3   .  74 17         je      short 00403BDC---->si如果小于0就跳
00403BC5   .  66:81FE 00C0  cmp     si, 0C000
00403BCA   .  73 10         jnb     short 00403BDC---->si如果大于C00就跳默认消息处理方式
00403BCC   .  50            push    eax--------------------->保存对象指针
00403BCD   .  8B00          mov     eax, [eax]---->虚函数表给eax
00403BCF   .  E8 58FFFFFF   call    00403B2C-----> GetDynaMethod索引动态函数指针表
00403BD4   .  58            pop     eax--------------------->对象指针放到eax
00403BD5   .  74 05         je      short 00403BDC---->如果相等标志为1就说明没有相关事件处理方法就跳否则就不跳.
00403BD7   .  89F1          mov     ecx, esi
00403BD9   .  5E            pop     esi
00403BDA   .  FFE1          jmp     ecx--------------->找到事件句柄,跳到消息处理事件方法
00403BDC   >  5E            pop     esi
00403BDD   .  8B08          mov     ecx, [eax]---->对象虚拟表首地址给ecx
00403BDF   .  FF61 F0       jmp     [ecx-10]----------->TControl.DefaultHandler(var Message);
00403BE2   .  C3            retn

以上消息分派模式是VCL固定不变,变的是继承对象的多态转换...以上分派模式不光是针对WM_COMMAND消息,而且还是WM_Paint等标准Window分派模式,
,同样也是控件与父窗体通信的消息分派模式例如Win标准控件消息(WM_COMMAND)和公共控件消息(WM_NOTIFY).

由于偶触发了单击Buttou事件而发出Click通知给父窗口TfrmMain类的父窗口,TfrmMain类的父窗口响应WM_COMMAND消息,看看TfrmMain类父窗口是否重载处理了WM_COMMAND
事件句柄,当然这也不一定的.之所以分析这么仔细不是做作,因为Dede分析的RCDATA节中没有看到任何的ButtonClick事件名,想必有可能做了某些处理.

继续分析...

TCustomForm.WMCommand(var Message: TWMCommand)
注意这个动态事件函数是从父类TObject.Dispatch(var Message)分派来的,与前面的消息分派函数一样都是eax传对象指针,edx传数据消息指针
TWMCommand = packed record
    Msg: Cardinal;
    ItemID: Word;
    NotifyCode: Word;
    Ctl: HWND;
    Result: Longint;
end;
以次检测窗口句柄,和菜单对象
00470BC4   .  53            push    ebx                           
00470BC5   .  56            push    esi
00470BC6   .  8BF2          mov     esi, edx---->消息Message对象地址给esi.
00470BC8   .  8BD8          mov     ebx, eax-------->TfrmMain类对象指针由eax传给ebx
00470BCA   .  837E 08 00    cmp     dword ptr [esi+8], 0--->Message.Ctl
00470BCE   .  75 1C         jnz     short 00470BEC--->对象窗口句柄为0就跳
00470BD0   .  83BB 48020000>cmp     dword ptr [ebx+248], 0--->[ebx+248]定位窗口TMenu对象
00470BD7   .  74 13         je      short 00470BEC--->TMenu为空,跳.
00470BD9   .  66:8B56 04    mov     dx, [esi+4]--->Message.ItemID 菜单ID号给dx
00470BDD   .  8B83 48020000 mov     eax, [ebx+248]--->菜单TMenu类对象[ebx+248]传给eax
00470BE3   .  E8 387DFFFF   call    00468920---->Menu.DispatchCommand(ItemID),菜单处理此消息.
00470BE8   .  84C0          test    al, al--->返回boolean变量给al,al=1 成功,al=0失败
00470BEA   .  75 09         jnz     short 00470BF5--->判断al跳
00470BEC   >  8BD6          mov     edx, esi---->消息TMessage对象给edx
00470BEE   .  8BC3          mov     eax, ebx------->TfrmMain对象地址给eax对象
00470BF0   .  E8 0B8BFEFF   call    00459700---------------->TWinControl.WMCommand(var Message: TWMCommand);
00470BF5   >  5E            pop     esi
00470BF6   .  5B            pop     ebx
00470BF7   .  C3            retn

TWinControl.WMCommand(var Message: TWMCommand);

00459700  /$  53            push    ebx
00459701  |.  56            push    esi
00459702  |.  8BDA          mov     ebx, edx
00459704  |.  8BF0          mov     esi, eax
00459706  |.  8BD3          mov     edx, ebx---->消息Message地址ebx传给edx
00459708  |.  8B43 08       mov     eax, [ebx+8]--->[ebx+8]TMessage的句柄Ctl字段,给eax传参数约定
0045970B  |.  E8 80F9FFFF   call    00459090----->DoControlMsg(ControlHandle: HWnd; var Message): Boolean;
00459710  |.  84C0          test    al, al-------->返回boolean变量给al,al=1 成功,al=0失败
00459712  |.  75 09         jnz     short 0045971D--->判断al跳
00459714  |.  8BD3          mov     edx, ebx--->传Message给edx
00459716  |.  8BC6          mov     eax, esi--->传TfrmMain对象给eax
00459718  |.  8B08          mov     ecx, [eax]---->TfrmMain对象地址给ecx
0045971A  |.  FF51 F0       call    [ecx-10]------>还记得它!是哪个虚函数么?在TObject.Dispatch(var Message)自己找!
0045971D  |>  5E            pop     esi
0045971E  |.  5B            pop     ebx
0045971F  \.  C3            retn

从上边给出的VCL WM_Command消息分派路线看出,TfrmMain父窗体没有处理这个消息,只是把它继续传递给下一个消息通道函数

DoControlMsg(ControlHandle: HWnd; var Message): Boolean;

00459090  /$  53            push    ebx
00459091  |.  56            push    esi
00459092  |.  57            push    edi
00459093  |.  8BF2          mov     esi, edx---->edx=Message是传进来的参数把消息又给了esi
00459095  |.  33DB          xor     ebx, ebx--->注意FindControl函数的参数是由eax传进来的,eax在上一个函数中已经传进来了
00459097  |.  E8 A488FFFF   call    00451940--------->FindControl(Handle: HWnd): TWinControl;
0045909C  |.  8BF8          mov     edi, eax---->返回TWinControl类对象在eax中,传给edi.注意我们这里找到这个控件是预知的Tbutton类
0045909E  |.  85FF          test    edi, edi---->判断TWinControl类对象是否为空
004590A0  |.  74 1B         je      short 004590BD 空就跳
004590A2  |.  8B46 08       mov     eax, [esi+8]--->[esi]是TWMCommand对象Ctl域
004590A5  |.  50            push    eax                          
004590A6  |.  8B4E 04       mov     ecx, [esi+4]--->[esi]是TWMCommand对象中ItemID和NotifyCode域      
004590A9  |.  8B16          mov     edx, [esi]  --->[esi]是TWMCommand对象中Msg域              
004590AB  |.  81C2 00BC0000 add     edx, 0BC00 --->Window Notify Message加上BC00就是VCL FrameWork内部约定的控件通知消息               
004590B1  |.  8BC7          mov     eax, edi  --->把Tbutton类对象地址给eax,现在开始向Button控件发送通知代码了,父TfrmMain窗体没有处理Click事件通知句柄.                  
004590B3  |.  E8 10CCFFFF   call    00455CC8   ------->TControl.Perform(Msg + CN_BASE, WParam, LParam);CN_BASE=BC00              
004590B8  |.  8946 0C       mov     [esi+C], eax--->[esi+C]是TWMCmmand对象的Result域
004590BB  |.  B3 01         mov     bl, 1--->DoControlMsg函数返回成功传bl=1
004590BD  |>  8BC3          mov     eax, ebx--->清零
004590BF  |.  5F            pop     edi
004590C0  |.  5E            pop     esi
004590C1  |.  5B            pop     ebx
004590C2  \.  C3            retn

TControl.Perform(Msg + CN_BASE, WParam, LParam);Longint;

00455CC8  /$  55            push    ebp               
00455CC9  |.  8BEC          mov     ebp, esp
00455CCB  |.  83C4 F0       add     esp, -10
00455CCE  |.  53            push    ebx
00455CCF  |.  8955 F0       mov     [ebp-10], edx---->edx=Msg+CN_BASE,edx是上一函数传进来
00455CD2  |.  894D F4       mov     [ebp-C], ecx---->Wparam 同上
00455CD5  |.  8B55 08       mov     edx, [ebp+8]---------->[ebp+8]也是从那个函数中传进来的,是TWMCommand对象Ctl域
00455CD8  |.  8955 F8       mov     [ebp-8], edx---->TWMCommand对象Ctl域给[ebp-8]
00455CDB  |.  33D2          xor     edx, edx
00455CDD  |.  8955 FC       mov     [ebp-4], edx---->Message.Result=0
00455CE0  |.  85C0          test    eax, eax------------->eax也是上一个函数传进来的Tbutton对象指针
00455CE2  |.  74 0B         je      short 00455CEF 空就跳
00455CE4  |.  8D55 F0       lea     edx, [ebp-10]---->由上边构造好的消息类TMessage地址给edx指针,再传给下边的函数
00455CE7  |.  8BD8          mov     ebx, eax--->Tbutton对象指针eax,传给ebx
00455CE9  |.  8B43 3C       mov     eax, [ebx+3C]--->[ebx+3c]与eax同指向一个Tbutton对象
00455CEC  |.  FF53 38       call    [ebx+38]-->这个虚函数熟悉不?它在TWinControl.MainWndProc中出现过.这里出现了多态了应该调用TButton.WndProc(var Message: TMessage)
00455CEF  |>  8B45 FC       mov     eax, [ebp-4]--->返回值又送到eax
00455CF2  |.  5B            pop     ebx
00455CF3  |.  8BE5          mov     esp, ebp
00455CF5  |.  5D            pop     ebp
00455CF6  \.  C2 0400       retn    4

到这里应该调用TButtonControl.WndProc(var Message: TMessage)控件通知分派路线了,检查是否TButton类有处理Click通知事件处理器!上边已经说了VCL消息模式分派是固定的模式所以不用分析了
它应该与上边TCustomForm.WndProc(var Message: TMessage)分派路线是相同的,但是终点是不同的.这正是多态对象改变了终点一个TfrmMain对象一个TButton类.

简单给出与上边相同的分派路线:

TButtonControl.WndProc(var Message: TMessage)

0044DD34   > \8BD7          mov     edx, edi ---->Message参数传递给edx
0044DD36   .  8BC3          mov     eax, ebx-------->TButton对象指针给eax
0044DD38   .  E8 E7B00000   call    00458E24--->TWinControl.WndProc(var Message: TMessage);
0044DD3D   >  5F            pop     edi
0044DD3E   .  5E            pop     esi
0044DD3F   .  5B            pop     ebx

直接给出来,与上边调用地址都相同.
TWinControl.WndProc(var Message: TMessage)-->TControl.WndProc(TControl;TMessage;TMessage)----
->TObject.Dispatch(var Message)------->终点到这里分派路线转了,开始发送到TButton事件处理器中.还记得我们上边处理VCL通知Click代码是多少么:(WM_COMMAND+CN_BASE)

TButton.CNCommand(var Message: TWMCommand);
0044DF5C   .  56            push    esi
0044DF5D   .  66:837A 06 00 cmp     word ptr [edx+6], 0--->[edx+6]存放Message的NotifyCode,0数值代表BN_CLICKED宏.
0044DF62   .  75 09         jnz     short 0044DF6D --->不等就跳
0044DF64   .  66:BE EBFF    mov     si, 0FFEB----->注意传给si的数值应该是EB是个关键的动态方法索引值
0044DF68   .  E8 EF5BFBFF   call    00403B5C->procedure _CallDynaInst;这个函数根据上边si传进来的索引值寻找动态方法它内部调用实现与TObject.Dispatch(var Message)相同.
0044DF6D   >  5E            pop     esi
0044DF6E   .  C3            retn
从上边进入procedure _CallDynaInst而它内部又调用GetDynaMethod(vmt: TClass; selector: Smallint) : Pointer,这一点与TObject.Dispatch(var Message)内部雷同,
它们共同约定的寄存器:eax是对象地址,si是动态方法索引值,[eax+vmtDynamicTable]动态方法表,这比C++等其他面向对象多了一个动态函数表格,最终找到句柄然后jmp进去.
我们这里最终跳到了TButton.Click,由此看出EB索引的是TButton.Click,当然VCL内部动态方法索引值还有很多,仅供参考用,或许有变动.

TCustomEdit.CNCommand(var Message: TWMCommand); B3
BeginAutoDrag;ed

来到TButton.Click动态方法中...
0044DE58   .  53            push    ebx         
0044DE59   .  8BD8          mov     ebx, eax-------->TButton对象地址由eax传给ebx
0044DE5B   .  8BC3          mov     eax, ebx---->eax函数参数Self
0044DE5D   .  E8 02E60100   call    0046C464---->GetParentForm(Self),查找TButton父类窗体.
0044DE62   .  85C0          test    eax, eax--->空就跳
0044DE64   .  74 0C         je      short 0044DE72
0044DE66   .  8B93 14020000 mov     edx, [ebx+214]----->[ebx+214]是TButton对象的ModalResult字段结果,给edx保存
0044DE6C   .  8990 4C020000 mov     [eax+24C], edx->[eax+24C]是TButton父窗体TfrmMain的ModalResult,它的数值由上边传进来.这是处理模式对话框的时候,当Button_Click事件返回的时候是不是要把控件ID给父窗体,以便交互约定调用
0044DE72   >  8BC3          mov     eax, ebx---->TButton对象地址给eax,开始调用TBuuton的继承父类方法TControl.Click
0044DE74   .  E8 D7810000   call    00456050 ---->TControl.Click
0044DE79   .  5B            pop     ebx
0044DE7A   .  C3            retn

关键的TControl.Click
到这里真相大白了...
给个Delphi Form 资源定义的例子:
object Button2: TButton
    Left = 288
    Top = 8
    Width = 75
    Height = 25
    Caption = 'demo'
    TabOrder = 5
    OnClick = Button1Click------->触发的TButton事件名,并把指针给了OnClick做了代理,搜1下Button1Click可以定位到其事件入口
end
用Dede反编译没有找出触发Button按钮的事件地址,但是点击Button的确有注册Neg出现来...感觉里边有东东在作梗,终于在这里找出了眉毛来.
仔细看看TControl.Click里边调用了三个虚函数第一个是TAction类的TAction.OnExecute第二是TActionLink.Execute,第三个才是TButton.FOnClick(Self)
看上边的Delphi Form 资源 OnClick代理的是第三个函数的指针即是:TButton.FOnClick(Self)这也是通常我们需要的Button事件.而其它两个被疏忽掉的事件
才是真正本片的内幕,它可害苦了我,害的我苦苦遍历了这三个事件.纯熟于个人巧合,在简单的说一下,,当用Dede编译的时候没有发现Button的事件处理地址,
但是点击Button还出现Neg,这说明有事件响应了,(后来才知道在TfrmMain中有个TActionList控件,它内部的Action对象代理这个Button的事件处理),开始怀疑是反调试了反Dede,其实都是这TActino对象在作梗,
害的我掘出VCL一点点跟...本片莫非虚构的,若有雷同纯属巧合:=)

00456050  /$  53            push    ebx                 
00456051  |.  8BD8          mov     ebx, eax
00456053  |.  66:83BB 22010>cmp     word ptr [ebx+122],0--->先比较FOnClick事件地址高二位字节是否为0,如果为0说明没有TButton.FOnClick(Self)事件
0045605B  |.  74 2D         je      short 0045608A--->TButton.FOnClick(Self)空否,就跳.
0045605D  |.  8BC3          mov     eax, ebx---->TButton对象指针给eax
0045605F  |.  8B10          mov     edx, [eax]----->TSpeedButton虚函数表给edx
00456061  |.  FF52 3C       call    [edx+3C]---------------------->虚函数TAction.OnExecute,由eax返回TAction对象地址
00456064  |.  85C0          test    eax, eax---->空就跳
00456066  |.  74 22         je      short 0045608A
-----------------------------------------------------
00456096  |.  8BD3          mov     edx, ebx--->TSpeedButton对象地址给edx
00456098  |.  8B43 6C       mov     eax, [ebx+6C]---->取出TSpeedButton内包容对象SpeedButtonActionLink
0045609B  |.  8B08          mov     ecx, [eax]--->SpeedButtonActionLink对象虚表给ecx
0045609D  |.  FF51 18       call    [ecx+18]--------------------虚函数TActionLink.Execute(Self)这才是真正的事件处理
-----------------------------------------------------
004560A0  |.  EB 18         jmp     short 004560BA
004560A2  |>  66:83BB 22010>cmp     word ptr [ebx+122],>
004560AA  |.  74 0E         je      short 004560BA
004560AC  |.  8BD3          mov     edx, ebx
004560AE  |.  8B83 24010000 mov     eax, [ebx+124]
004560B4  |.  FF93 20010000 call    [ebx+120] --------------->TButton.FOnClick(Self)
004560BA  |>  5B            pop     ebx
004560BB  \.  C3            retn

终点

看Delphi Form 资源定义

object acApply: TAction
      Caption = #24212#29992#27492#30456#26694
      Hint = #24212#29992#27492#30456#26694
      ImageIndex = 2
      OnExecute = acApplyExecute--------------------->这才是TSpeedButton的响应的事件.兜了一个大圈圈出来.
end
从上边的分析TSpeedButton的OnClick没有被赋值,而是把TSpeedButton事件加入TActionLink中关联了一个Action对象,并且这个TAction事件名为acApplyExecute.
用Dede分析TActionLink也能得到目标地址

直接来到TAction. OnExecute事件处理,也就是TSpeedButton的事件处理,Neg窗体就在这个事件中出现了...

00563E30  /.  55            push    ebp
00563E31  |.  8BEC          mov     ebp, esp
00563E33  |.  83C4 C0       add     esp, -40---------->看下面提取来关键变量
00563E36  |.  53            push    ebx
00563E37  |.  56            push    esi
00563E38  |.  57            push    edi
00563E39  |.  33C9          xor     ecx, ecx
00563E3B  |.  894D C0       mov     [ebp-40], ecx
00563E3E  |.  894D C8       mov     [ebp-38], ecx
00563E41  |.  894D CC       mov     [ebp-34], ecx
00563E44  |.  894D D0       mov     [ebp-30], ecx
00563E47  |.  894D F4       mov     [ebp-C], ecx
00563E4A  |.  8BD8          mov     ebx, eax
00563E4C  |.  33C0          xor     eax, eax
提取局部变量
PChar_[ebp-40],PChar_[ebp-38],pChar_[ebp-34],PChar_[ebp-30],PChar_[ebp-C]
提取关键比较Boolean变量
Boolean_[ebp-20],Boolean_[ebp-21]

00563E4E  |.  55            push    ebp
00563E4F  |.  68 FC415600   push    005641FC ----> 新SEH处理句柄
00563E54  |.  64:FF30       push    dword ptr fs:[eax]
00563E57  |.  64:8920       mov     fs:[eax], esp ----->SEH构造完毕.
00563E5A  |.  C645 E0 00    mov     byte ptr [ebp-20], 0  -----> 初始化Boolean 变量[ebp-20]:=false
00563E5E  |.  C645 DF 00    mov     byte ptr [ebp-21], 0 -------->初始化Boolean 变量[ebp-20]:=flase
00563E62  |.  8B83 E0040000 mov     eax, [ebx+4E0]  ------> [ebx]为TfrmMain类对象的堆地址[ebx+4E0]ImageEnView_Main 对象
00563E68  |.  E8 170AFDFF   call    00534884 ----->检查 [ebx+4B8]_TImageEnIO
00563E6D  |.  8B80 64010000 mov     eax, [eax+164]   -------> 定位到TIOParamsVals类对象...
00563E73  |.  8378 0C 00    cmp     dword ptr [eax+C], 0  ---> [eax+c] 指向选择的文件名缓冲区指针
00563E77  |.  75 1A         jnz     short 00563E93  ---->  如果文件名缓冲空就提示请选择图片对话框
00563E79  |.  6A 00         push    0
00563E7B  |.  B9 0C425600   mov     ecx, 0056420C ---> "提示"
00563E80  |.  BA 14425600   mov     edx, 00564214-------->"请先选择图片"
00563E85  |.  A1 38695700   mov     eax, [576938]--------> TApplication对象指针
00563E8A  |.  8B00          mov     eax, [eax]------>TApplication虚表
00563E8C  |.  E8 B715F1FF   call    00475448------------>弹出请先选择图片对话框
00563E91  |.  EB 04         jmp     short 00563E97
00563E93  |>  C645 E0 01    mov     byte ptr [ebp-20], 1 ---->  Boolean 变量[ebp-20]:=true
00563E97  |>  8B83 60030000 mov     eax, [ebx+360]  ----> 定位到TComboBox类对象对象.
00563E9D  |.  8B10          mov     edx, [eax]   -----> TComboBox对象地址给edx,准备取用户选择CombBox的索引值
00563E9F  |.  FF92 CC000000 call    [edx+CC] ----->  TCustomCombo.GetItemIndex: Integer; SendMessage(Handle, CB_GETCURSEL, 0, 0);
00563EA5  |.  85C0          test    eax, eax     ----->  如果用户选择了大于1的Combox索引值,下边就提示注册
00563EA7  |.  7E 2B         jle     short 00563ED4   ----->  小于等于0就跳
00563EA9  |.  6A 24         push    24
00563EAB  |.  B9 24425600   mov     ecx, 00564224   ----> "提示注册信息购买正版..."
00563EB0  |.  BA 34425600   mov     edx, 00564234 ----------> "提示注册信息购买正版..."
00563EB5  |.  A1 38695700   mov     eax, [576938]
00563EBA  |.  8B00          mov     eax, [eax]
00563EBC  |.  E8 8715F1FF   call    00475448 ---------> Neg对话框此时就出现了.上边有两个Button控件,
00563EC1  |.  83F8 06       cmp     eax, 6   ---------> 比较两button ID号...
00563EC4  |.  75 12         jnz     short 00563ED8  -------> 不等于6就跳
00563EC6  |.  BA 28435600   mov     edx, 00564328 ------->ASCII "http://www.softreg.com.cn/...."
00563ECB  |.  8BC3          mov     eax, ebx
00563ECD  |.  E8 96060000   call    00564568 -------->函数调用Shell32.ShellExecuteA输出Soft's Web
00563ED2  |.  EB 04         jmp     short 00563ED8
00563ED4  |>  C645 DF 01    mov     byte ptr [ebp-21], 1 --------> Boolean 变量[ebp-20]:=true
00563ED8  |>  8A45 E0       mov     al, [ebp-20] -----------> 把Boolean 变量[ebp-20]给al
00563EDB  |.  2245 DF       and     al, [ebp-21]
00563EDE  |.  0F84 ED020000 je      005641D1 --------------> 这是关键jump 跳了game over与Boolean[ebp-20]、[ebp-21]有关系

在软件目录中包含frames目录, frames目录又有0-7个8个图片文件夹,0包含了以a,b,c开头的文件,1文件夹只包含了b开头图片文件,2-7文件夹是放的是c开头的文件.

以a开头的图片文件(比如a1002.jpg放在0文件夹内),jpg文件中是黑象素渲染的图片框
以b开头的图片文件(比如b1002.jpg放在1文件夹内),jpg文件中是黑象素渲染的图片外框,白象素渲染的图片内框
以c开头的图片文件(比如c1002.jpg放在2-7文件夹内),jpg文件中是彩色的渲染的图片外框,同样白象素渲染的图片内框
就形状颜色象素的复杂程度应该是a<b<c,所以这个软件只处理为数不多的简单的图片,其他复杂的b,c类型文件都没有处理也是放在1-7下边的文件几乎都不能处理.

注意一点:在0文件夹内图片都是通明背景,而其他1-7文件夹内图片全是白色背景估计需要用PhotoShop等图形处理软件处理1下估计才能用.我没有试猜测而已.
全局常量
const char_[0056439C]=a;
const char_[00564390]=b;
const char_[005643A8]=c;
------------------------
局部变量
PChar_[ebp-40]:存放以c开头的文件
PChar_[ebp-38]:存放以b开头的文件
pChar_[ebp-34]:存放以a开头的文件
PChar_[ebp-30]:存放以b开头的文件
PChar_[ebp-C]:存放文件名与路径全名
--------------------

判断是否以b开头的图片文件

00563F7B  |.  8D55 D0       lea     edx, [ebp-30]
00563F7E  |.  8B45 F4       mov     eax, [ebp-C] ----> [ebp-C]存放选择的图片路径和名称
00563F81  |.  E8 DE55EAFF   call    00409564      ----> SysUtils.ExtractFileName(AnsiString):AnsiString;提取文件名
00563F86  |.  8B55 D0       mov     edx, [ebp-30]  ---->  返回文件名放到PChar_[ebp-30]
00563F89  |.  B8 90435600   mov     eax, 00564390---->const char_[00564390]=b;
00563F8E  |.  E8 A50DEAFF   call    00404D38 ---->StrPos(const Str1, Str2: PChar): PChar;比较字符串
00563F93  |.  48            dec     eax
00563F94  |.  74 20         je      short 00563FB6---->关键跳

判断是否以a开头的图片文件
00563F96  |.  8D55 CC       lea     edx, [ebp-34]
00563F99  |.  8B45 F4       mov     eax, [ebp-C]         
00563F9C  |.  E8 C355EAFF   call    00409564 ---> SysUtils.ExtractFileName(AnsiString):AnsiString;
00563FA1  |.  8B55 CC       mov     edx, [ebp-34]   ---->  返回文件名放到PChar_[ebp-30]   
00563FA4  |.  B8 9C435600   mov     eax, 0056439C--->const char_[0056439C]=a;
00563FA9  |.  E8 8A0DEAFF   call    00404D38  ---->StrPos(const Str1, Str2: PChar): PChar;比较字符串
00563FAE  |.  85C0          test    eax, eax
00563FB0  |.  0F8E 2A010000 jle     005640E0---->关键跳

这个也是判断是否以b开头的图片文件
00563FDB  |.  8D55 C8       lea     edx, [ebp-38]
00563FDE  |.  8B45 F4       mov     eax, [ebp-C]
00563FE1  |.  E8 7E55EAFF   call    00409564               
00563FE6  |.  8B55 C8       mov     edx, [ebp-38]           
00563FE9  |.  B8 90435600   mov     eax, 00564390     
00563FEE  |.  E8 450DEAFF   call    00404D38
00563FF3  |.  48            dec     eax
00563FF4  |.  75 0D         jnz     short 00564003

判断是否以c开头的图片文件
005640E0  |> \8D55 C0       lea     edx, [ebp-40]
005640E3  |.  8B45 F4       mov     eax, [ebp-C]    --->AnsiString  
005640E6 >|.  E8 7954EAFF   call    00409564  ---->SysUtils.ExtractFileName(AnsiString):AnsiString;提取文件名
005640EB  |.  8B55 C0       mov     edx, [ebp-40]--->返回文件名到PChar_[ebp-40]
005640EE  |.  B8 A8435600   mov     eax, 005643A8
005640F3 >|.  E8 400CEAFF   call    00404D38  ――――->StrPos(const Str1, Str2: PChar): PChar;比较字符串
005640F8  |.  48            dec     eax
005640F9  |.  75 56         jnz     short 00564151------>关键跳

以上关键脉络全部分析完毕了,如果你在动鼠标指点一二就OVER的时候,不如仔细分析清晰那才受用,也不辜负偶写了这么多东东,在说里边写的bug多多还需要大家指点三四!

尤其动鼠标就over它,不如写段程序over它雅观...
C#补丁去除两层Neg补丁源代码如下:
using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;

namespace Pediy
{
    public class PediyForm: System.Windows.Forms.Form
    {
        private Button button2;
        private Label label1;
        private TextBox textBox1;
        private OpenFileDialog openFileDialog1;
        private LinkLabel linkLabel1;
        private Button button1;
        private ProgressBar progressBar1;
        private Timer timer1;
        private IContainer components;
   
        public PediyForm()
        {
           
            this.InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
            this.linkLabel1 = new System.Windows.Forms.LinkLabel();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(380, 12);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(69, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "Open(&P)";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // button2
            //
            this.button2.Location = new System.Drawing.Point(380, 42);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(69, 23);
            this.button2.TabIndex = 1;
            this.button2.Text = "OK(&O)";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            //
            // label1
            //
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(10, 17);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(35, 12);
            this.label1.TabIndex = 2;
            this.label1.Text = "File:";
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(57, 12);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(305, 21);
            this.textBox1.TabIndex = 4;
            //
            // openFileDialog1
            //
            this.openFileDialog1.FileName = "FrameMaster.exe";
            this.openFileDialog1.Filter = "Open File(*.exe)|*.exe";
            this.openFileDialog1.ReadOnlyChecked = true;
            this.openFileDialog1.RestoreDirectory = true;
            this.openFileDialog1.Title = "<Please select file path....>";
            //
            // linkLabel1
            //
            this.linkLabel1.AutoSize = true;
            this.linkLabel1.Location = new System.Drawing.Point(12, 51);
            this.linkLabel1.Name = "linkLabel1";
            this.linkLabel1.Size = new System.Drawing.Size(53, 12);
            this.linkLabel1.TabIndex = 6;
            this.linkLabel1.TabStop = true;
            this.linkLabel1.Text = "About(&A)";
            this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
            //
            // progressBar1
            //
            this.progressBar1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.progressBar1.Location = new System.Drawing.Point(0, 66);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(461, 23);
            this.progressBar1.TabIndex = 8;
            //
            // timer1
            //
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
            //
            // PediyForm
            //
            this.AcceptButton = this.button2;
            this.ClientSize = new System.Drawing.Size(461, 89);
            this.Controls.Add(this.progressBar1);
            this.Controls.Add(this.linkLabel1);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "PediyForm";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "www.pediy.com---qiweixue";
            this.TopMost = true;
            this.Load += new System.EventHandler(this.PediyForm_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            textBox1.Text = openFileDialog1.FileName;
            
            
         
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            MessageBox.Show("http:\\www.pediy.com---qiweixue");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (textBox1.Text != "")
            {
                byte[] pebuf1 = new Byte[] { 235, 43 };//去第一处Nag补丁
                byte[] pebuf2 = new Byte[] { 235, 31, 144, 114, 114 };//去第二处Nag补丁
                FileStream fs1 = new FileStream(textBox1.Text, FileMode.Open, FileAccess.ReadWrite);
                fs1.Seek(1454759, SeekOrigin.Begin);去第一处Nag 补丁 Offset
                fs1.Write(pebuf1, 0, pebuf1.Length);
                fs1.Seek(1470994, SeekOrigin.Begin);去第二处Nag补丁offset
                fs1.Write(pebuf2, 0, pebuf2.Length);
                fs1.Close();
                button2.Enabled = false;
                timer1.Enabled=true;
               
              
            }
            else
            {
                MessageBox.Show("No File's Name...");
            }
        }

        private void PediyForm_Load(object sender, EventArgs e)
        {
            progressBar1.Value = 0;
        }

        

        private void timer1_Tick(object sender, EventArgs e)
        {
            while (progressBar1.Value<100)
            {
                //progressBar1.Value = +10;好象不支持这中语法
                progressBar1.Value = progressBar1.Value + 10;
                progressBar1.Refresh();
            }
            timer1.Enabled = false;
            
        }
    }

    public class RunPediyForm
    {
        [STAThread]
        public static void Main()
        {
            Application.Run(new PediyForm());
        }
    }
}
感谢指点错误bug...

菩提本无树,明镜亦非台。本来无一物,何处惹尘埃
Copyright © 2000 - 2006 PEdiy.com All Rights Reserved.By KanXue Studio

[培训]《安卓高级研修班(网课)》月薪三万计划

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (8)
雪    币: 26415
活跃值: (18468)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2006-9-14 20:23
2
0
qiweixue 文章很精彩;)
帖图看这里方法来:http://bbs.pediy.com/showthread.php?s=&postid=142837
雪    币: 250
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
qiweixue 19 2006-9-14 20:28
3
0
最初由 kanxue 发布
qiweixue 文章很精彩;)
帖图看这里方法来:http://bbs.pediy.com/showthread.php?s=&postid=142837

ok了.可能网速慢了点点.
谢谢.老大...
雪    币: 10012
活跃值: (1649)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wzmooo 2006-9-14 21:28
4
0
文章精彩
雪    币: 158
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
modi 2006-9-14 23:20
5
0
很详细,收藏起来..
雪    币: 217
活跃值: (81)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ww990 1 2006-9-15 07:47
6
0
很好的教程,学习
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
KAN 6 2006-9-15 09:39
7
0
刚才看了一下这个软件,一大堆垃圾在里面
启动的时候还要你点击广告,破得好,不过不用钱也不用这东西
雪    币: 1969
活跃值: (46)
能力值: (RANK:550 )
在线值:
发帖
回帖
粉丝
hawking 12 2006-9-15 11:04
8
0
//progressBar1.Value = +10;好象不支持这中语法


progressBar1.Value += 10 ;

跟着学习。
雪    币: 250
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
qiweixue 19 2006-9-15 16:56
9
0
最初由 寒秋 发布
这是对的,确实那些图片必须再重新进行处理,否则无法实现透明的。

thx.
为了这个我分析好长时间.最后对比图片的大小,文件名,背景颜色,才感觉应该排斥程序算法的可能...
真“汗”...兜了一个大圈,
游客
登录 | 注册 方可回帖
返回