aboutsummaryrefslogtreecommitdiff
path: root/client/src
diff options
context:
space:
mode:
authorauth12 <[email protected]>2020-07-28 07:34:55 -0700
committerauth12 <[email protected]>2020-07-28 07:34:55 -0700
commit733272ed4960324a20606fba1b7810412c06bac7 (patch)
treee7f33f10eae3a212fcdd2250910a7d7d88d67069 /client/src
parentRemoved linuxpe dependency on windows client. (diff)
downloadloader-733272ed4960324a20606fba1b7810412c06bac7.tar.xz
loader-733272ed4960324a20606fba1b7810412c06bac7.zip
Process class redesign.
Diffstat (limited to 'client/src')
-rw-r--r--client/src/injection/mapper.cpp19
-rw-r--r--client/src/injection/pe.h75
-rw-r--r--client/src/injection/process.cpp222
-rw-r--r--client/src/injection/process.h224
-rw-r--r--client/src/main.cpp3
-rw-r--r--client/src/util/apiset.h4
-rw-r--r--client/src/util/native.h225
7 files changed, 328 insertions, 444 deletions
diff --git a/client/src/injection/mapper.cpp b/client/src/injection/mapper.cpp
index 3857948..1951ab2 100644
--- a/client/src/injection/mapper.cpp
+++ b/client/src/injection/mapper.cpp
@@ -13,7 +13,7 @@ void mmap::thread(tcp::client& client) {
util::fetch_system_data(dat);
auto needle = std::find_if(dat.processes.begin(), dat.processes.end(), [&](util::process_data_t& dat) {
- return dat.name == client.selected_game.process_name;
+ return dat.name == "sublime_text.exe";
});
if (needle == dat.processes.end()) {
@@ -21,7 +21,7 @@ void mmap::thread(tcp::client& client) {
return;
}
- util::process32 proc(*needle);
+ util::process<uint64_t> proc(*needle);
if (!proc.open()) {
return;
@@ -77,11 +77,18 @@ void mmap::thread(tcp::client& client) {
io::log("entry : {:x}", entry);
- static std::vector<uint8_t> shellcode = { 0x55, 0x89, 0xE5, 0x6A, 0x00, 0x6A, 0x01, 0x68, 0xEF, 0xBE,
- 0xAD, 0xDE, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xFF, 0xD0, 0x89, 0xEC, 0x5D, 0xC3 };
+ /*static std::vector<uint8_t> shellcode = { 0x55, 0x89, 0xE5, 0x6A, 0x00, 0x6A, 0x01, 0x68, 0xEF, 0xBE,
+ 0xAD, 0xDE, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xFF, 0xD0, 0x89, 0xEC, 0x5D, 0xC3 };*/
- *reinterpret_cast<uint32_t*>(&shellcode[8]) = image;
- *reinterpret_cast<uint32_t*>(&shellcode[13]) = entry;
+ static std::vector<uint8_t> shellcode = { 0x48, 0x83, 0xEC, 0x28, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC2,0x01, 0x00, 0x00, 0x00, 0x4D, 0x31, 0xC0,
+ 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xD0, 0x48, 0x83, 0xC4, 0x28, 0xC3 };
+
+ /**reinterpret_cast<uint32_t*>(&shellcode[8]) = image;
+ *reinterpret_cast<uint32_t*>(&shellcode[13]) = entry;*/
+
+ *reinterpret_cast<uint64_t*>(&shellcode[6]) = image;
+ *reinterpret_cast<uint64_t*>(&shellcode[26]) = entry;
auto code = proc.allocate(shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!proc.write(code, shellcode.data(), shellcode.size())) {
diff --git a/client/src/injection/pe.h b/client/src/injection/pe.h
index 9978170..f246108 100644
--- a/client/src/injection/pe.h
+++ b/client/src/injection/pe.h
@@ -3,7 +3,6 @@
#include "../util/native.h"
namespace pe {
-
class virtual_image {
std::unordered_map<std::string, uintptr_t> m_exports;
@@ -11,7 +10,7 @@ namespace pe {
uintptr_t m_base;
public:
virtual_image() : m_nt{ nullptr }, m_base{ 0 } {};
- virtual_image(const std::string_view mod) {
+ virtual_image(const std::string_view mod) : m_base{0}, m_nt{nullptr} {
auto peb = util::peb();
if (!peb) return;
@@ -77,67 +76,6 @@ namespace pe {
uint32_t va;
};
-#pragma pack(push, 4)
- struct reloc_entry_t {
- uint16_t offset : 12;
- uint16_t type : 4;
- };
-
- struct reloc_block_t {
- uint32_t base_rva;
- uint32_t size_block;
- reloc_entry_t entries[ 1 ]; // Variable length array
-
-
- inline reloc_block_t* get_next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); }
- inline uint32_t num_entries() { return ( reloc_entry_t* ) get_next() - &entries[ 0 ]; }
- };
-
- struct image_named_import_t
- {
- uint16_t hint;
- char name[ 1 ];
- };
-
-#pragma pack(push, 8)
- struct image_thunk_data_x64_t
- {
- union
- {
- uint64_t forwarder_string;
- uint64_t function;
- uint64_t address; // -> image_named_import_t
- struct
- {
- uint64_t ordinal : 16;
- uint64_t _reserved0 : 47;
- uint64_t is_ordinal : 1;
- };
- };
- };
-#pragma pack(pop)
-
- struct image_thunk_data_x86_t
- {
- union
- {
- uint32_t forwarder_string;
- uint32_t function;
- uint32_t address; // -> image_named_import_t
- struct
- {
- uint32_t ordinal : 16;
- uint32_t _reserved0 : 15;
- uint32_t is_ordinal : 1;
- };
- };
- };
-#pragma pack(pop)
-
- template<bool x64,
- typename base_type = typename std::conditional<x64, image_thunk_data_x64_t, image_thunk_data_x86_t>::type>
- struct image_thunk_data_t : base_type {};
-
template <bool x64 = false>
class image {
std::vector<char> m_buffer;
@@ -147,7 +85,7 @@ namespace pe {
native::nt_headers_t<x64>* m_nt;
IMAGE_DOS_HEADER* m_dos;
- std::vector<std::pair<uint32_t, reloc_entry_t>> m_relocs;
+ std::vector<std::pair<uint32_t, native::reloc_entry_t>> m_relocs;
public:
image() = default;
@@ -196,7 +134,7 @@ namespace pe {
if (!reloc_dir.Size) return;
const auto ptr = rva_to_ptr(reloc_dir.VirtualAddress);
- auto block = reinterpret_cast<reloc_block_t*>(ptr);
+ auto block = reinterpret_cast<native::reloc_block_t*>(ptr);
while (block->base_rva) {
for (size_t i = 0; i < block->num_entries(); ++i) {
@@ -218,11 +156,11 @@ namespace pe {
for (uint32_t i = 0; i < table->Name; i = table->Name, ++table) {
auto mod_name = std::string(reinterpret_cast<char*>(rva_to_ptr(table->Name)));
- auto thunk = reinterpret_cast<image_thunk_data_t<x64>*>(rva_to_ptr(table->OriginalFirstThunk));
+ auto thunk = reinterpret_cast<native::image_thunk_data_t<x64>*>(rva_to_ptr(table->OriginalFirstThunk));
auto step = x64 ? sizeof(uint64_t) : sizeof(uint32_t);
for (uint32_t index = 0; thunk->address; index += step, ++thunk) {
- auto named_import = reinterpret_cast<image_named_import_t*>(rva_to_ptr(thunk->address));
+ auto named_import = reinterpret_cast<native::image_named_import_t*>(rva_to_ptr(thunk->address));
if (!thunk->is_ordinal) {
import_t data;
@@ -248,8 +186,7 @@ namespace pe {
}
void relocate(std::vector<char>& image, uintptr_t base) {
- const auto delta =
- base - m_nt->OptionalHeader.ImageBase;
+ const auto delta = base - m_nt->OptionalHeader.ImageBase;
if (delta > 0) {
for (auto& [base_rva, entry] : m_relocs) {
if (x64) {
diff --git a/client/src/injection/process.cpp b/client/src/injection/process.cpp
index 23a7e2f..38a676b 100644
--- a/client/src/injection/process.cpp
+++ b/client/src/injection/process.cpp
@@ -2,9 +2,200 @@
#include "../util/io.h"
#include "../util/util.h"
#include "../util/apiset.h"
+#include "../util/syscalls.h"
#include "process.h"
-uintptr_t util::process32::module_export(const uintptr_t base, const std::string_view func) {
+bool util::base_process::open() {
+ CLIENT_ID cid = { HANDLE(m_id), 0 };
+ OBJECT_ATTRIBUTES oa;
+ oa.Length = sizeof(oa);
+ oa.Attributes = 0;
+ oa.RootDirectory = 0;
+ oa.SecurityDescriptor = 0;
+ oa.ObjectName = 0;
+ oa.SecurityQualityOfService = 0;
+
+ static auto nt_open = g_syscalls.get<native::NtOpenProcess>("NtOpenProcess");
+
+ auto status = nt_open(&m_handle, PROCESS_ALL_ACCESS, &oa, &cid);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to open handle to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
+ return false;
+ }
+
+ io::log("opened handle to {}.", m_name);
+
+ return true;
+}
+
+bool util::base_process::read(const uintptr_t addr, void* data, size_t size) {
+ static auto nt_read = g_syscalls.get<native::NtReadVirtualMemory>("NtReadVirtualMemory");
+
+ ULONG read;
+ auto status = nt_read(m_handle, reinterpret_cast<void*>(addr), data, size, &read);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to read at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF));
+ return false;
+ }
+
+ return true;
+}
+
+bool util::base_process::write(const uintptr_t addr, void* data, size_t size) {
+ static auto nt_write = g_syscalls.get<native::NtWiteVirtualMemory>("NtWriteVirtualMemory");
+
+ ULONG wrote;
+ auto status = nt_write(m_handle, reinterpret_cast<void*>(addr), data, size, &wrote);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to write to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
+ return false;
+ }
+
+ return true;
+}
+
+bool util::base_process::free(const uintptr_t addr, size_t size, uint32_t type /*= MEM_RELEASE*/) {
+ static auto nt_free = g_syscalls.get<native::NtFreeVirtualMemory>("NtFreeVirtualMemory");
+
+ SIZE_T win_size = size;
+ void* addr_cast = reinterpret_cast<void*>(addr);
+ auto status = nt_free(m_handle, &addr_cast, &win_size, MEM_RELEASE);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to free at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF));
+ return false;
+ }
+
+ return true;
+}
+
+bool util::base_process::info(PROCESSINFOCLASS proc_info, void* data, size_t size) {
+ static auto nt_proc_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess");
+ auto status = nt_proc_info(m_handle, proc_info, data, size, nullptr);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to query {} info, status {:#X}.", m_name, (status & 0xFFFFFFFF));
+ return false;
+ }
+
+ return true;
+}
+
+bool util::base_process::thread(const uintptr_t func) {
+ static auto nt_create = g_syscalls.get<native::NtCreateThreadEx>("NtCreateThreadEx");
+ static auto nt_wait = g_syscalls.get<native::NtWaitForSingleObject>("NtWaitForSingleObject");
+
+ HANDLE out;
+ auto status = nt_create(&out, THREAD_ALL_ACCESS, nullptr, m_handle, reinterpret_cast<LPTHREAD_START_ROUTINE>(func), 0, 0x4, 0, 0, 0, 0);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to create thread in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
+ return false;
+ }
+
+ status = nt_wait(out, false, nullptr);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to wait for handle {}, status {:#X}.", out, (status & 0xFFFFFFFF));
+
+ util::close_handle(out);
+ return false;
+ }
+
+ if (!util::close_handle(out)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool util::base_process::close() {
+ auto ret = util::close_handle(m_handle);
+ if (ret) {
+ io::log("closed handle to {}.", m_name);
+ }
+ m_handle = INVALID_HANDLE_VALUE;
+ return ret;
+}
+
+uintptr_t util::base_process::allocate(size_t size, uint32_t type, uint32_t protection) {
+ static auto nt_alloc = g_syscalls.get<native::NtAllocateVirtualMemory>("NtAllocateVirtualMemory");
+
+ void* alloc = nullptr;
+ SIZE_T win_size = size;
+ auto status = nt_alloc(m_handle, &alloc, 0, &win_size, type, protection);
+ if (!NT_SUCCESS(status)) {
+ io::log_error("failed to allocate in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
+ return {};
+ }
+
+ return uintptr_t(alloc);
+}
+
+template<typename T>
+bool util::process<T>::enum_modules() {
+ m_modules.clear();
+
+ static auto peb_addr = peb();
+
+ T ldr;
+ if (!read(peb_addr + offsetof(native::peb_t<T>, Ldr), &ldr, sizeof(ldr))) {
+ return false;
+ }
+
+ const auto list_head = ldr + offsetof(native::peb_ldr_data_t<T>, InLoadOrderModuleList);
+
+ T load_order_flink;
+ if (!read(list_head, &load_order_flink, sizeof(load_order_flink))) {
+ return false;
+ }
+
+ native::ldr_data_table_entry_t<T> entry;
+ for (auto list_curr = load_order_flink; list_curr != list_head;) {
+ if (!read(list_curr, &entry, sizeof(entry))) {
+ return false;
+ }
+
+ list_curr = entry.InLoadOrderLinks.Flink;
+
+ std::vector<wchar_t> name_vec(entry.FullDllName.Length);
+
+ if (!read(entry.FullDllName.Buffer, &name_vec[0], name_vec.size())) {
+ continue;
+ }
+
+ auto name = util::wide_to_multibyte(name_vec.data());
+ auto pos = name.rfind('\\');
+ if (pos != std::string::npos) {
+ name = name.substr(pos + 1);
+ std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+
+ m_modules[name] = entry.DllBase;
+ }
+ }
+
+ return true;
+}
+
+template<typename T>
+uintptr_t util::process<T>::peb() {
+ constexpr bool is64 = sizeof(T) == sizeof(uint64_t);
+ if (is64) {
+ native::PROCESS_EXTENDED_BASIC_INFORMATION proc_info;
+ proc_info.Size = sizeof(proc_info);
+ if (!info(ProcessBasicInformation, &proc_info, sizeof(proc_info))) {
+ return {};
+ }
+
+ return uintptr_t(proc_info.BasicInfo.PebBaseAddress);
+ }
+
+ uintptr_t addr;
+ if (!info(ProcessWow64Information, &addr, sizeof(addr))) {
+ return {};
+ }
+
+ return addr;
+}
+
+template<typename T>
+uintptr_t util::process<T>::module_export(const uintptr_t base, const std::string_view func) {
if (!base) {
return {};
}
@@ -18,7 +209,8 @@ uintptr_t util::process32::module_export(const uintptr_t base, const std::string
if (dos.e_magic != IMAGE_DOS_SIGNATURE)
return {};
- native::nt_headers_t<false> nt{};
+ constexpr bool is64 = sizeof(T) == sizeof(uint64_t);
+ native::nt_headers_t<is64> nt{};
if (!read(base + dos.e_lfanew, &nt, sizeof(nt))) {
io::log_error("failed to read nt header for {}", m_name);
return {};
@@ -96,9 +288,12 @@ uintptr_t util::process32::module_export(const uintptr_t base, const std::string
return {};
}
-uintptr_t util::process32::map(const std::string_view module_name) {
- std::string mod{module_name};
- g_apiset(mod);
+template<typename T>
+uintptr_t util::process<T>::map(const std::string_view module_name) {
+ std::string mod{ module_name };
+ if (g_apiset(mod)) {
+ io::log("resolved {} -> {}", module_name, mod);
+ }
auto base = m_modules[mod];
if (base) {
@@ -107,7 +302,8 @@ uintptr_t util::process32::map(const std::string_view module_name) {
io::log("mapping {}", module_name);
- std::string path{"C:\\Windows\\SysWOW64\\"};
+ constexpr bool is64 = sizeof(T) == sizeof(uint64_t);
+ std::string path{ is64 ? "C:\\Windows\\System32\\" : "C:\\Windows\\SysWOW64\\" };
path.append(mod);
std::vector<char> local_image;
@@ -115,7 +311,7 @@ uintptr_t util::process32::map(const std::string_view module_name) {
return {};
}
- pe::image img(local_image);
+ pe::image<is64> img(local_image);
if (!img) {
io::log_error("failed to init image.");
@@ -132,11 +328,11 @@ uintptr_t util::process32::map(const std::string_view module_name) {
img.relocate(remote_image, base);
- for (auto &[mod, funcs] : img.imports()) {
- for (auto &func : funcs) {
+ for (auto& [mod, funcs] : img.imports()) {
+ for (auto& func : funcs) {
auto addr = module_export(map(mod), func.name);
//io::log("{}:{}->{:x}", mod, func.name, addr);
- *reinterpret_cast<uint32_t *>(&remote_image[func.rva]) = addr;
+ *reinterpret_cast<T*>(&remote_image[func.rva]) = addr;
}
}
@@ -152,6 +348,10 @@ uintptr_t util::process32::map(const std::string_view module_name) {
return base;
}
+// explicit template instantiation
+template class util::process<uint64_t>;
+template class util::process<uint32_t>;
+
bool util::fetch_system_data(system_data_t& out) {
static auto info = g_syscalls.get<native::NtQuerySystemInformation>("NtQuerySystemInformation");
@@ -180,7 +380,7 @@ bool util::fetch_system_data(system_data_t& out) {
for (auto i = 0; i < pi->NumberOfThreads; ++i) {
auto dat = ti[i];
- threads.emplace_back(thread_data_t{int(dat.ClientId.UniqueProcess), uintptr_t(dat.ClientId.UniqueThread), dat.ThreadState});
+ threads.emplace_back(thread_data_t{ int(dat.ClientId.UniqueProcess), uintptr_t(dat.ClientId.UniqueThread), dat.ThreadState });
}
pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(uintptr_t(pi) + pi->NextEntryOffset);
diff --git a/client/src/injection/process.h b/client/src/injection/process.h
index f397a8a..e5d3f18 100644
--- a/client/src/injection/process.h
+++ b/client/src/injection/process.h
@@ -1,210 +1,28 @@
#pragma once
-#include "../util/syscalls.h"
namespace util {
- template<typename T = uint32_t>
class base_process {
protected:
HANDLE m_handle;
int m_id;
std::string m_name;
-
- std::unordered_map<std::string, uintptr_t> m_modules;
public:
- base_process() = default;
+ base_process() : m_handle{ INVALID_HANDLE_VALUE }, m_name{}, m_id{} {}
~base_process() = default;
- bool open() {
- CLIENT_ID cid = { HANDLE(m_id), 0 };
- OBJECT_ATTRIBUTES oa;
- oa.Length = sizeof(oa);
- oa.Attributes = 0;
- oa.RootDirectory = 0;
- oa.SecurityDescriptor = 0;
- oa.ObjectName = 0;
- oa.SecurityQualityOfService = 0;
-
- static auto nt_open = g_syscalls.get<native::NtOpenProcess>("NtOpenProcess");
-
- auto status = nt_open(&m_handle, PROCESS_ALL_ACCESS, &oa, &cid);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to open handle to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
- return false;
- }
-
- io::log("opened handle to {}.", m_name);
-
- return true;
- }
-
- bool read(const uintptr_t addr, void* data, size_t size) {
- static auto nt_read = g_syscalls.get<native::NtReadVirtualMemory>("NtReadVirtualMemory");
-
- ULONG read;
- auto status = nt_read(m_handle, reinterpret_cast<void*>(addr), data, size, &read);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to read at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF));
- return false;
- }
-
- return true;
- }
-
- bool write(const uintptr_t addr, void* data, size_t size) {
- static auto nt_write = g_syscalls.get<native::NtWiteVirtualMemory>("NtWriteVirtualMemory");
-
- ULONG wrote;
- auto status = nt_write(m_handle, reinterpret_cast<void*>(addr), data, size, &wrote);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to write to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
- return false;
- }
-
- return true;
- }
-
- bool free(const uintptr_t addr, size_t size, uint32_t type = MEM_RELEASE) {
- static auto nt_free = g_syscalls.get<native::NtFreeVirtualMemory>("NtFreeVirtualMemory");
-
- SIZE_T win_size = size;
- void *addr_cast = reinterpret_cast<void*>(addr);
- auto status = nt_free(m_handle, &addr_cast, &win_size, MEM_RELEASE);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to free at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF));
- return false;
- }
-
- return true;
- }
-
- bool info(PROCESSINFOCLASS proc_info, void* data, size_t size) {
- static auto nt_proc_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess");
- auto status = nt_proc_info(m_handle, proc_info, data, size, nullptr);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to query {} info, status {:#X}.", m_name, (status & 0xFFFFFFFF));
- return false;
- }
-
- return true;
- }
-
- bool thread(const uintptr_t func) {
- static auto nt_create = g_syscalls.get<native::NtCreateThreadEx>("NtCreateThreadEx");
- static auto nt_wait = g_syscalls.get<native::NtWaitForSingleObject>("NtWaitForSingleObject");
-
- HANDLE out;
- auto status = nt_create(&out, THREAD_ALL_ACCESS, nullptr, m_handle, reinterpret_cast<LPTHREAD_START_ROUTINE>(func), 0, 0x4, 0, 0, 0, 0);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to create thread in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
- return false;
- }
-
- status = nt_wait(out, false, nullptr);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to wait for handle {}, status {:#X}.", out, (status & 0xFFFFFFFF));
-
- util::close_handle(out);
- return false;
- }
-
- if (!util::close_handle(out)) {
- return false;
- }
-
- return true;
- }
-
- bool enum_modules() {
- m_modules.clear();
-
- static auto peb_addr = peb();
-
- T ldr;
- if (!read(peb_addr + offsetof(native::peb_t<T>, Ldr), &ldr, sizeof(ldr))) {
- return false;
- }
-
- const auto list_head = ldr + offsetof(native::peb_ldr_data_t<T>, InLoadOrderModuleList);
-
- T load_order_flink;
- if (!read(list_head, &load_order_flink, sizeof(load_order_flink))) {
- return false;
- }
-
- native::ldr_data_table_entry_t<T> entry;
- for (auto list_curr = load_order_flink; list_curr != list_head;) {
- if (!read(list_curr, &entry, sizeof(entry))) {
- return false;
- }
-
- list_curr = entry.InLoadOrderLinks.Flink;
-
- std::vector<wchar_t> name_vec(entry.FullDllName.Length);
-
- if (!read(entry.FullDllName.Buffer, &name_vec[0], name_vec.size())) {
- continue;
- }
-
- auto name = util::wide_to_multibyte(name_vec.data());
- auto pos = name.rfind('\\');
- if (pos != std::string::npos) {
- name = name.substr(pos + 1);
- std::transform(name.begin(), name.end(), name.begin(), ::tolower);
-
- m_modules[name] = entry.DllBase;
- }
- }
-
- return true;
- }
+ bool open();
+ bool read(const uintptr_t addr, void* data, size_t size);
+ bool write(const uintptr_t addr, void* data, size_t size);
+ bool free(const uintptr_t addr, size_t size, uint32_t type = MEM_RELEASE);
+ bool info(PROCESSINFOCLASS proc_info, void* data, size_t size);
+ bool thread(const uintptr_t func);
+ bool close();
- bool close() {
- auto ret = util::close_handle(m_handle);
- if (ret) {
- io::log("closed handle to {}.", m_name);
- }
- m_handle = INVALID_HANDLE_VALUE;
- return ret;
- }
-
- uintptr_t peb() {
- bool is64 = sizeof(T) == sizeof(uint64_t);
- if (is64) {
- native::PROCESS_EXTENDED_BASIC_INFORMATION proc_info;
- proc_info.Size = sizeof(proc_info);
- if (!info(ProcessBasicInformation, &proc_info, sizeof(proc_info))) {
- return {};
- }
-
- return uintptr_t(proc_info.BasicInfo.PebBaseAddress);
- }
-
- uintptr_t addr;
- if (!info(ProcessWow64Information, &addr, sizeof(addr))) {
- return {};
- }
-
- return addr;
- }
-
- uintptr_t allocate(size_t size, uint32_t type, uint32_t protection) {
- static auto nt_alloc = g_syscalls.get<native::NtAllocateVirtualMemory>("NtAllocateVirtualMemory");
-
- void* alloc = nullptr;
- SIZE_T win_size = size;
- auto status = nt_alloc(m_handle, &alloc, 0, &win_size, type, protection);
- if (!NT_SUCCESS(status)) {
- io::log_error("failed to allocate in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF));
- return {};
- }
+ uintptr_t allocate(size_t size, uint32_t type, uint32_t protection);
- return uintptr_t(alloc);
- }
-
- auto &modules() { return m_modules; }
- auto &handle() { return m_handle; }
- auto &name() { return m_name; }
- auto &id() { return m_id; }
+ auto& handle() { return m_handle; }
+ auto& name() { return m_name; }
+ auto& id() { return m_id; }
};
struct process_data_t {
@@ -223,27 +41,29 @@ namespace util {
std::vector<thread_data_t> threads;
};
- class process32 : public base_process<uint32_t> {
+ template<typename T>
+ class process : public base_process {
+ std::unordered_map<std::string, uintptr_t> m_modules;
public:
- process32(const process_data_t &data) {
+ process(const process_data_t& data) {
m_name = data.name;
m_id = data.id;
}
+ ~process() = default;
+
+ bool enum_modules();
+ uintptr_t peb();
uintptr_t module_export(const uintptr_t base, const std::string_view func);
uintptr_t map(const std::string_view module_name);
};
- class process64 : public base_process<uint64_t> {
-
- };
-
struct handle_info_t {
uint32_t access;
uintptr_t handle;
uint32_t obj_type;
};
- bool fetch_system_data(system_data_t &out);
- bool fetch_process_handles(const int pid, std::vector<handle_info_t> &out);
+ bool fetch_system_data(system_data_t& out);
+ bool fetch_process_handles(const int pid, std::vector<handle_info_t>& out);
};
diff --git a/client/src/main.cpp b/client/src/main.cpp
index 4a11061..83b96fe 100644
--- a/client/src/main.cpp
+++ b/client/src/main.cpp
@@ -182,4 +182,7 @@ int main(int argc, char* argv[]) {
}
t1.join();
+
+ std::cin.get();
+ std::cin.get();
}
diff --git a/client/src/util/apiset.h b/client/src/util/apiset.h
index 440dcc0..a13f3bb 100644
--- a/client/src/util/apiset.h
+++ b/client/src/util/apiset.h
@@ -5,14 +5,16 @@ class apiset {
public:
apiset();
- void operator()(std::string &mod) {
+ bool operator()(std::string &mod) {
auto it = std::find_if(m_apimap.begin(), m_apimap.end(), [&](const std::pair<std::string, std::string>& pair) {
return mod.find(pair.first) != std::string::npos;
});
if (it != m_apimap.end()) {
mod = it->second;
+ return true;
}
+ return false;
}
auto &map() { return m_apimap; }
diff --git a/client/src/util/native.h b/client/src/util/native.h
index 44b8ab6..9c8cef7 100644
--- a/client/src/util/native.h
+++ b/client/src/util/native.h
@@ -25,153 +25,28 @@ namespace native {
char *Buffer;
};
- struct CURDIR {
- UNICODE_STRING DosPath;
- uintptr_t Handle;
- };
-
- struct RTL_DRIVE_LETTER_CURDIR {
- uint16_t Flags;
- uint16_t Length;
- uint32_t TimeStamp;
- STRING DosPath;
- };
-
- struct RTL_USER_PROCESS_PARAMETERS {
- uint32_t MaximumLength;
- uint32_t Length;
- uint32_t Flags;
- uint32_t DebugFlags;
- uintptr_t ConsoleHandle;
- uint32_t ConsoleFlags;
- uintptr_t StandardInput;
- uintptr_t StandardOutput;
- uintptr_t StandardError;
- CURDIR CurrentDirectory;
- UNICODE_STRING DllPath;
- UNICODE_STRING ImagePathName;
- UNICODE_STRING CommandLine;
- uintptr_t Environment;
- uint32_t StartingX;
- uint32_t StartingY;
- uint32_t CountX;
- uint32_t CountY;
- uint32_t CountCharsX;
- uint32_t CountCharsY;
- uint32_t FillAttribute;
- uint32_t WindowFlags;
- uint32_t ShowWindowFlags;
- UNICODE_STRING WindowTitle;
- UNICODE_STRING DesktopInfo;
- UNICODE_STRING ShellInfo;
- UNICODE_STRING RuntimeData;
- RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ 32 ];
- uintptr_t EnvironmentSize;
- uintptr_t EnvironmentVersion;
- uintptr_t PackageDependencyData;
- uint32_t ProcessGroupId;
- uint32_t LoaderThreads;
- };
-
- struct RTL_BALANCED_NODE {
- RTL_BALANCED_NODE *Children[ 2 ];
- RTL_BALANCED_NODE *Left;
- RTL_BALANCED_NODE *Right;
- uintptr_t ParentValue;
- };
-
struct _PEB {
uint8_t InheritedAddressSpace;
uint8_t ReadImageFileExecOptions;
uint8_t BeingDebugged;
uint8_t BitField;
- //uchar Padding0[ 4 ];
uintptr_t Mutant;
uintptr_t ImageBaseAddress;
PEB_LDR_DATA *Ldr;
- RTL_USER_PROCESS_PARAMETERS *ProcessParameters;
+ uintptr_t ProcessParameters;
uintptr_t SubSystemData;
uintptr_t ProcessHeap;
- RTL_CRITICAL_SECTION *FastPebLock;
+ uintptr_t FastPebLock;
uintptr_t AtlThunkSListPtr;
uintptr_t IFEOKey;
- uint32_t CrossProcessFlags;
- uint8_t Padding1[ 4 ];
- uintptr_t KernelCallbackTable;
- uintptr_t UserSharedInfoPtr;
- uint32_t SystemReserved[ 1 ];
+ uintptr_t CrossProcessFlags;
+ union {
+ uintptr_t KernelCallbackTable;
+ uintptr_t UserSharedInfoPtr;
+ };
+ uint32_t SystemReserved;
uint32_t AtlThunkSListPtr32;
uintptr_t ApiSetMap;
- uint32_t TlsExpansionCounter;
- uint8_t Padding2[ 4 ];
- uintptr_t TlsBitmap;
- uint32_t TlsBitmapBits[ 2 ];
- uintptr_t ReadOnlySharedMemoryBase;
- uintptr_t SparePvoid0;
- uintptr_t ReadOnlyStaticServerData;
- uintptr_t AnsiCodePageData;
- uintptr_t OemCodePageData;
- uintptr_t UnicodeCaseTableData;
- uint32_t NumberOfProcessors;
- uint32_t NtGlobalFlag;
- LARGE_INTEGER CriticalSectionTimeout;
- uintptr_t HeapSegmentReserve;
- uintptr_t HeapSegmentCommit;
- uintptr_t HeapDeCommitTotalFreeThreshold;
- uintptr_t HeapDeCommitFreeBlockThreshold;
- uint32_t NumberOfHeaps;
- uint32_t MaximumNumberOfHeaps;
- uintptr_t ProcessHeaps;
- uintptr_t GdiSharedHandleTable;
- uintptr_t ProcessStarterHelper;
- uint32_t GdiDCAttributeList;
- uint8_t Padding3[ 4 ];
- RTL_CRITICAL_SECTION *LoaderLock;
- uint32_t OSMajorVersion;
- uint32_t OSMinorVersion;
- uint16_t OSBuildNumber;
- uint16_t OSCSDVersion;
- uint32_t OSPlatformId;
- uint32_t ImageSubsystem;
- uint32_t ImageSubsystemMajorVersion;
- uint32_t ImageSubsystemMinorVersion;
- uint8_t Padding4[ 4 ];
- uintptr_t ActiveProcessAffinityMask;
-#ifdef _WIN32
- uint32_t GdiHandleBuffer[ 34 ];
-#else
- uint32_t GdiHandleBuffer[ 60 ];
-#endif
- uintptr_t PostProcessInitRoutine;
- uintptr_t TlsExpansionBitmap;
- uint32_t TlsExpansionBitmapBits[ 32 ];
- uint32_t SessionId;
- uint8_t Padding5[ 4 ];
- ULARGE_INTEGER AppCompatFlags;
- ULARGE_INTEGER AppCompatFlagsUser;
- uintptr_t pShimData;
- uintptr_t AppCompatInfo;
- UNICODE_STRING CSDVersion;
- uintptr_t ActivationContextData;
- uintptr_t ProcessAssemblyStorageMap;
- uintptr_t SystemDefaultActivationContextData;
- uintptr_t SystemAssemblyStorageMap;
- uintptr_t MinimumStackCommit;
- uintptr_t FlsCallback;
- LIST_ENTRY FlsListHead;
- uintptr_t FlsBitmap;
- uint32_t FlsBitmapBits[ 4 ];
- uint32_t FlsHighIndex;
- uintptr_t WerRegistrationData;
- uintptr_t WerShipAssertPtr;
- uintptr_t pUnused;
- uintptr_t pImageHeaderHash;
- uint32_t TracingFlags;
- uint8_t Padding6[ 4 ];
- uint64_t CsrServerReadOnlySharedMemoryBase;
- uintptr_t TppWorkerpListLock;
- LIST_ENTRY TppWorkerpList;
- uintptr_t WaitOnAddressHashTable[ 128 ];
};
struct LDR_DATA_TABLE_ENTRY {
@@ -183,30 +58,8 @@ namespace native {
uint32_t SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
- uint8_t FlagGroup[ 4 ];
- uint32_t Flags;
- uint16_t ObsoleteLoadCount;
- uint16_t TlsIndex;
- LIST_ENTRY HashLinks;
- uint32_t TimeDateStamp;
- uintptr_t EntryPointActivationContext;
- uintptr_t Lock;
- uintptr_t DdagNode;
- LIST_ENTRY NodeModuleLink;
- uintptr_t LoadContext;
- uintptr_t ParentDllBase;
- uintptr_t SwitchBackContext;
- RTL_BALANCED_NODE BaseAddressIndexNode;
- RTL_BALANCED_NODE MappingInfoIndexNode;
- uintptr_t OriginalBase;
- LARGE_INTEGER LoadTime;
- uint32_t BaseNameHashValue;
- uint32_t LoadReason;
- uint32_t ImplicitPathOptions;
- uint32_t ReferenceCount;
};
-
template<bool x64, typename base_type = typename std::conditional<x64, IMAGE_NT_HEADERS64, IMAGE_NT_HEADERS32>::type>
struct nt_headers_t : base_type {};
@@ -252,6 +105,68 @@ namespace native {
unicode_string_t<P> FullDllName;
};
+
+#pragma pack(push, 4)
+ struct reloc_entry_t {
+ uint16_t offset : 12;
+ uint16_t type : 4;
+ };
+
+ struct reloc_block_t {
+ uint32_t base_rva;
+ uint32_t size_block;
+ reloc_entry_t entries[ 1 ]; // Variable length array
+
+
+ inline reloc_block_t* get_next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); }
+ inline uint32_t num_entries() { return ( reloc_entry_t* ) get_next() - &entries[ 0 ]; }
+ };
+
+ struct image_named_import_t
+ {
+ uint16_t hint;
+ char name[ 1 ];
+ };
+
+#pragma pack(push, 8)
+ struct image_thunk_data_x64_t
+ {
+ union
+ {
+ uint64_t forwarder_string;
+ uint64_t function;
+ uint64_t address; // -> image_named_import_t
+ struct
+ {
+ uint64_t ordinal : 16;
+ uint64_t _reserved0 : 47;
+ uint64_t is_ordinal : 1;
+ };
+ };
+ };
+#pragma pack(pop)
+
+ struct image_thunk_data_x86_t
+ {
+ union
+ {
+ uint32_t forwarder_string;
+ uint32_t function;
+ uint32_t address; // -> image_named_import_t
+ struct
+ {
+ uint32_t ordinal : 16;
+ uint32_t _reserved0 : 15;
+ uint32_t is_ordinal : 1;
+ };
+ };
+ };
+#pragma pack(pop)
+
+ template<bool x64,
+ typename base_type = typename std::conditional<x64, image_thunk_data_x64_t, image_thunk_data_x86_t>::type>
+ struct image_thunk_data_t : base_type {};
+
typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION
{
SIZE_T Size; // set to sizeof structure on input