详解C语言内核字符串转换方法
作者:lyshark 发布时间:2022-12-09 13:53:55
在内核编程中字符串有两种格式ANSI_STRING
与UNICODE_STRING
,这两种格式是微软推出的安全版本的字符串结构体,也是微软推荐使用的格式,通常情况下ANSI_STRING
代表的类型是char *
也就是ANSI多字节模式的字符串,而UNICODE_STRING
则代表的是wchar*
也就是UNCODE类型的字符,如下文章将介绍这两种字符格式在内核中是如何转换的。
在内核开发模式下初始化字符串也需要调用专用的初始化函数,如下分别初始化ANSI和UNCODE字符串,我们来看看代码是如何实现的。
#include <ntifs.h>
#include <ntstrsafe.h>
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint("驱动卸载成功 \n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
// 定义内核字符串
ANSI_STRING ansi;
UNICODE_STRING unicode;
UNICODE_STRING str;
// 定义普通字符串
char * char_string = "hello lyshark";
wchar_t *wchar_string = (WCHAR*)"hello lyshark";
// 初始化字符串的多种方式
RtlInitAnsiString(&ansi, char_string);
RtlInitUnicodeString(&unicode, wchar_string);
RtlUnicodeStringInit(&str, L"hello lyshark");
// 改变原始字符串(乱码位置,此处仅用于演示赋值方式)
char_string[0] = (CHAR)"A"; // char类型每个占用1字节
char_string[1] = (CHAR)"B";
wchar_string[0] = (WCHAR)"A"; // wchar类型每个占用2字节
wchar_string[2] = (WCHAR)"B";
// 输出字符串 %Z
DbgPrint("输出ANSI: %Z \n", &ansi);
DbgPrint("输出WCHAR: %Z \n", &unicode);
DbgPrint("输出字符串: %wZ \n", &str);
DbgPrint("驱动加载成功 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
代码输出效果:
内核中还可实现字符串与整数之间的灵活转换,内核中提供了RtlUnicodeStringToInteger
这个函数来实现字符串转整数,与之对应的RtlIntegerToUnicodeString
则是将整数转为字符串这两个内核函数也是非常常用的。
#include <ntifs.h>
#include <ntstrsafe.h>
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint("驱动卸载成功 \n");
}
// Power: lyshark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
NTSTATUS flag;
ULONG number;
DbgPrint("hello lyshark \n");
UNICODE_STRING uncode_buffer_source = { 0 };
UNICODE_STRING uncode_buffer_target = { 0 };
// 字符串转为数字
// By:LyShark
RtlInitUnicodeString(&uncode_buffer_source, L"100");
flag = RtlUnicodeStringToInteger(&uncode_buffer_source, 10, &number);
if (NT_SUCCESS(flag))
{
DbgPrint("字符串 -> 数字: %d \n", number);
}
// 数字转为字符串
uncode_buffer_target.Buffer = (PWSTR)ExAllocatePool(PagedPool, 1024);
uncode_buffer_target.MaximumLength = 1024;
flag = RtlIntegerToUnicodeString(number, 10, &uncode_buffer_target);
if (NT_SUCCESS(flag))
{
DbgPrint("数字 -> 字符串: %wZ \n", &uncode_buffer_target);
}
// 释放堆空间
RtlFreeUnicodeString(&uncode_buffer_target);
DbgPrint("驱动加载成功 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
代码输出效果:
继续看另一种转换模式,将UNICODE_STRING
结构转换成ANSI_STRING
结构,代码中调用了RtlUnicodeStringToAnsiString
内核函数,该函数也是微软提供的。
#include <ntifs.h>
#include <ntstrsafe.h>
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint("驱动卸载成功 \n");
}
// Power: lyshark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n");
UNICODE_STRING uncode_buffer_source = { 0 };
ANSI_STRING ansi_buffer_target = { 0 };
// 初始化 UNICODE 字符串
RtlInitUnicodeString(&uncode_buffer_source, L"hello lyshark");
// 转换函数
NTSTATUS flag = RtlUnicodeStringToAnsiString(&ansi_buffer_target, &uncode_buffer_source, TRUE);
if (NT_SUCCESS(flag))
{
DbgPrint("ANSI: %Z \n", &ansi_buffer_target);
}
// 销毁ANSI字符串
RtlFreeAnsiString(&ansi_buffer_target);
DbgPrint("驱动加载成功 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
代码输出效果:
如果将上述过程反过来,将ANSI_STRING
转换为UNICODE_STRING
结构,则需要调用RtlAnsiStringToUnicodeString
这个内核专用函数实现。
#include <ntifs.h>
#include <ntstrsafe.h>
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint("驱动卸载成功 \n");
}
// Power: lyshark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n");
UNICODE_STRING uncode_buffer_source = { 0 };
ANSI_STRING ansi_buffer_target = { 0 };
// 初始化字符串
RtlInitString(&ansi_buffer_target, "hello lyshark");
// 转换函数
NTSTATUS flag = RtlAnsiStringToUnicodeString(&uncode_buffer_source, &ansi_buffer_target, TRUE);
if (NT_SUCCESS(flag))
{
DbgPrint("UNICODE: %wZ \n", &uncode_buffer_source);
}
// 销毁UNICODE字符串
RtlFreeUnicodeString(&uncode_buffer_source);
DbgPrint("驱动加载成功 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
代码输出效果:
如上代码是内核通用结构体之间的转换类型,又是还需要将各类结构体转为普通的字符类型,例如下方的两个案例:
例如将UNICODE_STRING
转为 CHAR*
类型。
#define _CRT_SECURE_NO_WARNINGS
#include <ntifs.h>
#include <windef.h>
#include <ntstrsafe.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 };
ANSI_STRING ansi_buffer_target = { 0 };
char szBuf[1024] = { 0 };
// 初始化 UNICODE 字符串
RtlInitUnicodeString(&uncode_buffer_source, L"hello lyshark");
// 转换函数
NTSTATUS flag = RtlUnicodeStringToAnsiString(&ansi_buffer_target, &uncode_buffer_source, TRUE);
if (NT_SUCCESS(flag))
{
strcpy(szBuf, ansi_buffer_target.Buffer);
DbgPrint("输出char*字符串: %s \n", szBuf);
}
// 销毁ANSI字符串
RtlFreeAnsiString(&ansi_buffer_target);
DbgPrint("驱动加载成功 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
代码输出效果:
如果反过来,将 CHAR*
类型转为UNICODE_STRING
结构呢,可以进行中转最终转为UNICODE_STRING
结构体。
#define _CRT_SECURE_NO_WARNINGS
#include <ntifs.h>
#include <windef.h>
#include <ntstrsafe.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 };
ANSI_STRING ansi_buffer_target = { 0 };
// 设置CHAR*
char szBuf[1024] = { 0 };
strcpy(szBuf, "hello lyshark");
// 初始化ANSI字符串
RtlInitString(&ansi_buffer_target, szBuf);
// 转换函数
NTSTATUS flag = RtlAnsiStringToUnicodeString(&uncode_buffer_source, &ansi_buffer_target, TRUE);
if (NT_SUCCESS(flag))
{
DbgPrint("UNICODE: %wZ \n", &uncode_buffer_source);
}
// 销毁UNICODE字符串
RtlFreeUnicodeString(&uncode_buffer_source);
DbgPrint("驱动加载成功 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
代码输出效果:
来源:https://www.cnblogs.com/LyShark/p/16739228.html


猜你喜欢
- 本文实例讲述了Android创建或升级数据库时执行的语句,如果是创建或升级数据库,请使用带List参数的构造方法,带SQL语句的构造方法将在
- 1.launch启动协程fun main() = runBlocking { launch { &
- 异步操作C++11为异步操作提供了4个接口std::future : 异步指向某个任务,然后通过future特性去获取任务函数的返回结果。s
- 前言当我们在手机上使用360安全卫士时,手机屏幕上时刻都会出现一个小浮动窗口,点击该浮动窗口可跳转到安全卫士的操作界面,而且该浮动窗口不受其
- 1.下载AndroidStudioAndroidStudio官网下载地址:http://developer.android.com/intl
- 上一篇:C# 异步多线程入门到精通之Thread篇下一篇:异步多线程之入Task,待更新启动线程池线程ThreadPool 提供的 API
- 1.简介使用线程池可以避免线程的频繁创建以及销毁。JAVA中提供的用于实现线程池的API:Executor、ExecutorService、
- 相比于直线检测,直线拟合的最大特点是将所有数据只拟合出一条直线void fitLine( InputArray points, Output
- 说明一下性能方面 还可以接受 循环1000次普通Switch是用了0.001秒 ,扩展函数为0.002秒 , 如果是大项目在有负
- 显示当前运行java代码的运行时的各种参数。不带显String操作。package systeminfo;import java.util.
- RestTemplate反序列化嵌套对象假设某个接口返回的数据如下格式{ "msg" : "ok&
- 多线程@Async的使用体验场景导入:可以将大批量的数据insert操作采用多线程的方式并行执行第三方服务的接口调用:由于存在个别第三方服务
- 一、IO流的分类字符流ReaderInputStreamReader(节点流)BufferedReader(处理流)WriterOutput
- HandlerThread 简介:我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了。
- 大数据量操作的场景大致如下:数据迁移数据导出批量处理数据在实际工作中当指定查询数据过大时,我们一般使用分页查询的方式一页一页的将数据放到内存
- //FilterKalman.csnamespace FusionFiltering{public class FilterKalman &
- 前言解释:之前用的ScreenToGif录屏,因为上传的.gif最大不超过5MB,所以做了不少删帧和色彩弱化等处理,这才导致色彩看上去不是很
- 事件缘由:一个主项目“图说美物”,另外一个子功能是品牌商的入驻功能,是跟主项目分开的项目,为了共享登录的用户信息,而实现session共享,
- PDF文件包(Portfolio)允许用户将多种不同类型的文件如Word、Excel、PDF、PowerPoint和图片等集合到一个PDF文
- Android Init进程对信号的处理流程在Android中,当一个进程退出(exit())时,会向它的父进程发送一个SIGC