日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

一种注册表沙箱的思路、实现——Hook Nt函数

發布時間:2023/11/27 生活经验 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一种注册表沙箱的思路、实现——Hook Nt函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??????? Nt函數是在Ring3層最底層的函數了,選擇此類函數進行Hook,是為了提高繞過門檻。我的Hook方案使用的是微軟的Detours。(轉載請指明出處)

??????? Detours的Hook和反Hook的寫入如下:

DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(lpOriFuncAddr, lpNewFuncAddr);
DetourTransactionCommit();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(lpOriFuncAddr, lpNewFuncAddr);
DetourTransactionCommit();

??????? 從以上可以見得,我們需要保存lpOriFuncAddr(原始函數入口地址)和lpNewFuncAddr(修改后函數入口地址),我們使用一個結構體來保存這兩個信息。

// 記錄(函數原始函數地址,修改后函數地址)的結構
typedef struct _FuncPointer_{VOID* lpOri;VOID* lpNew;
}FuncPointer, *pFuncPointer;

??????? 因為我們要Hook很多函數,我們定義一個Map來保存信息,以方便尋找到相關的函數入口,我們的Map是以函數名為Key,以保存原始函數入口和修改后函數入口結構體為值。

// 以函數名為Key,其(函數原始函數地址,修改后函數地址)為值的map
typedef std::map<std::string,FuncPointer> MapFuncPointer;
typedef MapFuncPointer::iterator MapFuncPointerIter;
typedef MapFuncPointer::const_iterator MapFuncPointerCIter;

??????? 尋找原始函數的入口地址可以通過Detours提供的DetourFindFunction,而修改后的函數入口地址則需要我們自己定義。在我工程的NewNtRegFunc.h和NewNtRegFunc.cpp文件中,我分別定義了所有修改后函數聲明和實現。新函數名的規則是“New_原函數名”,如

NTSTATUS __stdcall New_NtOpenKey(__out       PHANDLE KeyHandle,__in        ACCESS_MASK DesiredAccess,__in        POBJECT_ATTRIBUTES ObjectAttributes );

??????? 我們第一步就是要生成這樣Map

extern MapFuncPointer g_MapRegFuncPointer;VOID GetHookNtRegFuncInfo()
{HOOKNTDLLFUNC( CreateKey );HOOKNTDLLFUNC( OpenKey );HOOKNTDLLFUNC( DeleteKey );HOOKNTDLLFUNC( DeleteValueKey );HOOKNTDLLFUNC( QueryKey );HOOKNTDLLFUNC( SetValueKey );HOOKNTDLLFUNC( QueryValueKey );HOOKNTDLLFUNC( EnumerateKey );HOOKNTDLLFUNC( EnumerateValueKey );HOOKNTDLLFUNC( FlushKey );HOOKNTDLLFUNC( NotifyChangeKey );HOOKNTDLLFUNC( Close );HOOKNTDLLFUNC( SetSecurityObject );HOOKNTDLLFUNC( QuerySecurityObject );// vista及以上系統HOOKNTDLLFUNC( OpenKeyEx );HOOKNTDLLFUNC( CreateKeyTransacted );HOOKNTDLLFUNC( OpenKeyTransacted );HOOKNTDLLFUNC( OpenKeyTransactedEx );
}

??????? 其中HOOKTNDLLFUNC是一個宏,其定義如下

#define HOOKNTDLLFUNC(x)\HOOKNTITEM("NtDll.dll", x )

????? HOOKNTITEM也是個宏

// Hook函數,同時將{函數名,(函數原始函數地址,修改后函數地址)}保存到map中
#define HOOKNTITEM(x,y)\FuncPointer FP_##y; FP_##y.lpOri = DetourFindFunction( x , "Nt"#y );FP_##y.lpNew = static_cast<VOID*>(New_Nt##y); g_MapRegFuncPointer["Nt"#y]= FP_##y;

??????? 現在來說說這個宏,這個也是這篇文章中的一個重點。宏其實可以認為是一個模板,對于使用宏的地方,編譯器會將其原封不動的替換到使用該宏處,這個特點和內聯函數(inline)很像(但是VC的內聯卻不是人能控制的,編譯器會根據它的判斷來決定是否將你定義為inline的函數內容替換到調用處)。首先,我們要定義一個FuncPointer結構體對象,如果你在宏定義這個對象如下:FuncPointer FP;則在編譯時報很多錯,錯誤的原因就是一個變量名被定義多次,想想為什么?就是因為我們多次調用HOOKNTITEM,編譯器也多次將FuncPointer FP插入到調用處。結果展開后如下

{FuncPointer FP;……FuncPointer FP;……FuncPointer FP;……
}

??????? 為了讓每次定義的變量名不一樣,我們使用了結合傳入參數的方法,故定義為:

FuncPointer FP_##y

??????? 該宏之后的內容很淺顯易懂了。

??????? 現在開始我們的HOOK操作

BOOL HookRegApi()
{BOOL bSuc = FALSE;do {GetHookNtRegFuncInfo();DetourTransactionBegin();DetourUpdateThread(GetCurrentThread());for ( MapFuncPointerIter it = g_MapRegFuncPointer.begin(); it != g_MapRegFuncPointer.end(); it++ ) {// 必須要加以判斷,否則之后不應該是失敗的也失敗了if ( NULL != it->second.lpOri && NULL != it->second.lpNew ) {LONG lRes = DetourAttach(&(it->second.lpOri), it->second.lpNew );}}DetourTransactionCommit();bSuc = TRUE;} while (0);return bSuc;
}

??????? 該函數也很簡單,但是其中有個細節一定要注意,那就是要判斷原函數地址和修改后函數地址是否為空。使用Detours進行Hook特別要注意這點,否則會出現你也想不到的問題。當時我寫這塊時,偽代碼可以如下表示

HOOK(CreateKey)
HOOK(OpenKeyEx)
HOOK(OpenKey)

??????? 結果我發現NtCreateKey函數被Hook了,而OpenKey卻沒有被Hook,出錯的原因是:NtOpenKeyEx這個函數在vista及其以上系統才有,而我的開發環境是Xp,于是DetourFindFunction尋找到NtOpenKeyEx函數的入口地址為NULL,調用DetourAttach(NULL,lpNewFuncAddr)失敗后,所有理論上應該成功的Hook(如Hook(OpenKey),NtOpenKey在xp上是存在的)也都會失敗。當然最好還可以判斷之前一步DetourAttach的返回值是否成功來決定是否繼續Hook。

??????? 反Hook的代碼如下

BOOL UnHookRegApi()
{BOOL bSuc = FALSE;do {DetourTransactionBegin();DetourUpdateThread(GetCurrentThread());for ( MapFuncPointerIter it = g_MapRegFuncPointer.begin(); it != g_MapRegFuncPointer.end(); it++ ) {// 必須要加以判斷,否則之后不應該是失敗的也失敗了if ( NULL != it->second.lpOri && NULL != it->second.lpNew ) {LONG lRes = DetourDetach(&(PVOID&)it->second.lpOri, it->second.lpNew );}}DetourTransactionCommit();bSuc = TRUE;} while (0);return bSuc;
}

??????? 為了之后方便調用真實函數,我定義了一個宏

// 獲取原始函數入口
#define GETORIFUNC(x)\( (pfn_Nt##x)g_MapRegFuncPointer["Nt"#x].lpOri )

總結

以上是生活随笔為你收集整理的一种注册表沙箱的思路、实现——Hook Nt函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。