iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >详解C语言内核字符串拷贝与比较
  • 217
分享到

详解C语言内核字符串拷贝与比较

2024-04-02 19:04:59 217人浏览 独家记忆
摘要

在上一篇文章《驱动开发:内核字符串转换方法》中简单介绍了内核是如何使用字符串以及字符串之间的转换方法,本章将继续探索字符串的拷贝与比较,与应用层不同内核字符串拷贝与比较也需要使用内核

在上一篇文章《驱动开发:内核字符串转换方法》中简单介绍了内核是如何使用字符串以及字符串之间的转换方法,本章将继续探索字符串的拷贝与比较,与应用层不同内核字符串拷贝与比较也需要使用内核专用的api函数,字符串的拷贝往往伴随有内核内存分配,我们将首先简单介绍内核如何分配堆空间,然后再以此为契机简介字符串的拷贝与比较。

首先内核中的堆栈分配可以使用ExAllocatePool()这个内核函数实现,此外还可以使用ExAllocatePoolWithTag()函数,两者的区别是,第一个函数可以直接分配内存,第二个函数在分配时需要指定一个标签,此外内核属性常用的有两种NonPagedPool用于分配非分页内存,而PagePool则用于分配分页内存,在开发中推荐使用非分页内存,因为分页内存数量有限。

内存分配使用ExAllocatePool函数,内存拷贝可使用RtlCopyMemory函数,需要注意该函数其实是对Memcpy函数的包装。

#include <ntifs.h>

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

