struct unicode_string_t {
- std::uint16_t Length;
- std::uint16_t MaximumLength;
+ uint16_t Length;
+ uint16_t MaximumLength;
P Buffer;
};
@@ -105,141 +104,6 @@ namespace native {
unicode_string_t FullDllName;
};
-
-#pragma pack(push, 4)
- struct reloc_entry_t {
- uint16_t offset : 12;
- uint16_t type : 4;
- };
-
- struct reloc_block_t {
- uint32_t base_rva;
- uint32_t size_block;
- reloc_entry_t entries[ 1 ]; // Variable length array
-
-
- inline reloc_block_t* get_next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); }
- inline uint32_t num_entries() { return ( reloc_entry_t* ) get_next() - &entries[ 0 ]; }
- };
-
- struct image_named_import_t
- {
- uint16_t hint;
- char name[ 1 ];
- };
-
-#pragma pack(push, 8)
- struct image_thunk_data_x64_t
- {
- union
- {
- uint64_t forwarder_string;
- uint64_t function;
- uint64_t address; // -> image_named_import_t
- struct
- {
- uint64_t ordinal : 16;
- uint64_t _reserved0 : 47;
- uint64_t is_ordinal : 1;
- };
- };
- };
-#pragma pack(pop)
-
- struct image_thunk_data_x86_t
- {
- union
- {
- uint32_t forwarder_string;
- uint32_t function;
- uint32_t address; // -> image_named_import_t
- struct
- {
- uint32_t ordinal : 16;
- uint32_t _reserved0 : 15;
- uint32_t is_ordinal : 1;
- };
- };
- };
-#pragma pack(pop)
-
- template::type>
- struct image_thunk_data_t : base_type {};
-
- typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION
- {
- SIZE_T Size; // set to sizeof structure on input
- PROCESS_BASIC_INFORMATION BasicInfo;
- union
- {
- ULONG Flags;
- struct
- {
- ULONG IsProtectedProcess : 1;
- ULONG IsWow64Process : 1;
- ULONG IsProcessDeleting : 1;
- ULONG IsCrossSessionCreate : 1;
- ULONG IsFrozen : 1;
- ULONG IsBackground : 1;
- ULONG IsStronglyNamed : 1;
- ULONG IsSecureProcess : 1;
- ULONG IsSubsystemProcess : 1;
- ULONG SpareBits : 23;
- };
- };
- } PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION;
-
-
- typedef enum _SYSTEM_INFORMATION_CLASS {
- SystemBasicInformation,
- SystemProcessorInformation,
- SystemPerformanceInformation,
- SystemTimeOfDayInformation,
- SystemPathInformation,
- SystemProcessInformation,
- SystemCallCountInformation,
- SystemDeviceInformation,
- SystemProcessorPerformanceInformation,
- SystemFlagsInformation,
- SystemCallTimeInformation,
- SystemModuleInformation,
- SystemLocksInformation,
- SystemStackTraceInformation,
- SystemPagedPoolInformation,
- SystemNonPagedPoolInformation,
- SystemHandleInformation,
- SystemObjectInformation,
- SystemPageFileInformation,
- SystemVdmInstemulInformation,
- SystemVdmBopInformation,
- SystemFileCacheInformation,
- SystemPoolTagInformation,
- SystemInterruptInformation,
- SystemDpcBehaviorInformation,
- SystemFullMemoryInformation,
- SystemLoadGdiDriverInformation,
- SystemUnloadGdiDriverInformation,
- SystemTimeAdjustmentInformation,
- SystemSummaryMemoryInformation,
- SystemNextEventIdInformation,
- SystemEventIdsInformation,
- SystemCrashDumpInformation,
- SystemExceptionInformation,
- SystemCrashDumpStateInformation,
- SystemKernelDebuggerInformation,
- SystemContextSwitchInformation,
- SystemRegistryQuotaInformation,
- SystemExtendServiceTableInformation,
- SystemPrioritySeperation,
- SystemPlugPlayBusInformation,
- SystemDockInformation,
- SystemPowerInformation,
- SystemProcessorSpeedInformation,
- SystemCurrentTimeZoneInformation,
- SystemLookasideInformation
- } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
-
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
@@ -287,15 +151,23 @@ namespace native {
ULONG Unk[2];
};
- using NtQuerySystemInformation = NTSTATUS(__stdcall*)(native::SYSTEM_INFORMATION_CLASS, PVOID, SIZE_T, PULONG);
+ struct PROCESS_EXTENDED_BASIC_INFORMATION {
+ SIZE_T Size; // set to sizeof structure on input
+ PROCESS_BASIC_INFORMATION BasicInfo;
+ uint8_t Flags;
+ };
+
+ using NtQuerySystemInformation = NTSTATUS(__stdcall*)(SYSTEM_INFORMATION_CLASS, PVOID, SIZE_T, PULONG);
using NtOpenProcess = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*);
+ using NtOpenThread = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*);
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 NtWriteVirtualMemory = 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);
+ using NtGetContextThread = NTSTATUS(__stdcall*)(HANDLE, PCONTEXT);
}; // namespace native
\ No newline at end of file
diff --git a/client/src/util/syscalls.cpp b/client/src/util/syscalls.cpp
index 96036a3..a755d22 100644
--- a/client/src/util/syscalls.cpp
+++ b/client/src/util/syscalls.cpp
@@ -9,9 +9,9 @@ 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));
+ io::log("syscalls call table : {:x}", uintptr_t(m_call_table));
- static auto nt = pe::virtual_image("ntdll.dll");
+ static auto nt = pe::ntdll();
for (auto& exp : nt.exports()) {
auto addr = exp.second;
diff --git a/client/src/util/syscalls.h b/client/src/util/syscalls.h
index 713e24c..0855d18 100644
--- a/client/src/util/syscalls.h
+++ b/client/src/util/syscalls.h
@@ -17,6 +17,10 @@ public:
return reinterpret_cast(uintptr_t(m_call_table) + (m_indexes[func.data()].first * m_stub.size()));
};
+ uintptr_t operator()(const std::string_view func) {
+ return uintptr_t(m_call_table) + (m_indexes[func.data()].first * m_stub.size());
+ }
+
uintptr_t operator()() {
return uintptr_t(m_call_table);
}
diff --git a/client/src/util/util.cpp b/client/src/util/util.cpp
index 1847780..fab886e 100644
--- a/client/src/util/util.cpp
+++ b/client/src/util/util.cpp
@@ -15,7 +15,7 @@ std::string util::wide_to_multibyte(const std::wstring& str) {
str_len = WideCharToMultiByte(CP_UTF8, 0, &str[0], str.size(), 0, 0, 0, 0);
// setup return value
- ret = std::string(str_len, 0);
+ ret.resize(str_len);
// final conversion
WideCharToMultiByte(CP_UTF8, 0, &str[0], str.size(), &ret[0], str_len, 0, 0);
@@ -40,7 +40,7 @@ std::wstring util::multibyte_to_wide(const std::string& str) {
bool util::close_handle(HANDLE handle) {
if (!handle) {
- io::log_error("invalid handle specified to close.");
+ io::log_error("invalid handle to close.");
return false;
}
@@ -54,3 +54,24 @@ bool util::close_handle(HANDLE handle) {
return true;
}
+
+
+void pe::get_all_modules(std::unordered_map& modules) {
+ auto peb = util::peb();
+ if (!peb) return;
+
+ if (!peb->Ldr->InMemoryOrderModuleList.Flink) return;
+
+ 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 = util::wide_to_multibyte(entry->BaseDllName.Buffer);
+ std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+
+ modules[name] = virtual_image(entry->DllBase);
+ }
+}
\ No newline at end of file
diff --git a/server/src/image/pe.h b/server/src/image/pe.h
index 23a0e4f..1025f13 100644
--- a/server/src/image/pe.h
+++ b/server/src/image/pe.h
@@ -18,6 +18,7 @@ template
class image {
win::image_t *m_image;
std::vector m_buffer;
+ std::string m_name;
std::unordered_map> m_imports;
std::vector m_sections;
@@ -25,7 +26,7 @@ class image {
public:
image() = default;
- image(const std::string_view name) : m_image{nullptr} {
+ image(const std::string_view name) : m_image{nullptr}, m_name{name} {
if (!io::read_file(name, m_buffer)) {
io::logger->error("failed to load image {}.", name);
return;
@@ -41,15 +42,17 @@ class image {
parse_imports();
}
- void reload(const std::string_view name) {
- io::read_file(name, m_buffer);
+ void reload() {
+ io::read_file(m_name, m_buffer);
if (m_buffer.empty()) {
- io::logger->error("failed to reload image {}.", name);
+ io::logger->error("failed to reload image {}.", m_name);
return;
}
m_image = reinterpret_cast *>(m_buffer.data());
load();
+
+ io::logger->info("reloaded {}.", m_name);
}
void parse_sections() {
@@ -103,16 +106,20 @@ class image {
auto named_import = reinterpret_cast(
m_image->rva_to_ptr(thunk->address));
- if (!thunk->is_ordinal) {
- import_t data;
- data.name = reinterpret_cast(named_import->name);
- data.rva = table->rva_first_thunk + index;
+ if (thunk->is_ordinal) {
+ io::logger->error("found import by ordinal in module {}, {}.",
+ mod_name, m_name);
+ continue;
+ }
- std::transform(mod_name.begin(), mod_name.end(), mod_name.begin(),
- ::tolower);
+ import_t data;
+ data.name = reinterpret_cast(named_import->name);
+ data.rva = table->rva_first_thunk + index;
- m_imports[mod_name].emplace_back(std::move(data));
- }
+ std::transform(mod_name.begin(), mod_name.end(), mod_name.begin(),
+ ::tolower);
+
+ m_imports[mod_name].emplace_back(std::move(data));
}
}
}
@@ -124,6 +131,10 @@ class image {
out.resize(nt->optional_header.size_image);
for (auto &sec : m_sections) {
+ if(sec.name == ".reloc" || sec.name == ".rsrc" || sec.name == ".idata") {
+ continue;
+ }
+
std::memcpy(&out[sec.va], &m_buffer[sec.rva], sec.size);
}
}
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 2a50ecd..80dbe62 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -18,12 +18,23 @@ int main(int argc, char* argv[]) {
client_server.start();
+ uint16_t ver;
+ for(int i = 0; i < version.size(); ++i) {
+ if (i % 2) {
+ continue;
+ }
+
+ ver += static_cast(version[i]) << 5;
+ }
+ io::logger->info("client version {}.", ver);
+
client_server.connect_event.add([&](tcp::client& client) {
auto ip = client.get_ip();
io::logger->info("{} connected.", ip);
client.gen_session();
+
client.write(tcp::packet_t(version, tcp::packet_type::write, client(),
tcp::packet_id::session));
@@ -163,11 +174,11 @@ int main(int argc, char* argv[]) {
}
json["result"] = tcp::client_response::login_success;
- json["games"]["notepad"] = {{"version", "0.1"},
+ json["games"]["notepad"] = {{"version", 1},
{"id", 0},
{"process", "notepad++.exe"},
{"x64", false}};
- json["games"]["sublime text"] = {{"version", "0.1"},
+ json["games"]["sublime text"] = {{"version", 1},
{"id", 1},
{"process", "sublime_text.exe"},
{"x64", true}};
@@ -382,6 +393,29 @@ int main(int argc, char* argv[]) {
io::logger->info("{} timed out.", client.get_ip());
});
+
+ commands cmds;
+ cmds.add("reload", [&]() {
+ for(auto&[key, image] : client_server.images) {
+ image.reload();
+ }
+
+ for(auto&[key, image] : client_server.images64) {
+ image.reload();
+ }
+ });
+
+ std::thread t1{[&](tcp::server &srv) {
+ while (srv) {
+ std::string cmd;
+ getline(std::cin, cmd);
+ if(!cmds.parse_input(cmd)) {
+ io::logger->warn("invalid command.");
+ }
+ };
+ }, std::ref(client_server)};
+ t1.detach();
+
std::thread t{tcp::server::monitor, std::ref(client_server)};
t.join();
}
--
cgit v1.2.3