1. 程式人生 > >C++ 32位程式列舉64位系統登錄檔子項,含關閉重定向和提權

C++ 32位程式列舉64位系統登錄檔子項,含關閉重定向和提權

原英文註釋對應翻譯了,方便朋友們閱讀

在VS2013中通過測試。增加了許可權,可解決訪問部分需要高許可權的註冊項,無法取得項名和值名的問題。

也可用“RtlAdjustPrivilege”函式提權,具體使用百度一下吧。

//	QueryKey - 列舉登錄檔子項和其關聯的值.
//	hKey - 被列舉的登錄檔子項和值.

//	如何以 TrustedInstaller 使用者許可權修改登錄檔
//	通過程式碼將當前許可權提升到 TrustedInstaller 很麻煩, 但是可以通過獲取備份還原許可權來繞過DACL的監測機制.

#pragma comment(lib,"advapi32")
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

#define KEY_ALL_WOW64 (KEY_QUERY_VALUE | KEY_WOW64_64KEY)

bool EnablePriviledge(LPCTSTR lpSystemName) {
	HANDLE hToken;
	TOKEN_PRIVILEGES tkp = { 1 };
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		if (LookupPrivilegeValue(NULL, lpSystemName, &tkp.Privileges[0].Luid)) {
			tkp.PrivilegeCount = 1;
			tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
			AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
			if (GetLastError() != ERROR_SUCCESS) {
				CloseHandle(hToken);
				return false;
			}
		}
		CloseHandle(hToken);
	}
	return true;
}

void QueryKey(HKEY hKey)
{
	TCHAR    achKey[MAX_KEY_LENGTH];			// 登錄檔子項名稱緩衝區
	DWORD    cbName;							// 名稱字串大小
	TCHAR    achClass[MAX_PATH] = TEXT("");		// 類名緩衝區
	DWORD    cchClassName = MAX_PATH;			// 類字串大小
	DWORD    cSubKeys = 0;						// 登錄檔子項數量
	DWORD    cbMaxSubKey;						// 最長登錄檔子項大小
	DWORD    cchMaxClass;						// 最長類字串 
	DWORD    cValues;							// 項值數量(項內有多少個值)
	DWORD    cchMaxValue;						// 最長值名稱
	DWORD    cbMaxValueData;					// 最長值資料
	DWORD    cbSecurityDescriptor;				// 安全描述符大小
	FILETIME ftLastWriteTime;					// 最後寫入時間

	DWORD i, retCode;

	TCHAR	achValue[MAX_VALUE_NAME];
	DWORD	cchValue = MAX_VALUE_NAME;

	// 獲取類名和值數.
	retCode = RegQueryInfoKey(
		hKey,                    // 一個已開啟項的控制代碼(由 RegOpenKeyEx 或 RegCreateKeyEx 得到)
		achClass,                // 類名緩衝區
		&cchClassName,           // 類字串大小 
		NULL,                    // 保留值, 設為 NULL
		&cSubKeys,               // 登錄檔子項數量
		&cbMaxSubKey,            // 最長登錄檔子項大小
		&cchMaxClass,            // 最長類字串
		&cValues,                // 項值數量
		&cchMaxValue,            // 最長值名稱
		&cbMaxValueData,         // 最長值資料
		&cbSecurityDescriptor,   // 安全描述符
		&ftLastWriteTime);       // 最後寫入時間

	// 列舉登錄檔子項, 直到 RegEnumKeyEx 方法失敗.
	if (cSubKeys)
	{
		printf("\n子項數量: %d\n", cSubKeys);
		for (i = 0; i < cSubKeys; i++)
		{
			cbName = MAX_KEY_LENGTH;
			retCode = RegEnumKeyEx(	// 呼叫 RegEnumKeyExA 時 如果老返回 5 訪問拒絕, 可嘗試 RegCreateKeyEx
				hKey,
				i,
				achKey,
				&cbName,
				NULL,
				NULL,
				NULL,	// 呼叫 RegEnumKeyExA 時, 此值設為 MAX_PATH 可解決方法返回 234 錯誤問題.(貌似非 NULL 都可以)
				// 例如 DWORD cNameLen [MAX_PATH]; RegEnumKeyExA(hKey, i, achKey, cbName, NULL, NULL, cNameLen, &ftLastWriteTime);
				&ftLastWriteTime);
			if (retCode == ERROR_SUCCESS)
			{
				_tprintf(TEXT("(%d) %s\n"), i + 1, achKey);
			}
		}
	}

	// 列舉項值.

	if (cValues)
	{
		printf("\n值數量: %d\n", cValues);

		for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
		{
			cchValue = MAX_VALUE_NAME;
			achValue[0] = '\0';
			retCode = RegEnumValue(
				hKey,
				i,
				achValue,
				&cchValue,
				NULL,
				NULL,
				NULL,
				NULL);
			if (retCode == ERROR_SUCCESS)
			{
				_tprintf(TEXT("(%d) %s\n"), i + 1, achValue);
			}
		}
	}
}

int __cdecl _tmain() {
	bool bRet;
	LONG lResult;
	PVOID oldWow64State = NULL;	// 無型別指標
	bRet = EnablePriviledge(SE_BACKUP_NAME);	// 這個函式讓當前程序具有備份/還原的特權.
	if (bRet) {
		bRet = EnablePriviledge(SE_RESTORE_NAME);
		if (bRet) {
			HKEY hResult = NULL;
			DWORD dwDisposition;
			if (Wow64DisableWow64FsRedirection(&oldWow64State)){

				/*lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,	// 使用 RegOpenKeyEx 會因為許可權不夠無法訪問部分需要高許可權的註冊項
				TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles"),
				0,
				KEY_ALL_WOW64,
				&hResult
				);
				*/

				lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
					TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles"),
					0,
					NULL,
					REG_OPTION_BACKUP_RESTORE,		// 這個是重點, 傳入這個引數可以直接忽視 KEY_ALL_ACCESS 這個引數的作用, 直接以備份/還原的特權去操作登錄檔
					KEY_ALL_WOW64,					// 64位系統用 KEY_ALL_ACCESS 會無法訪問 64 位註冊項, 關閉重定向也會失敗
					NULL,
					&hResult,
					&dwDisposition);

				RegDisableReflectionKey(hResult);
				QueryKey(hResult);
				RegCloseKey(hResult);
				RegEnableReflectionKey(hResult);
			}
			Wow64RevertWow64FsRedirection(oldWow64State);
			if (lResult != ERROR_SUCCESS) {
				return 3;
			}
			getchar();
			return 0;
		}
		else return 2;
	}
	else return 1;
}


相關推薦

C++ 32程式列舉64系統子項關閉定向

原英文註釋對應翻譯了,方便朋友們閱讀 在VS2013中通過測試。增加了許可權,可解決訪問部分需要高許可權的註冊項,無法取得項名和值名的問題。 也可用“RtlAdjustPrivilege”函式提權,具體使用百度一下吧。 // QueryKey - 列舉登錄檔子項和其

32程式64系統問題

我們進行專案開發時,有些配置經常會放在登錄檔中進行控制。一般情況下,為了能夠相容32位系統和64位系統,我們的應用程式都是32位的。在解決專案問題中,就涉及到32位和64位的登錄檔問題,今天記錄如下。 問題現象: 我們的程式在32位系統執行的正常,但在64位

32程式64系統下隱藏托盤圖示

網上有很多程式碼,多是在32位系統下正常,64位系統則無法隱藏系統圖標,分析發現原因如下。 原因:64位系統下Explorer.exe是64位的,訪問其程序時結構體資料與32位系統有所差異,導致讀取資料錯誤。 解決:按64位系統內結構讀取資料賦值,結構如下: #defin

關於32程式64系統下執行中需要注意的定向問題(有圖有真相)(***)

0x00 前言 最近學習了[email protected]的文章《Persistence Architecture Matters》,恰巧解決了我之前遇到過的一個問題,理清了檔案和登錄檔重定向中需要注意的細節 大家在學習的過程中難免也會碰到,所以在此分享一下。

32程式64系統上呼叫GetModuleFileNameEx失敗

今天客戶打來電話說我們公司的伺服器程式在新裝的64位Windows 2003上以系統服務方式啟動不起來。初步懷疑是我們的32位服務程式哪個地方在64位機上不相容了。結果忙活了一上午,終於找到了問題所在。程式裡有一段程式碼是用來判斷程式是以服務方式啟動還是以視窗形式啟動:在應

WIN10應用程式自啟動功能及InstallShield讀寫64系統相關問題的解決

1. 問題:應用程式需要隨系統啟動,同時該應用程式也需要獲得管理員許可權才可以執行,在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run位置,設定了相關啟動項,發現無法隨機啟動。發現,若應用程式不獲

32程式64平臺移植的注意事項

新近的64位平臺在二進位制上與32位應用程式相容,這意味著可以非常簡單地移植現有的程式。許多目前在32位平臺上執行良好的程式也許不必移植,除非程式有以下要求: ·需要多於4GB的記憶體。 ·使用的檔案大小常大於2GB。 ·密集浮點運算,需要利用64位架構的優勢。 ·能從64位平臺的優化數學庫中受益。 否則

