读取注册表中的REG_QWORD和REG_BINARY(二进制)类型数据

news2024/9/20 18:54:02

读取注册表中的REG_QWORD和REG_BINARY二进制类型数据

    • 发现的问题
    • 注册表中的一些概念(统一认识)
    • 读取代码(字节数据大于8的会显示f开头的前缀)
    • 说明(备注)
    • 改进代码
    • 参考链接


发现的问题

首先我们要明确,REG_QWORD类型的数据,甚至某些REG_DWORD类型的数据,在win32程序中是读不出来的,例如下图中的1、CurrentMajorVersionNumber这类简单的REG_DWORD可以顺利在win32环境下读出来,而InstallDate的REG_DWORD却读不出来;
InstallTime这类REG_QWORD类型、REG_BINARY这类REG_BINARY类型的数据在win32环境下函数RegQueryInfoKey根本就不读取它(不理它、识别不了):

在这里插入图片描述
在x64环境下,函数RegQueryInfoKey能够识别判断出REG_QWORD和REG_BINARY这两种类型的数据。


注册表中的一些概念(统一认识)

注册表的结构是一个树状结构,一个(key,或称“项”)就是一个节点,子键(subkey)就是这个节点的子节点,子健也是键。
键的一条属性被称为一个value(值项)value由名称、类型、数据类型和数据组成
一个键可以有多个值,每个值的名称不同,如果值名称是空,则该值为该键的默认值。
这里所说的项就是键key,子项就是子键subkey,键的一条属性被称为一个value(值项),最底层的子键里面的项其实就是值项value,value由名称、类型、数据类型和数据组成,这里所说的值名对应的就是值项的名称,这里所说的值数据就是值项的数据)


读取代码(字节数据大于8的会显示f开头的前缀)

//m_list_key和m_list_value是两个CListCtrl控件变量,分别用来显示读取的注册表中的键和值项;m_strPath是CString类型的注册表键值路径。
//测试路径:SOFTWARE\Microsoft\Windows NT\CurrentVersion
//打开父键
	//m_strPath其实就是编辑框里面的内容(例如SYSTEM或者SYSTEM\CurrentControlSet\Services)
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,m_strPath,0,KEY_ALL_ACCESS,&hKey)==ERROR_SUCCESS)//打开
	{
		DWORD dwIndex=0,NameSize,NameCnt,NameMaxLen,Type;
		DWORD KeySize,KeyCnt,KeyMaxLen,MaxDateLen,DataSize;
		//这就是枚举了
		//如果某一个键的值项value为空(例如HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT只有一条名称为默认、
		//类型为REG_SZ、数据是数值未设置的值项)的话,NameCnt、NameMaxLen、MaxDateLen都为空,由于Windows NT下面只有一个
		//键CurrentVersion,该键名称一共14个字符(不包括结尾的空字符),所以KeyMaxLen的值就是0xe
		//当键为HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion的时候,NameCnt的为0x19,
		if(RegQueryInfoKey(hKey,NULL,NULL,NULL,&KeyCnt,&KeyMaxLen,NULL,&NameCnt,&NameMaxLen,&MaxDateLen,NULL,NULL)==ERROR_SUCCESS)
		{
			KeySize=KeyMaxLen + 1;
			char * tmp=new  char[KeySize];
			//枚举得到的每一个键
			for(dwIndex=0;dwIndex<KeyCnt;dwIndex++)		//枚举项
			{
				ZeroMemory(tmp,KeySize);
				DWORD i=KeySize;
				RegEnumKeyEx(hKey,dwIndex,tmp,&i,NULL,NULL,NULL,NULL);
				m_list_key.InsertItem(0,tmp,0);
			}
			delete[] tmp;

			tmp=new char [NameMaxLen+1];
			char *tmpData=new char[MaxDateLen+1];
			
			CString str;

			//-----------这里开始枚举键值-------------------------------------
			for(dwIndex=0;dwIndex<NameCnt;dwIndex++)
			{
				str.Empty();
				ZeroMemory(tmp, NameMaxLen+1);
				ZeroMemory(tmpData, MaxDateLen+1);
				NameSize = NameMaxLen + 1;		//注意,因为每执行一次RegEnumValue,NameSize和DataSize都会
				DataSize = MaxDateLen + 1;		//变成实际的缓冲区大小,所以这里每次循环都要重新赋值
				LSTATUS status = ::RegEnumValue(hKey,dwIndex,tmp,&NameSize,NULL,&Type,(BYTE*)tmpData,&DataSize);//读取键值
				if(status != ERROR_SUCCESS)
				{
					break;
				}
				m_list_value.InsertItem(0,tmp,0);     //写入名称(即值名称)
				//键值的类型不同我们应该处理一下,显示不同类型的字符
				if(Type==REG_SZ)
				{
					m_list_value.SetItemText(0,1,"REG_SZ");
					//插入数值
					str=tmpData;
				}
				if(Type==REG_EXPAND_SZ)
				{
					m_list_value.SetItemText(0,1,"REG_EXPAND_SZ");
					//插入数值
					str=tmpData;
				}
				if(Type==REG_DWORD)
				{
					m_list_value.SetItemText(0,1,"REG_DWORD");
					str.Format("0x%08x",*(PDWORD)tmpData);
				}
				if(Type==REG_QWORD)
				{
					m_list_value.SetItemText(0,1,"REG_QWORD");
					str.Format("0x%llx",*(PQWORD)(tmpData));
				}
				if(Type==REG_BINARY)
				{
					m_list_value.SetItemText(0,1,"REG_BINARY");
					CString cstr;
					size_t i = 0;
					for(i = 0; i < DataSize; i++)
					{
						cstr.Empty();
						cstr.Format(_T("%hx"), tmpData[i]);
						//插入数值
						str += cstr + " ";
					}
				}

				m_list_value.SetItemText(0,2,str);
			}

			RegCloseKey(hKey);
			return ;
		}
	}

