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

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


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

在VS2013中通过测试。增加了权限,可解决访问部分需要高权限的注册项,无法取得项名和值名的问题。

也可用“RtlAdjustPrivilege”函数提权,具体使用百度一下吧。


[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. //  QueryKey - 枚举注册表子项和其关联的值.  
  2. //  hKey - 被枚举的注册表子项和值.  
  3.   
  4. //  如何以 TrustedInstaller 用户权限修改注册表  
  5. //  通过代码将当前权限提升到 TrustedInstaller 很麻烦, 但是可以通过获取备份还原权限来绕过DACL的监测机制.  
  6.   
  7. #pragma comment(lib,"advapi32")  
  8. #include <stdio.h>  
  9. #include <tchar.h>  
  10. #include <windows.h>  
  11.   
  12. #define MAX_KEY_LENGTH 255  
  13. #define MAX_VALUE_NAME 16383  
  14.   
  15. #define KEY_ALL_WOW64 (KEY_QUERY_VALUE | KEY_WOW64_64KEY)  
  16.   
  17. bool EnablePriviledge(LPCTSTR lpSystemName) {  
  18.     HANDLE hToken;  
  19.     TOKEN_PRIVILEGES tkp = { 1 };  
  20.     if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {  
  21.         if (LookupPrivilegeValue(NULL, lpSystemName, &tkp.Privileges[0].Luid)) {  
  22.             tkp.PrivilegeCount = 1;  
  23.             tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  
  24.             AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);  
  25.             if (GetLastError() != ERROR_SUCCESS) {  
  26.                 CloseHandle(hToken);  
  27.                 return false;  
  28.             }  
  29.         }  
  30.         CloseHandle(hToken);  
  31.     }  
  32.     return true;  
  33. }  
  34.   
  35. void QueryKey(HKEY hKey)  
  36. {  
  37.     TCHAR    achKey[MAX_KEY_LENGTH];            // 注册表子项名称缓冲区  
  38.     DWORD    cbName;                            // 名称字符串大小  
  39.     TCHAR    achClass[MAX_PATH] = TEXT("");     // 类名缓冲区  
  40.     DWORD    cchClassName = MAX_PATH;           // 类字符串大小  
  41.     DWORD    cSubKeys = 0;                      // 注册表子项数量  
  42.     DWORD    cbMaxSubKey;                       // 最长注册表子项大小  
  43.     DWORD    cchMaxClass;                       // 最长类字符串   
  44.     DWORD    cValues;                           // 项值数量(项内有多少个值)  
  45.     DWORD    cchMaxValue;                       // 最长值名称  
  46.     DWORD    cbMaxValueData;                    // 最长值数据  
  47.     DWORD    cbSecurityDescriptor;              // 安全描述符大小  
  48.     FILETIME ftLastWriteTime;                   // 最后写入时间  
  49.   
  50.     DWORD i, retCode;  
  51.   
  52.     TCHAR   achValue[MAX_VALUE_NAME];  
  53.     DWORD   cchValue = MAX_VALUE_NAME;  
  54.   
  55.     // 获取类名和值数.  
  56.     retCode = RegQueryInfoKey(  
  57.         hKey,                    // 一个已打开项的句柄(由 RegOpenKeyEx 或 RegCreateKeyEx 得到)  
  58.         achClass,                // 类名缓冲区  
  59.         &cchClassName,           // 类字符串大小   
  60.         NULL,                    // 保留值, 设为 NULL  
  61.         &cSubKeys,               // 注册表子项数量  
  62.         &cbMaxSubKey,            // 最长注册表子项大小  
  63.         &cchMaxClass,            // 最长类字符串  
  64.         &cValues,                // 项值数量  
  65.         &cchMaxValue,            // 最长值名称  
  66.         &cbMaxValueData,         // 最长值数据  
  67.         &cbSecurityDescriptor,   // 安全描述符  
  68.         &ftLastWriteTime);       // 最后写入时间  
  69.   
  70.     // 枚举注册表子项, 直到 RegEnumKeyEx 方法失败.  
  71.     if (cSubKeys)  
  72.     {  
  73.         printf("\n子项数量: %d\n", cSubKeys);  
  74.         for (i = 0; i < cSubKeys; i++)  
  75.         {  
  76.             cbName = MAX_KEY_LENGTH;  
  77.             retCode = RegEnumKeyEx( // 调用 RegEnumKeyExA 时 如果老返回 5 访问拒绝, 可尝试 RegCreateKeyEx  
  78.                 hKey,  
  79.                 i,  
  80.                 achKey,  
  81.                 &cbName,  
  82.                 NULL,  
  83.                 NULL,  
  84.                 NULL,   // 调用 RegEnumKeyExA 时, 此值设为 MAX_PATH 可解决方法返回 234 错误问题.(貌似非 NULL 都可以)  
  85.                 // 例如 DWORD cNameLen [MAX_PATH]; RegEnumKeyExA(hKey, i, achKey, cbName, NULL, NULL, cNameLen, &ftLastWriteTime);  
  86.                 &ftLastWriteTime);  
  87.             if (retCode == ERROR_SUCCESS)  
  88.             {  
  89.                 _tprintf(TEXT("(%d) %s\n"), i + 1, achKey);  
  90.             }  
  91.         }  
  92.     }  
  93.   
  94.     // 枚举项值.  
  95.   
  96.     if (cValues)  
  97.     {  
  98.         printf("\n值数量: %d\n", cValues);  
  99.   
  100.         for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)  
  101.         {  
  102.             cchValue = MAX_VALUE_NAME;  
  103.             achValue[0] = '\0';  
  104.             retCode = RegEnumValue(  
  105.                 hKey,  
  106.                 i,  
  107.                 achValue,  
  108.                 &cchValue,  
  109.                 NULL,  
  110.                 NULL,  
  111.                 NULL,  
  112.                 NULL);  
  113.             if (retCode == ERROR_SUCCESS)  
  114.             {  
  115.                 _tprintf(TEXT("(%d) %s\n"), i + 1, achValue);  
  116.             }  
  117.         }  
  118.     }  
  119. }  
  120.   
  121. int __cdecl _tmain() {  
  122.     bool bRet;  
  123.     LONG lResult;  
  124.     PVOID oldWow64State = NULL; // 无类型指针  
  125.     bRet = EnablePriviledge(SE_BACKUP_NAME);    // 这个函数让当前进程具有备份/还原的特权.  
  126.     if (bRet) {  
  127.         bRet = EnablePriviledge(SE_RESTORE_NAME);  
  128.         if (bRet) {  
  129.             HKEY hResult = NULL;  
  130.             DWORD dwDisposition;  
  131.             if (Wow64DisableWow64FsRedirection(&oldWow64State)){  
  132.   
  133.                 /*lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,    // 使用 RegOpenKeyEx 会因为权限不够无法访问部分需要高权限的注册项 
  134.                 TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles"), 
  135.                 0, 
  136.                 KEY_ALL_WOW64, 
  137.                 &hResult 
  138.                 ); 
  139.                 */  
  140.   
  141.                 lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,  
  142.                     TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles"),  
  143.                     0,  
  144.                     NULL,  
  145.                     REG_OPTION_BACKUP_RESTORE,      // 这个是重点, 传入这个参数可以直接忽视 KEY_ALL_ACCESS 这个参数的作用, 直接以备份/还原的特权去操作注册表  
  146.                     KEY_ALL_WOW64,                  // 64位系统用 KEY_ALL_ACCESS 会无法访问 64 位注册项, 关闭重定向也会失败  
  147.                     NULL,  
  148.                     &hResult,  
  149.                     &dwDisposition);  
  150.   
  151.                 RegDisableReflectionKey(hResult);  
  152.                 QueryKey(hResult);  
  153.                 RegCloseKey(hResult);  
  154.                 RegEnableReflectionKey(hResult);  
  155.             }  
  156.             Wow64RevertWow64FsRedirection(oldWow64State);  
  157.             if (lResult != ERROR_SUCCESS) {  
  158.                 return 3;  
  159.             }  
  160.             getchar();  
  161.             return 0;  
  162.         }  
  163.         else return 2;  
  164.     }  
  165.     else return 1;  
  166. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值