您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何逆向分析Etw框架windows內核監控注冊表的實現原理,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Window7以及以上系統的ETW日志自帶了一個注冊表日志信息的輸出,在windows事件查看器的Microsoft Windows KernelRegistry / Analytic可以看到并且開啟或者關閉注冊表日志,它的監控操作包括CreateKey_Opt、OpenKey_Opt、DeleteKey_Opt、QueryKey_Opt、SetValueKey_Opt、DeleteValueKey_Opt、QueryValueKey_Opt監控的輸出數據包括根據每個不同的操作它的內容也不一樣,例如
CreateKey_Opt
mName = 0x000001e0ca423d30 L"BaseObject": ulongptr
mName = 0x000001e0ca423d30 L"KeyObject" : ulongptr
mName = 0x000001e0ca423da8L"Status" ULONG32
mName = 0x000001e0ca423e20L"Disposition" ULONG32
mName = 0x000001e0ca423e98 L"BaseName" 2
mName = 0x000001e0ca423f10L"RelativeName" 0x82
SetValueKey_Opt
mName =0x0000025ea4054208 L"KeyObject" ulongptr
mName =0x0000025ea4054280 L"Status" ULONG32
mName =0x0000025ea40542f8 L"Type" ULONG32
mName =0x0000025ea4054370 L"DataSize" ULONG32
mName =0x0000025ea40543e8 L"KeyName" 2
mName =0x0000025ea4054460 L"ValueName" char*
mName =0x0000025ea40544d8 L"CapturedDataSize" 2
mName =0x0000025ea4054550 L"CapturedData" 0
mName =0x0000025ea40545c8 L"PreviousDataType" ULONG32
mName =0x0000025ea4054640 L"PreviousDataSize" ULONG32
mName =0x0000025ea40546b8 L"PreviousDataCapturedSize" 2
mName =0x0000025ea4054730 L"PreviousData" 0
DeleteValueKey_Opt
mName =0x000001f3275e5c28 L"KeyObject" ulongptr
mName =0x0000025ea4054280 L"Status" ULONG32
mName =0x0000025ea40543e8 L"KeyName" 2
mName = 0x000001f3275e5d90L"ValueName"
DeleteKey_Opt
mName =0x000001f3275e5c28 L"KeyObject" ulongptr
mName =0x0000025ea4054280 L"Status" ULONG32
mName =0x0000025ea40543e8 L"KeyName" 2
更多具體的數據,讀者可以自行去研究我們今天講解的不是他的具體使用方法,而是windows內核是怎么樣實現輸出這些數據的。
Windows的內核程序ntoskrnl.exe初始化的時候會啟動和初始化很多信息,啟動ETW組件就是啟動一項內容,在void __fastcall EtwInitialize(unsigned int Phase)的函數里,最下面有幾個調用了EtwRegister函數去注冊一些Etw事件,如下
我們可以看到EventTracingProvGuid、KernelProvGuid、NetProvGuid、DiskProvGuid等等一些日志事件,在這些注冊之間還有一個函數EtwpInitializeRegTracing(),這個是初始化注冊注冊表事件的函數,跟進去繼續追蹤,實現很簡單
int __cdeclEtwpInitializeRegTracing()
{
return EtwRegister(
(_GUID *)&RegistryProvGuid,
(void (__cdecl *)(_GUID *, unsignedint, char, unsigned __int64, unsigned __int64, _EVENT_FILTER_DESCRIPTOR *, void*))EtwpRegTraceEnableCallback, 0i64,
&EtwpRegTraceHandle);
}
RegistryProvGuid就是注冊表的事件的id :
{70eb4f03-c1de-4f73-a051-33d13d5413bd
注冊的回調函數是EtwpRegTraceEnableCallback,注冊得到的句柄是:EtwpRegTraceHandle,最后內核也是通過EtwWrite寫句柄EtwpRegTraceHandle來輸出日志。
注意知識講解點:
查詢MSDN庫,EtwRegister定義如下:
NTSTATUS EtwRegister(
LPCGUID ProviderId,
PETWENABLECALLBACK EnableCallback,
PVOID CallbackContext,
PREGHANDLE RegHandle
);
EnableCallback是應用層調用EnableTrace后,內核會把應用層傳入的CallbackContext參數傳輸給EnableCallback的回調,PETWENABLECALLBACK定義如下:
void Etwenablecallback(
LPCGUIDSourceId,
ULONGControlCode,
UCHAR Level,
ULONGLONG MatchAnyKeyword,
ULONGLONGMatchAllKeyword,
PEVENT_FILTER_DESCRIPTORFilterData,
PVOIDCallbackContext
)
ControlCode就是True or false的開關
Level是日志等級
MatchAnyKeyword 和 MatchAllKeyword是兩個過濾keyword id
FilterData 這個參數只有windows 7或者以上系統才有的參數,是應用層通過EnableTraceEx或者 EnableTraceEx2來傳入的參數。
接下來我們繼續看EtwpRegTraceEnableCallback回調函數的實現
當應用層開啟Enable日志的時候,即ControlId = True時,回調函數內部會通過CmRegisterCallbackEx函數注冊注冊表過濾回調EtwpRegTraceCallback,注冊成功后,全局變量EtwpRegTracingEnabled會設置為True,如果ControlId = False時,即關閉日志,會調用CmUnRegisterCallback注銷回調函數。
注意:
if ( FilterData&& FilterData->Size == 4 )
EtwpRegTraceOptions= *(unsigned int *)FilterData->Ptr;
這兩句代碼,這是一個未文檔化隱含的“技能”,當設置過濾數據后,就會設置EtwpRegTraceOptions的全局值,設置不同的數值會輸出不同的數據,默認是0,當EtwpRegTraceOptions為0時內核只會輸出一些基本的key 、 value 、 Type值,但不會輸出一些很具體的設置的CaptureData數據。
接下來我們看EtwpRegTraceCallback函數
這里是組裝QueryValueKey_Opt的數據,注意EtwpRegTraceOptions & 2就如前所講EtwpRegTraceOptions有2的標志位就會再次組裝注冊表里查詢的KeyValueData,注意這個大小最多只給你2048個字節
if ( EtwpRegTraceOptions & 4 )
EtwpCapturePreviousRegistryData((_REG_SET_VALUE_KEY_INFORMATION*)Argument2);
如果EtwpRegTraceOptions參數包含4的時候就會輸出設置之前的ValueData,(但是這里卻沒有設置輸出最大值,有點奇怪)。
其他類型就不集體講解了,一樣的方式,在內核里有如下定義
后面那個一串數據80000000000010000000200410000001是當前MatchKeyWord,如之前所講應用層可以通過EnableTrace/EnableTraceEx/EnableTraceEx2的keyword參數設置輸出不同的數據。
最后組合起來的數據會通過EtwWrite函數寫句柄EtwpRegTraceHandle,哪個實例注冊了這個事件id,Etw的組件就會把這個數據輸出給實例。
下面我們寫個程序去展示下獲取這個日志輸出,(怎樣創建Etw不再講解),
ULONG64 KeyWord = (ULONG64)((CreateKey_Keyword |
DeleteKey_Keyword |
SetValueKey_Keyword |
DeleteValueKey_Keyword) & 0xFFFF);
EVENT_FILTER_DESCRIPTOR EnableFilterDesc = {0};
ULONG64 dwVal = 0x02;
UCHAR Level = EVENT_CONTROL_CODE_ENABLE_PROVIDER;
Level = EVENT_CONTROL_CODE_ENABLE_PROVIDER;
EnableFilterDesc.Ptr = (ULONGLONG)&dwVal;
EnableFilterDesc.Size = 4;
EnableTraceEx(
&RegistryProvGuid,
0,
m_Session,
Level,
TRACE_LEVEL_VERBOSE,
KeyWord,
0,
0,
&EnableFilterDesc
);
注意我設置定義了EnableFilterDesc的其他把EnableFilterDesc.Size= 4,和dwVal設置為2,就是之前講解的要windows注冊表內核去設置EtwpRegTraceOptions參數,
運行后,可以看到內核輸出的日志信息
KeyName:
ValueName:
當前操作是SetValueKey,設置的Data
輸出了CaptureData數據,大小1460,數據如下
這里也輸出了設置之前的data
至此內核里如何實現注冊表Etw日志的原理講解以及實例展示完畢,整個結構很簡單,可以不用自己去專門寫個注冊表驅動去實現監測了,微軟已經為我們提供一套完整的解決方案,只是更多未文檔化的細節需要去發現。
以上就是如何逆向分析Etw框架windows內核監控注冊表的實現原理,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。