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

歡迎訪問 生活随笔!

生活随笔

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

生活经验

一种注册表沙箱的思路、实现——研究Reactos中注册表函数的实现1

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

? ? ? ? 因為我們沙箱注入了一個DLL到了目標進程,并且Hook了一系列NtXX(NtOpenKey)函數,所以我們在注入的代碼中是不能使用RegXX(RegOpenKey等)這類函數的。因為RegXX系列函數在底層使用了NtXX系列函數,如果在注入DLL執行Hook后的邏輯中使用了RegXX系列函數,將會導致遞歸調用的問題,就讓程序產生“蛋生雞,雞生蛋”這樣的“思考”,可是程序不知道停止,最終腦袋用完了就掛了。于是使用Nt函數實現我們曾經習慣使用的RegXX函數是必要的。(轉載請指明出處)

? ? ? ? 編寫這塊代碼時,我參考了reactos注冊表相關的源碼。它的源碼寫的很好,但是也存在一定的漏洞,我會在之后介紹。

? ? ? ? 列出一個比較簡單的RegXX函數的實現:

LONG WINAPI RegOpenKeyExW(HKEY hKey,LPCWSTR lpSubKey,DWORD ulOptions,REGSAM samDesired,PHKEY phkResult)
{OBJECT_ATTRIBUTES ObjectAttributes;UNICODE_STRING SubKeyString;HANDLE KeyHandle;NTSTATUS Status;LONG ErrorCode = ERROR_SUCCESS;if (!phkResult){return ERROR_INVALID_PARAMETER;}Status = MapDefaultKey(&KeyHandle, hKey);if (!NT_SUCCESS(Status)){return RtlNtStatusToDosError(Status);}if (lpSubKey != NULL)RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);elseRtlInitUnicodeString(&SubKeyString, (LPWSTR)L"");InitializeObjectAttributes(&ObjectAttributes,&SubKeyString,OBJ_CASE_INSENSITIVE,KeyHandle,NULL);Status = NtOpenKey((PHANDLE)phkResult,samDesired,&ObjectAttributes);if (!NT_SUCCESS(Status)){ErrorCode = RtlNtStatusToDosError(Status);}ClosePredefKey(KeyHandle);return ErrorCode;
}

? ? ? ? 總的來說,該函數的實現流程是:

  1. 參數合法性判斷
  2. 用MapDefaultKey將HKEY轉換成HANDLE
  3. 組裝ObjectAttributes
  4. 調用Nt式函數
  5. 關閉第一步獲得的HANDLE

? ? ? ? 我們發現其他很多Reg函數都是走這個套路的,比如RegSetKeyValue和RegEnumKeyEx等。

? ? ? ? 因為我們Hook的是Nt式函數,我們在函數中可以獲取鍵對應的HANDLE,而不會得到HKEY。于是我們關心的是HKEY和HANDLE轉換的過程。我們查看MapDefaultKey

#define MAX_DEFAULT_HANDLES ? 6
static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
#define IsPredefKey(HKey) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\(((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)
#define GetPredefKeyIndex(HKey) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\((ULONG_PTR)(HKey) & 0x0FFFFFFF)
static NTSTATUS MapDefaultKey(OUT PHANDLE RealKey, IN HKEY Key)
{PHANDLE Handle;ULONG Index;BOOLEAN DoOpen, DefDisabled;NTSTATUS Status = STATUS_SUCCESS;if (!IsPredefKey(Key)) {*RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);return STATUS_SUCCESS;}/* Handle special cases here */Index = GetPredefKeyIndex(Key);if (Index >= MAX_DEFAULT_HANDLES) {return STATUS_INVALID_PARAMETER;}RegInitialize(); /* HACK until delay-loading is implemented */RtlEnterCriticalSection (&HandleTableCS);if (Key == HKEY_CURRENT_USER)DefDisabled = DefaultHandleHKUDisabled;elseDefDisabled = DefaultHandlesDisabled;if (!DefDisabled) {Handle = &DefaultHandleTable[Index];DoOpen = (*Handle == NULL);}else {Handle = RealKey;DoOpen = TRUE;}if (DoOpen) {/* create/open the default handle */Status = OpenPredefinedKey(Index,Handle);}if (NT_SUCCESS(Status)) {if (!DefDisabled)*RealKey = *Handle;else*(PULONG_PTR)Handle |= 0x1;}RtlLeaveCriticalSection (&HandleTableCS);return Status;
}

? ? ? ? ? 我來解釋下上述代碼,我們先來看一些定義

