天天看點

重新設定指定Label内容

{  

    程式名   : 重新設定指定Label的内容

    說明     : 無

    作者     : JJony

    QQ       : 254706028

    部落格     : http://blog.csdn.net/jzj_jony

    空間     : http://jonychen,ys168.com

    測試環境 : WinXPSP2+Delphi7+MadCodeHook控件

}

程式說明:

    程式通過鈎子重新設定指定Label的顯示内容。

使用說明:

    運作主程式,輸入你要改變的Label所屬程序PID,點“注入dll”按鈕,

    然後輸入你要改的Label的原内容,再輸入你想改的内容,點“設定”按鈕,

    最小化目标程式再還原,你就可以看到效果了。

聲明:

    你可以任意使用或轉載程式,但請注明作者,謝謝。

    今天在大富翁看到一個文章,說是不知道怎麼重新設定其他程式中Label的内容,我起初拿來一看

感覺就是太容易了嘛!結果我錯了,因為Label沒有句柄,沒有句柄當然就無法設定了,經過我的研究

發現,Label并不是用CreateWindow建立的窗體,而是直接用TextOut或DrawText直接在窗體上畫出的,

這也是為什麼我在使用說明中說“最小化目标程式再還原”的原因了,因為這兩個API是在窗體重畫時

才調用的,你也可以用别的視窗把他擋住然後在移開,也會看到同樣效果的。知道了問題關鍵就好解決

了,既然是用TextOut或DrawText那我們就挂鈎這兩個API就好了,馬上動手。

//Hook.dll的源代碼

library Hook;

uses

  windows,

  SysUtils,

  Classes,

  madcodehook;//很強大的元件HookAPI用,可以從http://madshi.net下載下傳

{$R Ver.RES}

//記憶體共享結構

type

  PShareMem = ^TShareMem;

  TShareMem = record

    OldCaption: array[0..255] of char;//原始Label的Caption

    NewCaption: array[0..255] of char;//想要顯示的Caption

  end;

var

  PShare: PShareMem;

  MapHandle: THandle;

