RW-Everything的RwDrv.sys驱动调用

RW-Everything的RwDrv.sys驱动调用


一、RwDrv.sys

RW-Everything是一个硬件底层的工具,可用于物理内存、BIOS、PCI和IO端口的查看和修改,其基于驱动RwDrv.sys来实现,利用这个驱动可以实现系统的侵入。


二、示例代码

  • 使用服务来加载RwDrv驱动
  • 打开Win Object对象,通过调用DeviceIoControl通信调用
cpp 复制代码
#include <Windows.h>
#include <stdio.h>

#define RW_DRIVER_ID							"RwDrv"

// type of access: U8 = 0; U16 = 1, U32 =2, ref to READ_REGISTER_BUFFER_UCHAR / USHORT / ULONG
typedef struct {
	DWORD64 physicalAddress;
	DWORD size;
	DWORD access;
	DWORD64 buffer;
} PhysRw_t;

typedef struct {
	DWORD low;
	DWORD pad;
	DWORD reg;
	DWORD high;
} MSRRw_t;

HANDLE hDrv;

DWORD LoadDriver()
{
	TCHAR sDrv[MAX_PATH] = {0};
	GetFullPathName("RwDrv.sys", MAX_PATH, sDrv, NULL);
	
	//check driver exist
	WIN32_FIND_DATA	findData;
	HANDLE hFile = FindFirstFile(sDrv, &findData);
	if(hFile == INVALID_HANDLE_VALUE)
	{
		printf("Driver File Doesn't Exist, errno = %d.\n", GetLastError());
		return -1;
	}

	//establishes a connection to the service control manager
	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(hSCM == NULL)
	{
		printf("Open SCM Failed, errno = %d.\n", GetLastError());
		return -1;
	}
	
	//create a service object and add to SCM
	SC_HANDLE hSrv = CreateService(hSCM, RW_DRIVER_ID, RW_DRIVER_ID, SC_MANAGER_ALL_ACCESS, 
		SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, 
		sDrv, NULL, NULL, NULL, NULL, NULL);
	if(hSrv == NULL)
	{
		if(GetLastError() != ERROR_SERVICE_EXISTS)
		{
			CloseHandle(hSCM);
			printf("Create Service Failed, errno = %d.\n", GetLastError());
			return -1;
		}
	}

	//open service
	hSrv = OpenService(hSCM, RW_DRIVER_ID, SERVICE_ALL_ACCESS);
	if(hSrv == NULL)
	{
		CloseHandle(hSCM);
		printf("Open Service Failed, errno = %d.\n", GetLastError());
		return -1;
	}
	
	//start service
	if(!StartService(hSrv, 0, NULL))
	{
		if(GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
		{
			CloseHandle(hSCM);
			CloseServiceHandle(hSrv);
			printf("Start Service Failed, errno = %d.\n", GetLastError());
			return -1;
		}
	}

	//create or open device object, see "Win32 Device Namespaces" section 
	//of https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
	//and https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
	hDrv = CreateFile("\\\\.\\"RW_DRIVER_ID, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hDrv == INVALID_HANDLE_VALUE)
	{
		CloseHandle(hSCM);
		CloseServiceHandle(hSrv);
		printf("Create File Failed, errno = %d.\n", GetLastError());
		return -1;
	}

	return 0;
}

DWORD UnloadDriver()
{
	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(hSCM == NULL)
	{
		printf("Open SCM Failed, errno = %d.\n", GetLastError());
		return -1;
	}

	SC_HANDLE hSrv = OpenService(hSCM, RW_DRIVER_ID, SERVICE_ALL_ACCESS);
	if(hSrv == NULL)
	{
		CloseHandle(hSCM);
		printf("Open Service Failed, errno = %d.\n", GetLastError());
		return -1;
	}

	SERVICE_STATUS status;
	if (!ControlService(hSrv, SERVICE_CONTROL_STOP, &status)) 
	{
		CloseHandle(hSCM);
		CloseHandle(hDrv);
		printf("Stop Service Failed, errno = %d.\n", GetLastError());
		return -1;
	}

	CloseHandle(hSCM);
	CloseHandle(hDrv);

	return 0;
}

BOOL isElevated() {
	HANDLE hToken = NULL;
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
		TOKEN_ELEVATION Elevation;
		DWORD cbSize = sizeof(TOKEN_ELEVATION);
		if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) {
			return Elevation.TokenIsElevated;
		}
	}
	if (hToken) {
		CloseHandle(hToken);
	}
	return FALSE;
}

