關於DELPHI中的API HOOK 1

2021-04-02 21:29:57 字數 4555 閱讀 3102

angliu (aixihuan_at_21cn.com)

關於api hook,我相信大家比我知道的多,大家應該記得在dos中程式設計,經常都要用擷取中斷向量的技術,這樣我們可以設定新的中斷服務程式,因此當乙個新的程式呼叫這個中斷向量的時候,它就會先呼叫我們自己設定的中斷程式,然後呼叫原來的中斷程式,這樣我們就能夠非凡的控制權,許多的病毒程式都是這樣的。在windows中,也可以採用類似的技術,當系統呼叫某個api函式時,就會先進入我們設定的函式,其工作原理和dos的中斷差不多,這種技術也有很多的名稱,像"陷阱技術","重入技術"。可我認為api hook好一些吧!這些技術再很多的軟體中也有應用的,像"金山詞霸"就是的了。呵呵~~~不是故意拿金山公司的產品說的啊!這個軟體就運用了這個技術,像當你把滑鼠指向乙個單詞,這時就會彈出乙個視窗翻譯單詞了。這也就是用了鉤子的原理。說了這麼多廢話,說正題了,要使自己的**正確執行,函式必須和要改寫的api函式有相同形式的引數。我在程式中,攔截了messageboxa和messageboxw這兩個函式。如:

fuction myboxa(hwn:hwnd;iptext:pcter;ipcapion:pchar;utype:cardinal):interger;stdcall;

fuction myboxw(hwn:hwnd;iptext:pchter;ipcapiom:pchar;utype:cardinal):interger;stdcall;

這裡我使用了stdcall關鍵字,這個我上面已經說了,函式的形參的進出棧順序要和攔截的函式一樣,在win32中並不允許直接修改記憶體中的**,但可以呼叫乙個函式來運用:writeproces**emory。當然有的人問這個不能改寫,可我用著很好!也許用它會有些bug,可我不知道,知道的人請給我來信。

在pe檔案中,當你呼叫另一模組中的函式列如:user32.dll中的getmessage),編譯出來的call指令並不會吧控制權直接傳給dll裡的函式,而是傳給了jmp dword ptr [*********]指令,[*********x]裡有該函式的真正位址(進入點),要得到api函式,可以這樣寫:address:=@messageboxa。像上面說的那樣,這裡只得到了乙個跳轉的指令,後面的messageboxa才是**開始的地方。下面的程式我自己定義了乙個結構(使用了packed關鍵字)

tlmportcode =packed record

jumplnstruction: word; //是$25ff,jump指令

addressofpointer tofunction: ppointer;//真正開始的位址

end;

plmportcode = ^tlportcode;

function truefunctionaddress(func: pointer): pointer;

varcode: plmportcode;

begin

result:= func;

if func = nil then exit;

trycode := func;

if (code.jumplnstruction = $25ff) then begin

result := code.addressofpointer tofunction^;

end;

except

result :=nil;

end;

end;

procedure permutefunction(oldfunc:ppointer; newfunc:poiner);

varwritten: dword;

begin

writeproces**emory(getcurrentprocess,oldfunc,@newfunc,4,written);

end;

新建乙個api hook,把上面的儲存就可以了。

unit mess

inte***ce

uses

windows,message,sysutils,classes,apihook;

procedure api_hookup;

procedure un_api_hook;

varfuncmessageboxa,funcmessagew;plmportcode;

implementation

type

tmessagea = function(hwn: hwnd; iptext: pchar; ipcapion:pchar; utype: cardinal): interger;stdcall;

tmessagew = function(hwn: hwnd; iptext: pchar; ipcapion:pchar; utype: cardinal): interger;stdcall;

varoldmessageboxa: tmessagea;

oldmessageboxw: tmessagew;

functionj myboxa (hwn: hwnd; iptext: pchar; ipcapion:pchar; utype: cardinal): interger;stdcall;

begin