var //定義相關API,分ANSI和UNICODE版本

 TextOutANext:function(DC: HDC; X, Y: Integer; Str: PAnsiChar; Count: Integer): BOOL; stdcall;

 TextOutWNext:function(DC: HDC; X, Y: Integer; Str: PWideChar; Count: Integer): BOOL; stdcall;

 DrawTextANext:function(hDC: HDC; lpString: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;

 DrawTextWNext:function(hDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;

function TextOutACallBack(DC: HDC; X, Y: Integer; Str: PAnsiChar; Count: Integer): BOOL; stdcall;

begin

   if strpas(str)=strpas(PShare^.OldCaption) then

    begin

     result:=TextOutANext(DC, X, Y, PShare^.NewCaption, sizeof(PShare^.NewCaption));

    end

   else

    result:=TextOutANext(DC, X, Y, str, Count);

end;

function TextOutWCallBack(DC: HDC; X, Y: Integer; Str: PWideChar; Count: Integer): BOOL; stdcall;

var

 np:widestring;

begin

   np:=strpas(PShare^.NewCaption);

   if widechartostring(str)=strpas(PShare^.OldCaption) then

    result:=TextOutWNext(DC, X, Y,Pwidechar(np), length(np))

   else

    result:=TextOutWNext(DC, X, Y,str, Count);

end;

function DrawTextACallBack(hDC: HDC; lpString: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer;

stdcall;

begin

if strpas(lpString)=strpas(PShare^.OldCaption) then

   result:=DrawTextANext(hDC, PShare^.NewCaption, sizeof(PShare^.NewCaption), lpRect, uFormat)

else

   result:=DrawTextANext(hDC, lpString, ncount, lpRect, uFormat)

end;

function DrawTextWCallBack(hDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer;

stdcall;

var

 np:widestring;

begin

   np:=strpas(PShare^.NewCaption);

   if widechartostring( lpString)=strpas(PShare^.OldCaption) then

   result:=DrawTextWNext(hDC, pwidechar(np), length(np), lpRect, uFormat)

   else

    result:=DrawTextWNext(hDC,lpString, nCount, lpRect, uFormat)

end;

begin

  MapHandle := OpenFileMapping(FILE_MAP_WRITE, //打開記憶體映射為了與主程式共享資料

    False,

    pchar('MyShareMem'));

  PShare := PShareMem(MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0));

  if PShare = nil then

  begin

    CloseHandle(MapHandle);

    exit;

  end;

FillChar(PShare^, SizeOf(TShareMem), 0);

//以下為Hook相關API,分ASNI和UNICODE版本

HookAPI('Gdi32.dll','TextOutA',@TextOutACallBack,@TextOutANext);

HookAPI('Gdi32.dll','TextOutW',@TextOutWCallBack,@TextOutWNext);

HookAPI('User32.dll','DrawTextA',@DrawTextACallBack,@DrawTextANext);

HookAPI('User32.dll','DrawTextW',@DrawTextWCallBack,@DrawTextWNext);

end.

以下是主程式testu.pas的代碼:

{

  testu.frm包含控件有3個button,4個Label,3個Edit.

}

unit testu;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls,madcodehook;

type

  PShareMem = ^TShareMem;

  TShareMem = record

    OldCaption: array[0..255] of char;

    NewCaption: array[0..255] of char;

  end;

type

  TForm1 = class(TForm)

    Label1: TLabel;

    Label2: TLabel;

    Button2: TButton;

    Button3: TButton;

    Edit1: TEdit;

    Button4: TButton;

    Edit2: TEdit;

    Edit3: TEdit;

    Label3: TLabel;

    Label4: TLabel;

    procedure Button2Click(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure Button3Click(Sender: TObject);

    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);

    procedure Button4Click(Sender: TObject);

    procedure FormShow(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

var

  Form1: TForm1;

  HookFileA:pchar;

  HookFileW:pwidechar;

  PShare: PShareMem;

  isInject:boolean;

  h:thandle;

implementation

{$R *.dfm}

var

  HMapping: THandle;

  HMapMutex: THandle;

const

  MAPFILESIZE = 1000;

  REQUEST_TIMEOUT = 1000;

procedure OpenMap;

begin

  HMapping := CreateFileMapping(

    $FFFFFFFF,

    nil,

    PAGE_READWRITE,

    0,

    SizeOf(TShareMem),

   pchar('MyShareMem')

    );

  if (hMapping = 0) then

  begin

    ShowMessage('不能建立記憶體映射檔案');

    Application.Terminate;

    exit;

  end;

   {将檔案資料映射到程序的位址空間}

   {當建立了一個檔案映射對象之後,仍然必須讓系統為檔案的資料保留

    一個位址空間區域,并将檔案的資料作為映射到該區域的實體存儲器進行送出。

    }

  PShare := PShareMem(MapViewOfFile(HMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));

  if PShare = nil then

  begin

    CloseHandle(HMapping);

    ShowMessage('Can''t View Memory Map');

    Application.Terminate;

    exit;

  end;

end;

procedure CloseMap;

begin

  if PShare <> nil then

    UnMapViewOfFile(PShare);

  if HMapping <> 0 then

    CloseHandle(HMapping);

end;

function LockMap: Boolean;

begin

  Result := true;

  HMapMutex := CreateMutex(nil, false,

    pchar('MY MUTEX NAME GOES HERE'));

  if HMapMutex = 0 then

  begin

    ShowMessage('不能建立互斥對象');

    Result := false;

  end else begin

    if WaitForSingleObject(HMapMutex, REQUEST_TIMEOUT)

      = WAIT_FAILED then

    begin

      ShowMessage('不能對互斥對象加鎖!');

      Result := false;

    end

  end

end;

procedure UnlockMap;

begin

  ReleaseMutex(HMapMutex);

  CloseHandle(HMapMutex);

end;

function EnableDebugPrivilege(PName:pchar):Boolean;

var

 TokenHandle:THandle;

 DebugNameValue:TLargeInteger;

 Privileges:TOKEN_PRIVILEGES;

 RetLen:Cardinal;

begin

 Result:=False;

 if not OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,TokenHandle) then Exit;

 if not LookupPrivilegeValue(nil,PName,DebugNameValue) then

 begin

  CloseHandle(TokenHandle);

  Exit;

 end;

 Privileges.PrivilegeCount:=1;

 Privileges.Privileges[0].Luid:=DebugNameValue;

 Privileges.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;

 Result:=AdjustTokenPrivileges(TokenHandle,False,Privileges,SizeOf(Privileges),nil,RetLen);

 CloseHandle(TokenHandle);

end;

procedure TForm1.Button2Click(Sender: TObject);

var

b1:boolean;

pid:integer;

begin

EnableDebugPrivilege('SeDebugPrivilege');

PID:=strtoint(edit3.Text);

h:=openprocess(PROCESS_ALL_ACCESS,false,PID);

if GetVersion and $80000000 <> 0 then  begin

               b1:= InjectLibraryA(h ,HookFileA)

        end else

               b1 := InjectLibraryW(h,HookFileW);

        if not b1 then

          MessageBox(0, '隻有 administrator權限才可以注入dlls',

                     '提示...', MB_ICONINFORMATION);

 if b1 then

  isInject:=true

 else

  isInject:=false;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

 HookFileA:='hook.dll';

  HookFileW:='hook.dll';

  OpenMap;

  LockMap;

  isInject:=false;

end;

procedure TForm1.Button3Click(Sender: TObject);

var

b1:boolean;

begin

 if GetVersion and $80000000 <> 0 then begin

                 b1 := UninjectLibraryA(h, HookFileA)

          end else

                 b1 := UninjectLibraryW(h, HookFileW);

          if (not b1) and (GetLastError = ERROR_ACCESS_DENIED) then

            MessageBox(0, '隻有administrator權限才能解除安裝Dll',

                       '提示...', MB_ICONINFORMATION);

 if b1 then

  isInject:=false

 else

  isInject:=true;

end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

var

b1:boolean;

begin

 if GetVersion and $80000000 <> 0 then begin

                 b1 := UninjectLibraryA(CURRENT_SESSION or CURRENT_PROCESS, HookFileA)

          end else

                 b1 := UninjectLibraryW(CURRENT_SESSION or CURRENT_PROCESS, HookFileW);

          if (not b1) and (GetLastError = ERROR_ACCESS_DENIED) then

            MessageBox(0, '隻有administrator權限才能解除安裝Dll',

                       '提示...', MB_ICONINFORMATION);

 UnlockMap;

 CloseMap;

end;

procedure TForm1.Button4Click(Sender: TObject);

var

  str1: pchar;

  str2: pchar;

begin

if not isInject then

 begin

  MessageBoxA(handle,'請先注入Dll到指定程序','提示',mb_ok);

  exit;

 end;

  str1 := pchar(edit1.Text);

  str2 := pchar(edit2.Text);

  CopyMemory(@(pShare^.OldCaption), Str1, Length(str1));

  CopyMemory(@(pShare^.NewCaption), Str2, Length(str2));

end;

procedure TForm1.FormShow(Sender: TObject);

begin

  Label4.Caption:='作者: JJony '#13#10'QQ: 254706028'#13#10+

                'Blog: http://blog.csdn.net/jzj_jony'#13#10+

                '空間: http://jonychen.ys168.com';

end;

end.

繼續閱讀