Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down
4 changes: 0 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ if(WIN32)

# Listed by dependency order
Common

# Crypto
Network
Symbols
System
Expand All @@ -77,8 +75,6 @@ else()

# Listed by dependency order
Common

# Crypto
Network
System

Expand Down
5 changes: 4 additions & 1 deletion Modules/Common/Include/Error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,11 @@ enum class ErrorCode : uint32_t
/// @brief Unexpected size comparison
SizeMismatch,

/// @brief MalformedFile
/// @brief Malformed file
MalformedFile,

/// @brief Malformed data
MalformedData,
};


Expand Down
27 changes: 24 additions & 3 deletions Modules/Common/Include/Handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename T, auto Deleter>
using GenericHandle = std::unique_ptr<
Expand All @@ -26,8 +25,30 @@ using GenericHandle = std::unique_ptr<
#ifdef __linux__
using UniqueHandle = GenericHandle<FILE, ::fclose>;
#else
using UniqueHandle = GenericHandle<void, ::CloseHandle>;

///
/// @brief A unique (as-in `unique_ptr`) Windows handle. It will close itself on scope-exit.
///
using UniqueHandle = GenericHandle<void, ::CloseHandle>;

///
/// @brief A unique (as-in `unique_ptr`) Windows module handle.
///
using UniqueLibraryHandle = GenericHandle<HINSTANCE__, ::FreeLibrary>;

///
/// @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<UniqueHandle>;
17 changes: 15 additions & 2 deletions Modules/Process/Include/Win32/Process.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,16 @@ class Process
ExecuteCallbacks();


// TODO:
// - modules
///
/// @brief Enumerate the process modules
///
/// @return Result<std::vector<LDR_DATA_TABLE_ENTRY>>
///
Result<std::vector<LDR_DATA_TABLE_ENTRY>>
Modules();


// TODO (finish):
// - inject
// - hook

Expand Down Expand Up @@ -478,6 +486,11 @@ class Process
Result<std::unique_ptr<u8[]>>
QueryInternal(const PROCESSINFOCLASS, const usize);

Result<std::vector<LDR_DATA_TABLE_ENTRY>>
EnumerateLocalModules();

Result<std::vector<LDR_DATA_TABLE_ENTRY>>
EnumerateRemoteModules();

private: // Members
u32 m_ProcessId {0};
Expand Down
69 changes: 67 additions & 2 deletions Modules/Process/Source/Win32/Process.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "Win32/Process.hpp"

#include <accctrl.h>
#include <aclapi.h>
#include <psapi.h>
Expand All @@ -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"

Expand Down Expand Up @@ -570,6 +571,71 @@ Process::QueryInternal(const PROCESSINFOCLASS ProcessInformationClass, const usi
return Ok(std::move(Buffer));
}

Result<std::vector<LDR_DATA_TABLE_ENTRY>>
Process::Modules()
{
return IsRemote() ? EnumerateRemoteModules() : EnumerateLocalModules();
}


Result<std::vector<LDR_DATA_TABLE_ENTRY>>
Process::EnumerateLocalModules()
{
std::vector<LDR_DATA_TABLE_ENTRY> res;
auto peb = Peb();
UniqueCriticalSection 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<std::vector<LDR_DATA_TABLE_ENTRY>>
Process::EnumerateRemoteModules()
{
std::vector<LDR_DATA_TABLE_ENTRY> res;
auto ppeb = Peb();
auto mem = Memory(*this);
auto peb_buf = Value(mem.Read((uptr)ppeb, sizeof(PEB)));
auto peb = reinterpret_cast<PPEB>(peb_buf.data());

auto ldr_buf = Value(mem.Read((uptr)peb->Ldr, sizeof(PEB_LDR_DATA)));
auto ldr = reinterpret_cast<PPEB_LDR_DATA>(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


Expand Down Expand Up @@ -633,7 +699,6 @@ AppContainer::AppContainer(
throw std::runtime_error("Failed to get SID");
}


dbg(L"sid={}", m_SidAsString.c_str());

//
Expand Down
32 changes: 32 additions & 0 deletions Modules/Process/Tests/pwn_win_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<a href="https://discord.gg/5HmwPxy3HP"><img alt="Discord" src="https://img.shields.io/badge/Discord-BlahCats-yellow"></a>
<a href="https://github.dev/hugsy/pwn--"><img alt="Read Code" src="https://img.shields.io/badge/Code-Read%20pwn++-brightgreen?logo=visualstudiocode"></a>
<a href="https://open.vscode.dev/hugsy/pwn--"><img alt="Open in VSCode" src="https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20VSCode&labelColor=2c2c32&color=007acc&logoColor=007acc"></a>
<a href="https://github.com/hugsy/pwn--/actions?query=workflow%3A%22CI+Build+for+MSVC%22"><img alt="CI" src="https://github.com/hugsy/pwn--/workflows/CI%20Build%20for%20MSVC/badge.svg"></a>
<a href="https://github.com/hugsy/pwn--/actions?query=workflow%3A%22Build%22"><img alt="CI" src="https://github.com/hugsy/pwn--/workflows/Build/badge.svg"></a>
</p>

## Quick start
Expand Down
Loading