CppUtils/Utils/ProcessOperator.cpp

346 lines
13 KiB
C++
Raw Permalink Normal View History

2025-06-05 10:06:43 +08:00
#include "ProcessOperator.h"
#include "MemLoadLibrary2.h"
#include <Psapi.h>
#include "Utils.h"
typedef struct _PARAMX
{
PVOID lpFileData;
DWORD DataLength;
PVOID LdrGetProcedureAddress;
PVOID pLdrLoadDll;
PVOID RtlInitAnsiString;
PVOID RtlAnsiStringToUnicodeString;
PVOID RtlFreeUnicodeString;
PVOID pMemoryAddress;
}PARAMX, * PPARAMX;
ProcessOperator::ProcessOperator(DWORD pid) :PID(pid)
{
}
BOOL ProcessOperator::Open()
{
Handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, this->PID);
return Handle != NULL;
}
BOOL ProcessOperator::Close()
{
return CloseHandle(this->Handle);
}
BOOL ProcessOperator::Read(ULONG64 addr, const PVOID buffer, SIZE_T size)
{
return ReadProcessMemory(this->Handle, PVOID(addr), buffer, size, NULL);
}
BOOL ProcessOperator::Write(ULONG64 addr, const PVOID buffer, SIZE_T size)
{
return WriteProcessMemory(this->Handle, PVOID(addr), buffer, size, NULL);
}
long long ProcessOperator::VirtualMemorySize()
{
PROCESS_MEMORY_COUNTERS pmc;
K32GetProcessMemoryInfo(this->Handle, &pmc, sizeof(pmc));
return pmc.WorkingSetSize;
}
ULONG64 ProcessOperator::AllocateMemory(SIZE_T size, DWORD protect, DWORD type,ULONG64 baseAddr)
{
return (ULONG64)VirtualAllocEx(this->Handle, (PVOID*)baseAddr, size, type, protect);
}
ULONG64 ProcessOperator::AllocateString(std::string s)
{
ULONG64 ptr = AllocateMemory(s.size() + 1, PAGE_READWRITE, MEM_COMMIT, NULL);
if (ptr)
{
this->Write(ptr, (void*)s.c_str(), s.size() + 1);
return ptr;
}
return NULL;
}
ULONG64 ProcessOperator::AllocateWString(std::wstring s)
{
ULONG64 ptr = AllocateMemory((s.size() + 1) * sizeof(wchar_t), PAGE_READWRITE, MEM_COMMIT, NULL);
if (ptr)
{
this->Write(ptr, (void*)s.c_str(), (s.size() + 1) * sizeof(wchar_t));
return ptr;
}
return NULL;
}
BOOL ProcessOperator::FreeMemory(ULONG64 addr, SIZE_T size, DWORD freeType)
{
return VirtualFreeEx(this->Handle, (PVOID*)&addr, size, freeType);
}
ULONG64 ProcessOperator::CallRemote(ULONG64 func, std::vector<ULONG64> args)
{
std::vector<uint8_t> code = std::vector<uint8_t>();
auto pushcode = [](std::vector<uint8_t>&codeList, const void* code, int size){ codeList.insert(codeList.end(),(uint8_t*)code, (uint8_t*)code+size); };
pushcode(code, "\x55", 1);
pushcode(code, "\x48\x8B\xEC", 3);
if (args.size() < 16)
pushcode(code, "\x48\x83\xEC", 3);
else
pushcode(code, "\x48\x81\xEC", 3);
if (args.size() > 4){
if (args.size() < 16)
code.push_back((args.size() + 1) * 8);
else{
int val = (args.size() + 1) * 8;
pushcode(code, &val, 4);
}
}
else{
code.push_back(0x20);
}
for (int i = 0; i < args.size(); i++){
if (i == 0)
pushcode(code, "\x48\xB9", 2);
else if (i == 1)
pushcode(code, "\x48\xBA", 2);
else if (i == 2)
pushcode(code, "\x49\xB8", 2);
else if (i == 3)
pushcode(code, "\x49\xB9", 2);
else
pushcode(code, "\x48\xB8", 2);
pushcode(code, &args[i], 8);
if (i > 3){
if (i < 16){
pushcode(code, "\x48\x89\x44\x24", 4);
code.push_back(i * 8);
}
else {
pushcode(code, "\x48\x89\x84\x24", 4);
int tmpVal = i * 8;
pushcode(code, &tmpVal, 4);
}
}
}
pushcode(code, "\x48\xB8", 2);
pushcode(code, &func, 8);
pushcode(code, "\xFF\xD0", 2);
pushcode(code, "\x48\xA3", 2);
pushcode(code, "00000000", 8);
if (args.size() < 16)
pushcode(code, "\x48\x83\xC4", 3);
else
pushcode(code, "\x48\x81\xC4", 3);
if (args.size() > 4) {
if (args.size() < 16)
code.push_back((args.size() + 1) * 8);
else{
int val = (args.size() + 1) * 8;
pushcode(code, &val, 4);
}
}
else {
code.push_back(0x20);
}
pushcode(code, "\x48\x8B\xE5", 3);
pushcode(code, "\x5D", 1);
pushcode(code, "\xC3", 1);
pushcode(code, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
ULONG64 membase = this->AllocateMemory(code.size(), PAGE_EXECUTE_READWRITE, MEM_COMMIT, NULL);
ULONG64* p_rax = (ULONG64*)(code.data() + (code.size() - ((args.size() < 16) ? 25 : 28)));
*p_rax = (membase + (code.size() - 8));
if (membase){
if (this->Write(membase, code.data(), code.size())){
ULONG64 result = NULL;
HANDLE tHadnle = CreateRemoteThread(this->Handle, NULL, 0x400, (LPTHREAD_START_ROUTINE)membase, 0, 0, 0);
if (tHadnle){
if (WaitForSingleObject(tHadnle, INFINITE) != WAIT_FAILED)
result = this->Read<ULONG64>(membase + (code.size() - 8));
}
this->FreeMemory(membase, code.size());
return result;
}
this->FreeMemory(membase, code.size());
}
return NULL;
return NULL;
}
ULONG64 ProcessOperator::CallRemote(ULONG64 func,ULONG64 rcx,ULONG64 rdx,ULONG64 r8,ULONG64 r9, ULONG64 rsp20, ULONG64 rsp28, ULONG64 rsp30, ULONG64 rsp38)
{
uint8_t code[] =
{
0x55,
0x48,0x8B,0xEC,
0x48,0x83,0xEC,0x50,
0x48,0xB9,0,0,0,0,0,0,0,0,
0x48,0xBA,0,0,0,0,0,0,0,0,
0x49,0xB8,0,0,0,0,0,0,0,0,
0x49,0xB9,0,0,0,0,0,0,0,0,
0x48,0xB8,0,0,0,0,0,0,0,0,
0x48,0x89,0x44,0x24,0x20,
0x48,0xB8,0,0,0,0,0,0,0,0,
0x48,0x89,0x44,0x24,0x28,
0x48,0xB8,0,0,0,0,0,0,0,0,
0x48,0x89,0x44,0x24,0x30,
0x48,0xB8,0,0,0,0,0,0,0,0,
0x48,0x89,0x44,0x24,0x38,
0x48,0xB8,0,0,0,0,0,0,0,0,
0xFF,0xD0,
0x48,0xA3,0,0,0,0,0,0,0,0,
0x48,0x83,0xC4,0x50,
0x48,0x8B,0xE5,
0x5D,
0xC3,
0,0,0,0,0,0,0,0
};
ULONG64* p_rcx = (ULONG64*)(code + 10);
ULONG64* p_rdx = (ULONG64*)(code + 20);
ULONG64* p_r8 = (ULONG64*)(code + 30);
ULONG64* p_r9 = (ULONG64*)(code + 40);
ULONG64* p_rsp20 = (ULONG64*)(code + 50);
ULONG64* p_rsp28 = (ULONG64*)(code + 65);
ULONG64* p_rsp30 = (ULONG64*)(code + 80);
ULONG64* p_rsp38 = (ULONG64*)(code + 95);
ULONG64* p_call = (ULONG64*)(code + 110);
ULONG64* p_rax = (ULONG64*)(code + 122);
*p_rcx = rcx;
*p_rdx = rdx;
*p_r8 = r8;
*p_r9 = r9;
*p_call = func;
*p_rsp20 = rsp20;
*p_rsp28 = rsp28;
*p_rsp30 = rsp30;
*p_rsp38 = rsp38;
ULONG64 membase = this->AllocateMemory(sizeof(code), PAGE_EXECUTE_READWRITE, MEM_COMMIT, NULL);
*p_rax = ((ULONG64)membase + (sizeof(code) - 8));
if (membase)
{
if (this->Write(membase, code, sizeof(code)))
{
ULONG64 result = NULL;
HANDLE tHadnle = CreateRemoteThread(this->Handle, NULL, 0x400, (LPTHREAD_START_ROUTINE)membase, 0, 0, 0);
if (tHadnle)
{
if(WaitForSingleObject(tHadnle, INFINITE)!= WAIT_FAILED)
result = this->Read<ULONG64>(((ULONG64)membase + (sizeof(code) - 8)));
}
this->FreeMemory(membase, sizeof(code));
return result;
}
this->FreeMemory(membase, sizeof(code));
}
return NULL;
}
ULONG64 ProcessOperator::InjectDll(uint8_t* buffer,SIZE_T size)
{
HMODULE NtBase = GetModuleHandleA("ntdll.dll");
LPVOID dllbase = VirtualAllocEx(this->Handle, NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (dllbase)
{
SIZE_T tmpSize = 0;
WriteProcessMemory(this->Handle, dllbase, buffer, size, &tmpSize);
PARAMX MemLoadLibrary2Param = {};
MemLoadLibrary2Param.pLdrLoadDll = GetProcAddress(NtBase, "LdrLoadDll");
MemLoadLibrary2Param.RtlInitAnsiString = GetProcAddress(NtBase, "RtlInitAnsiString");
MemLoadLibrary2Param.RtlAnsiStringToUnicodeString = GetProcAddress(NtBase, "RtlAnsiStringToUnicodeString");
MemLoadLibrary2Param.RtlFreeUnicodeString = GetProcAddress(NtBase, "RtlFreeUnicodeString");
MemLoadLibrary2Param.LdrGetProcedureAddress = GetProcAddress(NtBase, "LdrGetProcedureAddress");
MemLoadLibrary2Param.lpFileData = dllbase;
MemLoadLibrary2Param.DataLength = size;
MemLoadLibrary2Param.pMemoryAddress = VirtualAllocEx(this->Handle, NULL, GetSectionSize((PVOID)buffer), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
auto RemoteMemLoadLibrary2Param = VirtualAllocEx(this->Handle, NULL, sizeof(PARAMX), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (RemoteMemLoadLibrary2Param)
{
WriteProcessMemory(this->Handle, RemoteMemLoadLibrary2Param, &MemLoadLibrary2Param, sizeof(PARAMX), &tmpSize);
PVOID MemLoadLibrary2Address = VirtualAllocEx(this->Handle, NULL, sizeof(MemLoadLibrary2), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (MemLoadLibrary2Address)
{
WriteProcessMemory(this->Handle, MemLoadLibrary2Address, &MemLoadLibrary2, sizeof(MemLoadLibrary2), &tmpSize);
uint8_t shellcode[] =
{
0x90,
0xC6,0x05,0xF8,0xFF,0xFF,0xFF,0xC3,
0x48,0xB9,0,0,0,0,0,0,0,0,
0xFF,0x25,0,0,0,0,0,0,0,0,0,0,0,0,
0xC3
};
*(ULONG64*)(shellcode + 10) = (ULONG64)RemoteMemLoadLibrary2Param;
*(ULONG64*)(shellcode + 24) = (ULONG64)MemLoadLibrary2Address;
ULONG64 jmpmem = (ULONG64)VirtualAllocEx(this->Handle, NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!jmpmem)
return NULL;
WriteProcessMemory(this->Handle, (PVOID)jmpmem, (PVOID)shellcode, sizeof(shellcode), &tmpSize);
HANDLE tHadnle = CreateRemoteThread(this->Handle, NULL, 0, (LPTHREAD_START_ROUTINE)jmpmem, 0, 0, 0);
WaitForSingleObject(tHadnle, INFINITE);
this->FreeMemory(jmpmem);
this->FreeMemory((ULONG64)dllbase);
this->FreeMemory((ULONG64)RemoteMemLoadLibrary2Param);
this->FreeMemory((ULONG64)MemLoadLibrary2Address);
}
}
return (ULONG64)MemLoadLibrary2Param.pMemoryAddress;
}
return NULL;
}
ULONG64 ProcessOperator::FindPattern(const char* szModule, const char* sPattern, int offset)
{
ULONG64 offset_ = 0;
std::vector<PATTERNVALUE> pattern = ParserPattern(sPattern);
if (pattern.size() == 0) return NULL;
MODULEINFO mi{ };
ULONG64 md_str = this->AllocateString(szModule);
HMODULE remote_hModule = (HMODULE)this->CallRemote((ULONG64)GetModuleHandleA, md_str);
this->FreeMemory(md_str);
if (K32GetModuleInformation(this->Handle, remote_hModule, &mi, sizeof(mi)))
{
BYTE* begin = new BYTE[mi.SizeOfImage];
this->Read((ULONG64)mi.lpBaseOfDll, begin, mi.SizeOfImage);
DWORD size = mi.SizeOfImage;
for (unsigned char* curr = begin + offset; curr <= (begin + size) - pattern.size(); curr++)
{
for (int i = 0; i < pattern.size(); i++)
{
if (pattern[i].ignore == 0x11) continue;
if (!pattern[i].ignore_left && ((curr[i] & 0xF0) >> 4) != pattern[i].left)goto nxt;
if (!pattern[i].ignore_right && (curr[i] & 0x0F) != pattern[i].right)goto nxt;
}
offset_ = (curr - begin);
delete[] begin;
return offset_ + (ULONG64)mi.lpBaseOfDll;
nxt:;
}
delete[] begin;
}
return NULL;
}
ULONG64 ProcessOperator::FindPattern(ULONG64 _begin, const char* sPattern, int search_size, int offset)
{
ULONG64 offset_ = 0;
std::vector<PATTERNVALUE> pattern = ParserPattern(sPattern);
if (pattern.size() == 0) return NULL;
BYTE* begin = new BYTE[search_size];
this->Read((ULONG64)_begin, begin, search_size);
for (unsigned char* curr = begin + offset; curr <= (begin + search_size) - pattern.size(); curr++)
{
for (int i = 0; i < pattern.size(); i++)
{
if (pattern[i].ignore == 0x11) continue;
if (!pattern[i].ignore_left && ((curr[i] & 0xF0) >> 4) != pattern[i].left)goto nxt;
if (!pattern[i].ignore_right && (curr[i] & 0x0F) != pattern[i].right)goto nxt;
}
offset_ = (curr - begin);
delete[] begin;
return offset_ + (ULONG64)_begin;
nxt:;
}
delete[] begin;
return NULL;
}
ULONG64 ProcessOperator::calcRVA(ULONG64 ptr, int offset)
{
uint8_t* buffer = new uint8_t[offset + 0x10];
this->Read(ptr, buffer, offset + 0x10);
int offset_ = *(int*)(buffer + offset);
delete[] buffer;
return ptr + offset_ + offset + 4;
}