當前位置:編程學習大全網 - 源碼下載 - 鉤子程序源代碼

鉤子程序源代碼

簡單來說,壹個完整的選詞過程可以概括為以下幾個步驟:

1.安裝鼠標鉤子,通過鉤子函數獲取鼠標消息。

使用的api函數:setwindowshookex

2.獲取鼠標的當前位置,向鼠標下的窗口發送重畫消息,讓其調用系統函數重畫窗口。

使用的Api函數:windowfrompoint,screentoclient,invalidaterect。

3.攔截對系統函數的調用,獲取參數,也就是我們要取的字。

對於大多數windows應用程序來說,如果要檢索單詞,需要截取“gdi32.dll”中的“textouta”函數。

讓我們編寫壹個類似於textouta函數的Mytextouta函數,比如:

bool winapi mytextouta(hdc hdc,int nxstart,int nystart,lpcstr lpszstring,int cbstring)

{

//這裏執行輸出lpszstring的處理。

//然後調用正版textouta函數。

}

把這個函數放到安裝了鉤子的動態鏈接庫中,然後調用我們最後給出的hookimportfunction函數來攔截進程對textouta函數的調用,跳轉到我們的mytextouta函數來捕獲輸出字符串。hookimportfunction的用法:

hookfuncdesc hd

proc porigfuns

hd.szfunc = " textouta

HD . pproc =(proc)mytextouta;

hookinportfunction(afxgetinstancehandle()," gdi32.dll ",& amp高清、porigfuns);

下面給出了hookimportfunction的源代碼。相信詳細的評論不會讓妳覺得很難理解攔截是如何實現的。好了,我們走吧:

//////////////////////begin/begin/begin/begin/begin/begin/begin/begin/begin/begin/begin/begin/begin/begin

# include & ltcrtdbg.h & gt

//這裏定義了壹個生成指針的宏。

#define makeptr(cast,ptr,addvalue)(cast)((dword)(ptr)+(dword)(addvalue))

//定義hookfuncdesc結構,我們將它用作傳遞給hookimportfunction函數的參數。

typedef struct tag_hookfuncdesc

{

lpcstr szfunc//要掛鉤的函數的名稱。

proc pproc//要沖進去的程序。

} hookfuncdesc,* lphookfuncdesc

//這個函數監視當前系統是否是windownt。

bool nots();

//這個函數獲取h module——我們需要攔截的函數所在的dll模塊的導入描述符。

pimage _ import _ descriptor getnamedimportdescriptor(hmodule hmodule,lpcstr sziportmodule);

//我們的主要功能

bool hook import function(hmodule hmodule,lpcstr szimportmodule,

lphookfuncdesc pahookfunc,proc* paorigfuncs)

{

//////////////////以下代碼檢測參數///////////////////////////////////////////////。

_ assert(szimportmodule);

_assert(!isbadreadptr(pahookfunc,sizeof(hook func desc)));

#ifdef _debug

if (paorigfuncs) _assert(!isbadwriteptr(paorigfuncs,sizeof(proc)));

_ assert(pahook func . SZ func);

_assert(*pahookfunc.szfunc!= \0 );

_assert(!isbadcodeptr(pahook func . pproc));

#endif

if((szimportmodule = = null)| |(isbadreadptr(pahook func,sizeof(hookfuncdesc))))

{

_ assert(false);

setlasterrorex(error _ invalid _ parameter,SLE _ error);

返回false

}

//////////////////////////////////////////////////////////////////////////////

//監控當前模塊是否在2gb以上的虛擬內存空間。

//這部分地址內存屬於win32進程* * *。

如果(!不是()& amp& amp((dword)hmodule & gt;= 0x80000000))

{

_ assert(false);

setlasterrorex(error _ invalid _ handle,SLE _ error);

返回false

}

//清除

if(paorigfuncs)memset(paorigfuncs,null,sizeof(proc));

//調用getnamedimportdescriptor()函數來獲取h module——也就是說,我們需要

//導入被截獲函數所在的dll模塊的描述符。

pimage _ import _ descriptor pimportdesc = getnamedimportdescriptor(hm odule,sziportmodule);

if (pimportdesc == null)

返回false//如果為空,則該模塊尚未被當前進程引入。

//從dll模塊中獲取原thunk信息,因為pimportdesc->;firstthunk數組中的原始信息已被

//當應用程序引入dll時,它覆蓋了所有的導入信息,所以我們需要獲取pimportdesc->;originalfirstthunk

//訪問信息的指針,如引入函數的名稱。

pimage _ thunk _ data porigthunk = make ptr(pimage _ thunk _ data,hmodule,

pimportdesc-& gt;originalfirsthunk);

//From pimportdesc-& gt;Firstthunk獲得壹個指向image_thunk_data數組的指針,因為在引入dll時已經填充了該數組。

//所有傳入的信息,所以真正的攔截其實是在這裏進行的。

pimage _ thunk _ data prealthunk = make ptr(pimage _ thunk _ data,hmodule,pimportdesc-& gt;first thunk);

//枚舉image_thunk_data數組,找到我們需要截取的函數。這是最關鍵的部分!

while(porigthunk-& gt;u1.function)

{

//只查找那些由函數名而不是序列號引入的函數。

if (image_ordinal_flag!=(porigthunk-& gt;u1。圖像序號標誌))

{

//獲取引入函數的函數名。

pimage _ import _ by _ name pby name = make ptr(pimage _ import _ by _ name,hmodule,

porigthunk-& gt;u 1 . address of data);

//如果函數名以null開頭,則跳過並繼續下壹個函數。

if(\ 0 = = pbyname-& gt;名稱[0])

繼續;

// bdohook用於檢查攔截是否成功。

bool bdohook = false

//檢查當前函數是否是我們需要截取的函數。

if((pahook func . SZ func[0]= = pbyname-& gt;name[0])& amp;& amp

(strcmpi(pahookfunc.szfunc,(char *)pbyname-& gt;name) == 0))

{

//找到了!

if (pahookfunc.pproc)

bdohook = true

}

if(bdo book)

{

//我們已經找到了要攔截的函數,開始吧。

//首先要做的是改變這個虛擬內存的內存保護狀態,讓我們可以自由訪問。

memory _ basic _ information mbi _ thunk;

虛擬查詢(prealthunk & amp;mbi_thunk,sizeof(內存_基本_信息));

_ assert(virtual protect(mbi _ thunk . base address,mbi_thunk.regionsize,

page _ read write & amp;mbi _ thunk . protect));

//保存我們要攔截的函數的正確跳轉地址。

if (paorigfuncs)

paorigfuncs =(proc)prealthunk-& gt;u 1 . function;

//將image_thunk_data數組中的函數跳轉地址重寫為我們自己的函數地址!

//以後所有進程對這個系統函數的調用都變成對自己寫的函數的調用。

prealthunk-& gt;u 1 . function =(PD word)pahook func . pproc;

//操作完成!將這塊虛擬內存更改回其原始保護狀態。

dword dwoldprotect

_ assert(virtual protect(mbi _ thunk . base address,mbi_thunk.regionsize,

mbi_thunk.protect。dwold protect));

setlasterror(error _ success);

返回true

}

}

//訪問image_thunk_data數組中的下壹個元素。

porigthunk++;

prealthunk++;

}

返回true

}