#define HKEY_CLASSES_ROOT           (( HKEY ) (ULONG_PTR)((LONG)0x80000000) )
#define HKEY_CURRENT_USER           (( HKEY ) (ULONG_PTR)((LONG)0x80000001) )
#define HKEY_LOCAL_MACHINE          (( HKEY ) (ULONG_PTR)((LONG)0x80000002) )
#define HKEY_USERS                  (( HKEY ) (ULONG_PTR)((LONG)0x80000003) )
#define HKEY_PERFORMANCE_DATA       (( HKEY ) (ULONG_PTR)((LONG)0x80000004) )
#define HKEY_PERFORMANCE_TEXT       (( HKEY ) (ULONG_PTR)((LONG)0x80000050) )
#define HKEY_PERFORMANCE_NLSTEXT    (( HKEY ) (ULONG_PTR)((LONG)0x80000060) )
#if(WINVER >= 0x0400)
#define HKEY_CURRENT_CONFIG         (( HKEY ) (ULONG_PTR)((LONG)0x80000005) )
#define HKEY_DYN_DATA               (( HKEY ) (ULONG_PTR)((LONG)0x80000006) )

? ? ? ? ? 看到這些主鍵的值都是0x80000000+,IsPredefKey(Key)函數就是判斷hKey是否為這些主鍵。如果不是主鍵,則可能是我們通過RegOpenKey等函數打開的主鍵下的子鍵(RegOpenKey(HKEY_CLASS_ROOT,L".txt",&hKey); hKey可能是形如0x000003AB這樣的值),對于這樣的子鍵Hkey,其通過(HANDLE)((ULONG_PTR)Key & ~0x1)就可以轉換為HANDLE了。

? ? ? ? 如果是以上主鍵,這些主鍵的后28位是一個數組的Index,該數組保存的其對應的HANDLE。但是這個版本的Reactos只保存了MAX_DEFAULT_HANDLES(6)個元素,于是HKEY_PERFORMANCE_TEXT、HKEY_DYN_DATA和HKEY_PERFORMANCE_NLSTEXT這樣主鍵就會被認為不合法了。

if (Index >= MAX_DEFAULT_HANDLES){//HKEY_PERFORMANCE_TEXT、HKEY_PERFORMANCE_NLSTEXT、HKEY_DYN_DATAreturn STATUS_INVALID_PARAMETER;}

? ? ? ? 拿到Index后使用OpenPredefinedKey打開這些主鍵的HANDLE

static NTSTATUS
OpenPredefinedKey(IN ULONG Index,OUT HANDLE Handle)
{NTSTATUS Status;switch (Index){case 0: /* HKEY_CLASSES_ROOT */Status = OpenClassesRootKey (Handle);break;case 1: /* HKEY_CURRENT_USER */Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,Handle);break;case 2: /* HKEY_LOCAL_MACHINE */Status = OpenLocalMachineKey (Handle);break;case 3: /* HKEY_USERS */Status = OpenUsersKey (Handle);break;
#if 0case 4: /* HKEY_PERFORMANCE_DATA */Status = OpenPerformanceDataKey (Handle);break;
#endifcase 5: /* HKEY_CURRENT_CONFIG */Status = OpenCurrentConfigKey (Handle);break;case 6: /* HKEY_DYN_DATA */Status = STATUS_NOT_IMPLEMENTED;break;default:WARN("MapDefaultHandle() no handle creator\n");Status = STATUS_INVALID_PARAMETER;break;}return Status;

? ? ? ?這些獲取HANDLE的方法在底層都是通過NtOpenKey實現的,如獲取HKEY_CURRENT_USER鍵的路徑的函數

NTSTATUS
NTAPI
RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess,OUT PHANDLE KeyHandle)
{OBJECT_ATTRIBUTES ObjectAttributes;UNICODE_STRING KeyPath;NTSTATUS Status;PAGED_CODE_RTL();/* Get the user key */Status = RtlFormatCurrentUserKeyPath(&KeyPath);if (NT_SUCCESS(Status)){/* Initialize the attributes and open it */InitializeObjectAttributes(&ObjectAttributes,&KeyPath,OBJ_CASE_INSENSITIVE,NULL,NULL);Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);/* Free the path and return success if it worked */RtlFreeUnicodeString(&KeyPath);if (NT_SUCCESS(Status)) return STATUS_SUCCESS;}/* It didn't work, so use the default key */RtlInitUnicodeString(&KeyPath, RtlpRegPaths[RTL_REGISTRY_USER]);InitializeObjectAttributes(&ObjectAttributes,&KeyPath,OBJ_CASE_INSENSITIVE,NULL,NULL);Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);/* Return status */return Status;
}

? ? ? ? 經過以上各步的轉換,我們就可以獲得HKEY和HANDLE對應的關系了。但是實際我們卻不會去關心這個過程,因為我們在Nt式函數里獲得就是HANDLE,我們不用去執行這個轉換過程。但是作為知識,既然研究到這兒,就得好好研究透。

總結

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

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