aboutsummaryrefslogtreecommitdiff
path: root/client/src/util/syscalls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/util/syscalls.cpp')
-rw-r--r--client/src/util/syscalls.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/client/src/util/syscalls.cpp b/client/src/util/syscalls.cpp
new file mode 100644
index 0000000..624ce5a
--- /dev/null
+++ b/client/src/util/syscalls.cpp
@@ -0,0 +1,99 @@
+#include "../include.h"
+#include "io.h"
+#include "util.h"
+#include "syscalls.h"
+
+syscalls g_syscalls;
+
+syscalls::syscalls() {
+ m_call_table = VirtualAlloc(0, 0x100000, MEM_COMMIT | MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE);
+ std::memset(m_call_table, 0x90, 0x100000);
+}
+
+syscalls::~syscalls() {
+ VirtualFree(m_call_table, 0, MEM_RELEASE);
+}
+
+void syscalls::init() {
+ auto nt = util::ntdll();
+ for (auto& exp : nt.exports()) {
+ auto addr = exp.second;
+
+ uint16_t offset;
+ auto idx = get_index(addr, offset);
+
+ if(!idx) continue;
+
+ m_indexes[exp.first] = std::make_pair(idx, offset);
+
+ if (m_stub.empty()) {
+ auto s = func_size(reinterpret_cast<uint8_t*>(addr));
+
+ m_stub.resize(s);
+
+ std::memcpy(&m_stub[0], (void*)addr, s);
+ }
+ }
+
+ io::logger->info("{:x}", uintptr_t(m_call_table));
+
+ for (auto& syscall : m_indexes) {
+ auto idx = syscall.second.first;
+
+ auto addr = uintptr_t(m_call_table) + (idx * m_stub.size());
+ std::memcpy(reinterpret_cast<void*>(addr), m_stub.data(), m_stub.size());
+
+ *reinterpret_cast<uint8_t*>(addr + m_stub.size() - 1) = 0xc3;
+ *reinterpret_cast<uint16_t*>(addr + syscall.second.second + 1) = idx;
+ }
+}
+
+bool syscalls::valid(const uintptr_t addr, const size_t &size) {
+ auto func = reinterpret_cast<uint8_t*>(addr);
+
+ // mov r10, rcx
+ uint32_t a = func[0] + func[1] + func[2];
+ if (a != 0x1a8) {
+ return false;
+ }
+
+ for (size_t i{}; i < size; i++) {
+ auto op = func[i];
+ auto next = func[i + 1];
+
+ if (op == 0x0f && next == 0x05) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint16_t syscalls::get_index(const uintptr_t va, uint16_t &offset) {
+ auto func = reinterpret_cast<uint8_t*>(va);
+ auto size = func_size(reinterpret_cast<uint8_t*>(va));
+ if (!valid(va, size)) {
+ return 0;
+ }
+
+ for (size_t i{}; i < size; i++) {
+ auto op = func[i];
+ if (op == 0xb8) {
+ offset = i;
+
+ return *reinterpret_cast<uint16_t*>(va + i + 1);
+ }
+ }
+ return 0;
+}
+
+size_t syscalls::func_size(const uint8_t* func) {
+ for (size_t i = 0; i < 64; i++) {
+ auto op = func[i];
+ if (op == 0xc3 || op == 0xc2) {
+ return i + 1;
+ }
+ }
+ return 0;
+}