Skip to content

Commit

Permalink
Fix bug in loaded modules (#30)
Browse files Browse the repository at this point in the history
Fix bug in loaded modules which was making the pwn_Modules variable relative to the namespace ExternalImport was in.

Also fixing tests once and for all
  • Loading branch information
hugsy authored Nov 24, 2023
1 parent 90256b2 commit 6cbe578
Show file tree
Hide file tree
Showing 16 changed files with 99 additions and 50 deletions.
9 changes: 4 additions & 5 deletions Docs/examples/common/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@

```cpp
#include <pwn++\pwn.h>

#include <pwn>
using namespace pwn;

auto wmain() -> int
{
auto const [major, minor] = pwn::VersionInfo;
ok(L"Running pwn++ v{:d}.{:02d}", major, minor);

Context.set("x64");
Context.Set(ArchitectureType::x64);
dbg(L"The default log_level is INFO, this message will not show!");

Context.set_log_level(log::LogLevel::Debug);
Context.Set(Log::LogLevel::Debug);
dbg(L"Now it will!");

try
{
Context.set("whatever_arch_that_dont_exist");
Context.Set("whatever_arch_that_dont_exist");
}
catch(...)
{
Expand Down
24 changes: 13 additions & 11 deletions Docs/examples/common/ctf.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ Description: Some pwntools goodies
### Local processes

```cpp
#include <pwn++\pwn.h>
#include <pwn>
using namespace pwn;

void wmain()
{
namespace log = pwn::log;
namespace ctf = pwn::ctf;
namespace utils = pwn::utils;
namespace ctf = pwn::CTF;
namespace utils = pwn::Utils;

pwn::Context.set("x64");
pwn::Context.set(log::LogLevel::Debug);
pwn::Context.Set(ArchitectureType::x64);
pwn::Context.Set(log::LogLevel::Debug);

{
auto p = ctf::Process(L"python.exe -i");
Expand All @@ -37,16 +38,17 @@ void wmain()
### Remote processes

```cpp
#include <pwn++\pwn.h>
#include <pwn>
using namespace pwn;

void wmain()
{
namespace log = pwn::log;
namespace ctf = pwn::ctf;
namespace utils = pwn::utils;
namespace log = pwn::Log;
namespace ctf = pwn::CTF;
namespace utils = pwn::Utils;

pwn::Context.set("x64");
pwn::Context.set(log::LogLevel::Debug);
pwn::Context.Set(ArchitectureType::x64);
pwn::Context.Set(Log::LogLevel::Debug);

{
auto io = ctf::Remote(L"target_vm", 1337);
Expand Down
8 changes: 4 additions & 4 deletions Modules/Assembly/Tests/pwn_disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ TEST_CASE("Disassemble", "[Assembly]")

// disassemble one insn (auto arch)
{
Context.Set("x64");
Context.Set(ArchitectureType::x64);
Assembly::Disassembler d;

auto res = d.Disassemble(code);
Expand Down Expand Up @@ -65,7 +65,7 @@ TEST_CASE("Disassemble", "[Assembly]")

// disassemble one insn
{
Context.Set("x86");
Context.Set(ArchitectureType::x86);
Assembly::Disassembler d;

auto res = d.Disassemble(code);
Expand Down Expand Up @@ -98,7 +98,7 @@ TEST_CASE("Disassemble", "[Assembly]")
code {0xc8, 0x18, 0x80, 0xd2, 0x01, 0xfd, 0x47, 0xd3, 0x20, 0xf8, 0x7f, 0xd3, 0xe2, 0x03, 0x1f, 0xaa};

{
Context.Set("arm64");
Context.Set(ArchitectureType::arm64);
Assembly::Disassembler d;

auto res = d.Disassemble(code);
Expand All @@ -110,7 +110,7 @@ TEST_CASE("Disassemble", "[Assembly]")


{
Context.Set("x64");
Context.Set(ArchitectureType::x64);
auto a = Architecture::Find("arm64");
auto d = Assembly::Disassembler(a);

Expand Down
23 changes: 19 additions & 4 deletions Modules/Common/Include/Architecture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct Architecture
ArchitectureType id {};
usize ptrsize {};
Endianess endian {};
std::array<std::string_view, 4> aliases {};

auto
operator<=>(Architecture const& other) const = default;
Expand Down Expand Up @@ -104,10 +105,24 @@ struct Architecture
///
static constexpr CMap<ArchitectureType, Architecture, 4> Architectures {
{{
{ArchitectureType::x64, {"X86_64"sv, ArchitectureType::x64, 8, Endianess::little}},
{ArchitectureType::x86, {"X86_32"sv, ArchitectureType::x86, 4, Endianess::little}},
{ArchitectureType::arm64, {"ARM_AARCH64"sv, ArchitectureType::arm64, 8, Endianess::little}},
{ArchitectureType::arm, {"ARM_AARCH64"sv, ArchitectureType::arm, 4, Endianess::little}},
{ArchitectureType::x64,
{"x64"sv,
ArchitectureType::x64,
8,
Endianess::little,
{
"x86-64"sv,
}}},
{ArchitectureType::x86,
{"x86"sv,
ArchitectureType::x86,
4,
Endianess::little,
{
"i386"sv,
}}},
{ArchitectureType::arm64, {"arm64"sv, ArchitectureType::arm64, 8, Endianess::little, {"aarch64"sv}}},
{ArchitectureType::arm, {"arm"sv, ArchitectureType::arm, 4, Endianess::little}},
}},
};

Expand Down
15 changes: 6 additions & 9 deletions Modules/Common/Include/Context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ class GlobalContext
{
if constexpr ( std::is_same_v<T, std::string_view> )
{
warn("Deprecated, prefer using ArchitectureType");
SetArchitecture(arg);
return;
}

if constexpr ( std::is_same_v<T, std::wstring_view> )
{
warn("Deprecated, prefer using ArchitectureType");
SetArchitecture(Utils::StringLib::To<std::string>(arg));
return;
}
Expand All @@ -62,16 +64,10 @@ class GlobalContext
throw new std::bad_typeid();
}

void
Set(const char* arg)
{
return Set(std::string_view(arg));
}


private:
///
/// @brief Set the Architecture object
/// @brief Set the Architecture for the global context
///
/// @param arch
///
Expand All @@ -80,7 +76,7 @@ class GlobalContext


///
///@brief Set the Architecture object from a string
///@brief Set the Architecture object from its name
///
///@param type
///
Expand All @@ -89,7 +85,8 @@ class GlobalContext


///
///@brief Set the Endianess object
///@brief Force the endianess on the selected architecture. Note that this will impact function that automatically
/// collect context info to determine their behavior (for instance `Utils::Pack` etc.)
///
///@param end
///
Expand Down
3 changes: 2 additions & 1 deletion Modules/Common/Source/Architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ Architecture::Find(std::string_view const& sv)
Architectures.data.cend(),
[&](auto const& e)
{
return e.second.name == sv;
return e.second.name == sv ||
(std::find(e.second.aliases.begin(), e.second.aliases.end(), sv) != e.second.aliases.end());
});
if ( entry == Architectures.data.cend() )
{
Expand Down
8 changes: 6 additions & 2 deletions Modules/Common/Source/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ struct GlobalContext Context;
GlobalContext::GlobalContext()
{
Utils::Random::Seed(std::chrono::system_clock::now().time_since_epoch().count());
Set("x64");
SetArchitecture(ArchitectureType::x64);
};

void
GlobalContext::SetArchitecture(ArchitectureType const& archtype)
{
architecture = Architectures.at(archtype);
auto arch = Architectures.at(archtype);
architecture = arch;
endianess = arch.endian;
ptrsize = arch.ptrsize;
dbg("Selecting '{}'", arch);
}

void
Expand Down
5 changes: 5 additions & 0 deletions Modules/FileSystem/Tests/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#define CATCH_CONFIG_MAIN

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Test checker")
{
CHECK(true);
}
5 changes: 5 additions & 0 deletions Modules/Network/Tests/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#define CATCH_CONFIG_MAIN

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Test checker")
{
CHECK(true);
}
5 changes: 5 additions & 0 deletions Modules/Registry/Tests/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#define CATCH_CONFIG_MAIN

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Test checker")
{
CHECK(true);
}
5 changes: 5 additions & 0 deletions Modules/Remote/Tests/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#define CATCH_CONFIG_MAIN

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Test checker")
{
CHECK(true);
}
5 changes: 5 additions & 0 deletions Modules/Service/Tests/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#define CATCH_CONFIG_MAIN

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Test checker")
{
CHECK(true);
}
28 changes: 17 additions & 11 deletions Modules/Symbols/Include/Win32/Resolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,36 @@
#include <unordered_map>

#include "Common.hpp"

namespace pwn::Resolver
{

#if defined(PWN_BUILD_FOR_WINDOWS)
static std::unordered_map<std::string_view, HMODULE> pwn_Modules {};
using ModuleHandle = HMODULE;
#elif defined(PWN_BUILD_FOR_LINUX)
using ModuleHandle = void*;
#endif // PWN_BUILD_FOR_WINDOWS

static std::unordered_map<std::string_view, ModuleHandle> LoadedModules {};
} // namespace pwn::Resolver

#if defined(PWN_BUILD_FOR_WINDOWS)
#define ExternalImport(Dll, Func, Ret, ...) \
typedef Ret(NTAPI* CONCAT(pwnFn_, Func))(__VA_ARGS__); \
template<typename... Ts> \
static auto Func(Ts... Args) -> Ret \
{ \
if ( !pwn_Modules.contains(Dll) ) [[unlikely]] \
if ( !pwn::Resolver::LoadedModules.contains(Dll) ) [[unlikely]] \
{ \
HMODULE hMod = ::LoadLibraryA(Dll); \
if ( !hMod ) \
{ \
throw std::runtime_error("Missing library " Dll "!"); \
} \
pwn_Modules[Dll] = hMod; \
pwn::Resolver::LoadedModules[Dll] = hMod; \
} \
static auto fnPtr = reinterpret_cast<pwnFn_##Func>(::GetProcAddress(pwn_Modules[Dll], #Func)); \
static auto fnPtr = \
reinterpret_cast<pwnFn_##Func>(::GetProcAddress(pwn::Resolver::LoadedModules[Dll], #Func)); \
if ( !fnPtr ) [[unlikely]] \
{ \
throw std::runtime_error("Missing import " Dll "!" #Func); \
Expand All @@ -32,25 +41,24 @@ static std::unordered_map<std::string_view, HMODULE> pwn_Modules {};
}
#endif // PWN_BUILD_FOR_WINDOWS


#if defined(PWN_BUILD_FOR_LINUX)
static std::unordered_map<std::string_view, void*> pwn_Modules {};
static std::unordered_map<std::string_view, void*> LoadedModules {};

#define ExternalImport(Dll, Func, Ret, ...) \
typedef Ret(NTAPI* CONCAT(pwnFn_, Func))(__VA_ARGS__); \
template<typename... Ts> \
auto Func(Ts... Args) -> Ret \
{ \
if ( !pwn_Modules.contains(Dll) ) \
if ( !pwn::Resolver::LoadedModules.contains(Dll) ) \
{ \
void * hMod = ::::dlopen((Dll, RTLD_LAZY); \
if ( !hMod ) \
{ \
throw std::runtime_error("Missing library " Dll "!"); \
} \
pwn_Modules[Dll] = hMod; \
pwn::Resolver::LoadedModules[Dll] = hMod; \
} \
static auto fnPtr = ::dlsym(pwn_Modules[Dll], #Func)); \
static auto fnPtr = ::dlsym(pwn::Resolver::LoadedModules[Dll], #Func)); \
if ( !fnPtr ) \
{ \
throw std::runtime_error("Missing import " Dll "!" #Func); \
Expand All @@ -59,8 +67,6 @@ static std::unordered_map<std::string_view, void*> pwn_Modules {};
}
#endif // PWN_BUILD_FOR_LINUX

}; // namespace pwn::Resolver


#define RestrictedType(...) const auto& __VA_OPT__(, RestrictedType(__VA_ARGS__))
#define RestrictApiType(Ret, Func, ...) Ret Func()
2 changes: 1 addition & 1 deletion Tools/Win32/AppContainMe/AppContainMe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ wmain(_In_ int argc, _In_ const wchar_t** argv) -> int
return EXIT_FAILURE;
}

Context.Set("x64");
Context.Set(ArchitectureType::x64);
Context.LogLevel = Log::LogLevel::Debug;

const std::wstring containerName {L"appcontainer-" + Utils::Random::AlnumWideString(10)};
Expand Down
2 changes: 1 addition & 1 deletion Tools/Win32/ExploitTemplate/xp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ using namespace pwn;
int
wmain()
{
Context.Set("x64");
Context.Set(ArchitectureType::x64);
Context.Set(Log::LogLevel::Debug);

info(L"Starting...");
Expand Down
2 changes: 1 addition & 1 deletion Tools/Win32/ProcessReparent/ProcessReparent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ using namespace pwn;
auto
wmain(const int argc, const wchar_t** argv) -> int
{
Context.Set("x64");
Context.Set(ArchitectureType::x64);
Context.LogLevel = Log::LogLevel::Debug;

const auto target_process = (argc >= 2) ? std::wstring(argv[1]) : std::wstring(L"powershell.exe");
Expand Down

0 comments on commit 6cbe578

Please sign in to comment.