detour庫
1. 原始碼
detour庫很小,直接編譯成lib比較好,在用到的**中做靜態鏈結。
detours 3.0加入的新的功能:
支援x64的api hook,包括 amd64 和 ia64兩套
支援所有的windows處理器(包括arm)
不再依賴detoured.dll
列舉pe匯入表,匯出表的api,確定函式指標引用的模組
原始碼結構:
disasm.cpp / detours / detours.h 共同構成了detours基本功能
modules.cpp 提供了遍歷pe檔案的api
image.cpp / creatwth.cpp / uimports.cpp 用於構建新的pe檔案,新增.detours 節
編譯:直接在vs中建立乙個lib工程,然後將原始檔匯入即可(uimports.cpp 除外)。
注: uimports.cpp 被 include進了 creatwth.cpp 中了,如果加入到工程,就會提示編譯錯誤。
其實detours的工作比較簡單,但是要做乙個健壯的庫,還是不太容易的。
自己感覺detours比較困難的幾個點難點:
1. 給出乙個位址,判斷能否hook
不能hook jmp指令,否則trampline **會有問題
2. **段的判斷:
需要trampline 幾個位元組,不能在hook時將指令截斷
3. trampline部分 位址重定位的問題
這就需要識別出被搬走**中的位址,並進行修改
2和3是乙個問題,就是要能夠識別指令,其實就是解析cpu的 opcode
detours api的作用,以及內部做的工作:
long winapi detourtransactionbegin(void);
鎖住detour庫,並將trampline的所有塊變為可讀可寫可執行,方便後面向trampline塊中寫入。
long winapi detourtransactionabort(void);
恢復所有的 operation(一次可以有多個operation),修改trampline塊為執行屬性,並恢復所有執行緒執行
long winapi detourtransactioncommit(void);
首先恢復hook或插入hook,對執行到trampline的執行緒進行調整,flush icache保證**更新到快取,讓cpu執行新的指令,
修改trampline塊組執行屬性,恢復所有執行緒
long winapi detourtransactioncommitex(pvoid **pppfailedpointer);
同上long winapi detourupdatethread(handle hthread);
掛起指定控制代碼指定的執行緒
long winapi detourattach(pvoid *pppointer, pvoid pdetour);
尋找可以hook的位址(當前位址可能無法hook),分配trampline塊,並且確定trampline中的拷貝的指令位元組數,加入操作(operation)列表
long winapi detourattachex(pvoid *pppointer, pvoid pdetour, pdetour_trampoline *pprealtrampoline, pvoid *pprealtarget, pvoid *pprealdetour);
同上long winapi detourdetach(pvoid *pppointer, pvoid pdetour);
與attach逆向的操作,建立乙個operation,指明為remove hook的操作,將要恢復的hook的trampline掛入operation中。
3. detours需要注意的地方:
1. detourtransactionbegin()方法
每個hook如果只做了一次,在多執行緒情況下可能出現hook失敗的情況。
// only one transaction is allowed at a time.
if (s_npendingthreadid != 0)
// make sure only one thread can start a transaction.
if (interlockedcompareexchange(&s_npendingthreadid, (long)getcurrentthreadid(), 0) != 0)
如果兩個執行緒同時執行到了 detourtransactionbegin的起始位置,同時向下執行,肯定有乙個執行緒會 return error_invalid_operation; 。
2. detourupdatethread() 方法
這個函式是掛起指定控制代碼的執行緒,只留下執行hook的執行緒。
所以要遍歷當前程序中的所有的執行緒,逐一執行這個函式。
3. 如果攔截函式在dll中,那麼絕大多數情況下不能在unhook之後解除安裝這個dll,或者解除安裝存在造成崩潰的危險。
因為某些執行緒的呼叫堆疊中可能還包含hook函式,這時解除安裝掉dll,呼叫堆疊返回到hook函式時記憶體位置已經不是合法的**了。
4. 有一些非常短的目標函式無法hook。
jmp指令需要占用一定空間,有些函式太過短小,甚至不夠jmp指令的長度,沒有辦法hook,(比如ntdll!dbgbreakpoint函式)
4. 示例:
#include #include "detours.h"
#pragma comment(lib, "detours.lib")
static int (winapi * old_messageboxw)(hwnd hwnd, lpcwstr lptext, lpcwstr lpcaption, uint utype) = messageboxw;
int winapi new_messageboxw(hwnd hwnd, lpcwstr lptext, lpcwstr lpcation, uint utype)
void hook()
void unhook()
void main()
閱讀筆記 fsnotify原始碼閱讀
fsnotify的github位址是 fsnotify是乙個資料夾監控應用。可以使用建立乙個watcher來對某個資料夾進行監控 檔案目錄很簡單,實際就兩個程式檔案,fsnotify.go 和 各平台的fsnotify go 後乙個檔案是各個不同平台的實現 example test.go中給的是最簡...
《原始碼閱讀》原始碼閱讀技巧,原始碼閱讀工具
檢視某個類的完整繼承關係 選中類的名稱,然後按f4 quick type hierarchy quick type hierarchy可以顯示出類的繼承結構,包括它的父類和子類 supertype hierarchy supertype hierarchy可以顯示出類的繼承和實現結構,包括它的父類和...
redis原始碼閱讀筆記
在redis中乙個資料庫結構體是這樣的 每個dict是乙個hash表 typedef struct redisdb redisdb dict欄位中存放以key值為鍵,以value指標為值的hash表項dict根據型別的不同分為如下幾種 1 字串 string 操作 set key value get...