HanDs
管理员

[Delphi文章] QQ控件Spy句柄的实现方案 





学习中请遵循国家相关法律法规,黑客不作恶。没有网络安全就没有国家安全

本站需要登陆后才能查看

QQ2009版本的界面,和以前的版本有个显著的不同,就是无法通过Spy++抓到界面上某些元素的句柄了,对于这个技术的实现方案,相信好多人都有一些揣度,实现方法怎样,有人说是应用的DirectUI技术,也有人说是用反Hook,等等一些列的说道!在这,我也说说我的一点看法!我说的一种方法不属于以上的任何一种方法。至于如何,且听我慢慢道来!此思路,来源于一个偶然,在聊天窗口失去焦点与获得焦点时的一个偶然。

  聊天的时候,我们要输入信息,首先要让窗口获得焦点!然后输入框也要获得焦点,才能输入。那么我们可以想象一下,在Delphi中什么情况下的控件时没有句柄的,用Delphi的同僚都知道,TGraphicControl继承下来的控件都没有焦点,既然如此,那么咱们就可以有一个混淆视听的方式,写的控件都从TGraphicControl继承来写,那么肯定就没句柄的,这个Button,ScrollBar等不必体现输入的,我相信没有争议,那么我实现一个编辑框Edit,也从TGraphicControl继承来写!这样,别人不就无法找到这个编辑框的句柄了么?嘿嘿,此时一定会有很多人大惑不解,那么输入呢,从TGraphicControl继承的Edit,如何实现输入?难道全部自己模拟消息来实现输入?当然不是,如果这样,那将让工作量增大N 倍而不尽然能成功!重点就在这里,这是,我们可以在内部放一个TEdit,本Edit是活动的,在鼠标点下,或者模拟获得焦点的时候,我们将内置的 Edit的Parent设置成我们从TGraphicControl继承的Edit的Parent,也就是Edt.parent := self.parent;并且设置内置Edit的区域,然后在内置Edit.setFocus,这样就能够输入了,然后当这个内置Edit失去焦点的时候,我们将内置Edit的显示文字抓成图片,之后,将内置edit的parent设置为nil,然后在在这个GrphicControl的Edit的对应区域绘制上我们抓取出来的那个真实Edit的图片,这样,内置的Edit已经不再本界面上了,从而当外部Spy++在Spy的时候,就无法找到那个 Edit进而进行信息的获取等操作了!这便是我的实现思路。那么就可以想象,QQ聊天窗口在我们要输入信息的时候,获得焦点了,RichEdit的 parent为QQ聊天窗口,然后我们输入信息,当信息输入完成,我们离开了之后,将内部的RichEdit的parent设置为nil,然后再将 RichEdit的画面获得到绘制到原来的位置上去。这样 ,我们就无法Spy到RichEdit的句柄了。

下面给出俺的模拟代码:

这个代码中的DxEdit就是了,大家可用Spy查一下,肯定是查不到句柄的说!呵呵!

不过这个只是实现了一个简单的模拟而已,如果要完全达到QQ的那个效果,还有许多其他工作要做,这里仅提供一个实现的思路参考

unit Unit4;  
interface 
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  Dialogs, StdCtrls;  
type  
  TDxEdit = class(TGraphicControl)  
  private 
    edt: TEdit;  
    edtbndrect: TRect;  
    bmp: TBitmap;  
    OldEdtwndproc: TWndMethod;  
  protected 
    procedure Paint;override;  
    procedure HookedtWndProc(var msg: TMessage);  
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;  
      X, Y: Integer); override;  
    procedure SetParent(AParent: TWinControl);override;  
  public 
    constructor Create(AOwner: TComponent);  
    procedure BeforeDestruction;override;  
    destructor Destroy;override;  
  end;  
  TForm4 = class(TForm)  
    procedure FormCreate(Sender: TObject);  
  private 
    { Private declarations }  
  public 
    { Public declarations }  
    medt,edt2: TDxEdit;  
  end;  
var  
  Form4: TForm4;  
