无驱动执行Ring0代码

 // 原理:通过/Device/PhysicalMemory修改NtVdmControl入口,跳转到Ring0Code
//************************************************************************
#include <Windows.h>
#include <Ntsecapi.h>
#include <Aclapi.h>

#pragma comment (lib,"ntdll.lib")        // Copy From DDK
#pragma comment (lib,"Kernel32.lib")
#pragma comment (lib,"Advapi32.lib")


//------------------ 数据类型声明开始 --------------------//
typedef struct _SYSTEM_MODULE_INFORMATION {
     ULONG Reserved[2];
     PVOID Base;
     ULONG Size;
     ULONG Flags;
     USHORT Index;
     USHORT Unknown;
     USHORT LoadCount;
     USHORT ModuleNameOffset;
     CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef struct _OBJECT_ATTRIBUTES {
     ULONG Length;
     HANDLE RootDirectory;
     PUNICODE_STRING ObjectName;
     ULONG Attributes;
     PVOID SecurityDescriptor;
     PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

typedef enum _SECTION_INHERIT {
     ViewShare = 1,
     ViewUnmap = 2
} SECTION_INHERIT;

typedef struct _MY_PROCESS_INFO {
     ULONG PID;
     ULONG KPEB;
     ULONG CR3;
     CHAR Name[16];
     ULONG Reserved;
} MY_PROCESS_INFO, *PMY_PROCESS_INFO;

typedef long NTSTATUS;
//------------------ 数据类型声明结束 --------------------//

//--------------------- 预定义开始 -----------------------//
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS               0x00000000
#define STATUS_UNSUCCESSFUL          0xC0000001
#define STATUS_NOT_IMPLEMENTED       0xC0000002
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define STATUS_INVALID_PARAMETER     0xC000000D
#define STATUS_ACCESS_DENIED         0xC0000022
#define STATUS_BUFFER_TOO_SMALL      0xC0000023
#define OBJ_KERNEL_HANDLE            0x00000200
#define SystemModuleInformation      11

#define InitializeObjectAttributes( p, n, a, r, s ) { /     /* 注意,由于php标签过滤,以下6行缺少续行符/ */
     (p)->Length = sizeof( OBJECT_ATTRIBUTES );         
     (p)->RootDirectory = r;                            
     (p)->Attributes = a;                               
     (p)->ObjectName = n;                               
     (p)->SecurityDescriptor = s;                       
     (p)->SecurityQualityOfService = NULL;              
     }
//--------------------- 预定义结束 -----------------------//

//------------------ Native API声明开始 ------------------//
NTSYSAPI
VOID
NTAPI
RtlInitUnicodeString(
     PUNICODE_STRING DestinationString,
     PCWSTR SourceString
     );

NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
     ULONG SystemInformationClass,
     PVOID SystemInformation,
     ULONG SystemInformationLength,
     PULONG ReturnLength
     );

NTSYSAPI
NTSTATUS
NTAPI
ZwOpenSection(
     OUT PHANDLE SectionHandle,
     IN ACCESS_MASK DesiredAccess,
     IN POBJECT_ATTRIBUTES ObjectAttributes
     );

NTSYSAPI
NTSTATUS
NTAPI
ZwMapViewOfSection(
     IN HANDLE SectionHandle,
     IN HANDLE ProcessHandle,
     IN OUT PVOID *BaseAddress,
     IN ULONG ZeroBits,
     IN ULONG CommitSize,
     IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
     IN OUT PULONG ViewSize,
     IN SECTION_INHERIT InheritDisposition,
     IN ULONG AllocationType,
     IN ULONG Protect
     );

NTSYSAPI
NTSTATUS
NTAPI
ZwUnmapViewOfSection(
     IN HANDLE ProcessHandle,
     IN PVOID BaseAddress
     );

NTSYSAPI
NTSTATUS
NTAPI
ZwClose(
     IN HANDLE Handle
     );

NTSYSAPI
NTSTATUS
NTAPI
NtVdmControl(
     IN ULONG ControlCode,
     IN PVOID ControlData
     );
//------------------ Native API声明结束 ------------------//

//------------------ 全局变量定义开始 --------------------//
NTSTATUS
(NTAPI *pfnNtVdmControl)(
     IN ULONG ControlCode,
     IN PVOID ControlData
     );

BOOLEAN
(NTAPI *pfnPsGetVersion)(
     PULONG MajorVersion OPTIONAL,
     PULONG MinorVersion OPTIONAL,
     PULONG BuildNumber OPTIONAL,
     PUNICODE_STRING CSDVersion OPTIONAL
     );

HANDLE
(NTAPI *pfnPsGetCurrentProcessId)(
     );

PVOID
(NTAPI *pfnMemcpy)(
     IN VOID UNALIGNED *Destination,
     IN CONST VOID UNALIGNED *Source,
     IN SIZE_T Length
     );

ULONG
(_cdecl *pfnDbgPrint)(
     IN PCHAR Format,
     ...
     );

ULONG *pPsInitialSystemProcess;
//------------------ 全局变量定义结束 --------------------//


// 获取指定模块的基址
PVOID GetModuleBase(PCSTR name)
{
     NTSTATUS status;
     PVOID pBuffer, pModule;
     ULONG nRetSize, i, n;
     PSYSTEM_MODULE_INFORMATION pmi;

     pBuffer = LocalAlloc(LPTR, 0x1000);
     if (NULL == pBuffer)
     {
         printf("LocalAlloc[0] Failed: %d/n", GetLastError());
         return NULL;
     }

     status = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, 0x1000, &nRetSize);
     if (STATUS_INFO_LENGTH_MISMATCH == status)
     {
         // 缓冲区太小,重新分配
         LocalFree(pBuffer);
         pBuffer = LocalAlloc(LPTR, nRetSize);
         if (NULL == pBuffer)
         {
             printf("LocalAlloc[1] Failed: %d/n", GetLastError());
             return NULL;
         }
         status = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, nRetSize, &nRetSize);
     }
     if (!NT_SUCCESS(status))
     {
         printf("ZwQuerySystemInformation Failed: %d/n", LsaNtStatusToWinError(status));
         LocalFree(pBuffer);
         return NULL;
     }

     pmi = (PSYSTEM_MODULE_INFORMATION)((ULONG)pBuffer + 4);
     n = *(ULONG*)pBuffer;
     pModule = NULL;

     // 搜索指定的模块名,获取基址
     for (i=0; i<n; i++)
     {
         if (!_stricmp(pmi->ImageName+pmi->ModuleNameOffset, name))
         {
             pModule = pmi->Base;
             break;
         }
         pmi++;
     }

     LocalFree(pBuffer);
     return pModule;
}


// 获取/Device/PhysicalMemory的可读写句柄
HANDLE OpenPhysicalMemory()
{
     DWORD dwRet;
     NTSTATUS status;
     UNICODE_STRING name;
     OBJECT_ATTRIBUTES oa;
     EXPLICIT_ACCESS ea;
     PSECURITY_DESCRIPTOR pSD;
     PACL pDacl = NULL;
     PACL pNewDacl = NULL;
     HANDLE hSection = NULL;
     HANDLE hSectionRet = NULL;

     RtlInitUnicodeString(&name, L"//Device//PhysicalMemory");
     InitializeObjectAttributes(&oa, &name, OBJ_KERNEL_HANDLE, NULL, NULL);

     // 以可读写Section权限打开PhysicalMemory
     status = ZwOpenSection(&hSectionRet, SECTION_MAP_READ | SECTION_MAP_WRITE, &oa);

     if (NT_SUCCESS(status)) goto FreeAndExit; // 打开成功,直接返回

     if (status != STATUS_ACCESS_DENIED)
     {
         // 错误,但非权限不足,打开失败
         printf("ZwOpenSection[0] Failed: %d/n", LsaNtStatusToWinError(status));
         hSectionRet = NULL;
         goto FreeAndExit;
     }

   // 以可读写ACL权限打开PhysicalMemory
     status = ZwOpenSection(&hSection, READ_CONTROL | WRITE_DAC, &oa);
     if (!NT_SUCCESS(status))
     {
         printf("ZwOpenSection[1] Failed: %d/n", LsaNtStatusToWinError(status));
         goto FreeAndExit;
     }

     // 获取PhysicalMemory的DACL
     dwRet = GetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
         NULL, NULL, &pDacl, NULL, &pSD);
     if (dwRet != ERROR_SUCCESS)
     {
         printf("GetSecurityInfo Failed: %d/n", dwRet);
         goto FreeAndExit;
     }

     // 创建一个ACE,允许当前用户读写PhysicalMemory
     ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
     ea.grfAccessPermissions = SECTION_MAP_READ | SECTION_MAP_WRITE;
     ea.grfAccessMode = GRANT_ACCESS;
     ea.grfInheritance = NO_INHERITANCE;
     ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
     ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
     ea.Trustee.ptstrName = "CURRENT_USER";

     // 将新的ACE加入DACL
     dwRet = SetEntriesInAcl(1, &ea, pDacl, &pNewDacl);
     if (dwRet != ERROR_SUCCESS)
     {
         printf("SetEntriesInAcl Failed: %d/n", dwRet);
         goto FreeAndExit;
     }

     // 更新PhysicalMemory的DACL
     dwRet = SetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
         NULL, NULL, pNewDacl, NULL);
     if (dwRet != ERROR_SUCCESS)
     {
         printf("SetSecurityInfo Failed: %d/n", dwRet);
         goto FreeAndExit;
     }

     // 再次以可读写权限打开PhysicalMemory
     status = ZwOpenSection(&hSectionRet, SECTION_MAP_READ | SECTION_MAP_WRITE, &oa);
     if (!NT_SUCCESS(status))
     {
         printf("ZwOpenSection[2] Failed: %d/n", LsaNtStatusToWinError(status));
         goto FreeAndExit;
     }

FreeAndExit:
     if (pSD) LocalFree(pSD);
     if (pNewDacl) LocalFree(pNewDacl);
     if (hSection) ZwClose(hSection);
     return hSectionRet;
}


// 将物理内存映射到当前进程的用户空间
PVOID MapPhysicalMemory(HANDLE hSection, // 物理内存的Section句柄
                         ULONG Offset,     // 映射起始偏移量,相对于物理内存的0地址
                         ULONG CommitSize // 映射范围
                         )
{
     NTSTATUS status;
     PVOID BaseAddress = NULL;
     LARGE_INTEGER PhysicalAddress = {Offset, 0};
     SIZE_T ViewSize = CommitSize;

     status = ZwMapViewOfSection(hSection, (HANDLE)-1, &BaseAddress, 0,
         CommitSize, &PhysicalAddress, &ViewSize, ViewShare, 0, PAGE_READWRITE);
     if (!NT_SUCCESS(status))
     {
         printf("ZwMapViewOfSection Failed: %d/n", LsaNtStatusToWinError(status));
         return NULL;
     }

     return BaseAddress;
}


// 在Ring0执行的代码。这里演示如何获取每个进程的PID、KPEB、CR3和ImageName
NTSTATUS Ring0Code(ULONG size,       // 缓冲区大小
                    PULONG buffer)    // 缓冲区指针,指向调用者分配的缓存
                                     // 参数个数与NtVdmControl一致,以平衡堆栈
{
     ULONG BuildNumber;
     ULONG ListOffset;
     ULONG PIDOffset;
     ULONG NameOffset;
     PLIST_ENTRY ListHead, ListPtr;
     PMY_PROCESS_INFO mypi;

     pfnDbgPrint("Run in Ring0!/n"); // 输出调试信息

     pfnPsGetVersion(NULL, NULL, &BuildNumber, NULL);
     pfnDbgPrint("BuildNumber = %d/n", BuildNumber);

     switch (BuildNumber)     // 各版本OS的KPEB结构不同
     {
         case 2195:   // Win2000
             ListOffset = 0xa0;
             PIDOffset = 0x9c;
             NameOffset = 0x1fc;
             break;
         case 2600:   // WinXP
             ListOffset = 0x88;
             PIDOffset = 0x84;
             NameOffset = 0x174;
             break;
         case 3790:   // Win2003
             ListOffset = 0x88;
             PIDOffset = 0x84;
             NameOffset = 0x154;
             break;
         default:
             return STATUS_NOT_IMPLEMENTED;
     }

     if (size<4) return STATUS_BUFFER_TOO_SMALL;
     size -= 4;

     if (NULL == buffer) return STATUS_INVALID_PARAMETER;
     *buffer = 0L;    // 缓存的第一个ULONG用于保存进程总数

     mypi = (PMY_PROCESS_INFO)(buffer + 1);

     // 历遍ActiveProcessLinks
     ListHead = ListPtr = (PLIST_ENTRY)(*pPsInitialSystemProcess + ListOffset);
     while (ListPtr->Flink != ListHead)
     {
         if (size < sizeof(MY_PROCESS_INFO)) return STATUS_BUFFER_TOO_SMALL;

         mypi->KPEB = (ULONG)ListPtr - ListOffset;
         mypi->PID = *(ULONG*)(mypi->KPEB + PIDOffset);
         mypi->CR3 = *(ULONG*)(mypi->KPEB + 0x18);
         pfnMemcpy(mypi->Name, (PVOID)(mypi->KPEB + NameOffset), 16);

         (*buffer)++;
         mypi++;
         size -= sizeof(MY_PROCESS_INFO);
         ListPtr = ListPtr->Flink;
     }

     return STATUS_SUCCESS;
}


// 显示进程信息
void ListProcessInfo(PULONG buffer)
{
     ULONG i, n = *buffer;
     PMY_PROCESS_INFO mypi = (PMY_PROCESS_INFO)(buffer + 1);

     printf(" PID    KPEB       CR3        Name/n"
            " ----   --------   --------   ----/n");
     for (i=0; i<n; i++)
     {
         printf(" %-4d   %08x   %08x   %s/n",
             mypi->PID, mypi->KPEB, mypi->CR3, mypi->Name);
         mypi++;
     }
}