void readMem(DWORD64 address, const DWORD64* buffer, DWORD size, DWORD access = 0) 
{
	PhysRw_t tPhyMem;
	tPhyMem.physicalAddress = address;
	tPhyMem.size = size;
	tPhyMem.access = access;
	tPhyMem.buffer = (DWORD64)buffer;
	DeviceIoControl(hDrv, 0x222808, &tPhyMem, sizeof(tPhyMem), &tPhyMem, sizeof(tPhyMem), NULL, NULL);
}
void writeMem(DWORD64 address, const DWORD64* buffer, DWORD size, DWORD access = 0) 
{
	PhysRw_t tPhyMem;
	tPhyMem.physicalAddress = address;
	tPhyMem.size = size;
	tPhyMem.access = access;
	tPhyMem.buffer = (DWORD64)buffer;
	DeviceIoControl(hDrv, 0x22280C, &tPhyMem, sizeof(tPhyMem), NULL, 0, NULL, NULL);
}

void readMSR(int reg, LARGE_INTEGER& value) 
{
    MSRRw_t tMSR;
	tMSR.low = 0;
	tMSR.pad = 0;
	tMSR.reg = reg;	
	tMSR.high = 0;

    DeviceIoControl(hDrv, 0x222848, &tMSR, sizeof(tMSR), &tMSR, sizeof(tMSR), NULL, NULL);

	value.LowPart = tMSR.low;
	value.HighPart = tMSR.high;
}
void writeMSR(int reg, LARGE_INTEGER& value) {
    MSRRw_t tMSR;
	ZeroMemory(&tMSR, sizeof(tMSR));
    tMSR.reg = reg;
    tMSR.low = value.LowPart;
    tMSR.high= value.HighPart;
	
    DeviceIoControl(hDrv, 0x22284C, &tMSR, sizeof(tMSR), &tMSR, sizeof(tMSR), NULL, NULL);
}

int main()
{
	//Check UAC
	if(isElevated() == FALSE)
	{
		printf("This program requires run as administrator.\n");
		return 0;
	}

	LoadDriver();

	//Read Mem
	DWORD64 buf[1] = {0};
	readMem(0x0000CCCC, buf, 1);
	/*
	DWORD64 buf[16] = {0};
	readMem(0x0000CCCC, buf, 2, 1);
	*/
	printf("read mem = %x\n", buf[0]);
	
	//Read Msr
	LARGE_INTEGER value;
	readMSR(0x20, value);
	printf("read msr high part = %08x, low part = %08x\n", value.HighPart, value.LowPart);

	UnloadDriver();

	return 0;
}

三、总结

合法的签名驱动可以调用内核的很多方法来实现系统或硬件的控制,但对于一些情况我们无法申请签名,可以借用第三方驱动来实现,其次,这种方式是一种高风险的漏洞。

相关推荐
Ajiang282473530430 分钟前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
梓仁沐白2 小时前
ubuntu+windows双系统切换后蓝牙设备无法连接
windows·ubuntu
‘’林花谢了春红‘’5 小时前
C++ list (链表)容器
c++·链表·list
九鼎科技-Leo6 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
机器视觉知识推荐、就业指导7 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
Yang.999 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王9 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_9 小时前
C++自己写类 和 运算符重载函数
c++
我不瘦但很逗9 小时前
Windows下使用DBeaver连接云数据库(MySQL)
数据库·windows