win7開機提示由於系統檔案丟失或損壞

今天魅力網路用的戴爾電腦就出現了這個問題,被人借了一天,回來了就開不了機了,進入pe修復啟動項也無法解決問題,經過研究發現,電腦系統自帶備份檔案,我們進入pe將檔案拷入指定目錄就行。 進入PE系統後,進入“C:\Windows\System32\config\RegBack”目錄,將其中的SYSTEM檔案

寫MFC程式還是先註釋寫或者先清理吧!

血的教訓,浪費了大把時間除錯找問題,然而卻不知道MFC自動寫註冊帶來的巨坑有多坑。一次次讓你懷疑人生, 微軟這個設計老子真心想拍死你。 1.自動寫登錄檔,這裡說自動是建立工程自帶SetRegistryKey將巨坑埋下伏筆 2.註冊資訊不是空,講道理應該為空,但老vc都知道軟

0xc000000f 由於系統檔案丟失或損壞因此Windows無法載入

WIN7出現以下情況,是thinkpad x61筆記本。 Windows未能啟動。原因可能是最近更改了硬體或軟體,解決此問題的步驟: 1:插入Windows安裝光碟並從新啟動計算機。 2:選擇語言設定,然後單擊“下一步”。 3:單擊“修復計算機”。 如果沒有此光碟,請與

問題:必須使用記錄或另一備份以恢復包含系統

這是因你安裝的第三方軟體導致系統註冊出現錯亂有幾個解決方法:1,在命令列下輸入:secedit /configure /cfg %windir%\repair\secsetup.inf /db secsetup.sdb /areas REGKEYS 然後回車2,在Windo

wpf使用Inkcanvas編寫應用程式64Win7系統中執行

c#input函式WMEncoder錄屏雙擊事件無效c#input函式WMEncoder錄屏雙擊事件無效 Socket類中AcceptAsync和BeginAccept在效能上有什麼區別引數化查詢出錯了我也沒找到錯在哪裡麻煩老師們幫我看一下。Socket類中AcceptAsy

WINDOWS中, 如何檢視一個執行中的程式64還是32的?

方法一: 工作管理員法 工作管理員>>>程序(processes)>> 程序後帶有*32的是32位程式 方法二: 簡化顏色模式法 右鍵exe>>>屬性>>>相容性 若Settings框中的降低色彩和解析度的選項

怎樣判斷一個exe可執行程式(dll檔案)是32的還是64的?

簡便方法: 直接用記事本或者notepad++開啟exe檔案(dll檔案),會有很多亂碼,不要頭疼,接下來只需要在第二段中找到PE兩個字母,在其後的不遠出會出現d? 或者L。若是d,則證明該程式是64位;若是L,則證明是32位。

如果32程式非要獲取64需要在開啟鍵時新增引數KEY_WOW64_64KEY。

專案為 vc mfc 32程式,系統安裝的是Win7 64位,在寫C++程式碼讀取登錄檔OFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall這個位置時,發現自動跳轉到了Software\\Wow6432Node\\Mi

檢視CentOS系統版本是32的還是64

轉自:http://www.centoscn.com/CentOS/help/2014/0701/3231.html 一、[root@linuxzgf ~]#getconf LONG_BIT[root@linuxzgf ~]#getconf WORD_BIT(32位的系

判斷某程式64還是32

1. 用程式碼判斷本身 if (IntPtr.Size == 4) {     // 32-bit } else if (IntPtr.Size == 8) {     // 64-bit } 2. 用程式碼判斷正在執行的其他程序 If you have a hex editor program,

GCC 64程式的makefile條件編譯心得——32版與64版、debug版與release版(相容MinGW、TDM-GCC)

  為了適應現在越來越流行的64位系統,經常需要將程式碼分別編譯為32位版和64位版。其次,除了需要生成debug版用於開發測試外,還需要生成release版用於釋出。本文介紹瞭如何利用makefile條件編譯來生成這些版本,而且不僅相容Linux下的GCC,還支援MinGW、TDM-GCC等Windows

32程式如何訪問64

64位OS中,從32位Nunit呼叫32位DLL中的方法執行,如何訪問64位的登錄檔項? (也即關閉登錄檔轉向功能。) 如讀取HKEY_LOCAL_MACHINE/Software/Microsoft子項的value,而非   HKEY_LOCAL_MACHINE/Softw

32程序下調用64函數——進程32模式與64模式切換

always imu tab 之間 pointer icm bool list ack 之前學習的32位進程中調用64位進程函數的知識整理一下,也就是32位模式與64位模式之間的切換。 相關博客:http://www.cnblogs.com/lanrenxinxin/p/4