?? -
字號:
if ('\0' == pbyname->name[0])
continue;
// bdohook用來檢查是否截獲成功
bool bdohook = false;
// 檢查是否當前函數是我們需要截獲的函數
if ((pahookfunc.szfunc[0] == pbyname->name[0]) &&
(strcmpi(pahookfunc.szfunc, (char*)pbyname->name) == 0))
{
// 找到了!
if (pahookfunc.pproc)
bdohook = true;
}
if (bdohook)
{
// 我們已經找到了所要截獲的函數,那么就開始動手吧
// 首先要做的是改變這一塊虛擬內存的內存保護狀態,讓我們可以自由存取
memory_basic_information mbi_thunk;
virtualquery(prealthunk, &mbi_thunk, sizeof(memory_basic_information));
_assert(virtualprotect(mbi_thunk.baseaddress, mbi_thunk.regionsize,
page_readwrite, &mbi_thunk.protect));
// 保存我們所要截獲的函數的正確跳轉地址
if (paorigfuncs)
paorigfuncs = (proc)prealthunk->u1.function;
// 將image_thunk_data數組中的函數跳轉地址改寫為我們自己的函數地址!
// 以后所有進程對這個系統函數的所有調用都將成為對我們自己編寫的函數的調用
prealthunk->u1.function = (pdword)pahookfunc.pproc;
// 操作完畢!將這一塊虛擬內存改回原來的保護狀態
dword dwoldprotect;
_assert(virtualprotect(mbi_thunk.baseaddress, mbi_thunk.regionsize,
mbi_thunk.protect, &dwoldprotect));
setlasterror(error_success);
return true;
}
}
// 訪問image_thunk_data數組中的下一個元素
porigthunk++;
prealthunk++;
}
return true;
}
// getnamedimportdescriptor函數的實現
pimage_import_descriptor getnamedimportdescriptor(hmodule hmodule, lpcstr szimportmodule)
{
// 檢測參數
_assert(szimportmodule);
_assert(hmodule);
if ((szimportmodule == null) || (hmodule == null))
{
_assert(false);
setlasterrorex(error_invalid_parameter, sle_error);
return null;
}
// 得到dos文件頭
pimage_dos_header pdosheader = (pimage_dos_header) hmodule;
// 檢測是否mz文件頭
if (isbadreadptr(pdosheader, sizeof(image_dos_header)) ||
(pdosheader->e_magic != image_dos_signature))
{
_assert(false);
setlasterrorex(error_invalid_parameter, sle_error);
return null;
}
// 取得pe文件頭
pimage_nt_headers pntheader = makeptr(pimage_nt_headers, pdosheader, pdosheader->e_lfanew);
// 檢測是否pe映像文件
if (isbadreadptr(pntheader, sizeof(image_nt_headers)) ||
(pntheader->signature != image_nt_signature))
{
_assert(false);
setlasterrorex(error_invalid_parameter, sle_error);
return null;
}
// 檢查pe文件的引入段(即 .idata section)
if (pntheader->optionalheader.datadirectory[image_directory_entry_import].virtualaddress == 0)
return null;
// 得到引入段(即 .idata section)的指針
pimage_import_descriptor pimportdesc = makeptr(pimage_import_descriptor, pdosheader,
pntheader->optionalheader.datadirectory[image_directory_entry_import].virtualaddress);
// 窮舉pimage_import_descriptor數組尋找我們需要截獲的函數所在的模塊
while (pimportdesc->name)
{
pstr szcurrmod = makeptr(pstr, pdosheader, pimportdesc->name);
if (stricmp(szcurrmod, szimportmodule) == 0)
break; // 找到!中斷循環
// 下一個元素
pimportdesc++;
}
// 如果沒有找到,說明我們尋找的模塊沒有被當前的進程所引入!
if (pimportdesc->name == null)
return null;
// 返回函數所找到的模塊描述符(import descriptor)
return pimportdesc;
}
// isnt()函數的實現
bool isnt()
{
osversioninfo stosvi;
memset(&stosvi, null, sizeof(osversioninfo));
stosvi.dwosversioninfosize = sizeof(osversioninfo);
bool bret = getversionex(&stosvi);
_assert(true == bret);
if (false == bret) return false;
return (ver_platform_win32_nt == stosvi.dwplatformid);
}
/////////////////////////////////////////////// end //////////////////////////////////////////////////////////////////////
不知道在這篇文章問世之前,有多少朋友嘗試過去實現“鼠標屏幕取詞”這項充滿了挑戰的技術,也只有嘗試過的朋友才能體會到其間的不易,尤其在探索api函數的截獲時,手頭的幾篇資料沒有一篇是涉及到關鍵代碼的,重要的地方都是一筆代過,msdn更是顯得蒼白而無力,也不知道除了image_import_descriptor和image_thunk_data,微軟還隱藏了多少秘密,好在硬著頭皮還是把它給攻克了,希望這篇文章對大家能有所幫助。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -