838 lines
26 KiB
C++
838 lines
26 KiB
C++
#pragma once
|
|
#include <Windows.h>
|
|
#include <iostream>
|
|
#include <Shlobj.h>
|
|
#include <commdlg.h>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <TlHelp32.h>
|
|
#include <winternl.h>
|
|
#include <vector>
|
|
#include "../Utils/Utils.h"
|
|
|
|
#ifndef NT_SUCCESS
|
|
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
|
#endif //NT_SUCCESS
|
|
typedef __int64 (*t_callkernel)(__int64, __int64, __int64, __int64);
|
|
static t_callkernel callkernel = NULL;
|
|
static HDC desktopDC = NULL;
|
|
|
|
typedef struct _KPROCESS* PEPROCESS;
|
|
typedef struct _KTHREAD* PETHREAD;
|
|
|
|
typedef struct _UNICODE_STRING64 {
|
|
USHORT Length;
|
|
USHORT MaximumLength;
|
|
PWCH Buffer;
|
|
} UNICODE_STRING64;
|
|
typedef struct _LDR_DATA_TABLE_ENTRY64
|
|
{
|
|
LIST_ENTRY InLoadOrderLinks;
|
|
LIST_ENTRY InMemoryOrderLinks;
|
|
LIST_ENTRY InInitializationOrderLinks;
|
|
PVOID DllBase;
|
|
PVOID EntryPoint;
|
|
ULONG SizeOfImage;
|
|
UNICODE_STRING64 FullDllName;
|
|
UNICODE_STRING64 BaseDllName;
|
|
ULONG Flags;
|
|
USHORT LoadCount;
|
|
USHORT TlsIndex;
|
|
LIST_ENTRY HashLinks;
|
|
ULONG TimeDateStamp;
|
|
} LDR_DATA_TABLE_ENTRY64, * PLDR_DATA_TABLE_ENTRY64;
|
|
typedef struct _PEB_LDR_DATA32
|
|
{
|
|
ULONG Length;
|
|
BOOLEAN Initialized;
|
|
ULONG SsHandle;
|
|
LIST_ENTRY32 InLoadOrderModuleList;
|
|
LIST_ENTRY32 InMemoryOrderModuleList;
|
|
LIST_ENTRY32 InInitializationOrderModuleList;
|
|
ULONG EntryInProgress;
|
|
} PEB_LDR_DATA32, * PPEB_LDR_DATA32;
|
|
typedef struct _STRING32 {
|
|
USHORT Length;
|
|
USHORT MaximumLength;
|
|
ULONG Buffer;
|
|
} STRING32;
|
|
typedef STRING32* PSTRING32;
|
|
typedef STRING32 UNICODE_STRING32;
|
|
typedef struct _LDR_DATA_TABLE_ENTRY32
|
|
{
|
|
LIST_ENTRY32 InLoadOrderLinks;
|
|
LIST_ENTRY32 InMemoryOrderModuleList;
|
|
LIST_ENTRY32 InInitializationOrderModuleList;
|
|
ULONG DllBase;
|
|
ULONG EntryPoint;
|
|
ULONG SizeOfImage;
|
|
UNICODE_STRING32 FullDllName;
|
|
UNICODE_STRING32 BaseDllName;
|
|
ULONG Flags;
|
|
USHORT LoadCount;
|
|
USHORT TlsIndex;
|
|
union
|
|
{
|
|
LIST_ENTRY32 HashLinks;
|
|
ULONG SectionPointer;
|
|
};
|
|
ULONG CheckSum;
|
|
union
|
|
{
|
|
ULONG TimeDateStamp;
|
|
ULONG LoadedImports;
|
|
};
|
|
ULONG EntryPointActivationContext;
|
|
ULONG PatchInformation;
|
|
} LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
|
|
enum class COMTYPE : ULONG64
|
|
{
|
|
LOOKUP_PROCESS = 0xFFFFFFFF00000000,
|
|
LOOKUP_THREAD,
|
|
GET_PROCESS_EXIT_STATUS,
|
|
GET_THREAD_EXIT_STATUS,
|
|
GET_PROCESS_SECTION_BASE,
|
|
|
|
READ_PROCESS_MEMORY,
|
|
READ_PROCESS_MEMORY_DIR,
|
|
SAFE_READ_PROCESS_MEMORY,
|
|
READ_PROCESS_MEMORY_ATTACH,
|
|
|
|
WRITE_PROCESS_MEMORY,
|
|
WRITE_PROCESS_MEMORY_DIR,
|
|
SAFE_WRITE_PROCESS_MEMORY,
|
|
WRITE_PROCESS_MEMORY_ATTACH,
|
|
|
|
READ_PHYSICAL_MEMORY,
|
|
WRITE_PHYSICAL_MEMORY,
|
|
VIRTUAL_QUERY,
|
|
VIRTUAL_ALLOC,
|
|
VIRTUAL_FREE,
|
|
VIRTUAL_PROTECT,
|
|
CREATE_THREAD,
|
|
LOOKUP_PROCESS_MODULE,
|
|
LOOKUP_PROCESS_MODULE_INDEX,
|
|
MAP_ALL_PHYSICAL_MEMORY,
|
|
DELETE_FILE,
|
|
GET_CONTEXT_THREAD,
|
|
SET_CONTEXT_THREAD,
|
|
SUSPEND_PROCESS,
|
|
RESUME_PROCESS,
|
|
SUSPEND_THREAD,
|
|
RESUME_THREAD,
|
|
CALL_REMOTE_APC,
|
|
SHUTDOWN_SYSTEM,
|
|
READ_DIRTABLE,
|
|
};
|
|
typedef enum _SHUTDOWN_ACTION {
|
|
ShutdownNoReboot,
|
|
ShutdownReboot,
|
|
ShutdownPowerOff
|
|
}SHUTDOWN_ACTION;
|
|
typedef struct _COMCLASS
|
|
{
|
|
COMTYPE Type;
|
|
PVOID InputData;
|
|
PVOID RefData;
|
|
LONG64 Status;
|
|
}COMCLASS, * PCOMCLASS;
|
|
typedef struct _COMLOOKUP
|
|
{
|
|
HANDLE ProcessId;
|
|
PEPROCESS Process;
|
|
}COMLOOKUP, * PCOMLOOKUP;
|
|
typedef struct _COM_READWRITE
|
|
{
|
|
PEPROCESS Process;
|
|
ULONG64 Address;
|
|
SIZE_T Size;
|
|
}COM_READWRITE, * PCOM_READWRITE;
|
|
typedef struct _COM_VIRTUAL_PROTECT
|
|
{
|
|
PEPROCESS Process;
|
|
ULONG64 Address;
|
|
SIZE_T Size;
|
|
ULONG64 Protect;
|
|
}COM_VIRTUAL_PROTECT, * PCOM_VIRTUAL_PROTECT;
|
|
typedef struct _COM_ALLOC
|
|
{
|
|
PEPROCESS Process;
|
|
PVOID BaseAddress;
|
|
SIZE_T Size;
|
|
ULONG64 Type;
|
|
ULONG64 Protect;
|
|
PVOID Buffer;
|
|
}COM_ALLOC, * PCOM_ALLOC;
|
|
typedef struct _COM_FREE
|
|
{
|
|
PEPROCESS Process;
|
|
ULONG64 Address;
|
|
}COM_FREE, * PCOM_FREE;
|
|
typedef struct _LOOKUP_MODULE
|
|
{
|
|
PEPROCESS Process;
|
|
const wchar_t* ModuleName;
|
|
}LOOKUP_MODULE, * PLOOKUP_MODULE;
|
|
typedef struct _CREATE_THREAD
|
|
{
|
|
PEPROCESS Process;
|
|
PVOID Address;
|
|
PVOID Parameter;
|
|
}CREATE_THREAD, * PCREATE_THREAD;
|
|
typedef struct _MAP_INFO
|
|
{
|
|
ULONG64 PspCidTable;
|
|
ULONG64 SystemCr3;
|
|
ULONG64 SectionBaseAddressOffset;
|
|
ULONG64 ExitStatusOffset;
|
|
ULONG64 MapedAddress;
|
|
}MAP_INFO, * PMAP_INFO;
|
|
typedef struct _MEMORY_QUERT
|
|
{
|
|
PEPROCESS Process;
|
|
PVOID Address;
|
|
ULONG64 MemoryInformationClass;
|
|
PVOID Buffer;
|
|
ULONG64 Length;
|
|
PULONG64 ResultLength;
|
|
}MEMORY_QUERT, * PMEMORY_QUERT;
|
|
typedef struct _REMOTE_APC
|
|
{
|
|
PEPROCESS Process;
|
|
ULONG64 Address;
|
|
ULONG64 args[9];
|
|
BOOL AllThread;
|
|
}REMOTE_APC, * PREMOTE_APC;
|
|
|
|
BOOL InitIO();
|
|
static ULONG Peb64Offset()
|
|
{
|
|
auto nt = NtBuildVersion();
|
|
if (nt > 18363) {
|
|
return 0x550;
|
|
}
|
|
else
|
|
{
|
|
if (nt > 9600) {
|
|
return 0x3F8;
|
|
}
|
|
else {
|
|
if (nt > 7601)
|
|
return 0x3E8;
|
|
else
|
|
return 0x338;
|
|
}
|
|
}
|
|
}
|
|
static ULONG Peb32Offset()
|
|
{
|
|
auto nt = NtBuildVersion();
|
|
if (nt > 18363) {
|
|
return 0x580;
|
|
}
|
|
else
|
|
{
|
|
if (nt > 9600) {
|
|
return 0x428;
|
|
}
|
|
else {
|
|
if (nt > 7601)
|
|
return 0x418;
|
|
else
|
|
return 0x320;
|
|
}
|
|
}
|
|
}
|
|
static HANDLE GetProcessIdByName(const wchar_t* ProcName)
|
|
{
|
|
HANDLE Pid = NULL;
|
|
HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
PROCESSENTRY32W Entry;
|
|
ZeroMemory(&Entry, sizeof(Entry));
|
|
Entry.dwSize = sizeof(Entry);
|
|
if (Process32FirstW(Snapshot, &Entry)){
|
|
do{
|
|
if (_wcsicmp(Entry.szExeFile, ProcName) == 0){
|
|
Pid = (HANDLE)Entry.th32ProcessID;
|
|
break;
|
|
}
|
|
} while (Process32NextW(Snapshot, &Entry));
|
|
}
|
|
return Pid;
|
|
}
|
|
static NTSTATUS CallR0(COMTYPE type, PVOID inData, PVOID refData)
|
|
{
|
|
if (callkernel == NULL)
|
|
{
|
|
InitIO();
|
|
}
|
|
COMCLASS com = {};
|
|
com.Type = type;
|
|
com.InputData = inData;
|
|
com.RefData = refData;
|
|
ULONG64 enc = (ULONG64)&com;
|
|
enc += 0x1000000000000000;
|
|
UINT64 state = (ULONG64)desktopDC;
|
|
callkernel((__int64)&state, (__int64)&state, (__int64)&state, (__int64)enc);
|
|
return com.Status;
|
|
}
|
|
static BOOL InitIO()
|
|
{
|
|
if (!callkernel)
|
|
{
|
|
desktopDC = GetDC(NULL);
|
|
auto win32u = LoadLibraryA("win32u.dll");
|
|
if (win32u == NULL) return FALSE;
|
|
callkernel = (t_callkernel)GetProcAddress(win32u, "NtTokenManagerOpenSectionAndEvents");
|
|
|
|
//auto ntdll = LoadLibraryA("ntdll.dll");
|
|
//if (ntdll == NULL) return FALSE;
|
|
//callkernel = (t_callkernel)GetProcAddress(ntdll, "NtQueryAuxiliaryCounterFrequency");
|
|
|
|
if (callkernel == NULL) return FALSE;
|
|
auto tmp = VirtualAlloc((PVOID)NULL, 0x18, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
|
if (tmp == NULL) return FALSE;
|
|
memcpy(tmp, callkernel, 0x18);
|
|
callkernel = (t_callkernel)tmp;
|
|
}
|
|
PEPROCESS Process = NULL;
|
|
return (NT_SUCCESS(CallR0(COMTYPE::LOOKUP_PROCESS, (HANDLE)GetCurrentProcessId(), &Process))) & (Process != NULL);
|
|
}
|
|
static NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS* Process)
|
|
{
|
|
return CallR0(COMTYPE::LOOKUP_PROCESS, ProcessId, Process);
|
|
}
|
|
static NTSTATUS PsLookupThreadByThreadId(HANDLE ThreadId, PETHREAD* Thread)
|
|
{
|
|
return CallR0(COMTYPE::LOOKUP_THREAD, ThreadId, Thread);
|
|
}
|
|
static LDR_DATA_TABLE_ENTRY64 PsLookProcessModule(PEPROCESS Process, const wchar_t* moduleName)
|
|
{
|
|
LDR_DATA_TABLE_ENTRY64 result = {};
|
|
LOOKUP_MODULE inData = {};
|
|
inData.Process = Process;
|
|
inData.ModuleName = moduleName;
|
|
CallR0(COMTYPE::LOOKUP_PROCESS_MODULE, &inData, &result);
|
|
return result;
|
|
}
|
|
static LDR_DATA_TABLE_ENTRY64 PsLookProcessModuleIndex(PEPROCESS Process, unsigned int moduleIndex)
|
|
{
|
|
LDR_DATA_TABLE_ENTRY64 result = {};
|
|
LOOKUP_MODULE inData = {};
|
|
inData.Process = Process;
|
|
inData.ModuleName = (const wchar_t*)moduleIndex;
|
|
CallR0(COMTYPE::LOOKUP_PROCESS_MODULE_INDEX, &inData, &result);
|
|
return result;
|
|
}
|
|
static PVOID MmVirtualAlloc(PEPROCESS Process, SIZE_T Size, ULONG64 Type = MEM_COMMIT, ULONG64 Protect = PAGE_EXECUTE_READWRITE, PVOID BaseAddress = NULL,PVOID buffer = NULL)
|
|
{
|
|
COM_ALLOC inData = {};
|
|
inData.Process = Process;
|
|
inData.BaseAddress = BaseAddress;
|
|
inData.Size = Size;
|
|
inData.Type = Type;
|
|
inData.Protect = Protect;
|
|
inData.Buffer = buffer;
|
|
PVOID result = NULL;
|
|
CallR0(COMTYPE::VIRTUAL_ALLOC, &inData, &result);
|
|
return result;
|
|
}
|
|
static NTSTATUS VirtualFree(PEPROCESS Process, PVOID Address)
|
|
{
|
|
COM_FREE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = (ULONG64)Address;
|
|
return CallR0(COMTYPE::VIRTUAL_FREE, &inData, NULL);
|
|
}
|
|
static NTSTATUS PsGetProcessExitStatus(PEPROCESS Process)
|
|
{
|
|
return CallR0(COMTYPE::GET_PROCESS_EXIT_STATUS, Process, NULL);
|
|
}
|
|
static NTSTATUS PsGetThreadExitStatus(PETHREAD Thread)
|
|
{
|
|
return CallR0(COMTYPE::GET_THREAD_EXIT_STATUS, Thread, NULL);
|
|
}
|
|
static PVOID PsGetProcessSectionBaseAddress(PEPROCESS Process)
|
|
{
|
|
PVOID result = NULL;
|
|
CallR0(COMTYPE::GET_PROCESS_SECTION_BASE, Process, &result);
|
|
return result;
|
|
}
|
|
static NTSTATUS ReadProcessMemory(PEPROCESS Process, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::READ_PROCESS_MEMORY, &inData, Buffer);
|
|
}
|
|
static NTSTATUS MmReadProcessMemory(PEPROCESS Process, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::SAFE_READ_PROCESS_MEMORY, &inData, Buffer);
|
|
}
|
|
static NTSTATUS ReadProcessMemoryAttach(PEPROCESS Process, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::READ_PROCESS_MEMORY_ATTACH, &inData, Buffer);
|
|
}
|
|
static NTSTATUS WriteProcessMemory(PEPROCESS Process, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::WRITE_PROCESS_MEMORY, &inData, Buffer);
|
|
}
|
|
static NTSTATUS MmWriteProcessMemory(PEPROCESS Process, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::SAFE_WRITE_PROCESS_MEMORY, &inData, Buffer);
|
|
}
|
|
static NTSTATUS WriteProcessMemoryAttach(PEPROCESS Process, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::WRITE_PROCESS_MEMORY_ATTACH, &inData, Buffer);
|
|
}
|
|
static NTSTATUS ReadProcessMemoryDir(ULONG64* inTable, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = (PEPROCESS)inTable;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::READ_PROCESS_MEMORY_DIR, &inData, Buffer);
|
|
}
|
|
static NTSTATUS WriteProcessMemoryDir(ULONG64* inTable, ULONG64 Address, PVOID Buffer, SIZE_T Size)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = (PEPROCESS)inTable;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
return CallR0(COMTYPE::WRITE_PROCESS_MEMORY_DIR, &inData, Buffer);
|
|
}
|
|
static NTSTATUS ReadProcessDirTable(PEPROCESS Process, ULONG64* outTable)
|
|
{
|
|
COM_READWRITE inData = {};
|
|
inData.Process = Process;
|
|
return CallR0(COMTYPE::READ_DIRTABLE, &inData, outTable);
|
|
}
|
|
static NTSTATUS VirtualProtect(PEPROCESS Process, ULONG64 Address, SIZE_T Size,ULONG newProtect,PULONG oldProtect)
|
|
{
|
|
COM_VIRTUAL_PROTECT inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = Address;
|
|
inData.Size = Size;
|
|
inData.Protect = newProtect;
|
|
return CallR0(COMTYPE::VIRTUAL_PROTECT, &inData, oldProtect);
|
|
}
|
|
static HANDLE RtlCreateThread(PEPROCESS Process, ULONG64 Address, PVOID Parameter)
|
|
{
|
|
CREATE_THREAD inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = (PVOID)Address;
|
|
inData.Parameter = Parameter;
|
|
HANDLE handle = NULL;
|
|
CallR0(COMTYPE::CREATE_THREAD, &inData, &handle);
|
|
return handle;
|
|
}
|
|
static NTSTATUS WriteProcessMemory(PEPROCESS Process, ULONG64 Address, std::initializer_list<uint8_t> value)
|
|
{
|
|
return WriteProcessMemory(Process, Address, (void*)value.begin(), value.size());
|
|
}
|
|
EXTERN_C MAP_INFO MapedInfo;
|
|
static MAP_INFO MapAllPhysicalMemory(ULONG64 virtualBase)
|
|
{
|
|
MAP_INFO result = {};
|
|
CallR0(COMTYPE::MAP_ALL_PHYSICAL_MEMORY, (PVOID)virtualBase, &result);
|
|
MapedInfo = result;
|
|
return MapedInfo;
|
|
}
|
|
static NTSTATUS QueryVirtualMemory(PEPROCESS Process, PVOID BaseAddress,int MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength)
|
|
{
|
|
MEMORY_QUERT inData = {};
|
|
inData.Process = Process;
|
|
inData.Address = (PVOID)BaseAddress;
|
|
inData.MemoryInformationClass = MemoryInformationClass;
|
|
inData.Buffer = MemoryInformation;
|
|
inData.Length = MemoryInformationLength;
|
|
inData.ResultLength = ReturnLength;
|
|
return CallR0(COMTYPE::VIRTUAL_QUERY, &inData, NULL);
|
|
}
|
|
static NTSTATUS PsDeleteFile(std::wstring path)
|
|
{
|
|
return CallR0(COMTYPE::DELETE_FILE, (PVOID)path.c_str(), NULL);
|
|
}
|
|
static NTSTATUS PsGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext)
|
|
{
|
|
return CallR0(COMTYPE::GET_CONTEXT_THREAD, (PVOID)Thread, ThreadContext);
|
|
}
|
|
static NTSTATUS PsSetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext)
|
|
{
|
|
return CallR0(COMTYPE::SET_CONTEXT_THREAD, (PVOID)Thread, ThreadContext);
|
|
}
|
|
static NTSTATUS PsSuspendProcess(HANDLE ProcessId)
|
|
{
|
|
return CallR0(COMTYPE::SUSPEND_PROCESS, (PVOID)ProcessId, NULL);
|
|
}
|
|
static NTSTATUS PsResumeProcess(HANDLE ProcessId)
|
|
{
|
|
return CallR0(COMTYPE::RESUME_PROCESS, (PVOID)ProcessId, NULL);
|
|
}
|
|
static NTSTATUS PsSuspendThread(HANDLE ThreadHandle, PULONG PreviousSuspendCount)
|
|
{
|
|
return CallR0(COMTYPE::SUSPEND_THREAD, (PVOID)ThreadHandle, PreviousSuspendCount);
|
|
}
|
|
static NTSTATUS PsResumeThread(HANDLE ThreadHandle, PULONG SuspendCount)
|
|
{
|
|
return CallR0(COMTYPE::RESUME_THREAD, (PVOID)ThreadHandle, SuspendCount);
|
|
}
|
|
static NTSTATUS PsShutdownSystem(SHUTDOWN_ACTION sa)
|
|
{
|
|
return CallR0(COMTYPE::SHUTDOWN_SYSTEM, (PVOID)sa, NULL);
|
|
}
|
|
static NTSTATUS QueryRemoteAPC(PEPROCESS process,PVOID func,
|
|
PVOID arg1 = NULL,PVOID arg2 = NULL, PVOID arg3 = NULL, PVOID arg4 = NULL, PVOID arg5 = NULL, PVOID arg6 = NULL, PVOID arg7 = NULL, PVOID arg8 = NULL, PVOID arg9 = NULL)
|
|
{
|
|
REMOTE_APC inData = {};
|
|
inData.Process = process;
|
|
inData.Address = (ULONG64)func;
|
|
inData.args[0] = (ULONG64)arg1;
|
|
inData.args[1] = (ULONG64)arg2;
|
|
inData.args[2] = (ULONG64)arg3;
|
|
inData.args[3] = (ULONG64)arg4;
|
|
inData.args[4] = (ULONG64)arg5;
|
|
inData.args[5] = (ULONG64)arg6;
|
|
inData.args[6] = (ULONG64)arg7;
|
|
inData.args[7] = (ULONG64)arg8;
|
|
inData.args[8] = (ULONG64)arg9;
|
|
inData.AllThread = FALSE;
|
|
return CallR0(COMTYPE::CALL_REMOTE_APC, &inData, NULL);
|
|
}
|
|
static ULONG64 SerachProcess(PEPROCESS process, const wchar_t* _module, const char* key)
|
|
{
|
|
LDR_DATA_TABLE_ENTRY64 moduleinfo = PsLookProcessModule(process, _module);
|
|
SIZE_T dwsiz = 0;
|
|
uint8_t* BUFFER = new uint8_t[moduleinfo.SizeOfImage];
|
|
if (BUFFER)
|
|
{
|
|
ZeroMemory(BUFFER, moduleinfo.SizeOfImage);
|
|
auto st = MmReadProcessMemory(process, (ULONG64)moduleinfo.DllBase, BUFFER, moduleinfo.SizeOfImage);
|
|
if (NT_SUCCESS(st))
|
|
{
|
|
auto found = FindPattern(BUFFER, key, moduleinfo.SizeOfImage, 0);
|
|
if (found)
|
|
{
|
|
uint8_t* pb = (uint8_t*)found;
|
|
pb -= (ULONG64)BUFFER;
|
|
pb += (ULONG64)moduleinfo.DllBase;
|
|
return ULONG64(pb);
|
|
}
|
|
|
|
}
|
|
delete[] BUFFER;
|
|
}
|
|
return NULL;
|
|
}
|
|
static ULONG64 SerachProcess(PEPROCESS process, const char* key)
|
|
{
|
|
MEMORY_BASIC_INFORMATION info = { 0 };
|
|
SIZE_T dwsiz = 0;
|
|
PVOID CurrentAddress = NULL;
|
|
while NT_SUCCESS(QueryVirtualMemory(process, CurrentAddress, 0, &info, sizeof(MEMORY_BASIC_INFORMATION), &dwsiz))
|
|
{
|
|
if (info.State == MEM_COMMIT)
|
|
{
|
|
uint8_t* BUFFER = new uint8_t[info.RegionSize];
|
|
if (BUFFER)
|
|
{
|
|
ZeroMemory(BUFFER, info.RegionSize);
|
|
if (NT_SUCCESS(MmReadProcessMemory(process, (ULONG64)info.BaseAddress, BUFFER, info.RegionSize)))
|
|
{
|
|
auto found = FindAllPattern(BUFFER, key, info.RegionSize, 0);
|
|
for (auto p : found)
|
|
{
|
|
uint8_t* pb = (uint8_t*)p;
|
|
pb -= (ULONG64)BUFFER;
|
|
pb += (ULONG64)info.BaseAddress;
|
|
return ULONG64(pb);
|
|
}
|
|
}
|
|
delete[] BUFFER;
|
|
}
|
|
}
|
|
CurrentAddress = (PVOID)((UINT64)info.BaseAddress + info.RegionSize);
|
|
}
|
|
return NULL;
|
|
}
|
|
static std::vector<ULONG64> SerachProcessEx(PEPROCESS process, const wchar_t* _module, const char* key)
|
|
{
|
|
LDR_DATA_TABLE_ENTRY64 moduleinfo = PsLookProcessModule(process, _module);
|
|
SIZE_T dwsiz = 0;
|
|
std::vector<ULONG64> result = std::vector<ULONG64>();
|
|
uint8_t* BUFFER = new uint8_t[moduleinfo.SizeOfImage];
|
|
if (BUFFER)
|
|
{
|
|
ZeroMemory(BUFFER, moduleinfo.SizeOfImage);
|
|
if (NT_SUCCESS(MmReadProcessMemory(process, (ULONG64)moduleinfo.DllBase, BUFFER, moduleinfo.SizeOfImage)))
|
|
{
|
|
auto found = FindAllPattern(BUFFER, key, moduleinfo.SizeOfImage, 0);
|
|
for (auto p : found)
|
|
{
|
|
uint8_t* pb = (uint8_t*)p;
|
|
pb -= (ULONG64)BUFFER;
|
|
pb += (ULONG64)moduleinfo.DllBase;
|
|
result.push_back(ULONG64(pb));
|
|
}
|
|
|
|
}
|
|
else
|
|
printf("ReadProcessMemory Failed\n");
|
|
delete[] BUFFER;
|
|
}
|
|
return result;
|
|
}
|
|
static std::vector<ULONG64> SerachProcessEx(PEPROCESS process, const char* key)
|
|
{
|
|
MEMORY_BASIC_INFORMATION info = { 0 };
|
|
SIZE_T dwsiz = 0;
|
|
PVOID CurrentAddress = NULL;
|
|
std::vector<ULONG64> result = std::vector<ULONG64>();
|
|
while NT_SUCCESS(QueryVirtualMemory(process, CurrentAddress, 0, &info, sizeof(MEMORY_BASIC_INFORMATION), &dwsiz))
|
|
{
|
|
if (info.State == MEM_COMMIT)
|
|
{
|
|
uint8_t* BUFFER = new uint8_t[info.RegionSize];
|
|
if (BUFFER)
|
|
{
|
|
ZeroMemory(BUFFER, info.RegionSize);
|
|
if (NT_SUCCESS(MmReadProcessMemory(process, (ULONG64)info.BaseAddress, BUFFER, info.RegionSize)))
|
|
{
|
|
auto found = FindAllPattern(BUFFER, key, info.RegionSize, 0);
|
|
for (auto p : found)
|
|
{
|
|
uint8_t* pb = (uint8_t*)p;
|
|
pb -= (ULONG64)BUFFER;
|
|
pb += (ULONG64)info.BaseAddress;
|
|
result.push_back(ULONG64(pb));
|
|
}
|
|
}
|
|
delete[] BUFFER;
|
|
}
|
|
}
|
|
CurrentAddress = (PVOID)((UINT64)info.BaseAddress + info.RegionSize);
|
|
}
|
|
return result;
|
|
}
|
|
static BOOL DumpPE(PEPROCESS Process, const wchar_t* moduleName, const wchar_t* szOutPe)
|
|
{
|
|
LDR_DATA_TABLE_ENTRY64 info = PsLookProcessModule(Process, moduleName);
|
|
ULONG64 lpAddress = (ULONG64)info.DllBase;
|
|
CHAR bDosHeader[sizeof(IMAGE_DOS_HEADER)] = { 0 };
|
|
if (!NT_SUCCESS(MmReadProcessMemory(Process, lpAddress, bDosHeader, sizeof(bDosHeader))))
|
|
return FALSE;
|
|
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)bDosHeader;
|
|
CHAR bNtHeader[sizeof(IMAGE_NT_HEADERS)] = { 0 };
|
|
if (!NT_SUCCESS(MmReadProcessMemory(Process, (ULONG64)((ULONGLONG)lpAddress + lpDosHeader->e_lfanew), bNtHeader, sizeof(bNtHeader))))
|
|
return FALSE;
|
|
PIMAGE_NT_HEADERS lpNtHeader = (PIMAGE_NT_HEADERS)bNtHeader;
|
|
uint8_t* lpMappedImage = new uint8_t[lpNtHeader->OptionalHeader.SizeOfImage];
|
|
if (!lpMappedImage)
|
|
return FALSE;
|
|
memset(lpMappedImage, 0, lpNtHeader->OptionalHeader.SizeOfImage);
|
|
if (!NT_SUCCESS(MmReadProcessMemory(Process, lpAddress, lpMappedImage, lpNtHeader->OptionalHeader.SizeOfImage)))
|
|
return FALSE;
|
|
if (!DeleteFileW(szOutPe) && ERROR_FILE_NOT_FOUND != GetLastError())
|
|
return FALSE;
|
|
HANDLE hFile;
|
|
if (!(hFile = CreateFileW(
|
|
szOutPe,
|
|
FILE_APPEND_DATA,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
)) || INVALID_HANDLE_VALUE == hFile)
|
|
return FALSE;
|
|
DWORD dwWrittenBytes;
|
|
if (!WriteFile(
|
|
hFile,
|
|
lpMappedImage,
|
|
lpNtHeader->OptionalHeader.SizeOfHeaders,
|
|
&dwWrittenBytes,
|
|
NULL
|
|
) || (lpNtHeader->OptionalHeader.SizeOfHeaders != dwWrittenBytes))
|
|
return FALSE;
|
|
IMAGE_SECTION_HEADER* lpSectionHeaderArray = (IMAGE_SECTION_HEADER*)((ULONG_PTR)lpMappedImage + lpDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
|
|
|
|
for (DWORD dwSecIndex = 0; dwSecIndex < lpNtHeader->FileHeader.NumberOfSections; dwSecIndex++)
|
|
{
|
|
if (!WriteFile(
|
|
hFile,
|
|
(LPVOID)((ULONGLONG)lpMappedImage + lpSectionHeaderArray[dwSecIndex].VirtualAddress),
|
|
lpSectionHeaderArray[dwSecIndex].SizeOfRawData,
|
|
&dwWrittenBytes,
|
|
NULL
|
|
) || (lpSectionHeaderArray[dwSecIndex].SizeOfRawData != dwWrittenBytes))
|
|
return FALSE;
|
|
};
|
|
|
|
CloseHandle(hFile);
|
|
return TRUE;
|
|
}
|
|
static BOOL DumpPEEx(PEPROCESS Process, ULONG64 lpAddress, const wchar_t* szOutPe)
|
|
{
|
|
CHAR bDosHeader[sizeof(IMAGE_DOS_HEADER)] = { 0 };
|
|
if (!NT_SUCCESS(MmReadProcessMemory(Process, lpAddress, bDosHeader, sizeof(bDosHeader))))
|
|
return FALSE;
|
|
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)bDosHeader;
|
|
CHAR bNtHeader[sizeof(IMAGE_NT_HEADERS)] = { 0 };
|
|
if (!NT_SUCCESS(MmReadProcessMemory(Process, (ULONG64)((ULONGLONG)lpAddress + lpDosHeader->e_lfanew), bNtHeader, sizeof(bNtHeader))))
|
|
return FALSE;
|
|
PIMAGE_NT_HEADERS lpNtHeader = (PIMAGE_NT_HEADERS)bNtHeader;
|
|
uint8_t* lpMappedImage = new uint8_t[lpNtHeader->OptionalHeader.SizeOfImage];
|
|
if (!lpMappedImage)
|
|
return FALSE;
|
|
memset(lpMappedImage, 0, lpNtHeader->OptionalHeader.SizeOfImage);
|
|
if (!NT_SUCCESS(MmReadProcessMemory(Process, lpAddress, lpMappedImage, lpNtHeader->OptionalHeader.SizeOfImage)))
|
|
return FALSE;
|
|
if (!DeleteFileW(szOutPe) && ERROR_FILE_NOT_FOUND != GetLastError())
|
|
return FALSE;
|
|
HANDLE hFile;
|
|
if (!(hFile = CreateFileW(
|
|
szOutPe,
|
|
FILE_APPEND_DATA,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
)) || INVALID_HANDLE_VALUE == hFile)
|
|
return FALSE;
|
|
DWORD dwWrittenBytes;
|
|
if (!WriteFile(
|
|
hFile,
|
|
lpMappedImage,
|
|
lpNtHeader->OptionalHeader.SizeOfHeaders,
|
|
&dwWrittenBytes,
|
|
NULL
|
|
) || (lpNtHeader->OptionalHeader.SizeOfHeaders != dwWrittenBytes))
|
|
return FALSE;
|
|
IMAGE_SECTION_HEADER* lpSectionHeaderArray = (IMAGE_SECTION_HEADER*)((ULONG_PTR)lpMappedImage + lpDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
|
|
|
|
for (DWORD dwSecIndex = 0; dwSecIndex < lpNtHeader->FileHeader.NumberOfSections; dwSecIndex++)
|
|
{
|
|
if (!WriteFile(
|
|
hFile,
|
|
(LPVOID)((ULONGLONG)lpMappedImage + lpSectionHeaderArray[dwSecIndex].VirtualAddress),
|
|
lpSectionHeaderArray[dwSecIndex].SizeOfRawData,
|
|
&dwWrittenBytes,
|
|
NULL
|
|
) || (lpSectionHeaderArray[dwSecIndex].SizeOfRawData != dwWrittenBytes))
|
|
return FALSE;
|
|
};
|
|
|
|
CloseHandle(hFile);
|
|
return TRUE;
|
|
}
|
|
template<typename T>
|
|
static T ReadProcessMemory(PEPROCESS Process, ULONG64 Address)
|
|
{
|
|
T result = T();
|
|
ReadProcessMemory(Process, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|
|
template<typename T>
|
|
static T ReadProcessMemoryDir(ULONG64* dirTable, ULONG64 Address)
|
|
{
|
|
T result = T();
|
|
ReadProcessMemory(dirTable, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|
|
template<typename T>
|
|
static T MmReadProcessMemory(PEPROCESS Process, ULONG64 Address)
|
|
{
|
|
T result = T();
|
|
MmReadProcessMemory(Process, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|
|
template<typename T>
|
|
static NTSTATUS WriteProcessMemory(PEPROCESS Process, ULONG64 Address, T value)
|
|
{
|
|
return WriteProcessMemory(Process, Address, &value, sizeof(T));
|
|
}
|
|
template<typename T>
|
|
static NTSTATUS WriteProcessMemoryDir(ULONG64* dirTable, ULONG64 Address, T value)
|
|
{
|
|
return WriteProcessMemoryDir(dirTable, Address, &value, sizeof(T));
|
|
}
|
|
template<typename T>
|
|
static NTSTATUS MmWriteProcessMemory(PEPROCESS Process, ULONG64 Address, T value)
|
|
{
|
|
return SafeWriteProcessMemory(Process, Address, &value, sizeof(T));
|
|
}
|
|
template<typename T>
|
|
static T ReadProcessMemory(PEPROCESS Process, std::initializer_list<ULONG64> offsets)
|
|
{
|
|
ULONG64 Address = ReadProcessMemory<ULONG64>(Process, offsets.begin()[0]);
|
|
for (int i = 1; i < offsets.size() - 1; i++)
|
|
{
|
|
Address = ReadProcessMemory<ULONG64>(Process, Address + offsets.begin()[i]);
|
|
}
|
|
Address += offsets.begin()[offsets.size() - 1];
|
|
T result = T();
|
|
ReadProcessMemory(Process, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|
|
template<typename T>
|
|
static T MmReadProcessMemory(PEPROCESS Process, std::initializer_list<ULONG64> offsets)
|
|
{
|
|
ULONG64 Address = MmReadProcessMemory<ULONG64>(Process, offsets.begin()[0]);
|
|
for (int i = 1; i < offsets.size() - 1; i++)
|
|
{
|
|
Address = MmReadProcessMemory<ULONG64>(Process, Address + offsets.begin()[i]);
|
|
}
|
|
Address += offsets.begin()[offsets.size() - 1];
|
|
T result = T();
|
|
ReadProcessMemory(Process, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|
|
template<typename T>
|
|
static T ReadChain(PEPROCESS Process, ULONG64 Address, std::initializer_list<ULONG64> offsets)
|
|
{
|
|
for (auto offset : offsets)
|
|
{
|
|
Address = ReadProcessMemory<ULONG64>(Process, Address + offset);
|
|
if (!Address)
|
|
return T();
|
|
}
|
|
T result = T();
|
|
ReadProcessMemory(Process, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|
|
template<typename T>
|
|
static T MmReadChain(PEPROCESS Process, ULONG64 Address, std::initializer_list<ULONG64> offsets)
|
|
{
|
|
for (auto offset : offsets)
|
|
{
|
|
Address = MmReadProcessMemory<ULONG64>(Process, Address + offset);
|
|
if (!Address)
|
|
return T();
|
|
}
|
|
T result = T();
|
|
MmReadProcessMemory(Process, Address, &result, sizeof(T));
|
|
return result;
|
|
}
|