// PowerBy: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING ReGIStryPath)
{
	UNICODE_STRING uncode_buffer = { 0 };

	DbgPrint("hello lyshark \n");

	wchar_t * wchar_string = L"hello lyshark";

	// 设置最大长度
	uncode_buffer.MaximumLength = 1024;

	// 分配内存空间
	uncode_buffer.Buffer = (PWSTR)ExAllocatePool(PagedPool, 1024);

	// 设置字符长度 因为是宽字符,所以是字符长度的 2 倍
	uncode_buffer.Length = wcslen(wchar_string) * 2;

	// 保证缓冲区足够大,否则程序终止
	ASSERT(uncode_buffer.MaximumLength >= uncode_buffer.Length);

	// 将 wchar_string 中的字符串拷贝到 uncode_buffer.Buffer
	RtlCopyMemory(uncode_buffer.Buffer, wchar_string, uncode_buffer.Length);

	// 设置字符串长度 并输出
	uncode_buffer.Length = wcslen(wchar_string) * 2;
	DbgPrint("输出字符串: %wZ \n", uncode_buffer);

	// 释放堆空间
	ExFreePool(uncode_buffer.Buffer);
	uncode_buffer.Buffer = NULL;
	uncode_buffer.Length = uncode_buffer.MaximumLength = 0;

	DbgPrint("驱动已加载 \n");
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码输出效果:

实现空间分配

字符串结构UNICODE_STRING可以定义数组,空间的分配也可以循环进行,例如我们分配十个字符串结构,并输出结构内的参数。

#include <ntifs.h>

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

// PowerBy: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	UNICODE_STRING uncode_buffer[10] = { 0 };
	wchar_t * wchar_string = L"hello lyshark";

	DbgPrint("hello lyshark \n");

	int size = sizeof(uncode_buffer) / sizeof(uncode_buffer[0]);
	DbgPrint("数组长度: %d \n", size);

	for (int x = 0; x < size; x++)
	{
		// 分配空间
		uncode_buffer[x].Buffer = (PWSTR)ExAllocatePool(PagedPool, 1024);

		// 设置长度
		uncode_buffer[x].MaximumLength = 1024;
		uncode_buffer[x].Length = wcslen(wchar_string) * sizeof(WCHAR);
		ASSERT(uncode_buffer[x].MaximumLength >= uncode_buffer[x].Length);

		// 拷贝字符串并输出
		RtlCopyMemory(uncode_buffer[x].Buffer, wchar_string, uncode_buffer[x].Length);
		uncode_buffer[x].Length = wcslen(wchar_string) * sizeof(WCHAR);
		DbgPrint("循环: %d 输出字符串: %wZ \n", x, uncode_buffer[x]);

		// 释放内存
		ExFreePool(uncode_buffer[x].Buffer);
		uncode_buffer[x].Buffer = NULL;
		uncode_buffer[x].Length = uncode_buffer[x].MaximumLength = 0;
	}

	DbgPrint("驱动加载成功 \n");
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码输出效果:

实现字符串拷贝

此处可以直接使用RtlCopyMemory函数直接对内存操作,也可以调用内核提供的RtlCopyUnicodeString函数来实现,具体代码如下。

#include <ntifs.h>

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

// PowerBy: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark \n");

	UNICODE_STRING uncode_buffer_source = { 0 };
	UNICODE_STRING uncode_buffer_target = { 0 };

	// 该函数可用于初始化字符串
	RtlInitUnicodeString(&uncode_buffer_source, L"hello lyshark");

	// 初始化target字符串,分配空间
	uncode_buffer_target.Buffer = (PWSTR)ExAllocatePool(PagedPool, 1024);
	uncode_buffer_target.MaximumLength = 1024;

	// 将source中的内容拷贝到target中
	RtlCopyUnicodeString(&uncode_buffer_target, &uncode_buffer_source);

	// 输出结果
	DbgPrint("source = %wZ \n", &uncode_buffer_source);
	DbgPrint("target = %wZ \n", &uncode_buffer_target);

	// 释放空间 source 无需销毁
	// 如果强制释放掉source则会导致系统蓝屏,因为source是在栈上的
	RtlFreeUnicodeString(&uncode_buffer_target);

	DbgPrint("驱动加载成功 \n");

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码输出效果:

实现字符串比较

如果需要比较两个UNICODE_STRING字符串结构体是否相等,那么可以使用RtlEqualUnicodeString这个内核函数实现,该函数第三个参数是返回值类型,如果是TRUE则默认返回真,否则返回假,具体代码如下。

#include <ntifs.h>

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

// PowerBy: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark \n");

	UNICODE_STRING uncode_buffer_source = { 0 };
	UNICODE_STRING uncode_buffer_target = { 0 };

	// 该函数可用于初始化字符串
	RtlInitUnicodeString(&uncode_buffer_source, L"hello lyshark");
	RtlInitUnicodeString(&uncode_buffer_target, L"hello lyshark");

	// 比较字符串是否相等
	if (RtlEqualUnicodeString(&uncode_buffer_source, &uncode_buffer_target, TRUE))
	{
		DbgPrint("字符串相等 \n");
	}
	else
	{
		DbgPrint("字符串不相等 \n");
	}

	DbgPrint("驱动加载成功 \n");

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码输出效果:

有时在字符串比较时需要统一字符串格式,例如全部变大写以后在做比较等,此时可以使用RtlUpcaseUnicodeString函数将小写字符串为大写,然后在做比较,代码如下。

#include <ntifs.h>

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

// PowerBy: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark \n");

	UNICODE_STRING uncode_buffer_source = { 0 };
	UNICODE_STRING uncode_buffer_target = { 0 };

	// 该函数可用于初始化字符串
	RtlInitUnicodeString(&uncode_buffer_source, L"hello lyshark");
	RtlInitUnicodeString(&uncode_buffer_target, L"HELLO LYSHARK");

	// 字符串小写变大写
	RtlUpcaseUnicodeString(&uncode_buffer_target, &uncode_buffer_source, TRUE);
	DbgPrint("小写输出: %wZ \n", &uncode_buffer_source);
	DbgPrint("变大写输出: %wZ \n", &uncode_buffer_target);

	// 销毁字符串
	RtlFreeUnicodeString(&uncode_buffer_target);

	DbgPrint("驱动加载成功 \n");

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码输出效果:

以上就是详解C语言内核字符串拷贝与比较的详细内容,更多关于C语言内核字符串拷贝 比较的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解C语言内核字符串拷贝与比较

本文链接: https://www.lsjlt.com/news/168704.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 详解C语言内核字符串拷贝与比较
    在上一篇文章《驱动开发:内核字符串转换方法》中简单介绍了内核是如何使用字符串以及字符串之间的转换方法,本章将继续探索字符串的拷贝与比较,与应用层不同内核字符串拷贝与比较也需要使用内核...
    99+
    2022-11-13
  • 详解C语言内核字符串转换方法
    在内核编程中字符串有两种格式ANSI_STRING与UNICODE_STRING,这两种格式是微软推出的安全版本的字符串结构体,也是微软推荐使用的格式,通常情况下ANSI_STRIN...
    99+
    2022-11-13
  • C语言与C++中关于字符串使用的比较
    目录相似处字符串字面值C++标准库string类型相似处   C++作为C的进阶版,可以调用C的库函数。C++标准库包括了C标准库,C++头文件cctype其实就...
    99+
    2022-11-13
  • c语言中字符串与字符串数组详解
    目录字符串字符串输出输入字符串字符串常用方法字符串数组总结字符串 用双引号引起来的就是字符串,字符串由字符组成 字符串使用%s格式化输出 字符串以\0结尾,...
    99+
    2022-11-12
  • C语言字符函数与字符串函数详解
    目录本章重点前言1.strlen函数注意点1注意点22.strcpy注意点1:注意点2:注意点3:注意点4:总结本章重点 重点介绍处理字符和字符串的库函数的使用和注意事项 1.求字符...
    99+
    2022-11-12
  • C语言的变量与常量 字符字符串与转义字符详解
    目录一.变量1.1定义变量的方法1.2变量的分类1.3变量的使用二.常量2.1字面常量 2.2 const修饰的常变量 2.3#define定义的标识符常量2.4...
    99+
    2022-11-12
  • C语言数据结构与算法之字符串详解
    目录串的定义串的比较 串的抽象数据类型串的初始化相关定义初始化定长类初始化串的堆式顺序存储结构(Heap)初始化堆字符串 赋值操作比较两个堆字符串的大小 串的定义...
    99+
    2022-11-12
  • C语言的字符串函数,内存函数笔记详解
    目录strlenstrlen模拟实现strcpystrcpy的模拟实现strcatstrcat的模拟实现strcmpstrcmp模拟实现strstrstrstr模拟实现strncpy...
    99+
    2022-11-12
  • C语言字符串函数介绍与模拟实现详解
    目录2. strcpy(复制字符串)2.1 strncpy函数2.2 模拟实现strcpy3. strcat (追加字符)3.1 strncat 函数3.2 模拟实现strcat4....
    99+
    2022-11-12
  • C语言超详细讲解字符串函数和内存函数
    目录字符串函数长度不受限制的字符串函数strlenstrcpystrcatstrcmp长度受限制的字符串函数介绍strncpystrncatstrncmp字符串查找以及错误报告str...
    99+
    2022-11-13
  • C语言字符串与字符数组面试题中最易错考点详解
    目录一、'\0'对字符串与字符数组的重要性二、strlen与sizeof有什么区别三、含转义字符求字符串长度本文介绍字符串与字符数组中最易错的3个考点。若以后遇到其他...
    99+
    2022-11-13
  • C语言sizeof与字符串处理与动态内存分配及main函数参数详解
    目录常用的字符串处理函数(标准库里面的)sizeof 求字节运算符动态内存分配函数main的参数问题常用的字符串处理函数(标准库里面的) strlen : 用来求一个字符串的长度 &...
    99+
    2022-11-13
  • C语言详解如何应用模拟字符串和内存函数
    目录1.strlen 求字符串长度使用案例:1.计数法2.不创建临时变量计数器-递归3.指针-指针的方式2.长度不受限制的字符串函数1.strcpy使用案例:模拟实现:2.strca...
    99+
    2022-11-13
  • 一篇文章带你了解C语言的一些重要字符串与内存函数
    目录一.字符串函数1. 求字符串长度的strlen2.比较字符串大小的strcmp3.复制字符串的strcpy4.追加字符串的strcat5.查找字符串函数的strstr二、内存函数...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作