From cc8ee50a9edff89fe90f5477003109106524f85f Mon Sep 17 00:00:00 2001 From: crazy hugsy Date: Sat, 8 Feb 2025 12:38:16 -0800 Subject: [PATCH 1/2] Update README.md --- CMakeLists.txt | 4 -- Modules/Common/Include/Error.hpp | 5 +- Modules/Process/Include/Win32/Process.hpp | 17 ++++- Modules/Process/Source/Win32/Process.cpp | 76 ++++++++++++++++++++++- Modules/Process/Tests/pwn_win_process.cpp | 32 ++++++++++ README.md | 2 +- 6 files changed, 126 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73c8c26..405eea1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,8 +51,6 @@ if(WIN32) # Listed by dependency order Common - -# Crypto Network Symbols System @@ -77,8 +75,6 @@ else() # Listed by dependency order Common - - # Crypto Network System diff --git a/Modules/Common/Include/Error.hpp b/Modules/Common/Include/Error.hpp index 6095a2b..ed8aade 100644 --- a/Modules/Common/Include/Error.hpp +++ b/Modules/Common/Include/Error.hpp @@ -138,8 +138,11 @@ enum class ErrorCode : uint32_t /// @brief Unexpected size comparison SizeMismatch, - /// @brief MalformedFile + /// @brief Malformed file MalformedFile, + + /// @brief Malformed data + MalformedData, }; diff --git a/Modules/Process/Include/Win32/Process.hpp b/Modules/Process/Include/Win32/Process.hpp index 910ec48..061e6c0 100644 --- a/Modules/Process/Include/Win32/Process.hpp +++ b/Modules/Process/Include/Win32/Process.hpp @@ -413,8 +413,16 @@ class Process ExecuteCallbacks(); - // TODO: - // - modules + /// + /// @brief Enumerate the process modules + /// + /// @return Result> + /// + Result> + Modules(); + + + // TODO (finish): // - inject // - hook @@ -478,6 +486,11 @@ class Process Result> QueryInternal(const PROCESSINFOCLASS, const usize); + Result> + EnumerateLocalModules(); + + Result> + EnumerateRemoteModules(); private: // Members u32 m_ProcessId {0}; diff --git a/Modules/Process/Source/Win32/Process.cpp b/Modules/Process/Source/Win32/Process.cpp index 0c67f96..17b6271 100644 --- a/Modules/Process/Source/Win32/Process.cpp +++ b/Modules/Process/Source/Win32/Process.cpp @@ -1,3 +1,5 @@ +#include "Win32/Process.hpp" + #include #include #include @@ -10,7 +12,6 @@ #include "Log.hpp" #include "Utils.hpp" #include "Win32/API.hpp" -#include "Win32/Process.hpp" #include "Win32/System.hpp" #include "Win32/Thread.hpp" @@ -26,6 +27,13 @@ usize GetPebLength(); EXTERN_C_END +using CriticalSection = GenericHandle< + RTL_CRITICAL_SECTION, + [](auto p) + { + ::LeaveCriticalSection(p); + }>; + namespace pwn::Process { @@ -570,6 +578,71 @@ Process::QueryInternal(const PROCESSINFOCLASS ProcessInformationClass, const usi return Ok(std::move(Buffer)); } +Result> +Process::Modules() +{ + return IsRemote() ? EnumerateRemoteModules() : EnumerateLocalModules(); +} + + +Result> +Process::EnumerateLocalModules() +{ + std::vector res; + auto peb = Peb(); + CriticalSection csLoaderLock {[&]() + { + auto lock = peb->LoaderLock; + ::EnterCriticalSection(lock); + return lock; + }()}; + + if ( !peb->Ldr->Initialized ) + return Ok(res); + + + auto head = &(peb->Ldr->InLoadOrderModuleList); + + for ( auto cur = head; cur->Flink && cur->Flink != head; cur = cur->Flink ) + { + auto ptr = CONTAINING_RECORD(cur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + + // HACK We copy for now because the module may have been unloaded by the time we access it + LDR_DATA_TABLE_ENTRY entry {}; + ::memcpy(&entry, ptr, sizeof(LDR_DATA_TABLE_ENTRY)); + res.emplace_back(entry); + } + + return Ok(res); +} + +Result> +Process::EnumerateRemoteModules() +{ + std::vector res; + auto ppeb = Peb(); + auto mem = Memory(*this); + auto peb_buf = Value(mem.Read((uptr)ppeb, sizeof(PEB))); + auto peb = reinterpret_cast(peb_buf.data()); + + auto ldr_buf = Value(mem.Read((uptr)peb->Ldr, sizeof(PEB_LDR_DATA))); + auto ldr = reinterpret_cast(ldr_buf.data()); + auto head = &(ldr->InLoadOrderModuleList); + + for ( auto cur = head; cur->Flink && cur->Flink != head; cur = cur->Flink ) + { + LDR_DATA_TABLE_ENTRY entry {}; + auto buf = Value(mem.Read( + (uptr)CONTAINING_RECORD(cur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks), + sizeof(LDR_DATA_TABLE_ENTRY))); + ::memcpy(&entry, buf.data(), sizeof(LDR_DATA_TABLE_ENTRY)); + res.emplace_back(entry); + } + + return Ok(res); +} + + #pragma endregion Process @@ -633,7 +706,6 @@ AppContainer::AppContainer( throw std::runtime_error("Failed to get SID"); } - dbg(L"sid={}", m_SidAsString.c_str()); // diff --git a/Modules/Process/Tests/pwn_win_process.cpp b/Modules/Process/Tests/pwn_win_process.cpp index fe27d61..4bc0cd0 100644 --- a/Modules/Process/Tests/pwn_win_process.cpp +++ b/Modules/Process/Tests/pwn_win_process.cpp @@ -151,3 +151,35 @@ TEST_CASE("Process Memory", "[" NS "]") // TODO } } + + +TEST_CASE("Process Modules", "[" NS "]") +{ + SECTION("Local") + { + auto CurrentProcess = Process::Current(); + auto mods = CurrentProcess.Modules(); + REQUIRE(Success(mods)); + + for ( auto const& mod : Value(mods) ) + { + // Check betterer + CHECK((((uptr)mod.DllBase) & 0xfff) == 0); + } + } + + SECTION("Remote") + { + auto values = Value(System::PidOf(L"explorer.exe")); + REQUIRE(values.size() > 0); + + auto explorer = Process::Process(values[0]); + auto mods = explorer.Modules(); + REQUIRE(Success(mods)); + + for ( auto const& mod : Value(mods) ) + { + CHECK((((uptr)mod.DllBase) & 0xfff) == 0); + } + } +} diff --git a/README.md b/README.md index 8c416f1..be41f3e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Discord Read Code Open in VSCode - CI + CI