void main()
{
     char *Kernel = "ntoskrnl.exe";
     PVOID pKernel = NULL;
     HMODULE hKernel = NULL;
     HANDLE hSection = NULL;
     char *mapping = NULL;
     PVOID buffer = NULL;
     ULONG offset;
     NTSTATUS status;
     char origCode[24], HookCode[24] =
         "/xE8/xFF/xFF/xFF/xFF"   // call 0xffffffff       ;nt!PsGetCurrentProcessId
         "/x3D/xEE/xEE/xEE/xEE"   // cmp eax, 0xeeeeeeee   ;自己的PID
         "/x75/x05"               // jne $Content$5
         "/xE9/xDD/xDD/xDD/xDD"   // jmp 0xdddddddd        ;Ring0Code
         "/xB8/x01/x00/x00/xC0"   // mov eax, 0xc0000001   ;STATUS_UNSUCCESSFUL
         "/xC3";                  // ret

     printf("/n -=< Run Ring0 Code Without Driver Demo >=-/n/n");

     // 获取系统核心模块ntoskrnl.exe的基址
     pKernel = GetModuleBase(Kernel);
     if (NULL == pKernel) return;
     if ((ULONG)pKernel < 0x80000000 || (ULONG)pKernel > 0x9FFFFFFF)
     {
         // 模块基址超出直接内存映射范围
         printf("Error: Kernel module base (%08x) is out of range./n", pKernel);
         return;
     }

     // 在用户态加载一份ntoskrnl.exe
     hKernel = LoadLibrary(Kernel);
     if (NULL == hKernel)
     {
         printf("LoadLibrary Failed: %d/n", GetLastError());
         return;
     }

     // 获取内核例程/变量在用户态的相对位置
     if ((pfnMemcpy = (PVOID)GetProcAddress(hKernel, "memcpy")) &&
         (pfnDbgPrint = (PVOID)GetProcAddress(hKernel, "DbgPrint")) &&
         (pfnNtVdmControl = (PVOID)GetProcAddress(hKernel, "NtVdmControl")) &&
         (pfnPsGetVersion = (PVOID)GetProcAddress(hKernel, "PsGetVersion")) &&
         (pfnPsGetCurrentProcessId = (PVOID)GetProcAddress(hKernel, "PsGetCurrentProcessId")) &&
         (pPsInitialSystemProcess = (PVOID)GetProcAddress(hKernel, "PsInitialSystemProcess")));
     else
     {
         printf("GetProcAddress Failed: %d/n", GetLastError());
         goto FreeAndExit;
     }

     // 计算内核例程/变量的实际地址
     offset = (ULONG)pKernel - (ULONG)hKernel;
     (ULONG)pfnMemcpy += offset;
     (ULONG)pfnDbgPrint += offset;
     (ULONG)pfnNtVdmControl += offset;
     (ULONG)pfnPsGetVersion += offset;
     (ULONG)pfnPsGetCurrentProcessId += offset;
     (ULONG)pPsInitialSystemProcess += offset;

     // 设置HookCode
     *(ULONG*)(HookCode+1) = (ULONG)pfnPsGetCurrentProcessId - (ULONG)pfnNtVdmControl - 5;
     *(ULONG*)(HookCode+6) = GetCurrentProcessId();
     *(ULONG*)(HookCode+13) = (ULONG)Ring0Code - (ULONG)pfnNtVdmControl - 17;

     // 打开物理内存Section
     hSection = OpenPhysicalMemory();
     if (NULL == hSection) goto FreeAndExit;

     // 映射NtVdmControl入口附近的内存
     offset = (ULONG)pfnNtVdmControl & 0x1FFFF000;    // 转换到物理内存页地址
     mapping = MapPhysicalMemory(hSection, offset, 0x2000);
     if (NULL == mapping) goto FreeAndExit;

     // 保存NtVdmControl入口代码
     offset = (ULONG)pfnNtVdmControl & 0x00000FFF;    // 页内偏移
     memcpy(OrigCode, mapping+offset, 24);

     buffer = LocalAlloc(LPTR, 0x1000);
     if (NULL == buffer)
     {
         printf("LocalAlloc Failed: %d/n", GetLastError());
         goto FreeAndExit;
     }

     memcpy(mapping+offset, HookCode, 24);    // 挂钩NtVdmControl
     status = NtVdmControl(0x1000, buffer);   // 调用NtVdmControl,进入Ring0
     memcpy(mapping+offset, origCode, 24);    // 还原NtVdmControl入口

     if (!NT_SUCCESS(status))
     {
         printf("NtVdmControl Failed: %d/n", LsaNtStatusToWinError(status));
         goto FreeAndExit;
     }

     ListProcessInfo(buffer);

FreeAndExit:
     if (buffer != NULL) LocalFree(buffer);
     if (mapping != NULL) ZwUnmapViewOfSection(hSection, mapping);
     if (hSection != NULL) ZwClose(hSection);
     if (hKernel != NULL) FreeLibrary(hKernel);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值