aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorauth12 <[email protected]>2020-07-28 08:09:02 -0700
committerauth12 <[email protected]>2020-07-28 08:09:02 -0700
commitd4e2fe3f1a1d6d89e9110fa1361e942f57812e51 (patch)
tree2e602ce164be6baf0281ed73086701cb8ae0ff11
parentProcess class redesign. (diff)
downloadloader-d4e2fe3f1a1d6d89e9110fa1361e942f57812e51.tar.xz
loader-d4e2fe3f1a1d6d89e9110fa1361e942f57812e51.zip
Added server support for both x64 and x32 images with automatic selection.
-rw-r--r--client/src/client/client.h1
-rw-r--r--client/src/injection/mapper.cpp122
-rw-r--r--client/src/injection/mapper.h3
-rw-r--r--client/src/main.cpp8
-rw-r--r--client/src/util/io.h10
-rw-r--r--client/src/util/syscalls.cpp2
-rw-r--r--server/src/main.cpp170
-rw-r--r--server/src/server/server.h4
8 files changed, 241 insertions, 79 deletions
diff --git a/client/src/client/client.h b/client/src/client/client.h
index d840538..91cb494 100644
--- a/client/src/client/client.h
+++ b/client/src/client/client.h
@@ -18,6 +18,7 @@ struct game_data_t {
std::string name;
std::string version;
std::string process_name;
+ bool x64;
uint8_t id;
};
diff --git a/client/src/injection/mapper.cpp b/client/src/injection/mapper.cpp
index 1951ab2..c7f771c 100644
--- a/client/src/injection/mapper.cpp
+++ b/client/src/injection/mapper.cpp
@@ -9,11 +9,116 @@ void mmap::thread(tcp::client& client) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
+ if (client.selected_game.x64) {
+ map64(client);
+
+ return;
+ }
+
+ map32(client);
+}
+
+void mmap::map32(tcp::client& client) {
+ util::system_data_t dat;
+ 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;
+ });
+
+ if (needle == dat.processes.end()) {
+ io::log_error("failed to find process.");
+ return;
+ }
+
+ util::process<uint32_t> proc(*needle);
+
+ if (!proc.open()) {
+ return;
+ }
+
+ if (!proc.enum_modules()) {
+ io::log_error("failed to enum {} modules", proc.name());
+ return;
+ }
+
+ auto image = proc.allocate(client.mapper_data.image_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (!image) {
+ io::log_error("failed to allocate memory for image.");
+ return;
+ }
+
+ io::log("image base : {:x}", image);
+
+ auto imports = nlohmann::json::parse(client.mapper_data.imports);
+
+ nlohmann::json final_imports;
+ for (auto& [key, value] : imports.items()) {
+ for (auto& i : value) {
+ auto name = i.get<std::string>();
+
+ final_imports[name] = proc.module_export(proc.map(key), name);
+ }
+ }
+ imports.clear();
+
+ nlohmann::json resp;
+ resp["alloc"] = image;
+ resp["id"] = client.selected_game.process_name;
+ resp["x64"] = client.selected_game.x64;
+
+ client.write(tcp::packet_t(resp.dump(), tcp::packet_type::write, client.session_id, tcp::packet_id::image));
+ resp.clear();
+
+ client.stream(final_imports.dump());
+ final_imports.clear();
+
+ io::log("please wait...");
+ while (client.state != tcp::client_state::image_ready) {
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+
+ if (!proc.write(image, client.mapper_data.image.data(), client.mapper_data.image.size())) {
+ io::log_error("failed to write image.");
+ return;
+ }
+ client.mapper_data.image.clear();
+
+ auto entry = image + client.mapper_data.entry;
+
+ 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 };
+
+ *reinterpret_cast<uint32_t*>(&shellcode[8]) = image;
+ *reinterpret_cast<uint32_t*>(&shellcode[13]) = entry;
+
+ auto code = proc.allocate(shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (!proc.write(code, shellcode.data(), shellcode.size())) {
+ io::log_error("failed to write shellcode.");
+ return;
+ }
+
+ io::log("shellcode : {:x}", code);
+
+ proc.thread(code);
+
+ proc.free(code, shellcode.size());
+
+ proc.close();
+
+ client.state = tcp::client_state::injected;
+
+ io::log("done");
+}
+
+void mmap::map64(tcp::client& client) {
util::system_data_t dat;
util::fetch_system_data(dat);
auto needle = std::find_if(dat.processes.begin(), dat.processes.end(), [&](util::process_data_t& dat) {
- return dat.name == "sublime_text.exe";
+ return dat.name == client.selected_game.process_name;
});
if (needle == dat.processes.end()) {
@@ -54,7 +159,8 @@ void mmap::thread(tcp::client& client) {
nlohmann::json resp;
resp["alloc"] = image;
- resp["id"] = client.selected_game.id;
+ resp["id"] = client.selected_game.process_name;
+ resp["x64"] = client.selected_game.x64;
client.write(tcp::packet_t(resp.dump(), tcp::packet_type::write, client.session_id, tcp::packet_id::image));
resp.clear();
@@ -77,15 +183,9 @@ 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 = { 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;*/
+ 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<uint64_t*>(&shellcode[6]) = image;
*reinterpret_cast<uint64_t*>(&shellcode[26]) = entry;
@@ -102,8 +202,6 @@ void mmap::thread(tcp::client& client) {
proc.free(code, shellcode.size());
- //proc.free(image, client.mapper_data.image_size);
-
proc.close();
client.state = tcp::client_state::injected;
diff --git a/client/src/injection/mapper.h b/client/src/injection/mapper.h
index 0ce7b8f..bdc3565 100644
--- a/client/src/injection/mapper.h
+++ b/client/src/injection/mapper.h
@@ -2,4 +2,7 @@
namespace mmap {
void thread(tcp::client& client);
+
+ void map32(tcp::client& client);
+ void map64(tcp::client& client);
}; \ No newline at end of file
diff --git a/client/src/main.cpp b/client/src/main.cpp
index 83b96fe..71a064f 100644
--- a/client/src/main.cpp
+++ b/client/src/main.cpp
@@ -9,8 +9,6 @@
#include "util/apiset.h"
int main(int argc, char* argv[]) {
- io::log("{:x}", g_syscalls());
-
tcp::client client;
std::thread t{ tcp::client::monitor, std::ref(client) };
@@ -86,8 +84,9 @@ int main(int argc, char* argv[]) {
std::string version = value["version"];
std::string process = value["process"];
uint8_t id = value["id"];
+ bool x64 = value["x64"];
- client.games.emplace_back(game_data_t{ key, version, process, id });
+ client.games.emplace_back(game_data_t{ key, version, process, x64, id });
}
io::log("logged in.");
@@ -165,7 +164,8 @@ int main(int argc, char* argv[]) {
client.selected_game = *it;
nlohmann::json j;
- j["id"] = id;
+ j["id"] = client.selected_game.process_name;
+ j["x64"] = client.selected_game.x64;
int ret = client.write(tcp::packet_t(j.dump(), tcp::packet_type::write,
client.session_id,
diff --git a/client/src/util/io.h b/client/src/util/io.h
index 400c089..03d6964 100644
--- a/client/src/util/io.h
+++ b/client/src/util/io.h
@@ -7,9 +7,10 @@
namespace io {
template<typename... Args>
void log(const std::string_view str, Args... params) {
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
+ static auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(handle, FOREGROUND_GREEN);
fmt::print("$> ");
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
+ SetConsoleTextAttribute(handle, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
std::string msg{str};
msg.append("\n");
@@ -19,9 +20,10 @@ namespace io {
template<typename... Args>
void log_error(const std::string_view str, Args... params) {
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
+ static auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(handle, FOREGROUND_RED);
fmt::print("$> ");
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
+ SetConsoleTextAttribute(handle, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
std::string msg{str};
msg.append("\n");
diff --git a/client/src/util/syscalls.cpp b/client/src/util/syscalls.cpp
index e877932..96036a3 100644
--- a/client/src/util/syscalls.cpp
+++ b/client/src/util/syscalls.cpp
@@ -9,6 +9,8 @@ syscalls::syscalls() {
m_call_table = VirtualAlloc(0, 0x100000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
std::memset(m_call_table, 0x90, 0x100000);
+ io::log("syscalls call table : {:#x}", uintptr_t(m_call_table));
+
static auto nt = pe::virtual_image("ntdll.dll");
for (auto& exp : nt.exports()) {
auto addr = exp.second;
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 9008b8f..2a50ecd 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -11,7 +11,10 @@ int main(int argc, char* argv[]) {
tcp::server client_server("6666");
// id 0 : notepad test dll
- client_server.images[0] = pe::image<false>("img.dll");
+ client_server.images["notepad++.exe"] = pe::image<false>("img.dll");
+
+ // x64 image test
+ client_server.images64["sublime_text.exe"] = pe::image<true>("img64.dll");
client_server.start();
@@ -73,8 +76,7 @@ int main(int argc, char* argv[]) {
return;
}
auto j = nlohmann::json::parse(message);
- if(j.contains("uid"))
- client.hwid = j["uid"];
+ if (j.contains("uid")) client.hwid = j["uid"];
client.hwid_data = message;
@@ -145,7 +147,8 @@ int main(int argc, char* argv[]) {
io::logger->warn("failed to write new hwid for {}.", user);
}
- if (!client_server.forum().edit(data.id, "custom_fields[new_hwid_data]",
+ if (!client_server.forum().edit(data.id,
+ "custom_fields[new_hwid_data]",
client.hwid_data)) {
io::logger->warn("failed to write new hwid data for {}.", user);
}
@@ -160,10 +163,14 @@ int main(int argc, char* argv[]) {
}
json["result"] = tcp::client_response::login_success;
- json["games"]["test"] = {
- {"version", "0.1"}, {"id", 0}, {"process", "notepad++.exe"}};
- json["games"]["csgo"] = {
- {"version", "0.1"}, {"id", 1}, {"process", "csgo.exe"}};
+ json["games"]["notepad"] = {{"version", "0.1"},
+ {"id", 0},
+ {"process", "notepad++.exe"},
+ {"x64", false}};
+ json["games"]["sublime text"] = {{"version", "0.1"},
+ {"id", 1},
+ {"process", "sublime_text.exe"},
+ {"x64", true}};
client.write(tcp::packet_t(json.dump(), tcp::packet_type::write,
session, tcp::packet_id::login_resp));
@@ -209,50 +216,74 @@ int main(int argc, char* argv[]) {
}
auto resp = nlohmann::json::parse(message);
- if(!resp.contains("id")) {
- io::logger->warn(
- "id doesn't exist in game select json response for {}.", ip);
+ if (!resp.contains("id") || !resp.contains("x64")) {
+ io::logger->warn("invalid game select json response for {}.", ip);
client_server.disconnect_event.call(client);
return;
}
- int id = resp["id"];
+ std::string id = resp["id"];
+ bool x64 = resp["x64"];
- auto& img = client_server.images[id];
+ if (x64) {
+ auto it = client_server.images64.find(id);
+ if (it == client_server.images64.end()) {
+ io::logger->warn("{} sent invalid game id.");
- if (!img) {
- io::logger->warn("{} sent invalid game id.");
+ client_server.disconnect_event.call(client);
+ return;
+ }
+ auto& img = it->second;
- client_server.disconnect_event.call(client);
- return;
- }
+ io::logger->info("{} selected game id {}.", client.username, id);
+ auto nt = img->get_nt_headers();
- io::logger->info("{} selected game id {}.", client.username, id);
+ nlohmann::json j;
+ j["pe"].emplace_back(nt->optional_header.size_image);
+ j["pe"].emplace_back(nt->optional_header.entry_point);
- auto nt = img->get_nt_headers();
+ auto imports = img.get_json_imports();
- nlohmann::json j;
- j["pe"].emplace_back(nt->optional_header.size_image);
- j["pe"].emplace_back(nt->optional_header.entry_point);
+ j["size"] = imports.size();
+ client.write(tcp::packet_t(j.dump(), tcp::packet_type::write, session,
+ tcp::packet_id::game_select));
- auto imports = img.get_json_imports();
+ if (client.stream(imports) == imports.size()) {
+ io::logger->info("sent imports to {}.", client.username);
+ }
- j["size"] = imports.size();
+ client.state = tcp::client_state::waiting;
+ } else {
+ auto it = client_server.images.find(id);
+ if (it == client_server.images.end()) {
+ io::logger->warn("{} sent invalid game id.");
- client.write(tcp::packet_t(j.dump(), tcp::packet_type::write, session,
- tcp::packet_id::game_select));
+ client_server.disconnect_event.call(client);
+ return;
+ }
+ auto& img = it->second;
- if (client.stream(imports) == imports.size()) {
- io::logger->info("sent imports to {}.", client.username);
- }
+ io::logger->info("{} selected game id {}.", client.username, id);
+ auto nt = img->get_nt_headers();
- client.state = tcp::client_state::waiting;
- // select image
- // set message to be pe header
- // stream imports
- // wait for client to send back a packet with allocation base and fixed
- // imports
+ nlohmann::json j;
+ j["pe"].emplace_back(nt->optional_header.size_image);
+ j["pe"].emplace_back(nt->optional_header.entry_point);
+
+ auto imports = img.get_json_imports();
+
+ j["size"] = imports.size();
+
+ client.write(tcp::packet_t(j.dump(), tcp::packet_type::write, session,
+ tcp::packet_id::game_select));
+
+ if (client.stream(imports) == imports.size()) {
+ io::logger->info("sent imports to {}.", client.username);
+ }
+
+ client.state = tcp::client_state::waiting;
+ }
}
if (id == tcp::packet_id::image) {
@@ -272,7 +303,7 @@ int main(int argc, char* argv[]) {
auto j = nlohmann::json::parse(message);
- if (!j.contains("alloc") || !j.contains("id")) {
+ if (!j.contains("alloc") || !j.contains("id") || !j.contains("x64")) {
io::logger->warn("{} sent invalid json image reponse.", ip);
client_server.disconnect_event.call(client);
@@ -280,35 +311,58 @@ int main(int argc, char* argv[]) {
}
uintptr_t alloc = j["alloc"];
- int id = j["id"];
+ std::string id = j["id"];
+ bool x64 = j["x64"];
io::logger->info("{} allocated at {:x}", client.username, alloc);
- auto& img = client_server.images[id];
- if (!img) {
- io::logger->error("{} sent invalid game id.");
+ if (x64) {
+ auto it = client_server.images64.find(id);
+ if (it == client_server.images64.end()) {
+ io::logger->warn("{} sent invalid game id.");
- client_server.disconnect_event.call(client);
- return;
- }
+ client_server.disconnect_event.call(client);
+ return;
+ }
+ auto& img = it->second;
- std::vector<char> image;
- img.copy(image);
- img.relocate(image, alloc);
- img.fix_imports(image, imports);
+ std::vector<char> image;
+ img.copy(image);
+ img.relocate(image, alloc);
+ img.fix_imports(image, imports);
- client.write(tcp::packet_t("ready", tcp::packet_type::write, session,
- tcp::packet_id::image));
+ client.write(tcp::packet_t("ready", tcp::packet_type::write, session,
+ tcp::packet_id::image));
- if (client.stream(image) == image.size()) {
- io::logger->info("sent image to {}.", client.username);
- }
+ if (client.stream(image) == image.size()) {
+ io::logger->info("sent image to {}.", client.username);
+ }
+
+ client.state = tcp::client_state::injected;
+ } else {
+ auto it = client_server.images.find(id);
+ if (it == client_server.images.end()) {
+ io::logger->warn("{} sent invalid game id.");
- 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 set client status or
- // just drop them
+ client_server.disconnect_event.call(client);
+ return;
+ }
+ auto& img = it->second;
+
+ std::vector<char> image;
+ img.copy(image);
+ img.relocate(image, alloc);
+ img.fix_imports(image, imports);
+
+ client.write(tcp::packet_t("ready", tcp::packet_type::write, session,
+ tcp::packet_id::image));
+
+ if (client.stream(image) == image.size()) {
+ io::logger->info("sent image to {}.", client.username);
+ }
+
+ client.state = tcp::client_state::injected;
+ }
}
// client.write(tcp::packet_t(message, tcp::packet_type::write, session));
diff --git a/server/src/server/server.h b/server/src/server/server.h
index d882220..550d38d 100644
--- a/server/src/server/server.h
+++ b/server/src/server/server.h
@@ -30,7 +30,9 @@ class server {
event<client&> disconnect_event;
event<client&> timeout_event;
- std::unordered_map<int, pe::image<false>> images;
+ std::unordered_map<std::string, pe::image<false>> images;
+
+ std::unordered_map<std::string, pe::image<true>> images64;
server(const std::string_view port) : m_port{port}, m_active{false} {}
~server() = default;