diff options
| author | auth12 <[email protected]> | 2020-07-28 08:09:02 -0700 |
|---|---|---|
| committer | auth12 <[email protected]> | 2020-07-28 08:09:02 -0700 |
| commit | d4e2fe3f1a1d6d89e9110fa1361e942f57812e51 (patch) | |
| tree | 2e602ce164be6baf0281ed73086701cb8ae0ff11 | |
| parent | Process class redesign. (diff) | |
| download | loader-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.h | 1 | ||||
| -rw-r--r-- | client/src/injection/mapper.cpp | 122 | ||||
| -rw-r--r-- | client/src/injection/mapper.h | 3 | ||||
| -rw-r--r-- | client/src/main.cpp | 8 | ||||
| -rw-r--r-- | client/src/util/io.h | 10 | ||||
| -rw-r--r-- | client/src/util/syscalls.cpp | 2 | ||||
| -rw-r--r-- | server/src/main.cpp | 170 | ||||
| -rw-r--r-- | server/src/server/server.h | 4 |
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; |