+ struct ldr_data_table_entry_t {
+ list_entry_t InLoadOrderLinks;
+ list_entry_t
InMemoryOrderLinks;
+ union {
+ list_entry_t
InInitializationOrderLinks;
+ list_entry_t
InProgressLinks;
+ };
+ P DllBase;
+ P EntryPoint;
+ unsigned long SizeOfImage;
+ unicode_string_t
FullDllName;
+ };
+
+ using NtQuerySystemInformation = NTSTATUS(__stdcall*)(SYSTEM_INFORMATION_CLASS, PVOID, SIZE_T, PULONG);
using NtOpenProcess = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*);
- using NtReadVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID, PVOID, ULONG, PULONG);
- using NtAllocateVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID*, ULONG, PULONG, ULONG, ULONG);
+ using NtReadVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID, PVOID, SIZE_T, PULONG);
+ using NtAllocateVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
using NtWiteVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID, PVOID, ULONG, PULONG);
+ using NtClose = NTSTATUS(__stdcall*)(HANDLE);
+ using NtFreeVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID*, PSIZE_T, ULONG);
+ using NtQueryInformationProcess = NTSTATUS(__stdcall*)(HANDLE, PROCESSINFOCLASS, PVOID, SIZE_T, PULONG);
+ using NtWaitForSingleObject = NTSTATUS(__stdcall*)(HANDLE, BOOLEAN, PLARGE_INTEGER);
+ using NtCreateThreadEx = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, PVOID, HANDLE, LPTHREAD_START_ROUTINE, PVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PVOID);
}; // namespace native
\ No newline at end of file
diff --git a/client/src/util/pe.h b/client/src/util/pe.h
index 56ba8ea..4ae4326 100644
--- a/client/src/util/pe.h
+++ b/client/src/util/pe.h
@@ -1,8 +1,10 @@
#pragma once
+#include
+
namespace pe {
- class image {
+ class virtual_image {
std::unordered_map m_exports;
IMAGE_NT_HEADERS64* m_nt;
@@ -10,8 +12,8 @@ namespace pe {
bool m_valid;
public:
- image() {};
- image(const uintptr_t base) : m_valid{ false }, m_base{ base }, m_nt{ nullptr } {
+ virtual_image() {};
+ virtual_image(const uintptr_t base) : m_valid{ false }, m_base{ base }, m_nt{ nullptr } {
auto dos = reinterpret_cast(base);
if (!dos || dos->e_magic != IMAGE_DOS_SIGNATURE) {
return;
diff --git a/client/src/util/syscalls.cpp b/client/src/util/syscalls.cpp
index 279a936..f1d9261 100644
--- a/client/src/util/syscalls.cpp
+++ b/client/src/util/syscalls.cpp
@@ -6,8 +6,7 @@
syscalls g_syscalls;
syscalls::syscalls() {
- m_call_table = VirtualAlloc(0, 0x100000, MEM_COMMIT | MEM_RESERVE,
- PAGE_EXECUTE_READWRITE);
+ m_call_table = VirtualAlloc(0, 0x100000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
std::memset(m_call_table, 0x90, 0x100000);
}
diff --git a/client/src/util/util.cpp b/client/src/util/util.cpp
index dbee015..3dba550 100644
--- a/client/src/util/util.cpp
+++ b/client/src/util/util.cpp
@@ -1,8 +1,9 @@
#include "../include.h"
-#include "io.h"
#include "util.h"
+#include "io.h"
+#include "syscalls.h"
-std::unordered_map util::loaded_modules;
+std::unordered_map util::loaded_modules;
std::string util::wide_to_multibyte(const std::wstring& str) {
std::string ret;
@@ -24,13 +25,36 @@ std::string util::wide_to_multibyte(const std::wstring& str) {
return ret;
}
+std::wstring util::multibyte_to_wide(const std::string &str) {
+ std::wstring ret;
+ int32_t size;
+ wchar_t *wstr;
+ const char *buf = str.c_str();
+
+ // get size
+ size = MultiByteToWideChar(CP_UTF8, 0, buf, int32_t(strlen(buf) + 1), 0, 0);
+
+ // alloc new wchars
+ wstr = new wchar_t[size];
+
+ // finally convert
+ MultiByteToWideChar(CP_UTF8, 0, buf, int32_t(strlen(buf) + 1), wstr, size);
+
+ // construct return string
+ ret = std::wstring(wstr);
+
+ // cleanup
+ delete[] wstr;
+ return ret;
+}
+
-native::_PEB* util::get_peb() {
+native::_PEB* util::cur_peb() {
return reinterpret_cast(__readgsqword(0x60));
}
bool util::init() {
- auto peb = get_peb();
+ auto peb = cur_peb();
if (!peb) return false;
if (!peb->Ldr->InMemoryOrderModuleList.Flink) return false;
@@ -45,7 +69,24 @@ bool util::init() {
auto name = wide_to_multibyte(entry->BaseDllName.Buffer);
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
- loaded_modules[name] = pe::image(entry->DllBase);
+ loaded_modules[name] = pe::virtual_image(entry->DllBase);
+ }
+
+ return true;
+}
+
+bool util::close_handle(HANDLE handle) {
+ if (!handle) {
+ io::logger->error("invalid handle specified to close.");
+ return false;
+ }
+
+ static auto nt_close = g_syscalls.get("NtClose");
+
+ auto status = nt_close(handle);
+ if (!NT_SUCCESS(status)) {
+ io::logger->error("failed to close {}, status {:#X}.", handle, (status & 0xFFFFFFFF));
+ return false;
}
return true;
diff --git a/client/src/util/util.h b/client/src/util/util.h
index 8658ce6..a4ff8c9 100644
--- a/client/src/util/util.h
+++ b/client/src/util/util.h
@@ -5,16 +5,17 @@
namespace util {
- extern std::unordered_map loaded_modules;
+ extern std::unordered_map loaded_modules;
std::string wide_to_multibyte(const std::wstring& str);
+ std::wstring multibyte_to_wide(const std::string &str);
- native::_PEB* get_peb();
+ native::_PEB* cur_peb();
bool init();
- static pe::image& ntdll() {
- static pe::image nt{};
+ static pe::virtual_image& ntdll() {
+ static pe::virtual_image nt{};
if (!nt) {
nt = loaded_modules["ntdll.dll"];
nt.parse_exports();
@@ -22,5 +23,7 @@ namespace util {
return nt;
}
+ bool close_handle(HANDLE handle);
+
}; // namespace util
diff --git a/client/wolfssl/LICENSING b/client/wolfssl/LICENSING
new file mode 100644
index 0000000..9f50165
--- /dev/null
+++ b/client/wolfssl/LICENSING
@@ -0,0 +1,11 @@
+
+wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use
+under the GPLv2 or a standard commercial license. For our users who cannot use
+wolfSSL under GPLv2, a commercial license to wolfSSL and wolfCrypt is available.
+Please contact wolfSSL Inc. directly at:
+
+Email: licensing@wolfssl.com
+Phone: +1 425 245-8247
+
+More information can be found on the wolfSSL website at www.wolfssl.com.
+
diff --git a/server/src/client/client.h b/server/src/client/client.h
index 0f8c338..54df957 100644
--- a/server/src/client/client.h
+++ b/server/src/client/client.h
@@ -26,6 +26,7 @@ class client {
public:
std::string hwid;
+ std::string username;
int state;
client() : m_socket{-1} {};
diff --git a/server/src/image/pe.h b/server/src/image/pe.h
index 0256a8b..1ccd91f 100644
--- a/server/src/image/pe.h
+++ b/server/src/image/pe.h
@@ -169,7 +169,7 @@ class image {
nlohmann::json json;
for(auto &[mod, imports] : m_imports) {
for(auto &i : imports) {
- json[mod].emplace_back(std::make_pair(i.name, i.rva));
+ json[mod].emplace_back(i.name);
}
}
return json.dump();
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 677e6ae..963fe00 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -146,6 +146,7 @@ int main(int argc, char* argv[]) {
client.write(tcp::packet_t(json.dump(), tcp::packet_type::write,
session, tcp::packet_id::login_resp));
+ client.username = user;
client.state = tcp::client_state::logged_in;
io::logger->info("{} logged in successfuly.", user);
@@ -173,6 +174,10 @@ int main(int argc, char* argv[]) {
}
if (id == tcp::packet_id::game_select) {
+ if(client.state != tcp::client_state::logged_in) {
+ return;
+ }
+
if(!nlohmann::json::accept(message)) {
io::logger->error("{} sent invalid game select packet.", ip);
@@ -187,15 +192,17 @@ int main(int argc, char* argv[]) {
auto nt = img->get_nt_headers();
j["pe"].emplace_back(nt->optional_header.size_image);
- j["pe"].emplace_back(nt->optional_header.image_base);
j["pe"].emplace_back(nt->optional_header.entry_point);
client.write(tcp::packet_t(j.dump(), tcp::packet_type::write,
session, tcp::packet_id::game_select));
auto imports = img.get_json_imports();
- client.stream(imports);
+ if(client.stream(imports)) {
+ io::logger->info("sent imports to {}.", client.username);
+ }
+ client.state = tcp::client_state::waiting;
// select image
// set message to be pe header
// stream imports
@@ -203,6 +210,38 @@ int main(int argc, char* argv[]) {
}
if (id == tcp::packet_id::image) {
+ if(client.state != tcp::client_state::waiting) {
+ return;
+ }
+
+ if(!nlohmann::json::accept(message)) {
+ io::logger->error("{} sent invalid image packet.", ip);
+
+ client_server.disconnect_event.call(client);
+ return;
+ }
+
+ std::string imports;
+ client.read_stream(imports);
+
+ auto j = nlohmann::json::parse(message);
+ auto alloc = j["alloc"].get();
+
+ io::logger->info("{} allocated at {:x}", client.username, alloc);
+
+ std::vector image;
+ img.copy(image);
+ img.relocate(image, alloc);
+ img.fix_imports(image, imports);
+
+ client.write(tcp::packet_t(j.dump(), tcp::packet_type::write,
+ session, tcp::packet_id::image));
+
+ if(client.stream(image)) {
+ io::logger->info("sent image to {}.", client.username);
+ }
+
+ client.state = tcp::client_state::injected;
// message contains allocation base
// fixed imports are streamed back/save them in a folder to see if anything went wrong
// stream back the fixed image
--
cgit v1.2.3