aboutsummaryrefslogtreecommitdiff
path: root/client/src/util
diff options
context:
space:
mode:
authorauth12 <[email protected]>2020-07-20 03:09:25 -0700
committerauth12 <[email protected]>2020-07-20 03:09:25 -0700
commitc9e48c5e9eddfe5b7a895fb3940c41ccf75d3e93 (patch)
tree2b04471e76f7fb31aff0151b978ece9af4410a8b /client/src/util
parentMerge pull request #1 from auth12/windows (diff)
downloadloader-c9e48c5e9eddfe5b7a895fb3940c41ccf75d3e93.tar.xz
loader-c9e48c5e9eddfe5b7a895fb3940c41ccf75d3e93.zip
Syscalls.
Removed asmjit submodule and embedded it instead. Small PE wrapper.
Diffstat (limited to 'client/src/util')
-rw-r--r--client/src/util/native.h209
-rw-r--r--client/src/util/pe.h55
-rw-r--r--client/src/util/syscalls.cpp99
-rw-r--r--client/src/util/syscalls.h22
-rw-r--r--client/src/util/util.cpp52
-rw-r--r--client/src/util/util.h26
6 files changed, 463 insertions, 0 deletions
diff --git a/client/src/util/native.h b/client/src/util/native.h
new file mode 100644
index 0000000..623e577
--- /dev/null
+++ b/client/src/util/native.h
@@ -0,0 +1,209 @@
+#pragma once
+
+namespace native {
+ struct PEB_LDR_DATA {
+ uint32_t Length;
+ uint8_t Initialized;
+ uintptr_t SsHandle;
+ LIST_ENTRY InLoadOrderModuleList;
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ uintptr_t EntryInProgress;
+ uint8_t ShutdownInProgress;
+ uintptr_t ShutdownThreadId;
+ };
+
+ struct UNICODE_STRING {
+ uint16_t Length;
+ uint16_t MaximumLength;
+ wchar_t *Buffer;
+ };
+
+ struct STRING {
+ uint16_t Length;
+ uint16_t MaximumLength;
+ 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 SubSystemData;
+ uintptr_t ProcessHeap;
+ RTL_CRITICAL_SECTION *FastPebLock;
+ uintptr_t AtlThunkSListPtr;
+ uintptr_t IFEOKey;
+ uint32_t CrossProcessFlags;
+ uint8_t Padding1[ 4 ];
+ uintptr_t KernelCallbackTable;
+ uintptr_t UserSharedInfoPtr;
+ uint32_t SystemReserved[ 1 ];
+ 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 {
+ LIST_ENTRY InLoadOrderLinks;
+ LIST_ENTRY InMemoryOrderLinks;
+ LIST_ENTRY InInitializationOrderLinks;
+ uintptr_t DllBase;
+ uintptr_t EntryPoint;
+ 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;
+ };
+
+}; // namespace native \ No newline at end of file
diff --git a/client/src/util/pe.h b/client/src/util/pe.h
new file mode 100644
index 0000000..a4d835d
--- /dev/null
+++ b/client/src/util/pe.h
@@ -0,0 +1,55 @@
+#pragma once
+
+namespace pe {
+
+class image {
+ std::unordered_map<std::string, uintptr_t> m_exports;
+
+ IMAGE_NT_HEADERS64 *m_nt;
+ uintptr_t m_base;
+ bool m_valid;
+
+ public:
+ image(){};
+ image(const uintptr_t base) : m_valid{false}, m_base{base}, m_nt{nullptr} {
+ auto dos = reinterpret_cast<IMAGE_DOS_HEADER *>(base);
+ if (!dos || dos->e_magic != IMAGE_DOS_SIGNATURE) {
+ return;
+ }
+
+ m_nt = reinterpret_cast<IMAGE_NT_HEADERS64 *>(base + dos->e_lfanew);
+ if (m_nt->Signature != IMAGE_NT_SIGNATURE) {
+ return;
+ }
+
+ m_valid = true;
+ }
+
+ void parse_exports() {
+ auto dir = m_nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+ auto exp =
+ reinterpret_cast<IMAGE_EXPORT_DIRECTORY *>(m_base + dir.VirtualAddress);
+
+ if (exp->NumberOfFunctions == 0) return;
+
+ auto names = reinterpret_cast<uint32_t *>(m_base + exp->AddressOfNames);
+ auto funcs = reinterpret_cast<uint32_t *>(m_base + exp->AddressOfFunctions);
+ auto ords =
+ reinterpret_cast<uint16_t *>(m_base + exp->AddressOfNameOrdinals);
+
+ if (!names || !funcs || !ords) return;
+
+ for (size_t i{}; i < exp->NumberOfFunctions; i++) {
+ uintptr_t va = m_base + funcs[ords[i]];
+ std::string name = reinterpret_cast<const char *>(m_base + names[i]);
+
+ m_exports[name] = va;
+ }
+ }
+
+ auto &exports() { return m_exports; }
+
+ operator bool() { return m_valid; }
+};
+
+}; // namespace pe \ No newline at end of file
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;
+}
diff --git a/client/src/util/syscalls.h b/client/src/util/syscalls.h
new file mode 100644
index 0000000..0d73e4e
--- /dev/null
+++ b/client/src/util/syscalls.h
@@ -0,0 +1,22 @@
+#pragma once
+
+class syscalls {
+ std::unordered_map<std::string, std::pair<uint16_t, uint16_t>> m_indexes;
+ std::vector<char> m_stub;
+
+ void *m_call_table;
+public:
+ syscalls();
+ ~syscalls();
+ void init();
+ bool valid(const uintptr_t func, const size_t &size);
+ uint16_t get_index(const uintptr_t va, uint16_t &offset);
+ size_t func_size(const uint8_t *func);
+
+ template<class T>
+ T get(const std::string_view func) {
+ return reinterpret_cast<T>(uintptr_t(m_call_table) + (m_indexes[func.data()].first * m_stub.size()));
+ };
+};
+
+extern syscalls g_syscalls; \ No newline at end of file
diff --git a/client/src/util/util.cpp b/client/src/util/util.cpp
new file mode 100644
index 0000000..a23c03c
--- /dev/null
+++ b/client/src/util/util.cpp
@@ -0,0 +1,52 @@
+#include "../include.h"
+#include "io.h"
+#include "util.h"
+
+std::unordered_map<std::string, pe::image> util::loaded_modules;
+
+std::string util::wide_to_multibyte(const std::wstring &str) {
+ std::string ret;
+ int32_t str_len;
+
+ // check if not empty str
+ if (str.empty())
+ return{};
+
+ // count size
+ str_len = WideCharToMultiByte(CP_UTF8, 0, &str[0], (int32_t) str.size(), 0, 0, 0, 0);
+
+ // setup return value
+ ret = std::string(str_len, 0);
+
+ // final conversion
+ WideCharToMultiByte(CP_UTF8, 0, &str[0], (int32_t) str.size(), &ret[0], str_len, 0, 0);
+
+ return ret;
+}
+
+
+native::_PEB* util::get_peb() {
+ return reinterpret_cast<native::_PEB*>(__readgsqword(0x60));
+}
+
+bool util::init() {
+ auto peb = get_peb();
+ if (!peb) return false;
+
+ if (!peb->Ldr->InMemoryOrderModuleList.Flink) return false;
+
+ auto* list = &peb->Ldr->InMemoryOrderModuleList;
+
+ for (auto i = list->Flink; i != list; i = i->Flink) {
+ auto entry = CONTAINING_RECORD(i, native::LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
+ if (!entry)
+ continue;
+
+ auto name = wide_to_multibyte(entry->BaseDllName.Buffer);
+ std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+
+ loaded_modules[name] = pe::image(entry->DllBase);
+ }
+
+ return true;
+}
diff --git a/client/src/util/util.h b/client/src/util/util.h
new file mode 100644
index 0000000..b4bf699
--- /dev/null
+++ b/client/src/util/util.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "native.h"
+#include "pe.h"
+
+namespace util {
+
+extern std::unordered_map<std::string, pe::image> loaded_modules;
+
+std::string wide_to_multibyte(const std::wstring &str);
+
+native::_PEB *get_peb();
+
+bool init();
+
+static pe::image& ntdll() {
+ static pe::image nt{};
+ if (!nt) {
+ nt = loaded_modules["ntdll.dll"];
+ nt.parse_exports();
+ }
+ return nt;
+}
+
+}; // namespace util
+