说明(备注)

if(Type==REG_QWORD)
				{
					m_list_value.SetItemText(0,1,"REG_QWORD");
					str.Format("0x%llx",*(PQWORD)(tmpData));
				}

在这里插入图片描述
因为REG_QWORD占64位,所以字符串格式化符选用0x%llx即可打印完整。

if(Type==REG_BINARY)
				{
					m_list_value.SetItemText(0,1,"REG_BINARY");
					CString cstr;
					size_t i = 0;
					for(i = 0; i < DataSize; i++)
					{
						cstr.Empty();
						cstr.Format(_T("%hx"), tmpData[i]);
						//插入数值
						str += cstr + " ";
					}
				}

在这里插入图片描述
而DigitalProductId这类二进制数据的长度也是在函数RegQueryInfoKey中获取的(切记获取的这个长度不包括结尾的空字符0,所以我们为了读取该数据分配的空间大小,要在这个长度上加1);
通过函数RegEnumValue获取的二进制数据在内存中的为:

在这里插入图片描述
我们看到这些内存中的十六进制数据,通过一个for循环一个一个用cstr.Format(_T("%02x"), tmpData[i]);输出的话:

CString cstr;
					size_t i = 0;
					for(i = 0; i < DataSize; i++)
					{
						cstr.Empty();
						cstr.Format(_T("%02x"), tmpData[i]);
						//插入数值
						str += cstr + " ";
					}

效果如下:

在这里插入图片描述
我们看到输出中a4变成了ffffffa4,这是由于a4、d2这类十六进制数据的二进制位是以1开头导致的;
所以我们可以强制只输出2个十六进制字符,即只输出1个字节:
cstr.Format(_T("%hx"), tmpData[i]);

通过输出我们发现ffffffa4变为了ffa4,仍然达不到我们的目标。

改进代码

//测试路径:SOFTWARE\Microsoft\Windows NT\CurrentVersion
if(Type==REG_BINARY)
				{
					m_list_value.SetItemText(0,1,"REG_BINARY");
					CString cstr;
					DWORD dwData = 0;
					
					size_t i = 0;
					for(i = 0; i < DataSize; i++)
					{
						cstr.Empty();
						//cstr.Format(_T("%02hx"), tmpData[i]);
						dwData = tmpData[i];
						UINT temp = 0;
						while(dwData > 0)
						{
							temp = dwData % 16;
							if(temp < 10)
								cstr.AppendChar(temp + '0');
							else
								cstr.AppendChar('a' + temp - 10);
							dwData = dwData >> 4;
						}
						
						cstr.AppendChar('0');
						cstr.AppendChar('0');

						cstr.MakeReverse();
						//插入数值
						str += cstr.Right(2) + " ";
					}
				}