result :=oldmessageboxa(hwn,'succes hook a!', ipcapion,utype);

end;

functionj myboxw (hwn: hwnd; iptext: pchar; ipcapion:pchar; utype: cardinal): interger;stdcall;

result :=oldmessageboxw(hwn,'成功掛上w!'ipcapion,utype);

end;

procedure api_hookup;

begin

if @oldmessageboxa = nil then

@olemessageboxa = truefunctionaddress(@messageboxa);

if @oldmessageboxw = nil then

@olemessageboxw = truefunctionaddress(@messageboxw);

permutefunction(funcmessageboxa,addressofpointertofunction,@myboxa);

permutefunction(funcmessageboxw,addressofpointertofunction,@myboxw);

end;

procedure un_api_hook;

begin

if @oldmessageboxa <> nil then begin

permutefunction(funcmessageboxa,addressofpointer tofunction,@oldmessageboxa);

permutefunction(funcmessageboxw,addressofpointer tofunction,@oldmessageboxw);

end;

end;

initialization

fundmessageboxa := @meesageboxa;

fundmessageboxw := @meesageboxw;

end;

在主窗體中新增三按鈕,新增onclick事件的**,如下:

procedure tform1.button1click( sender: tobject);

begin

api_hook;

end;

procedure tform1.button3click( sender: tobject);

un_api_hook;

end;

procedure tform1.button2click( sender: tobject);

begin

messageboxa(form1.handle,'no hook up a','messageboxa',mb_ok);

messageboxw(form1.handle,'no hook up w','messageboxw',mb_ok);

messagebox (form1.handle,'no hook up box','messagebox',mb_ok);

end;

先執行try1,再執行testtry。看看結果,apihook僅僅再try1中掛上了,並沒有在所以的系統程序中掛上,這個時想想滑鼠鉤子的時候做法,用setwindowshookex掛上滑鼠鉤子,當其它的程序發出滑鼠訊息的時候,我們的程式就會攔截到並做出響應,還可以用uphooklwindowshookex解除滑鼠鉤子,這樣,我們就知道了,應該為我們的函式掛上鉤子,當然你要知道滑鼠鉤子有各種的訊息響應其它程序。有兩種方法,一種是模仿setwindowshookex,編制自己的mysetwindowshookex。還有一種也是windows所提供的另乙個函式:getmsgproc。這個函式在delphi幫助裡說的很清楚得了。我們的目的也就是在動態鏈結庫中掛上wh_getmessage訊息鉤子。當其它程序發出這個函式的時候,就會載入我們的動態鏈結庫,如果我們的dll載入時自動執行api_hook,就可以讓其它程序掛上我們的api hook了。

第二個程式我會在下次寫出來。以上的程式可能有些不足,大家可以來信指點。([email protected])

關於Delphi中的密碼框

平時由於比較少寫delphi程式,所以delphi的那些日常vcl控制項也不是很熟悉,所以把自己一些摸索的小東西就寫下來吧。在平時編寫web程式的時候,經常遇到的就是登入畫面,最典型的就是兩個輸入框,乙個是使用者名稱,乙個是密碼。在web程式的時候,這個很好寫,就是把使用者名稱的那個框type設定為...

關於 delphi中with在Python中的討論

下面這段是我昨天在python乙個討論群裡對delphi中with在python中的討論,希望能對大家有所啟發,同時我也將這個討論記錄下來,有時間多體會體會。不要小看這段,最後 seewind 說的話很經典。江南 23 46 27 其實 我覺得是想找 python中類似 delphi 的 with ...

關於DELPHI的布局

以下文章載自 巴蠻子的破新茅屋 windows程式設計的習慣是直接指定控制項的座標和大小,而unix下面的習慣是在容器裡面堆放,用不同的layout manager來控制布局 j a,wx等也是這種思想 這也是為什麼windows程式的對話方塊一般都不讓改變大小 因為這意味著要自己寫很多 逐步調整子...