implementation  
var  
  edt: TEdit;  
type  
  TWControl = class(TWinControl) end;  
procedure GetControlBitmap(Control: TWinControl;bmp: TBitmap);  
var  
  ControlWidth,ControlHeight: integer;  
  ControlDc,hCaptureDC: HDC;  
begin  
  ControlWidth := Control.ClientWidth;  
  ControlHeight := Control.ClientHeight;  
  ControlDc := GetDC(Control.Handle);  
  hCaptureDC := CreateCompatibleDC(ControlDc);  
  bmp.Handle :=CreateCompatibleBitmap(ControlDc,ControlWidth,ControlHeight);  
  SelectObject(hCaptureDC,bmp.Handle);  
  BitBlt(hCaptureDC,0,0,ControlWidth,ControlHeight,ControlDc,0,0,SRCCOPY);  
  ReleaseDC(GetDesktopWindow,ControlDc);  
  DeleteDC(hCaptureDC);  
end;  
{$R *.dfm}  
procedure TForm4.FormCreate(Sender: TObject);  
begin  
  medt := TDxEdit.Create(self);  
  medt.Parent := self;  
  edt2 := TDxEdit.Create(self);  
  edt2.Parent := self;  
  edt2.Left := 150;  
  edt2.Top := 10;  
end;  
{ TDxEdit }  
procedure TDxEdit.BeforeDestruction;  
begin  
  inherited;  
end;  
constructor TDxEdit.Create(AOwner: TComponent);  
begin  
  inherited;  
  edtbndrect := Rect(0,0,0,0);  
  bmp := TBitmap.Create;  
  Cursor := crIBeam;  
  Height := 21;  
  Width := 121;  
end;  
destructor TDxEdit.Destroy;  
begin  
  inherited;  
  bmp.Free;  
end;  
procedure TDxEdit.HookedtWndProc(var msg: TMessage);  
begin  
  OldEdtwndproc(msg);  
  case msg.Msg of  
  WM_KILLFOCUS:  
    begin  
      GetControlBitmap(edt,bmp);  
      //bmp.SaveToFile('C:\1.bmp');  
      edtbndrect.Left := 2;  
      edtbndrect.Top := (Height - edt.Height) div 2;  
      edtbndrect.Right := edtbndrect.Left + edt.Width;  
      edtbndrect.Bottom := edtbndrect.Top + edt.Height;  
      edt.Parent := nil;  
    end;  
  end;  
end;  
procedure TDxEdit.MouseDown(Button: TMouseButton; Shift: TShiftState;  
      X, Y: Integer);  
begin  
  inherited;  
  if Button = mbLeft then  
  begin  
    if edt = nil then  
    begin  
      edt := TEdit.Create(nil);  
      OldEdtwndproc := edt.WindowProc;  
      edt.WindowProc := HookedtWndProc;  
      edt.BorderStyle := bsNone;  
      edt.Height := 14;  
    end;  
    edt.Left := Left + 2;  
    edt.Top := top +  (Height - edt.Height) div 2;  
    edt.Width := Width - 4;  
    edt.Parent := self.Parent;  
    edt.SetFocus;  
    //edt.SelLength := 0;  
  end;  
end;  
procedure TDxEdit.Paint;  
begin  
  Canvas.Brush.Color := clWhite;  
  Canvas.FillRect(ClientRect);  
  Canvas.Brush.Color := clBlue;  
  Canvas.FrameRect(ClientRect);  
  //然后开始绘制文字  
  if (edt <> nil) and (edt.Parent = nil) then  
  begin  
    //bmp := TBitmap.Create;  
    //GetControlBitmap(edt);  
    if edtbndrect.Left <> edtbndrect.Right then  
    Canvas.CopyRect(edtbndrect,bmp.Canvas,bmp.Canvas.ClipRect);  
  end;  
end;  
 
procedure TDxEdit.SetParent(AParent: TWinControl);  
begin  
  inherited;  
end;  
initialization  
finalization  
end.

 


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
QQ 控件 Spy 句柄的实现方案
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组
快速回复