参考链接

int转string时候保留前导位0

读取注册表REG_BINARY(二进制)类型的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448873.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Jetpack】DataBinding 架构组件 ⑥ ( RecyclerView 数据绑定 )

文章目录 一、RecyclerView 数据绑定核心要点1、启用数据绑定 / 导入依赖2、RecyclerView 条目 DataBinding 布局3、自定义 RecyclerView.Adapter 适配器要点 ( 本博客重点 ★ ) 二、RecyclerView 数据绑定源码示例1、build.gradle 构建脚本 ( 启用数据绑定 / 导入依赖 )2、主界…

ggplot中的注释图层annotate

文章目录 介绍利用注释层添加图形利用注释层添加文本利用注释层添加公式 介绍 ggplot作图包中除了常见的geom图层外&#xff0c;还有一个annotate的注释图层&#xff0c;实现对作图对象的额外添加&#xff0c;其添加要素不在ggplot()所接受的数据框中。 利用注释层添加图形 …

家政服务APP小程序开发功能详解

随着人们生活水平的提高&#xff0c;对家政服务的要求也越来越高。而传统的到家政公司寻找服务人员的方法显然已经无法满足人们需求&#xff0c;取而代之的是线上预约家政服务。家政服务App小程序软件可以满足用户在线预约&#xff0c;还可以根据自己的需求定制家政服务、选择家…

【Hadoop-CosDistcp】通过CosDistcp的方式迁移Cos中的数据至HDFS

【Hadoop-CosDistcp】通过CosDistcp的方式迁移Cos中的数据至HDFS 1&#xff09;功能说明2&#xff09;使用环境3&#xff09;下载与安装4&#xff09;原理说明5&#xff09;参数说明6&#xff09;使用示例7&#xff09;迁移 Cos 中的数据至 HDFS 及数据校验7.1.数据迁移7.2.数据…

【Unity入门】16.脚本引用组件

【Unity入门】脚本引用组件 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity入门系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;脚本引用普通组件 &#xff08;1&#xff09;点击控制音频播放 还记得我们的车载音乐AudioSource吗&#xff1f;…

zabbix搭建

1.环境 本实验使用一台centos7主机&#xff0c;关闭了firewalld和selinux服务&#xff0c;zabbix版本为5.0版本&#xff0c;mysql使用版本为5.7版本 若要搭建6.0以上版本的zabbix&#xff0c;则需要使用mysql 8.0以上的版本 其它版本的zabbix可参考zabbix官网:Download and…

YOLOv5+单目实现三维跟踪(python)

YOLOv5单目跟踪&#xff08;python&#xff09; 1. 目标跟踪2. 测距模块2.1 设置测距模块2.2 添加测距 3. 主代码4. 实验效果 相关链接 1. YOLOv5单目测距&#xff08;python&#xff09; 2. YOLOv7单目测距&#xff08;python&#xff09; 3. YOLOv7单目跟踪&#xff08;pytho…

C++练级之初级:第四篇

C练级之初级&#xff1a;第四篇 引用 C练级之初级&#xff1a;第四篇1.引用1.1引用的介绍1.2引用的使用场景1.3常引用 2.引用的底层3.引用的与指针的比较 总结 1.引用 1.1引用的介绍 &#x1f914;首先还是一个问题&#xff0c;引用是解决C语言什么不足&#xff1f; 指针在&am…

Python自动化sql注入:布尔盲注

在sql注入时&#xff0c;使用python脚本可以大大提高注入效率&#xff0c;这里演示一下编写python脚本实现布尔盲注的基本流程&#xff1a; 演示靶场&#xff1a;sqli-labs 布尔盲注 特点&#xff1a;没有回显没有报错&#xff0c;但根据sql语句正常与否返回不同结果&#x…

