C++ 32位程序枚举64位系统注册表子项,含关闭重定向和提权

来源:互联网 发布:经济数据库 编辑:程序博客网 时间:2024/04/29 12:52

MSDN:http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms724256(v=vs.85).aspx


原英文注释对应翻译了,方便朋友们阅读

在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;TCHARachValue[MAX_VALUE_NAME];DWORDcchValue = 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 访问拒绝, 可尝试 RegCreateKeyExhKey,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;}


1 0
原创粉丝点击