## Quick start From bf855421361f0d031e8b68d1a4a50014c5780f96 Mon Sep 17 00:00:00 2001 From: hugsy Date: Tue, 29 Oct 2024 10:55:37 -0700 Subject: [PATCH 2/2] renamed `CriticalSection` -> `UniqueCriticalSection` --- .github/workflows/build.yml | 2 +- Modules/Common/Include/Handle.hpp | 27 +++++++++++++++++++++--- Modules/Process/Source/Win32/Process.cpp | 19 ++++++----------- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7f29f40..0054b48 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: - {os: windows-2022, arch: win32, config: RelWithDebInfo, crypto: ON} - {os: windows-2022, arch: win32, config: RelWithDebInfo, crypto: OFF} - {os: windows-2022, arch: arm64, config: RelWithDebInfo, crypto: ON} - - {os: windows-2022, arch: arm, config: RelWithDebInfo, crypto: ON} + # - {os: windows-2022, arch: arm, config: RelWithDebInfo, crypto: ON} # ARM not supported any longer # - {os: ubuntu-2204, arch: x64, config: RelWithDebInfo} # runner fails for some reason, works fine locally: see https://github.com/actions/runner-images/discussions/7188 # - {os: ubuntu-2204, arch: x86, config: RelWithDebInfo} diff --git a/Modules/Common/Include/Handle.hpp b/Modules/Common/Include/Handle.hpp index e6eb9ae..629ec44 100644 --- a/Modules/Common/Include/Handle.hpp +++ b/Modules/Common/Include/Handle.hpp @@ -5,10 +5,9 @@ #include "Common.hpp" /// -/// Scope-managed handles +/// @brief Scope-managed handles /// /// @ref https://andreasfertig.blog/2022/08/cpp-insights-lambdas-in-unevaluated-contexts/ -/// @link https://developercommunity.visualstudio.com/t/c20-internal-compiler-error-for-lambda-in-decltype/1631476 /// template using GenericHandle = std::unique_ptr< @@ -26,8 +25,30 @@ using GenericHandle = std::unique_ptr< #ifdef __linux__ using UniqueHandle = GenericHandle; #else -using UniqueHandle = GenericHandle; + +/// +/// @brief A unique (as-in `unique_ptr`) Windows handle. It will close itself on scope-exit. +/// +using UniqueHandle = GenericHandle; + +/// +/// @brief A unique (as-in `unique_ptr`) Windows module handle. +/// using UniqueLibraryHandle = GenericHandle; + +/// +/// @brief A unique Windows Critical Section. +/// +using UniqueCriticalSection = GenericHandle< + RTL_CRITICAL_SECTION, + [](RTL_CRITICAL_SECTION* p) + { + if ( p ) + { + ::LeaveCriticalSection(p); + p = nullptr; + } + }>; #endif // __linux__ using SharedHandle = std::shared_ptr; diff --git a/Modules/Process/Source/Win32/Process.cpp b/Modules/Process/Source/Win32/Process.cpp index 17b6271..0aae86e 100644 --- a/Modules/Process/Source/Win32/Process.cpp +++ b/Modules/Process/Source/Win32/Process.cpp @@ -27,13 +27,6 @@ usize GetPebLength(); EXTERN_C_END -using CriticalSection = GenericHandle< - RTL_CRITICAL_SECTION, - [](auto p) - { - ::LeaveCriticalSection(p); - }>; - namespace pwn::Process { @@ -590,12 +583,12 @@ Process::EnumerateLocalModules() { std::vector res; auto peb = Peb(); - CriticalSection csLoaderLock {[&]() - { - auto lock = peb->LoaderLock; - ::EnterCriticalSection(lock); - return lock; - }()}; + UniqueCriticalSection csLoaderLock {[&]() + { + auto lock = peb->LoaderLock; + ::EnterCriticalSection(lock); + return lock; + }()}; if ( !peb->Ldr->Initialized ) return Ok(res);