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 @@
-
+
## 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);