新手做电商直播带货怎么和快递合作谈价格

新手做电商直播带货怎么和快递合作谈价格达人带货一般怎样的合作模式&#xff1f;#达人带货 #直播带货 #红人 #百收网 跟快递谈价其实是有方法的&#xff0c;快递的价格不是说不能打下来&#xff0c;就是需要你们多一点点的心机。这个视频我就再给你们补充三个方法&#xff0c;…

HCIP之STP

企业网三层架构 线路冗余—二层网络桥接环路 因为路由器的路由表是由相对完善的计算所得&#xff0c;且存在防环规则&#xff1b;故路由器物理链路上实施备份时&#xff0c;一般不会出现环路&#xff1b;但交换转发数据依赖MAC表&#xff08;CAM表&#xff09;&#xff0c;该表…

【模式识别4】YOLO目标检测数据集xml格式转txt格式

YOLO目标检测数据集xml格式转txt格式 1. 转换前的xml格式2. xml格式转txt格式代码2.1 源代码2.2 需要修改的地方 3. 转换后的txt格式 代码资源&#xff1a;voc2txt.py 1. 转换前的xml格式 如果我们使用LabelImg工具标注数据集&#xff0c;生成的xml文件如下&#xff1a; xml…

Linux运维:推荐八款Linux远程连接工具

目录 2、XShell 3、SecureCRT 4、PuTTY 5、WindTerm 6、iTerm2 7、MobaXterm 8、Termius 今天给大家推荐八款Linux远程连接工具&#xff0c;非常实用&#xff0c;希望对大家能有所帮助&#xff01; 1、NxShell NxShell是一款开源的Linux远程管理工具&#xff0c;是我日…

Spring Boot 接口加解密

1. 介绍 在我们日常的Java开发中&#xff0c;免不了和其他系统的业务交互&#xff0c;或者微服务之间的接口调用 如果我们想保证数据传输的安全&#xff0c;对接口出参加密&#xff0c;入参解密。 但是不想写重复代码&#xff0c;我们可以提供一个通用starter&#xff0c;提…

【python数据可视化】基于networkx的10个绘图技巧

一、说明 networkx在02年5月产生&#xff0c;是用python语言编写的软件包&#xff0c;便于用户对复杂网络进行创建、操作和学习。利用networkx可以以标准化和非标准化的数据格式存储网络、生成多种随机网络和经典网络、分析网络结构、建立网络模型、设计新的网络算法、进行网络…

解决java.lang.IllegalStateException: Failed to load ApplicationContext错误~

错误描述&#xff1a; Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [D:\SSM\SSM_3.22\spring_transaction\target\classes\spring_txAnnotation\Controller\BookController.class]; nested …

装饰器模式C++用法示例

六.装饰器模式 一.装饰器模式1.原理2.适用场景 二.C程序示例1.语法组成2.C示例 一.装饰器模式 1.原理 装饰器模式是一种结构性设计模式&#xff0c;其目的是通过包装对象来扩展其行为而不改变其接口。该模式可以动态地将责任附加到对象上&#xff0c;从而提供一种灵活的替代方…

SQL Server基础 第三章 数据表基本操作(增删改查,不允许保存更改异常!)

往表里插数据我们现在有两种方式第一种是编辑直接修改&#xff0c;第二种是通过查询来修改数据 两种方法的区别 第一种更直接&#xff0c;如果数据量小那么直接改就好了&#xff0c;那如果数据量稍微庞大我们就需要用新建查询来进行表内容的修改了&#xff01;&#xff01;&a…

【Linux】进程信号 --- 信号的产生 保存 捕捉递达

被爱情困住的是傻子 文章目录 一、信号的预备知识1.通过生活例子来理解信号2.迁移到进程上来理解信号 二、信号的发送&#xff08;修改PCB的信号位图&#xff09;1.通过键盘发送信号&#xff08;kill指令 和 热键&#xff09;2.通过系统调用发送信号&#xff08;kill系统调用 和…

前端技术的miniui 和bootstartp

前端技术的miniui 和bootstartp 目录概述需求&#xff1a; 设计思路实现思路分析1.前端技术boostatrp2.miniui: 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better re…