getnamedimportdescriptor函數的實現

pimage _ import _ descriptor getnamedimportdescriptor(hmodule hmodule,lpcstr szimportmodule)

{

//檢測參數

_ assert(szimportmodule);

_ assert(hm odule);

if((szimportmodule = = null)| |(hm odule = = null))

{

_ assert(false);

setlasterrorex(error _ invalid _ parameter,SLE _ error);

返回null

}

//獲取dos文件頭

pimage _ dos _ header PDO header =(pimage _ dos _ header)hm odule;

//檢測mz文件頭是否

if(isbadreadptr(PDO header,sizeof(image_dos_header)) ||

(PDO header-& gt;e_magic!= image_dos_signature))

{

_ assert(false);

setlasterrorex(error _ invalid _ parameter,SLE _ error);

返回null

}

//獲取pe文件頭

pimage _ nt _ headers pntheader = make ptr(pimage _ nt _ headers,PDO header,PDO header-& gt;e _ LFA new);

//檢測pe圖像文件是否

if (isbadreadptr(pntheader,sizeof(image_nt_headers)) ||

(pntheader-& gt;簽名!=圖像_ nt _簽名))

{

_ assert(false);

setlasterrorex(error _ invalid _ parameter,SLE _ error);

返回null

}

//檢查導入部分(即..idata部分)。

if(pntheader-& gt;optional header . data directory[圖像目錄條目導入]。虛擬地址== 0)

返回null

//獲取指向導入部分的指針(即..idata部分)

pimage _ import _ descriptor pimportdesc = make ptr(pimage _ import _ descriptor,pdosheader,

pntheader-& gt;optional header . data directory[圖像目錄條目導入]。virtual address);

//窮舉pimage_import_descriptor數組,找到我們需要截取的函數所在的模塊。

while(pimportdesc-& gt;姓名)

{

pstr szcurrmod = makeptr(pstr,pdosheader,pimportdesc-& gt;姓名);

if (stricmp(szcurrmod,szimportmodule) == 0)

打破;//找到了!中斷周期

//下壹個元素

pimportdesc++;

}

//如果沒有找到,說明我們要找的模塊還沒有被當前進程引入!

if(pimportdesc-& gt;name == null)

返回null

//返回函數找到的模塊描述符。

返回pimportdesc

}

//ISNT()函數的實現

布爾不是()

{

osversioninfo stosvi

memset(& amp;stosvi,null,sizeof(OS version info));

sto svi . dwosversioninfosize = sizeof(osversioninfo);

bool bret = getversionex(& amp;stos VI);

_ assert(true = = bret);

if (false == bret)返回false;

return(ver _ platform _ win32 _ nt = = stos VI . dwplatformid);

}

  • 上一篇:如何打開epub文件
  • 下一篇:給使的結構給使的結構是什麽
  • copyright 2024編程學習大全網