Base Process class, to be expanded

This commit is contained in:
2026-08-04 20:09:50 +02:00
parent 6e3590d532
commit ab0090ddb1
8 changed files with 214 additions and 2 deletions
+1
View File
@@ -1,3 +1,4 @@
build
.clangd
.zed
.cache
+2 -1
View File
@@ -6,7 +6,8 @@ set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_library(xrbx STATIC
src/xrbx.cpp
src/xrbx.cpp
src/process.cpp
)
target_include_directories(xrbx
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <windows.h>
#include "ntproc.h"
namespace Nt {
inline HMODULE ntdll() {
static HMODULE mod = LoadLibraryA("ntdll.dll");
return mod;
}
template<typename T>
T resolve(const char *name) {
static T fn = reinterpret_cast<T>(GetProcAddress(ntdll(), name));
return fn;
}
}
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include <Windows.h>
#include <winternl.h>
namespace Nt {
typedef NTSTATUS(NTAPI* OpenProcess)(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
CLIENT_ID *ClientId
);
typedef NTSTATUS(NTAPI* DuplicateObject)(
HANDLE SourceProcessHandle,
HANDLE SourceHandle,
HANDLE TargetProcessHandle,
PHANDLE TargetHandle,
ACCESS_MASK DesiredAccess,
ULONG HandleAttributes,
ULONG Options
);
typedef NTSTATUS(NTAPI *Close)(
HANDLE Handle
);
typedef NTSTATUS(NTAPI *QuerySystemInformation)(
SYSTEM_INFORMATION_CLASS,
PVOID,
ULONG,
PULONG
);
typedef NTSTATUS(NTAPI *QueryInformationProcess)(
HANDLE,
PROCESSINFOCLASS,
PVOID,
ULONG,
PULONG
);
struct PROCESS_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
ULONG_PTR AffinityMask;
LONG BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
};
typedef NTSTATUS(NTAPI *ReadVirtualMemory)(
HANDLE,
PVOID,
PVOID,
SIZE_T,
PSIZE_T
);
typedef struct _PEB_PARTIAL
{
BYTE Reserved1[4];
PVOID Mutant;
PVOID ImageBaseAddress;
} PEB_PARTIAL;
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include <format>
#include <stdexcept>
#include <windows.h>
#include <vector>
#include <string>
#include <winnt.h>
#include "nt/nt.h"
#include "xrbx/nt/ntproc.h"
class Process {
private:
DWORD pid;
HANDLE proc;
BYTE *base;
HANDLE openProcess();
BYTE *getImageBase(void);
public:
static DWORD findProcessByName(const std::wstring &name);
inline BYTE *imageBase(void) {
return base;
}
template <typename T>
inline T Read(BYTE *addr) {
T buf;
SIZE_T bytesRead;
NTSTATUS status = Nt::resolve<Nt::ReadVirtualMemory>("NtReadVirtualMemory")(proc, addr, &buf, sizeof(buf), &bytesRead);
if (status < 0) {
throw std::runtime_error(std::format("Failed to read {} bytes from {:X}", sizeof(buf), uintptr_t(addr)));
}
return buf;
}
inline Process(const std::wstring &name) {
pid = findProcessByName(name);
if (pid == 0) {
throw std::runtime_error("Process not found");
}
proc = openProcess();
base = getImageBase();
}
inline ~Process() {
Nt::resolve<Nt::Close>("NtClose")(proc);
}
};
+2
View File
@@ -1,3 +1,5 @@
#pragma once
#include "process.h"
void helloWorld(void);
+70
View File
@@ -0,0 +1,70 @@
#include "xrbx/process.h"
HANDLE Process::openProcess() {
if (pid == 0) {
return nullptr;
}
CLIENT_ID cid{};
cid.UniqueProcess = (HANDLE)pid;
cid.UniqueThread = nullptr;
OBJECT_ATTRIBUTES oa{};
oa.Length = sizeof oa;
HANDLE proc;
if(Nt::resolve<Nt::OpenProcess>("NtOpenProcess")(&proc, PROCESS_ALL_ACCESS, &oa, &cid) < 0) {
throw std::runtime_error("Failed to open process");
}
HANDLE duplicate;
if(Nt::resolve<Nt::DuplicateObject>("NtDuplicateObject")(GetCurrentProcess(), proc, GetCurrentProcess(), &duplicate, PROCESS_ALL_ACCESS, 0, 0) < 0) {
Nt::resolve<Nt::Close>("NtClose")(proc);
throw std::runtime_error("Failed to duplicate process");
}
Nt::resolve<Nt::Close>("NtClose")(proc);
return duplicate;
}
BYTE *Process::getImageBase(void) {
Nt::PROCESS_BASIC_INFORMATION pbi{};
if (Nt::resolve<Nt::QueryInformationProcess>("NtQueryInformationProcess")(proc, ProcessBasicInformation, &pbi, sizeof(pbi), nullptr) < 0) {
throw std::runtime_error("Failed to get process information");
}
return (BYTE *)Read<Nt::PEB_PARTIAL>((BYTE *)pbi.PebBaseAddress).ImageBaseAddress;
}
DWORD Process::findProcessByName(const std::wstring &name) {
auto NtQuerySystemInformation = Nt::resolve<Nt::QuerySystemInformation>("NtQuerySystemInformation");
ULONG size = 0;
NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size);
std::vector<BYTE> buffer(size);
NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, buffer.data(), size, &size);
if (status < 0) return 0;
auto entry = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(buffer.data());
while (true) {
if (entry->ImageName.Buffer) {
if (_wcsicmp(entry->ImageName.Buffer, name.c_str()) == 0) {
return DWORD(ULONG_PTR(entry->UniqueProcessId));
}
}
if (entry->NextEntryOffset == 0)
break;
entry = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(
reinterpret_cast<BYTE*>(entry)
+ entry->NextEntryOffset
);
}
return 0;
}
+4 -1
View File
@@ -1,6 +1,9 @@
#include "xrbx/xrbx.h"
#include <format>
#include <iostream>
int main() {
helloWorld();
Process rbx(L"notepad.exe");
std::cout << std::format("Image Base: {:X}", uintptr_t(rbx.imageBase())) << std::endl;
return 0;
}