Add clang format configuration (#58)

This fixes #48
This commit is contained in:
Maurice Heumann
2025-01-06 17:24:58 +01:00
committed by GitHub
102 changed files with 16478 additions and 14509 deletions

26
.clang-format Normal file
View File

@@ -0,0 +1,26 @@
# Format Style Options - Created with Clang Power Tools
---
BasedOnStyle: Microsoft
AlwaysBreakTemplateDeclarations: Yes
BreakConstructorInitializers: BeforeColon
DerivePointerAlignment: false
FixNamespaceComments: false
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PointerAlignment: Left
SortIncludes: false
AlignEscapedNewlines: Left
PackConstructorInitializers: Never
IndentPPDirectives: None
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCompound: true
PadOperators: true
BraceWrapping:
AfterStruct: true
AfterUnion: true
...

View File

@@ -15,6 +15,19 @@ on:
# cancel-in-progress: true
jobs:
verify-formatting:
name: Verify Formatting
runs-on: ubuntu-24.04
steps:
- name: Checkout Source
uses: actions/checkout@v4
- name: Verify Formatting
uses: jidicula/clang-format-action@v4.14.0
with:
clang-format-version: '19'
check-path: 'src'
dump-registry:
name: Dump Registry
runs-on: windows-latest

View File

@@ -25,17 +25,14 @@ namespace
auto* params_hook = watch_object(win_emu, win_emu.process().process_params, cache_logging);
win_emu.emu().hook_memory_write(win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters), 0x8,
[&, cache_logging](const uint64_t address, size_t, const uint64_t value)
{
const auto target_address = win_emu.process().peb.value() + offsetof(
PEB64, ProcessParameters);
win_emu.emu().hook_memory_write(
win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters), 0x8,
[&, cache_logging](const uint64_t address, size_t, const uint64_t value) {
const auto target_address = win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters);
if (address == target_address)
{
const emulator_object<RTL_USER_PROCESS_PARAMETERS64> obj{
win_emu.emu(), value
};
const emulator_object<RTL_USER_PROCESS_PARAMETERS64> obj{win_emu.emu(), value};
win_emu.emu().delete_hook(params_hook);
params_hook = watch_object(win_emu, obj, cache_logging);
@@ -117,7 +114,7 @@ namespace
(void)&watch_system_objects;
watch_system_objects(win_emu, options.concise_logging);
win_emu.buffer_stdout = true;
//win_emu.verbose_calls = true;
// win_emu.verbose_calls = true;
const auto& exe = *win_emu.process().executable;
@@ -130,8 +127,7 @@ namespace
continue;
}
auto read_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t)
{
auto read_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
const auto rip = win_emu.emu().read_instruction_pointer();
if (win_emu.process().mod_manager.find_by_address(rip) != win_emu.process().executable)
{
@@ -142,17 +138,16 @@ namespace
{
static uint64_t count{0};
++count;
if (count > 100 && count % 10000 != 0) return;
if (count > 100 && count % 10000 != 0)
return;
}
win_emu.log.print(
color::green,
win_emu.log.print(color::green,
"Reading from executable section %s at 0x%" PRIx64 " via 0x%" PRIx64 "\n",
section.name.c_str(), address, rip);
};
const auto write_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t)
{
const auto write_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
const auto rip = win_emu.emu().read_instruction_pointer();
if (win_emu.process().mod_manager.find_by_address(rip) != win_emu.process().executable)
{
@@ -163,12 +158,11 @@ namespace
{
static uint64_t count{0};
++count;
if (count > 100 && count % 10000 != 0) return;
if (count > 100 && count % 10000 != 0)
return;
}
win_emu.log.print(
color::blue,
"Writing to executable section %s at 0x%" PRIx64 " via 0x%" PRIx64 "\n",
win_emu.log.print(color::blue, "Writing to executable section %s at 0x%" PRIx64 " via 0x%" PRIx64 "\n",
section.name.c_str(), address, rip);
};
@@ -235,8 +229,7 @@ int main(const int argc, char** argv)
do
{
run(options, args);
}
while (options.use_gdb);
} while (options.use_gdb);
return 0;
}

View File

@@ -7,10 +7,9 @@ emulator_hook* watch_object(windows_emulator& emu, emulator_object<T> object, co
{
const reflect_type_info<T> info{};
return emu.emu().hook_memory_read(object.value(), object.size(),
[i = std::move(info), object, &emu, cache_logging](
const uint64_t address, size_t, uint64_t)
{
return emu.emu().hook_memory_read(
object.value(), object.size(),
[i = std::move(info), object, &emu, cache_logging](const uint64_t address, size_t, uint64_t) {
const auto rip = emu.emu().read_instruction_pointer();
const auto* mod = emu.process().mod_manager.find_by_address(rip);
const auto is_main_access = mod == emu.process().executable;
@@ -31,10 +30,7 @@ emulator_hook* watch_object(windows_emulator& emu, emulator_object<T> object, co
const auto offset = address - object.value();
emu.log.print(is_main_access ? color::green : color::dark_gray,
"Object access: %s - 0x%llX (%s) at 0x%llX (%s)\n",
i.get_type_name().c_str(),
offset,
i.get_member_name(offset).c_str(), rip,
mod ? mod->name.c_str() : "<N/A>");
"Object access: %s - 0x%llX (%s) at 0x%llX (%s)\n", i.get_type_name().c_str(), offset,
i.get_member_name(offset).c_str(), rip, mod ? mod->name.c_str() : "<N/A>");
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,13 +15,12 @@
template <typename T>
class reflect_type_info
{
public:
public:
reflect_type_info()
{
this->type_name_ = reflect::type_name<T>();
reflect::for_each<T>([this](auto I)
{
reflect::for_each<T>([this](auto I) {
const auto member_name = reflect::member_name<I, T>();
const auto member_offset = reflect::offset_of<I, T>();
@@ -59,7 +58,7 @@ public:
return this->type_name_;
}
private:
private:
std::string type_name_{};
std::map<size_t, std::string> members_{};
};

View File

@@ -5,8 +5,7 @@
#define THE_SIZE 30
extern "C" NO_INLINE EXPORT_SYMBOL
void vulnerable(const uint8_t* data, const size_t size)
extern "C" NO_INLINE EXPORT_SYMBOL void vulnerable(const uint8_t* data, const size_t size)
{
if (size < 10)
{
@@ -48,7 +47,6 @@ void vulnerable(const uint8_t* data, const size_t size)
uint8_t buffer[THE_SIZE] = {};
int main(int argc, const char* argv[])
{
const void* input = buffer;

View File

@@ -13,7 +13,6 @@ namespace network
#ifdef _WIN32
static struct wsa_initializer
{
public:
wsa_initializer()
{
WSADATA wsa_data;
@@ -197,16 +196,13 @@ namespace network
}
// 192.168.X.X
if (bytes[0] == 192
&& bytes[1] == 168)
if (bytes[0] == 192 && bytes[1] == 168)
{
return true;
}
// 172.16.X.X - 172.31.X.X
if (bytes[0] == 172
&& bytes[1] >= 16
&& bytes[1] < 32)
if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] < 32)
{
return true;
}
@@ -313,10 +309,7 @@ namespace network
void address::resolve(const std::string& hostname, const std::optional<int>& family)
{
const auto port = this->get_port();
auto port_reset_action = utils::finally([this, port]()
{
this->set_port(port);
});
auto port_reset_action = utils::finally([this, port]() { this->set_port(port); });
const auto result = resolve_multiple(hostname);
for (const auto& addr : result)
@@ -339,10 +332,7 @@ namespace network
addrinfo* result = nullptr;
if (!getaddrinfo(hostname.data(), nullptr, nullptr, &result))
{
const auto _2 = utils::finally([&result]
{
freeaddrinfo(result);
});
const auto _2 = utils::finally([&result] { freeaddrinfo(result); });
for (auto* i = result; i; i = i->ai_next)
{
@@ -372,10 +362,9 @@ std::size_t std::hash<network::address>::operator()(const network::address& a) c
hash ^= std::hash<decltype(a.get_in_addr().sin_addr.s_addr)>{}(a.get_in_addr().sin_addr.s_addr);
break;
case AF_INET6:
hash ^= std::hash<std::string_view>{}(std::string_view{
reinterpret_cast<const char*>(a.get_in6_addr().sin6_addr.s6_addr),
sizeof(a.get_in6_addr().sin6_addr.s6_addr)
});
hash ^= std::hash<std::string_view>{}(
std::string_view{reinterpret_cast<const char*>(a.get_in6_addr().sin6_addr.s6_addr),
sizeof(a.get_in6_addr().sin6_addr.s6_addr)});
break;
}

View File

@@ -69,8 +69,7 @@ namespace network
bool socket::send(const address& target, const void* data, const size_t size) const
{
const auto res = sendto(this->socket_, static_cast<const char*>(data), static_cast<send_size>(size), 0,
&target.get_addr(),
target.get_size());
&target.get_addr(), target.get_size());
return static_cast<size_t>(res) == size;
}
@@ -84,8 +83,8 @@ namespace network
char buffer[0x2000];
auto len = source.get_max_size();
const auto result = recvfrom(this->socket_, buffer, static_cast<int>(sizeof(buffer)), 0, &source.get_addr(),
&len);
const auto result =
recvfrom(this->socket_, buffer, static_cast<int>(sizeof(buffer)), 0, &source.get_addr(), &len);
if (result == SOCKET_ERROR)
{
return false;
@@ -107,7 +106,8 @@ namespace network
return ioctlsocket(s, FIONBIO, &mode) == 0;
#else
int flags = fcntl(s, F_GETFL, 0);
if (flags == -1) return false;
if (flags == -1)
return false;
flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
return fcntl(s, F_SETFL, flags) == 0;
#endif
@@ -181,8 +181,7 @@ namespace network
pfd.revents = 0;
}
const auto retval = poll(pfds.data(), static_cast<uint32_t>(pfds.size()),
static_cast<int>(timeout.count()));
const auto retval = poll(pfds.data(), static_cast<uint32_t>(pfds.size()), static_cast<int>(timeout.count()));
if (retval == SOCKET_ERROR)
{

View File

@@ -3,7 +3,7 @@
#if defined(_WIN32) || defined(_WIN64)
#define OS_WINDOWS
#elif defined(__APPLE__) || defined(__MACH__)
#define OS_MAC
#define OS_MAC
#elif defined(__linux__)
#define OS_LINUX
#else

View File

@@ -44,7 +44,7 @@
#define FILE_DELETE_CHILD 0x0040 /* directory */
#define FILE_READ_ATTRIBUTES 0x0080 /* all */
#define FILE_WRITE_ATTRIBUTES 0x0100 /* all */
#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1ff)
#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1ff)
#endif
@@ -84,7 +84,8 @@ typedef enum _FSINFOCLASS
FileFsObjectIdInformation, // q; s: FILE_FS_OBJECTID_INFORMATION (s: requires FILE_WRITE_DATA to volume)
FileFsDriverPathInformation, // q: FILE_FS_DRIVER_PATH_INFORMATION
FileFsVolumeFlagsInformation,
// q; s: FILE_FS_VOLUME_FLAGS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES to volume) // 10
// q; s: FILE_FS_VOLUME_FLAGS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES to
// volume) // 10
FileFsSectorSizeInformation, // q: FILE_FS_SECTOR_SIZE_INFORMATION // since WIN8
FileFsDataCopyInformation, // q: FILE_FS_DATA_COPY_INFORMATION
FileFsMetadataSizeInformation, // q: FILE_FS_METADATA_SIZE_INFORMATION // since THRESHOLD
@@ -159,7 +160,8 @@ typedef enum _FILE_INFORMATION_CLASS
FileNormalizedNameInformation, // q: FILE_NAME_INFORMATION
FileNetworkPhysicalNameInformation, // q: FILE_NETWORK_PHYSICAL_NAME_INFORMATION
FileIdGlobalTxDirectoryInformation,
// q: FILE_ID_GLOBAL_TX_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since WIN7 // 50
// q: FILE_ID_GLOBAL_TX_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since WIN7 //
// 50
FileIsRemoteDeviceInformation, // q: FILE_IS_REMOTE_DEVICE_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileUnusedInformation,
FileNumaNodeInformation, // q: FILE_NUMA_NODE_INFORMATION
@@ -179,7 +181,8 @@ typedef enum _FILE_INFORMATION_CLASS
FileRenameInformationEx, // s: FILE_RENAME_INFORMATION_EX
FileRenameInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION_EX
FileDesiredStorageClassInformation,
// q; s: FILE_DESIRED_STORAGE_CLASS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since REDSTONE2
// q; s: FILE_DESIRED_STORAGE_CLASS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires
// FILE_WRITE_ATTRIBUTES) // since REDSTONE2
FileStatInformation, // q: FILE_STAT_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileMemoryPartitionInformation, // s: FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3
FileStatLxInformation,
@@ -192,7 +195,8 @@ typedef enum _FILE_INFORMATION_CLASS
// q; s: FILE_STORAGE_RESERVE_ID_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES)
FileCaseSensitiveInformationForceAccessCheck, // q; s: FILE_CASE_SENSITIVE_INFORMATION
FileKnownFolderInformation,
// q; s: FILE_KNOWN_FOLDER_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since WIN11
// q; s: FILE_KNOWN_FOLDER_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) //
// since WIN11
FileStatBasicInformation, // since 23H2
FileId64ExtdDirectoryInformation, // FILE_ID_64_EXTD_DIR_INFORMATION
FileId64ExtdBothDirectoryInformation, // FILE_ID_64_EXTD_BOTH_DIR_INFORMATION
@@ -353,8 +357,7 @@ typedef struct _FILE_BOTH_DIR_INFORMATION
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
#ifndef OS_WINDOWS
typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE,
* PSECURITY_CONTEXT_TRACKING_MODE;
typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, *PSECURITY_CONTEXT_TRACKING_MODE;
typedef struct _SECURITY_QUALITY_OF_SERVICE
{
DWORD Length;

View File

@@ -49,8 +49,8 @@ union PEB_BITFIELD_UNION
typedef struct _LIST_ENTRY64
{
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
struct _LIST_ENTRY* Flink;
struct _LIST_ENTRY* Blink;
} LIST_ENTRY64, *PLIST_ENTRY64, *RESTRICTED_POINTER PRLIST_ENTRY64;
#endif
@@ -391,7 +391,6 @@ union TEB_CURRENT_IDEAL_PROCESSOR_UNION
};
};
union TEB_CROSS_TEB_FLAGS_UNION
{
USHORT CrossTebFlags;
@@ -557,9 +556,9 @@ typedef struct _TEB64
} TEB64, *PTEB64;
#ifdef OS_WINDOWS
inline TEB64* NtCurrentTeb64(VOID)
inline TEB64* NtCurrentTeb64()
{
return (TEB64*)__readgsqword(FIELD_OFFSET(EMU_NT_TIB64, Self));
return reinterpret_cast<TEB64*>(__readgsqword(FIELD_OFFSET(EMU_NT_TIB64, Self)));
}
#endif
@@ -658,18 +657,22 @@ union KUSD_QPC_DATA_UNION
#ifndef OS_WINDOWS
#define MAXIMUM_XSTATE_FEATURES 64
typedef struct _XSTATE_FEATURE {
typedef struct _XSTATE_FEATURE
{
ULONG Offset;
ULONG Size;
} XSTATE_FEATURE;
typedef struct _XSTATE_CONFIGURATION {
typedef struct _XSTATE_CONFIGURATION
{
std::uint64_t EnabledFeatures;
std::uint64_t EnabledVolatileFeatures;
ULONG Size;
union {
union
{
ULONG ControlFlags;
struct {
struct
{
ULONG OptimizedSave : 1;
ULONG CompactionEnabled : 1;
ULONG Reserved1 : 30;

View File

@@ -62,7 +62,6 @@ typedef enum _SECTION_INHERIT
ViewUnmap = 2
} SECTION_INHERIT;
typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64
{
void* BaseAddress;
@@ -75,7 +74,6 @@ typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64
DWORD Type;
} EMU_MEMORY_BASIC_INFORMATION64, *PEMU_MEMORY_BASIC_INFORMATION64;
typedef struct _MEMORY_IMAGE_INFORMATION64
{
void* ImageBase;

View File

@@ -2,8 +2,8 @@
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable: 4201) // nameless struct/union
#pragma warning(disable: 4702) // unreachable code
#pragma warning(disable : 4201) // nameless struct/union
#pragma warning(disable : 4702) // unreachable code
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
@@ -27,18 +27,12 @@
#ifdef OS_WINDOWS
#pragma comment(lib, "ntdll")
extern "C" {
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySystemInformationEx(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
_In_reads_bytes_(InputBufferLength) PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
extern "C"
{
NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformationEx(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _In_reads_bytes_(InputBufferLength) PVOID InputBuffer,
_In_ ULONG InputBufferLength, _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
_In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength);
}
#pragma warning(pop)
#else

View File

@@ -44,7 +44,6 @@ using BYTE = std::uint8_t;
#define CHAR BYTE
#endif
using WORD = std::uint16_t;
#define UCHAR unsigned char
@@ -53,7 +52,6 @@ using WORD = std::uint16_t;
using CSHORT = short;
using USHORT = WORD;
#define DUMMYSTRUCTNAME
#ifndef TRUE

View File

@@ -15,9 +15,9 @@
#define CONTEXT_XSTATE_32 (CONTEXT_X86_MAIN | 0x20L)
#define CONTEXT_XSTATE_64 (CONTEXT_AMD64_MAIN | 0x20L)
#define CONTEXT64_ALL (CONTEXT_CONTROL_64 | CONTEXT_INTEGER_64 | CONTEXT_SEGMENTS_64 | \
CONTEXT_FLOATING_POINT_64 | CONTEXT_DEBUG_REGISTERS_64)
#define CONTEXT64_ALL \
(CONTEXT_CONTROL_64 | CONTEXT_INTEGER_64 | CONTEXT_SEGMENTS_64 | CONTEXT_FLOATING_POINT_64 | \
CONTEXT_DEBUG_REGISTERS_64)
typedef enum _SYSTEM_INFORMATION_CLASS
{
@@ -119,7 +119,8 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemProcessorPowerInformationEx, // not implemented
SystemRefTraceInformation, // q; s: SYSTEM_REF_TRACE_INFORMATION // ObQueryRefTraceInformation
SystemSpecialPoolInformation,
// q; s: SYSTEM_SPECIAL_POOL_INFORMATION (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0
// q; s: SYSTEM_SPECIAL_POOL_INFORMATION (requires SeDebugPrivilege) // MmSpecialPoolTag, then
// MmSpecialPoolCatchOverruns != 0
SystemProcessIdInformation, // q: SYSTEM_PROCESS_ID_INFORMATION
SystemErrorPortInformation, // s (requires SeTcbPrivilege)
SystemBootEnvironmentInformation, // q: SYSTEM_BOOT_ENVIRONMENT_INFORMATION // 90
@@ -142,9 +143,11 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemProcessorMicrocodeUpdateInformation, // s: SYSTEM_PROCESSOR_MICROCODE_UPDATE_INFORMATION
SystemProcessorBrandString, // q: CHAR[] // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23
SystemVirtualAddressInformation,
// q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) // MmQuerySystemVaInformation
// q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) //
// MmQuerySystemVaInformation
SystemLogicalProcessorAndGroupInformation,
// q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (EX in: LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType) // since WIN7 // KeQueryLogicalProcessorRelationship
// q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (EX in: LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType) // since WIN7
// // KeQueryLogicalProcessorRelationship
SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup)
SystemStoreInformation,
// q; s: SYSTEM_STORE_INFORMATION (requires SeProfileSingleProcessPrivilege) // SmQueryStoreInformation
@@ -165,7 +168,8 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemAcpiAuditInformation,
// q: SYSTEM_ACPI_AUDIT_INFORMATION // HaliQuerySystemInformation -> HalpAuditQueryResults, info class 26
SystemBasicPerformanceInformation,
// q: SYSTEM_BASIC_PERFORMANCE_INFORMATION // name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation
// q: SYSTEM_BASIC_PERFORMANCE_INFORMATION //
// name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation
SystemQueryPerformanceCounterInformation, // q: SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION // since WIN7 SP1
SystemSessionBigPoolInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION // since WIN8
SystemBootGraphicsInformation, // q; s: SYSTEM_BOOT_GRAPHICS_INFORMATION (kernel-mode only)
@@ -228,7 +232,8 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemCodeIntegrityPlatformManifestInformation,
// q: SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION // since REDSTONE
SystemInterruptSteeringInformation,
// q: in: SYSTEM_INTERRUPT_STEERING_INFORMATION_INPUT, out: SYSTEM_INTERRUPT_STEERING_INFORMATION_OUTPUT // NtQuerySystemInformationEx // 180
// q: in: SYSTEM_INTERRUPT_STEERING_INFORMATION_INPUT, out: SYSTEM_INTERRUPT_STEERING_INFORMATION_OUTPUT //
// NtQuerySystemInformationEx // 180
SystemSupportedProcessorArchitectures,
// p: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx
SystemMemoryUsageInformation, // q: SYSTEM_MEMORY_USAGE_INFORMATION
@@ -261,9 +266,11 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemSecurityModelInformation, // SYSTEM_SECURITY_MODEL_INFORMATION // since 19H1
SystemCodeIntegritySyntheticCacheInformation,
SystemFeatureConfigurationInformation,
// q: in: SYSTEM_FEATURE_CONFIGURATION_QUERY, out: SYSTEM_FEATURE_CONFIGURATION_INFORMATION; s: SYSTEM_FEATURE_CONFIGURATION_UPDATE // NtQuerySystemInformationEx // since 20H1 // 210
// q: in: SYSTEM_FEATURE_CONFIGURATION_QUERY, out: SYSTEM_FEATURE_CONFIGURATION_INFORMATION; s:
// SYSTEM_FEATURE_CONFIGURATION_UPDATE // NtQuerySystemInformationEx // since 20H1 // 210
SystemFeatureConfigurationSectionInformation,
// q: in: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_REQUEST, out: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_INFORMATION // NtQuerySystemInformationEx
// q: in: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_REQUEST, out: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_INFORMATION //
// NtQuerySystemInformationEx
SystemFeatureUsageSubscriptionInformation,
// q: SYSTEM_FEATURE_USAGE_SUBSCRIPTION_DETAILS; s: SYSTEM_FEATURE_USAGE_SUBSCRIPTION_UPDATE
SystemSecureSpeculationControlInformation, // SECURE_SPECULATION_CONTROL_INFORMATION
@@ -285,7 +292,8 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemDpcWatchdogInformation, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION
SystemDpcWatchdogInformation2, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION_V2
SystemSupportedProcessorArchitectures2,
// q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230
// q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx //
// 230
SystemSingleProcessorRelationshipInformation,
// q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // (EX in: PROCESSOR_NUMBER Processor)
SystemXfgCheckFailureInformation, // q: SYSTEM_XFG_FAILURE_INFORMATION
@@ -295,10 +303,12 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemPointerAuthInformation, // SYSTEM_POINTER_AUTH_INFORMATION
SystemSecureKernelDebuggerInformation,
SystemOriginalImageFeatureInformation,
// q: in: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_INPUT, out: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_OUTPUT // NtQuerySystemInformationEx
// q: in: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_INPUT, out: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_OUTPUT //
// NtQuerySystemInformationEx
SystemMemoryNumaInformation, // SYSTEM_MEMORY_NUMA_INFORMATION_INPUT, SYSTEM_MEMORY_NUMA_INFORMATION_OUTPUT
SystemMemoryNumaPerformanceInformation,
// SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUTSYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUT, SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT // since 24H2 // 240
// SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUTSYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUT,
// SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT // since 24H2 // 240
SystemCodeIntegritySignedPoliciesFullInformation,
SystemSecureSecretsInformation,
SystemTrustedAppsRuntimeInformation, // SYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION
@@ -359,7 +369,8 @@ typedef enum _TOKEN_INFORMATION_CLASS
TokenChildProcessFlags, // s: ULONG (requires SeTcbPrivilege) // since REDSTONE3
TokenIsLessPrivilegedAppContainer, // q: ULONG // since REDSTONE5
TokenIsSandboxed, // q: ULONG // since 19H1
TokenIsAppSilo, // q: ULONG // since WIN11 22H2 // previously TokenOriginatingProcessTrustLevel // q: TOKEN_PROCESS_TRUST_LEVEL
TokenIsAppSilo, // q: ULONG // since WIN11 22H2 // previously TokenOriginatingProcessTrustLevel // q:
// TOKEN_PROCESS_TRUST_LEVEL
TokenLoggingInformation, // TOKEN_LOGGING_INFORMATION // since 24H2
MaxTokenInfoClass
} TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS;
@@ -538,12 +549,14 @@ struct SYSTEM_PROCESSOR_INFORMATION64
#ifndef OS_WINDOWS
typedef struct _M128A {
typedef struct _M128A
{
ULONGLONG Low;
LONGLONG High;
} M128A, *PM128A;
typedef struct _XMM_SAVE_AREA32 {
typedef struct _XMM_SAVE_AREA32
{
WORD ControlWord;
WORD StatusWord;
BYTE TagWord;
@@ -656,7 +669,7 @@ struct EMU_EXCEPTION_RECORD
{
DWORD ExceptionCode;
DWORD ExceptionFlags;
EMULATOR_CAST(typename Traits::PVOID, struct EMU_EXCEPTION_RECORD *) ExceptionRecord;
EMULATOR_CAST(typename Traits::PVOID, struct EMU_EXCEPTION_RECORD*) ExceptionRecord;
typename Traits::PVOID ExceptionAddress;
DWORD NumberParameters;
typename Traits::ULONG_PTR ExceptionInformation[15];
@@ -742,30 +755,34 @@ struct TOKEN_MANDATORY_LABEL64
#ifndef OS_WINDOWS
typedef enum _TOKEN_TYPE {
typedef enum _TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
} TOKEN_TYPE;
typedef TOKEN_TYPE* PTOKEN_TYPE;
typedef struct _TOKEN_ELEVATION {
typedef struct _TOKEN_ELEVATION
{
DWORD TokenIsElevated;
} TOKEN_ELEVATION, * PTOKEN_ELEVATION;
} TOKEN_ELEVATION, *PTOKEN_ELEVATION;
typedef enum _SECURITY_IMPERSONATION_LEVEL {
typedef enum _SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
} SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;
typedef struct _LUID {
typedef struct _LUID
{
DWORD LowPart;
LONG HighPart;
} LUID, *PLUID;
typedef struct _TOKEN_STATISTICS {
typedef struct _TOKEN_STATISTICS
{
LUID TokenId;
LUID AuthenticationId;
LARGE_INTEGER ExpirationTime;

View File

@@ -11,8 +11,9 @@ using NTSTATUS = std::uint32_t;
#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005L)
#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
#define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS)0xC000001DL)
#define STATUS_PENDING ((DWORD)0x00000103L)
#define STATUS_PENDING ((NTSTATUS)0x00000103L)
#endif
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
@@ -25,7 +26,6 @@ using NTSTATUS = std::uint32_t;
#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
#define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
@@ -41,6 +41,5 @@ using NTSTATUS = std::uint32_t;
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define FILE_DEVICE_NETWORK 0x00000012
#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK

View File

@@ -65,7 +65,6 @@ typedef enum _THREADINFOCLASS
MaxThreadInfoClass
} THREADINFOCLASS;
template <typename Traits>
struct THREAD_NAME_INFORMATION
{

View File

@@ -91,7 +91,6 @@ enum class PEMachineType : std::uint16_t
CEE = 0xC0EE,
};
#pragma pack(push, 4)
template <typename T>
@@ -130,7 +129,6 @@ struct PEOptionalHeaderBasePart1_t
uint32_t BaseOfCode;
};
struct PEDirectory_t2
{
std::uint32_t VirtualAddress;
@@ -246,8 +244,9 @@ struct PEDosHeader_t
typedef struct _IMAGE_SECTION_HEADER
{
std::uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
union {
std:: uint32_t PhysicalAddress;
union
{
std::uint32_t PhysicalAddress;
std::uint32_t VirtualSize;
} Misc;
std::uint32_t VirtualAddress;
@@ -260,7 +259,8 @@ typedef struct _IMAGE_SECTION_HEADER
std::uint32_t Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
typedef struct _IMAGE_EXPORT_DIRECTORY {
typedef struct _IMAGE_EXPORT_DIRECTORY
{
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -274,7 +274,8 @@ typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
typedef struct _IMAGE_BASE_RELOCATION {
typedef struct _IMAGE_BASE_RELOCATION
{
DWORD VirtualAddress;
DWORD SizeOfBlock;
WORD TypeOffset[1];

View File

@@ -11,8 +11,8 @@ namespace utils
{
public:
safe_object_accessor(const std::span<S> buffer, const size_t offset)
: buffer_(buffer)
, offset_(offset)
: buffer_(buffer),
offset_(offset)
{
}

View File

@@ -36,8 +36,14 @@ namespace utils::concurrency
return accessor(object_, lock);
}
T& get_raw() { return object_; }
const T& get_raw() const { return object_; }
T& get_raw()
{
return object_;
}
const T& get_raw() const
{
return object_;
}
T copy() const
{

View File

@@ -5,23 +5,25 @@
namespace utils
{
/*
* Copied from here: https://github.com/microsoft/GSL/blob/e0880931ae5885eb988d1a8a57acf8bc2b8dacda/include/gsl/util#L57
* Copied from here:
* https://github.com/microsoft/GSL/blob/e0880931ae5885eb988d1a8a57acf8bc2b8dacda/include/gsl/util#L57
*/
template <class F>
class final_action
{
public:
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value &&
!std::is_volatile<F>::value,
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value && !std::is_volatile<F>::value,
"Final_action should store its callable by value");
explicit final_action(F f) noexcept : f_(std::move(f))
explicit final_action(F f) noexcept
: f_(std::move(f))
{
}
final_action(final_action&& other) noexcept
: f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false))
: f_(std::move(other.f_)),
invoke_(std::exchange(other.invoke_, false))
{
}
@@ -31,7 +33,8 @@ namespace utils
~final_action() noexcept
{
if (invoke_) f_();
if (invoke_)
f_();
}
// Added by momo5502
@@ -46,10 +49,8 @@ namespace utils
};
template <class F>
final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>
finally(F&& f) noexcept
final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type> finally(F&& f) noexcept
{
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(
std::forward<F>(f));
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(std::forward<F>(f));
}
}

View File

@@ -28,8 +28,8 @@ namespace utils::io
io::create_directory(file.parent_path());
}
std::ofstream stream(
file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : std::ofstream::out));
std::ofstream stream(file, std::ios::binary | std::ofstream::out |
(append ? std::ofstream::app : std::ofstream::out));
if (stream.is_open())
{
@@ -50,11 +50,13 @@ namespace utils::io
bool read_file(const std::filesystem::path& file, std::vector<uint8_t>* data)
{
if (!data) return false;
if (!data)
return false;
data->clear();
std::ifstream stream(file, std::ios::binary);
if (!stream) return false;
if (!stream)
return false;
*data = std::vector<uint8_t>{(std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()};
return true;
@@ -94,9 +96,9 @@ namespace utils::io
void copy_folder(const std::filesystem::path& src, const std::filesystem::path& target)
{
std::error_code ec{};
std::filesystem::copy(src, target,
std::filesystem::copy_options::overwrite_existing |
std::filesystem::copy_options::recursive, ec);
std::filesystem::copy(
src, target, std::filesystem::copy_options::overwrite_existing | std::filesystem::copy_options::recursive,
ec);
}
std::vector<std::filesystem::path> list_files(const std::filesystem::path& directory, const bool recursive)

View File

@@ -29,10 +29,7 @@ namespace utils::string
template <class Elem, class Traits, class Alloc>
void to_lower_inplace(std::basic_string<Elem, Traits, Alloc>& str)
{
std::ranges::transform(str, str.begin(), [](const Elem e)
{
return char_to_lower(e);
});
std::ranges::transform(str, str.begin(), [](const Elem e) { return char_to_lower(e); });
}
template <class Elem, class Traits, class Alloc>

View File

@@ -34,23 +34,22 @@ struct basic_block
size_t size;
};
using edge_generation_hook_callback = std::function<void(const basic_block& current_block,
const basic_block& previous_block)>;
using edge_generation_hook_callback =
std::function<void(const basic_block& current_block, const basic_block& previous_block)>;
using basic_block_hook_callback = std::function<void(const basic_block& block)>;
using instruction_hook_callback = std::function<instruction_hook_continuation()>;
using interrupt_hook_callback = std::function<void(int interrupt)>;
using simple_memory_hook_callback = std::function<void(uint64_t address, size_t size, uint64_t value)>;
using complex_memory_hook_callback = std::function<void(uint64_t address, size_t size, uint64_t value,
memory_operation operation)>;
using complex_memory_hook_callback =
std::function<void(uint64_t address, size_t size, uint64_t value, memory_operation operation)>;
using memory_violation_hook_callback = std::function<memory_violation_continuation(
uint64_t address, size_t size, memory_operation operation,
memory_violation_type type)>;
uint64_t address, size_t size, memory_operation operation, memory_violation_type type)>;
class emulator : public memory_manager
{
public:
public:
emulator() = default;
emulator(const emulator&) = delete;
@@ -133,7 +132,7 @@ public:
virtual bool has_violation() const = 0;
private:
private:
std::vector<std::byte> last_snapshot_data_{};
emulator_hook* hook_simple_memory_access(const uint64_t address, const size_t size,
@@ -143,10 +142,7 @@ private:
return this->hook_memory_access(address, size, operation,
[c = std::move(callback)](const uint64_t a, const size_t s,
const uint64_t value,
memory_operation)
{
c(a, s, value);
});
memory_operation) { c(a, s, value); });
}
void perform_serialization(utils::buffer_serializer& buffer, const bool is_snapshot) const

View File

@@ -227,11 +227,13 @@ bool memory_manager::allocate_mmio(const uint64_t address, const size_t size, mm
this->map_mmio(address, size, std::move(read_cb), std::move(write_cb));
const auto entry = this->reserved_regions_.try_emplace(address,
const auto entry = this->reserved_regions_
.try_emplace(address,
reserved_region{
.length = size,
.is_mmio = true,
}).first;
})
.first;
entry->second.committed_regions[address] = committed_region{size, memory_permission::read_write};
@@ -246,7 +248,12 @@ bool memory_manager::allocate_memory(const uint64_t address, const size_t size,
return false;
}
const auto entry = this->reserved_regions_.try_emplace(address, reserved_region{.length = size,}).first;
const auto entry = this->reserved_regions_
.try_emplace(address,
reserved_region{
.length = size,
})
.first;
if (!reserve_only)
{
@@ -416,8 +423,7 @@ bool memory_manager::release_memory(const uint64_t address, size_t size)
uint64_t memory_manager::find_free_allocation_base(const size_t size, const uint64_t start) const
{
uint64_t start_address =
std::max(MIN_ALLOCATION_ADDRESS, start ? start : 0x100000000ULL);
uint64_t start_address = std::max(MIN_ALLOCATION_ADDRESS, start ? start : 0x100000000ULL);
for (const auto& region : this->reserved_regions_)
{

View File

@@ -18,7 +18,7 @@ using mmio_write_callback = std::function<void(uint64_t addr, size_t size, uint6
class memory_manager
{
public:
public:
struct committed_region
{
size_t length{};
@@ -90,8 +90,7 @@ public:
memory_permission* old_permissions = nullptr);
bool allocate_mmio(uint64_t address, size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb);
bool allocate_memory(uint64_t address, size_t size, memory_permission permissions,
bool reserve_only = false);
bool allocate_memory(uint64_t address, size_t size, memory_permission permissions, bool reserve_only = false);
bool commit_memory(uint64_t address, size_t size, memory_permission permissions);
bool decommit_memory(uint64_t address, size_t size);
@@ -113,7 +112,7 @@ public:
return allocation_base;
}
private:
private:
using reserved_region_map = std::map<uint64_t, reserved_region>;
reserved_region_map reserved_regions_{};
@@ -126,7 +125,7 @@ private:
virtual void apply_memory_protection(uint64_t address, size_t size, memory_permission permissions) = 0;
protected:
protected:
void serialize_memory_state(utils::buffer_serializer& buffer, bool is_snapshot) const;
void deserialize_memory_state(utils::buffer_deserializer& buffer, bool is_snapshot);
};

View File

@@ -15,49 +15,39 @@ enum class memory_permission : uint8_t
*
****************************************************************************/
inline constexpr memory_permission
operator&(const memory_permission x, const memory_permission y)
inline constexpr memory_permission operator&(const memory_permission x, const memory_permission y)
{
return static_cast<memory_permission>
(static_cast<uint8_t>(x) & static_cast<uint8_t>(y));
return static_cast<memory_permission>(static_cast<uint8_t>(x) & static_cast<uint8_t>(y));
}
inline constexpr memory_permission
operator|(const memory_permission x, const memory_permission y)
inline constexpr memory_permission operator|(const memory_permission x, const memory_permission y)
{
return static_cast<memory_permission>
(static_cast<uint8_t>(x) | static_cast<uint8_t>(y));
return static_cast<memory_permission>(static_cast<uint8_t>(x) | static_cast<uint8_t>(y));
}
inline constexpr memory_permission
operator^(const memory_permission x, const memory_permission y)
inline constexpr memory_permission operator^(const memory_permission x, const memory_permission y)
{
return static_cast<memory_permission>
(static_cast<uint8_t>(x) ^ static_cast<uint8_t>(y));
return static_cast<memory_permission>(static_cast<uint8_t>(x) ^ static_cast<uint8_t>(y));
}
inline constexpr memory_permission
operator~(memory_permission x)
inline constexpr memory_permission operator~(memory_permission x)
{
return static_cast<memory_permission>(~static_cast<uint8_t>(x));
}
inline memory_permission&
operator&=(memory_permission& x, const memory_permission y)
inline memory_permission& operator&=(memory_permission& x, const memory_permission y)
{
x = x & y;
return x;
}
inline memory_permission&
operator|=(memory_permission& x, const memory_permission y)
inline memory_permission& operator|=(memory_permission& x, const memory_permission y)
{
x = x | y;
return x;
}
inline memory_permission&
operator^=(memory_permission& x, const memory_permission y)
inline memory_permission& operator^=(memory_permission& x, const memory_permission y)
{
x = x ^ y;
return x;

View File

@@ -3,12 +3,12 @@
class scoped_hook
{
public:
public:
scoped_hook() = default;
scoped_hook(emulator& emu, emulator_hook* hook)
: emu_(&emu)
, hook_(hook)
: emu_(&emu),
hook_(hook)
{
}
@@ -48,7 +48,7 @@ public:
}
}
private:
private:
emulator* emu_{};
emulator_hook* hook_{};
};

View File

@@ -15,8 +15,7 @@ namespace utils
class buffer_deserializer;
template <typename T>
concept Serializable = requires(T a, const T ac, buffer_serializer& serializer, buffer_deserializer& deserializer)
{
concept Serializable = requires(T a, const T ac, buffer_serializer& serializer, buffer_deserializer& deserializer) {
{ ac.serialize(serializer) } -> std::same_as<void>;
{ a.deserialize(deserializer) } -> std::same_as<void>;
};
@@ -38,9 +37,9 @@ namespace utils
};
template <typename T>
struct has_serialize_function<T, std::void_t<decltype(serialize(std::declval<buffer_serializer&>(),
std::declval<const std::remove_cvref_t<T>&>())
)>>
struct has_serialize_function<T,
std::void_t<decltype(serialize(std::declval<buffer_serializer&>(),
std::declval<const std::remove_cvref_t<T>&>()))>>
: std::true_type
{
};
@@ -51,16 +50,14 @@ namespace utils
};
template <typename T>
struct has_deserialize_function<T, std::void_t<decltype(deserialize(
std::declval<buffer_deserializer&>(),
struct has_deserialize_function<T, std::void_t<decltype(deserialize(std::declval<buffer_deserializer&>(),
std::declval<std::remove_cvref_t<T>&>()))>>
: std::true_type
{
};
template <typename T>
struct has_deserializer_constructor
: std::bool_constant<std::is_constructible_v<T, buffer_deserializer&>>
struct has_deserializer_constructor : std::bool_constant<std::is_constructible_v<T, buffer_deserializer&>>
{
};
}
@@ -70,8 +67,8 @@ namespace utils
public:
template <typename T>
buffer_deserializer(const std::span<T> buffer, bool no_debugging = false)
: no_debugging_(no_debugging)
, buffer_(reinterpret_cast<const std::byte*>(buffer.data()), buffer.size() * sizeof(T))
: no_debugging_(no_debugging),
buffer_(reinterpret_cast<const std::byte*>(buffer.data()), buffer.size() * sizeof(T))
{
static_assert(std::is_trivially_copyable_v<T>, "Type must be trivially copyable");
}
@@ -257,7 +254,7 @@ namespace utils
}
}
template <typename T= char>
template <typename T = char>
std::basic_string<T> read_string()
{
std::basic_string<T> result{};
@@ -284,9 +281,7 @@ namespace utils
requires(std::is_invocable_r_v<T, F>)
void register_factory(F factory)
{
this->factories_[std::type_index(typeid(T))] = [f = std::move(factory)]() -> T* {
return new T(f());
};
this->factories_[std::type_index(typeid(T))] = [f = std::move(factory)]() -> T* { return new T(f()); };
}
private:
@@ -311,8 +306,8 @@ namespace utils
const auto factory = this->factories_.find(std::type_index(typeid(T)));
if (factory == this->factories_.end())
{
throw std::runtime_error(
"Object construction failed. Missing factory for type: " + std::string(typeid(T).name()));
throw std::runtime_error("Object construction failed. Missing factory for type: " +
std::string(typeid(T).name()));
}
auto* object = static_cast<T*>(factory->second());

View File

@@ -2,11 +2,11 @@
#include "emulator.hpp"
template <typename PointerType, typename Register, Register InstructionPointer, Register
StackPointer, typename HookableInstructions>
template <typename PointerType, typename Register, Register InstructionPointer, Register StackPointer,
typename HookableInstructions>
class typed_emulator : public emulator
{
public:
public:
using registers = Register;
using pointer_type = PointerType;
using hookable_instructions = HookableInstructions;
@@ -87,7 +87,7 @@ public:
return this->hook_instruction(static_cast<int>(instruction_type), std::move(callback));
}
private:
private:
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override = 0;
void read_raw_register(int reg, void* value, size_t size) override = 0;

View File

@@ -11,5 +11,5 @@ enum class x64_hookable_instructions
rdtscp,
};
using x64_emulator = typed_emulator<uint64_t, x64_register, x64_register::rip,
x64_register::rsp, x64_hookable_instructions>;
using x64_emulator =
typed_emulator<uint64_t, x64_register, x64_register::rip, x64_register::rsp, x64_hookable_instructions>;

View File

@@ -35,10 +35,7 @@ namespace
void forward_emulator(windows_emulator& win_emu)
{
const auto target = win_emu.process().executable->find_export("vulnerable");
win_emu.emu().hook_memory_execution(target, 1, [&](uint64_t, size_t, uint64_t)
{
win_emu.emu().stop();
});
win_emu.emu().hook_memory_execution(target, 1, [&](uint64_t, size_t, uint64_t) { win_emu.emu().stop(); });
run_emulation(win_emu);
}
@@ -50,13 +47,11 @@ namespace
std::unordered_set<uint64_t> visited_blocks{};
const std::function<fuzzer::coverage_functor>* handler{nullptr};
fuzzer_executer(std::span<const std::byte> data)
: emulator_data(data)
{
emu.fuzzing = true;
emu.emu().hook_basic_block([&](const basic_block& block)
{
emu.emu().hook_basic_block([&](const basic_block& block) {
if (this->handler && visited_blocks.emplace(block.address).second)
{
(*this->handler)(block.address);
@@ -69,10 +64,7 @@ namespace
const auto ret = emu.emu().read_stack(0);
emu.emu().hook_memory_execution(ret, 1, [&](uint64_t, size_t, uint64_t)
{
emu.emu().stop();
});
emu.emu().hook_memory_execution(ret, 1, [&](uint64_t, size_t, uint64_t) { emu.emu().stop(); });
}
void restore_emulator()
@@ -85,7 +77,7 @@ namespace
fuzzer::execution_result execute(std::span<const uint8_t> data,
const std::function<fuzzer::coverage_functor>& coverage_handler) override
{
//printf("Input size: %zd\n", data.size());
// printf("Input size: %zd\n", data.size());
this->handler = &coverage_handler;
this->visited_blocks.clear();
@@ -164,7 +156,7 @@ int main(const int argc, char** argv)
return 1;
}
//setvbuf(stdout, nullptr, _IOFBF, 0x10000);
// setvbuf(stdout, nullptr, _IOFBF, 0x10000);
if (argc > 2 && argv[1] == "-d"s)
{
use_gdb = true;
@@ -175,8 +167,7 @@ int main(const int argc, char** argv)
do
{
run(argv[use_gdb ? 2 : 1]);
}
while (use_gdb);
} while (use_gdb);
return 0;
}

View File

@@ -11,8 +11,8 @@ namespace fuzzer
{
public:
fuzzing_context(input_generator& generator, fuzzing_handler& handler)
: generator(generator)
, handler(handler)
: generator(generator),
handler(handler)
{
}
@@ -48,13 +48,9 @@ namespace fuzzer
void perform_fuzzing_iteration(fuzzing_context& context, executer& executer)
{
++context.executions;
context.generator.access_input([&](const std::span<const uint8_t> input)
{
context.generator.access_input([&](const std::span<const uint8_t> input) {
uint64_t score{0};
const auto result = executer.execute(input, [&](uint64_t)
{
++score;
});
const auto result = executer.execute(input, [&](uint64_t) { ++score; });
if (result == execution_result::error)
{
@@ -88,10 +84,7 @@ namespace fuzzer
for (size_t i = 0; i < concurrency; ++i)
{
this->workers_.emplace_back([&context]
{
worker(context);
});
this->workers_.emplace_back([&context] { worker(context); });
}
}

View File

@@ -23,7 +23,6 @@ namespace fuzzer
const auto mutations = (rng.get_geometric<size_t>() + 1) % input.size();
for (size_t i = 0; i < mutations; ++i)
{
const auto index = rng.get<size_t>(input.size());
@@ -102,9 +101,8 @@ namespace fuzzer
}
const auto insert_at_random = this->rng.get(10) == 0;
const auto index = insert_at_random
? (this->rng.get<size_t>() % this->top_scorer_.size())
: this->lowest_scorer;
const auto index =
insert_at_random ? (this->rng.get<size_t>() % this->top_scorer_.size()) : this->lowest_scorer;
this->top_scorer_[index] = std::move(entry);

View File

@@ -52,13 +52,12 @@ bool test_threads()
for (auto i = 0ULL; i < thread_count; ++i)
{
threads.emplace_back([&counter]
{
threads.emplace_back([&counter] {
++counter;
std::this_thread::yield();
++counter;
// Host scheduling/cpu performance can have impact on emulator scheduling
//std::this_thread::sleep_for(std::chrono::milliseconds(100));
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
++counter;
});
}
@@ -82,8 +81,7 @@ bool test_tls()
for (size_t i = 0; i < thread_count; ++i)
{
ts.emplace_back([&]
{
ts.emplace_back([&] {
while (!kill)
{
std::this_thread::yield();
@@ -173,8 +171,7 @@ bool test_dir_io()
std::optional<std::string> read_registry_string(const HKEY root, const char* path, const char* value)
{
HKEY key{};
if (RegOpenKeyExA(root, path, 0, KEY_READ, &key) !=
ERROR_SUCCESS)
if (RegOpenKeyExA(root, path, 0, KEY_READ, &key) != ERROR_SUCCESS)
{
return std::nullopt;
}
@@ -203,8 +200,8 @@ std::optional<std::string> read_registry_string(const HKEY root, const char* pat
bool test_registry()
{
const auto val = read_registry_string(HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows\CurrentVersion)",
"ProgramFilesDir");
const auto val =
read_registry_string(HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows\CurrentVersion)", "ProgramFilesDir");
if (!val)
{
return false;
@@ -259,7 +256,7 @@ bool test_ud2_exception(void* address)
{
__try
{
static_cast<void(*)()>(address)();
static_cast<void (*)()>(address)();
return false;
}
__except (EXCEPTION_EXECUTE_HANDLER)
@@ -287,8 +284,7 @@ bool test_illegal_instruction_exception()
bool test_native_exceptions()
{
return test_access_violation_exception()
&& test_illegal_instruction_exception();
return test_access_violation_exception() && test_illegal_instruction_exception();
}
void print_time()
@@ -298,12 +294,12 @@ void print_time()
}
#define RUN_TEST(func, name) \
{ \
{ \
printf("Running test '" name "': "); \
const auto res = func(); \
valid &= res; \
puts(res ? "Success" : "Fail"); \
}
}
int main(int argc, const char* argv[])
{

View File

@@ -8,7 +8,7 @@
template <typename ReturnType, typename... Args>
class function_wrapper : public object
{
public:
public:
using user_data_pointer = void*;
using c_function_type = ReturnType(Args..., user_data_pointer);
using functor_type = std::function<ReturnType(Args...)>;
@@ -22,8 +22,7 @@ public:
c_function_type* get_c_function() const
{
return +[](Args... args, user_data_pointer user_data) -> ReturnType
{
return +[](Args... args, user_data_pointer user_data) -> ReturnType {
return (*static_cast<functor_type*>(user_data))(std::forward<Args>(args)...);
};
}
@@ -38,6 +37,6 @@ public:
return this->functor_.get();
}
private:
private:
std::unique_ptr<functor_type> functor_{};
};

View File

@@ -2,7 +2,7 @@
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4505)
#pragma warning(disable : 4505)
#endif
#ifdef __clang__
@@ -28,8 +28,8 @@ namespace unicorn
struct unicorn_error : std::runtime_error
{
unicorn_error(const uc_err error_code)
: std::runtime_error(uc_strerror(error_code))
, code(error_code)
: std::runtime_error(uc_strerror(error_code)),
code(error_code)
{
}

View File

@@ -15,8 +15,8 @@ namespace unicorn
}
unicorn_hook(uc_engine* uc, const uc_hook hook)
: uc_(uc)
, hook_(hook)
: uc_(uc),
hook_(hook)
{
}
@@ -28,7 +28,6 @@ namespace unicorn
unicorn_hook(const unicorn_hook&) = delete;
unicorn_hook& operator=(const unicorn_hook&) = delete;
unicorn_hook(unicorn_hook&& obj) noexcept
{
this->operator=(std::move(obj));

View File

@@ -14,7 +14,6 @@ namespace unicorn
uce(uc_mem_regions(uc, &this->regions_, &this->count_));
}
~unicorn_memory_regions()
{
this->release();

View File

@@ -85,8 +85,7 @@ namespace unicorn
{
public:
template <typename T>
requires(std::is_base_of_v<object, T>
&& std::is_move_constructible_v<T>)
requires(std::is_base_of_v<object, T> && std::is_move_constructible_v<T>)
void add(T data, unicorn_hook hook)
{
hook_entry entry{};
@@ -178,9 +177,7 @@ namespace unicorn
const std::shared_ptr<complex_memory_hook_callback>& callback)
{
function_wrapper<void, uc_engine*, uc_mem_type, uint64_t, int, int64_t> wrapper(
[callback](uc_engine*, const uc_mem_type type, const uint64_t address, const int size,
const int64_t)
{
[callback](uc_engine*, const uc_mem_type type, const uint64_t address, const int size, const int64_t) {
const auto operation = map_memory_operation(type);
if (operation != memory_permission::none)
{
@@ -201,8 +198,7 @@ namespace unicorn
{
function_wrapper<void, uc_engine*, uc_mem_type, uint64_t, int, int64_t> wrapper(
[callback](uc_engine*, const uc_mem_type type, const uint64_t address, const int size,
const uint64_t value)
{
const uint64_t value) {
const auto operation = map_memory_operation(type);
if (operation != memory_permission::none)
{
@@ -222,15 +218,14 @@ namespace unicorn
const std::shared_ptr<complex_memory_hook_callback>& callback)
{
function_wrapper<void, uc_engine*, uint64_t, uint32_t> wrapper(
[callback](uc_engine*, const uint64_t address, const uint32_t size)
{
[callback](uc_engine*, const uint64_t address, const uint32_t size) {
(*callback)(address, size, 0, memory_permission::exec);
});
unicorn_hook hook{uc};
uce(uc_hook_add(uc, hook.make_reference(), UC_HOOK_CODE, wrapper.get_function(),
wrapper.get_user_data(), address, address + size));
uce(uc_hook_add(uc, hook.make_reference(), UC_HOOK_CODE, wrapper.get_function(), wrapper.get_user_data(),
address, address + size));
container.add(std::move(wrapper), std::move(hook));
}
@@ -281,8 +276,7 @@ namespace unicorn
this->has_violation_ = false;
const auto timeoutYs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
const auto res = uc_emu_start(*this, start, end, static_cast<uint64_t>(timeoutYs.count()),
count);
const auto res = uc_emu_start(*this, start, end, static_cast<uint64_t>(timeoutYs.count()), count);
if (res == UC_ERR_OK)
{
return;
@@ -314,8 +308,8 @@ namespace unicorn
if (size < result_size)
{
throw std::runtime_error(
"Register size mismatch: " + std::to_string(size) + " != " + std::to_string(result_size));
throw std::runtime_error("Register size mismatch: " + std::to_string(size) +
" != " + std::to_string(result_size));
}
}
@@ -327,27 +321,21 @@ namespace unicorn
if (size < result_size)
{
throw std::runtime_error(
"Register size mismatch: " + std::to_string(size) + " != " + std::to_string(result_size));
throw std::runtime_error("Register size mismatch: " + std::to_string(size) +
" != " + std::to_string(result_size));
}
}
void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,
mmio_write_callback write_cb) override
{
mmio_callbacks cb{
.read = mmio_callbacks::read_wrapper(
[c = std::move(read_cb)](uc_engine*, const uint64_t addr, const uint32_t s)
{
mmio_callbacks cb{.read = mmio_callbacks::read_wrapper(
[c = std::move(read_cb)](uc_engine*, const uint64_t addr, const uint32_t s) {
return c(addr, s);
}),
.write = mmio_callbacks::write_wrapper(
[c = std::move(write_cb)](uc_engine*, const uint64_t addr, const uint32_t s,
const uint64_t value)
{
c(addr, s, value);
})
};
const uint64_t value) { c(addr, s, value); })};
uce(uc_mmio_map(*this, address, size, cb.read.get_c_function(), cb.read.get_user_data(),
cb.write.get_c_function(), cb.write.get_user_data()));
@@ -392,14 +380,10 @@ namespace unicorn
uce(uc_mem_protect(*this, address, size, static_cast<uint32_t>(permissions)));
}
emulator_hook* hook_instruction(int instruction_type,
instruction_hook_callback callback) override
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override
{
function_wrapper<int, uc_engine*> wrapper([c = std::move(callback)](uc_engine*)
{
return (c() == instruction_hook_continuation::skip_instruction)
? 1
: 0;
function_wrapper<int, uc_engine*> wrapper([c = std::move(callback)](uc_engine*) {
return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0;
});
unicorn_hook hook{*this};
@@ -432,8 +416,7 @@ namespace unicorn
emulator_hook* hook_basic_block(basic_block_hook_callback callback) override
{
function_wrapper<void, uc_engine*, uint64_t, size_t> wrapper(
[c = std::move(callback)](uc_engine*, const uint64_t address, const size_t size)
{
[c = std::move(callback)](uc_engine*, const uint64_t address, const size_t size) {
basic_block block{};
block.address = address;
block.size = size;
@@ -445,8 +428,7 @@ namespace unicorn
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_BLOCK, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max())
);
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
@@ -458,8 +440,7 @@ namespace unicorn
emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override
{
function_wrapper<void, uc_engine*, uc_tb*, uc_tb*> wrapper(
[c = std::move(callback)](uc_engine*, const uc_tb* cur_tb, const uc_tb* prev_tb)
{
[c = std::move(callback)](uc_engine*, const uc_tb* cur_tb, const uc_tb* prev_tb) {
const auto current_block = map_block(*cur_tb);
const auto previous_block = map_block(*prev_tb);
@@ -470,8 +451,7 @@ namespace unicorn
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_EDGE_GENERATED, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max())
);
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
@@ -483,17 +463,13 @@ namespace unicorn
emulator_hook* hook_interrupt(interrupt_hook_callback callback) override
{
function_wrapper<void, uc_engine*, int> wrapper(
[c = std::move(callback)](uc_engine*, const int interrupt_type)
{
c(interrupt_type);
});
[c = std::move(callback)](uc_engine*, const int interrupt_type) { c(interrupt_type); });
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INTR, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max())
);
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
@@ -506,9 +482,8 @@ namespace unicorn
memory_violation_hook_callback callback) override
{
function_wrapper<bool, uc_engine*, uc_mem_type, uint64_t, int, int64_t> wrapper(
[c = std::move(callback), this](uc_engine*, const uc_mem_type type,
const uint64_t address, const int size, const int64_t)
{
[c = std::move(callback), this](uc_engine*, const uc_mem_type type, const uint64_t address,
const int size, const int64_t) {
const auto ip = this->read_instruction_pointer();
assert(size >= 0);
@@ -584,8 +559,8 @@ namespace unicorn
void delete_hook(emulator_hook* hook) override
{
const auto entry = std::ranges::find_if(this->hooks_, [&](const std::unique_ptr<hook_object>& hook_ptr)
{
const auto entry =
std::ranges::find_if(this->hooks_, [&](const std::unique_ptr<hook_object>& hook_ptr) {
return hook_ptr->as_opaque_hook() == hook;
});

View File

@@ -4,19 +4,19 @@
#include <windows_emulator.hpp>
#define ASSERT_NOT_TERMINATED(win_emu) \
do { \
do \
{ \
ASSERT_FALSE((win_emu).process().exit_status.has_value()); \
} while(false)
} while (false)
#define ASSERT_TERMINATED_WITH_STATUS(win_emu, status) \
do { \
do \
{ \
ASSERT_TRUE((win_emu).process().exit_status.has_value()); \
ASSERT_EQ(*(win_emu).process().exit_status, status); \
} while(false)
} while (false)
#define ASSERT_TERMINATED_SUCCESSFULLY(win_emu) \
ASSERT_TERMINATED_WITH_STATUS(win_emu, STATUS_SUCCESS)
#define ASSERT_TERMINATED_SUCCESSFULLY(win_emu) ASSERT_TERMINATED_WITH_STATUS(win_emu, STATUS_SUCCESS)
namespace test
{
@@ -28,8 +28,7 @@ namespace test
inline windows_emulator create_sample_emulator()
{
emulator_settings settings
{
emulator_settings settings{
.disable_logging = true,
.use_relative_time = true,
};

View File

@@ -8,10 +8,7 @@ namespace test
const emulator_settings settings{
.arguments = {u"-time"},
.stdout_callback = [&output_buffer](const std::string_view data)
{
output_buffer.append(data);
},
.stdout_callback = [&output_buffer](const std::string_view data) { output_buffer.append(data); },
.disable_logging = true,
.use_relative_time = false,
};

View File

@@ -3,7 +3,8 @@
#include <utils/finally.hpp>
extern "C" {
extern "C"
{
#include <gdbstub.h>
}
@@ -114,8 +115,7 @@ namespace
bool run_gdb_stub(gdb_stub_handler& handler, std::string target_description, const size_t register_count,
std::string bind_address)
{
const arch_info_t info
{
const arch_info_t info{
target_description.data(),
static_cast<int>(register_count),
sizeof(uint64_t),
@@ -130,10 +130,7 @@ bool run_gdb_stub(gdb_stub_handler& handler, std::string target_description, con
return false;
}
const auto _ = utils::finally([&]
{
gdbstub_close(&stub);
});
const auto _ = utils::finally([&] { gdbstub_close(&stub); });
return gdbstub_run(&stub, &handler);
}

View File

@@ -5,10 +5,10 @@
class win_x64_gdb_stub_handler : public x64_gdb_stub_handler
{
public:
public:
win_x64_gdb_stub_handler(windows_emulator& win_emu)
: x64_gdb_stub_handler(win_emu.emu())
, win_emu_(&win_emu)
: x64_gdb_stub_handler(win_emu.emu()),
win_emu_(&win_emu)
{
}
@@ -40,6 +40,6 @@ public:
return gdb_action::resume;
}
private:
private:
windows_emulator* win_emu_{};
};

View File

@@ -4,24 +4,9 @@
#include "scoped_hook.hpp"
inline std::vector gdb_registers{
x64_register::rax,
x64_register::rbx,
x64_register::rcx,
x64_register::rdx,
x64_register::rsi,
x64_register::rdi,
x64_register::rbp,
x64_register::rsp,
x64_register::r8,
x64_register::r9,
x64_register::r10,
x64_register::r11,
x64_register::r12,
x64_register::r13,
x64_register::r14,
x64_register::r15,
x64_register::rip,
x64_register::rflags,
x64_register::rax, x64_register::rbx, x64_register::rcx, x64_register::rdx, x64_register::rsi, x64_register::rdi,
x64_register::rbp, x64_register::rsp, x64_register::r8, x64_register::r9, x64_register::r10, x64_register::r11,
x64_register::r12, x64_register::r13, x64_register::r14, x64_register::r15, x64_register::rip, x64_register::rflags,
/*x64_register::cs,
x64_register::ss,
x64_register::ds,
@@ -65,15 +50,14 @@ struct std::hash<breakpoint_key>
{
std::size_t operator()(const breakpoint_key& k) const noexcept
{
return ((std::hash<size_t>()(k.addr)
^ (std::hash<size_t>()(k.size) << 1)) >> 1)
^ (std::hash<size_t>()(static_cast<size_t>(k.type)) << 1);
return ((std::hash<size_t>()(k.addr) ^ (std::hash<size_t>()(k.size) << 1)) >> 1) ^
(std::hash<size_t>()(static_cast<size_t>(k.type)) << 1);
}
};
class x64_gdb_stub_handler : public gdb_stub_handler
{
public:
public:
x64_gdb_stub_handler(x64_emulator& emu)
: emu_(&emu)
{
@@ -169,12 +153,10 @@ public:
{
try
{
this->hooks_[{addr, size, type}] = scoped_hook(*this->emu_, this->emu_->hook_memory_access(
this->hooks_[{addr, size, type}] = scoped_hook(
*this->emu_, this->emu_->hook_memory_access(
addr, size, map_breakpoint_type(type),
[this](uint64_t, size_t, uint64_t, memory_operation)
{
this->on_interrupt();
}));
[this](uint64_t, size_t, uint64_t, memory_operation) { this->on_interrupt(); }));
return true;
}
@@ -209,7 +191,7 @@ public:
this->emu_->stop();
}
private:
private:
x64_emulator* emu_{};
std::unordered_map<breakpoint_key, scoped_hook> hooks_{};
};

View File

@@ -32,8 +32,8 @@ namespace
return win_emu.emu().read_memory<afd_creation_data>(data.buffer);
}
std::pair<AFD_POLL_INFO64, std::vector<AFD_POLL_HANDLE_INFO64>> get_poll_info(
windows_emulator& win_emu, const io_device_context& c)
std::pair<AFD_POLL_INFO64, std::vector<AFD_POLL_HANDLE_INFO64>> get_poll_info(windows_emulator& win_emu,
const io_device_context& c)
{
constexpr auto info_size = offsetof(AFD_POLL_INFO64, Handles);
if (!c.input_buffer || c.input_buffer_length < info_size)
@@ -170,10 +170,8 @@ namespace
assert(current_index == static_cast<size_t>(count));
emulator_object<AFD_POLL_INFO64>{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO64& info)
{
info.NumberOfHandles = static_cast<ULONG>(current_index);
});
emulator_object<AFD_POLL_INFO64>{win_emu.emu(), c.input_buffer}.access(
[&](AFD_POLL_INFO64& info) { info.NumberOfHandles = static_cast<ULONG>(current_index); });
return STATUS_SUCCESS;
}
@@ -259,10 +257,7 @@ namespace
}
this->executing_delayed_ioctl_ = true;
const auto _ = utils::finally([&]
{
this->executing_delayed_ioctl_ = false;
});
const auto _ = utils::finally([&] { this->executing_delayed_ioctl_ = false; });
if (this->require_poll_.has_value())
{
@@ -510,9 +505,9 @@ namespace
const auto data = emu.read_memory(buffer.buf, buffer.len);
const auto sent_data = sendto(*this->s_, reinterpret_cast<const char*>(data.data()),
static_cast<send_size>(data.size()), 0 /* ? */, &target.get_addr(),
target.get_size());
const auto sent_data =
sendto(*this->s_, reinterpret_cast<const char*>(data.data()), static_cast<send_size>(data.size()),
0 /* ? */, &target.get_addr(), target.get_size());
if (sent_data < 0)
{

View File

@@ -117,10 +117,8 @@ struct AFD_POLL_INFO64
#define AFD_NUM_POLL_EVENTS 11
#define AFD_POLL_ALL ((1 << AFD_NUM_POLL_EVENTS) - 1)
#define _AFD_REQUEST(ioctl) \
((((ULONG)(ioctl)) >> 2) & 0x03FF)
#define _AFD_BASE(ioctl) \
((((ULONG)(ioctl)) >> 12) & 0xFFFFF)
#define _AFD_REQUEST(ioctl) ((((ULONG)(ioctl)) >> 2) & 0x03FF)
#define _AFD_BASE(ioctl) ((((ULONG)(ioctl)) >> 12) & 0xFFFFF)
#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK

View File

@@ -10,7 +10,7 @@ class object_wrapper
{
T* obj_;
public:
public:
object_wrapper(T& obj)
: obj_(&obj)
{
@@ -45,7 +45,7 @@ using windows_emulator_wrapper = object_wrapper<windows_emulator>;
template <typename T>
class emulator_object
{
public:
public:
using value_type = T;
emulator_object(const x64_emulator_wrapper& wrapper, const uint64_t address = 0)
@@ -54,8 +54,8 @@ public:
}
emulator_object(emulator& emu, const uint64_t address = 0)
: emu_(&emu)
, address_(address)
: emu_(&emu),
address_(address)
{
}
@@ -135,26 +135,25 @@ public:
this->address_ = address;
}
private:
private:
emulator* emu_{};
uint64_t address_{};
};
// TODO: warning emulator_utils is hardcoded for 64bit unicode_string usage
class emulator_allocator
{
public:
public:
emulator_allocator(emulator& emu)
: emu_(&emu)
{
}
emulator_allocator(emulator& emu, const uint64_t address, const uint64_t size)
: emu_(&emu)
, address_(address)
, size_(size)
, active_address_(address)
: emu_(&emu),
address_(address),
size_(size),
active_address_(address)
{
}
@@ -181,7 +180,6 @@ public:
return emulator_object<T>(*this->emu_, potential_start);
}
char16_t* copy_string(const std::u16string_view str)
{
UNICODE_STRING<EmulatorTraits<Emu64>> uc_str{};
@@ -211,10 +209,8 @@ public:
{
const auto unicode_string = this->reserve<UNICODE_STRING<EmulatorTraits<Emu64>>>();
unicode_string.access([&](UNICODE_STRING<EmulatorTraits<Emu64>>& unicode_str)
{
this->make_unicode_string(unicode_str, str);
});
unicode_string.access(
[&](UNICODE_STRING<EmulatorTraits<Emu64>>& unicode_str) { this->make_unicode_string(unicode_str, str); });
return unicode_string;
}
@@ -263,14 +259,13 @@ public:
}
}
private:
private:
emulator* emu_{};
uint64_t address_{};
uint64_t size_{};
uint64_t active_address_{0};
};
inline std::u16string read_unicode_string(const emulator& emu, const UNICODE_STRING<EmulatorTraits<Emu64>> ucs)
{
static_assert(offsetof(UNICODE_STRING<EmulatorTraits<Emu64>>, Length) == 0);
@@ -286,7 +281,6 @@ inline std::u16string read_unicode_string(const emulator& emu, const UNICODE_STR
return result;
}
inline std::u16string read_unicode_string(const emulator& emu,
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> uc_string)
{

View File

@@ -121,7 +121,7 @@ template <handle_types::type Type, typename T, uint32_t IndexShift = 0>
requires(utils::Serializable<T>)
class handle_store : public generic_handle_store
{
public:
public:
using index_type = uint32_t;
using value_map = std::map<index_type, T>;
@@ -319,7 +319,7 @@ public:
return this->store_.end();
}
private:
private:
typename value_map::iterator get_iterator(const handle_value h)
{
if (h.type != Type || h.is_pseudo)

View File

@@ -14,11 +14,8 @@ namespace
std::unique_ptr<io_device> create_device(const std::u16string_view device)
{
if (device == u"CNG"
|| device == u"KsecDD"
|| device == u"PcwDrv"
|| device == u"DeviceApi\\CMApi"
|| device == u"ConDrv\\Server")
if (device == u"CNG" || device == u"KsecDD" || device == u"PcwDrv" || device == u"DeviceApi\\CMApi" ||
device == u"ConDrv\\Server")
{
return std::make_unique<dummy_device>();
}

View File

@@ -70,10 +70,8 @@ inline void write_io_status(const emulator_object<IO_STATUS_BLOCK<EmulatorTraits
{
if (io_status_block)
{
io_status_block.access([&](IO_STATUS_BLOCK<EmulatorTraits<Emu64>>& status_block)
{
status_block.Status = status;
});
io_status_block.access(
[&](IO_STATUS_BLOCK<EmulatorTraits<Emu64>>& status_block) { status_block.Status = status; });
}
}
@@ -136,7 +134,7 @@ std::unique_ptr<io_device> create_device(std::u16string_view device);
class io_device_container : public io_device
{
public:
public:
io_device_container() = default;
io_device_container(std::u16string device, windows_emulator& win_emu, const io_device_creation_data& data)
@@ -182,7 +180,7 @@ public:
return dynamic_cast<T*>(value);
}
private:
private:
std::u16string device_name_{};
std::unique_ptr<io_device> device_{};

View File

@@ -103,8 +103,8 @@ namespace utils
}
kusd_mmio::kusd_mmio(x64_emulator& emu, process_context& process)
: emu_(&emu)
, process_(&process)
: emu_(&emu),
process_(&process)
{
}
@@ -205,12 +205,10 @@ void kusd_mmio::register_mmio()
this->registered_ = true;
this->emu_->allocate_mmio(KUSD_ADDRESS, KUSD_BUFFER_SIZE,
[this](const uint64_t addr, const size_t size)
{
return this->read(addr, size);
}, [](const uint64_t, const size_t, const uint64_t)
{
this->emu_->allocate_mmio(
KUSD_ADDRESS, KUSD_BUFFER_SIZE,
[this](const uint64_t addr, const size_t size) { return this->read(addr, size); },
[](const uint64_t, const size_t, const uint64_t) {
// Writing not supported!
});
}

View File

@@ -10,7 +10,7 @@ class windows_emulator;
class kusd_mmio
{
public:
public:
kusd_mmio(x64_emulator& emu, process_context& process);
~kusd_mmio();
@@ -38,7 +38,7 @@ public:
void setup(bool use_relative_time);
private:
private:
x64_emulator* emu_{};
process_context* process_{};

View File

@@ -24,17 +24,27 @@ namespace
switch (c)
{
case black: return COLOR(0x8, "\033[0;90m");
case red: return COLOR(0xC, "\033[0;91m");
case green: return COLOR(0xA, "\033[0;92m");
case yellow: return COLOR(0xE, "\033[0;93m");
case blue: return COLOR(0x9, "\033[0;94m");
case cyan: return COLOR(0xB, "\033[0;96m");
case pink: return COLOR(0xD, "\033[0;95m");
case white: return COLOR(0xF, "\033[0;97m");
case dark_gray: return COLOR(0x8, "\033[0;97m");
case black:
return COLOR(0x8, "\033[0;90m");
case red:
return COLOR(0xC, "\033[0;91m");
case green:
return COLOR(0xA, "\033[0;92m");
case yellow:
return COLOR(0xE, "\033[0;93m");
case blue:
return COLOR(0x9, "\033[0;94m");
case cyan:
return COLOR(0xB, "\033[0;96m");
case pink:
return COLOR(0xD, "\033[0;95m");
case white:
return COLOR(0xF, "\033[0;97m");
case dark_gray:
return COLOR(0x8, "\033[0;97m");
case gray:
default: return get_reset_color();
default:
return get_reset_color();
}
}
@@ -71,14 +81,15 @@ namespace
const int count = vsnprintf(buffer, sizeof(buffer), message, *ap);
#endif
if (count < 0) return {};
if (count < 0)
return {};
return {buffer, static_cast<size_t>(count)};
}
#define format_to_string(msg, str)\
va_list ap;\
va_start(ap, msg);\
const auto str = format(&ap, msg);\
#define format_to_string(msg, str) \
va_list ap; \
va_start(ap, msg); \
const auto str = format(&ap, msg); \
va_end(ap);
void print_colored(const std::string_view& line, const color_type base_color)

View File

@@ -3,7 +3,7 @@
#ifdef OS_WINDOWS
#define FORMAT_ATTRIBUTE(fmt_pos, var_pos)
#else
#define FORMAT_ATTRIBUTE(fmt_pos, var_pos) __attribute__((format( printf, fmt_pos, var_pos)))
#define FORMAT_ATTRIBUTE(fmt_pos, var_pos) __attribute__((format(printf, fmt_pos, var_pos)))
#endif
enum class color
@@ -22,7 +22,7 @@ enum class color
class logger
{
public:
public:
void print(color c, std::string_view message) const;
void print(color c, const char* message, ...) const FORMAT_ATTRIBUTE(3, 4);
void info(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3);
@@ -41,6 +41,6 @@ public:
return this->disable_output_;
}
private:
private:
bool disable_output_{false};
};

View File

@@ -6,7 +6,7 @@ class logger;
class module_manager
{
public:
public:
module_manager(emulator& emu);
mapped_module* map_module(const std::filesystem::path& file, logger& logger);
@@ -38,7 +38,7 @@ public:
bool unmap(const uint64_t address);
private:
private:
emulator* emu_{};
using module_map = std::map<uint64_t, mapped_module>;

View File

@@ -10,8 +10,8 @@ namespace
uint64_t get_first_section_offset(const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
{
const uint8_t* nt_headers_addr = reinterpret_cast<const uint8_t*>(&nt_headers);
size_t optional_header_offset = reinterpret_cast<uintptr_t>(&(nt_headers.OptionalHeader)) - reinterpret_cast<
uintptr_t>(&nt_headers);
size_t optional_header_offset =
reinterpret_cast<uintptr_t>(&(nt_headers.OptionalHeader)) - reinterpret_cast<uintptr_t>(&nt_headers);
size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader;
const uint8_t* first_section_addr = nt_headers_addr + optional_header_offset + optional_header_size;
@@ -38,11 +38,10 @@ namespace
return;
}
const auto export_directory = buffer.as<IMAGE_EXPORT_DIRECTORY>(export_directory_entry.
VirtualAddress).get();
const auto export_directory = buffer.as<IMAGE_EXPORT_DIRECTORY>(export_directory_entry.VirtualAddress).get();
const auto names_count = export_directory.NumberOfNames;
//const auto function_count = export_directory.NumberOfFunctions;
// const auto function_count = export_directory.NumberOfFunctions;
const auto names = buffer.as<DWORD>(export_directory.AddressOfNames);
const auto ordinals = buffer.as<WORD>(export_directory.AddressOfNameOrdinals);
@@ -142,8 +141,7 @@ namespace
}
}
void map_sections(emulator& emu, mapped_module& binary,
const utils::safe_buffer_accessor<const uint8_t> buffer,
void map_sections(emulator& emu, mapped_module& binary, const utils::safe_buffer_accessor<const uint8_t> buffer,
const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
{
const auto first_section_offset = get_first_section_offset(nt_headers, nt_headers_offset);
@@ -197,8 +195,7 @@ namespace
}
}
mapped_module map_module_from_data(emulator& emu, const std::span<const uint8_t> data,
std::filesystem::path file)
mapped_module map_module_from_data(emulator& emu, const std::span<const uint8_t> data, std::filesystem::path file)
{
mapped_module binary{};
binary.path = std::move(file);
@@ -224,12 +221,10 @@ mapped_module map_module_from_data(emulator& emu, const std::span<const uint8_t>
{
binary.image_base = emu.find_free_allocation_base(binary.size_of_image);
const auto is_dll = nt_headers.FileHeader.Characteristics & IMAGE_FILE_DLL;
const auto has_dynamic_base =
optional_header.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
const auto has_dynamic_base = optional_header.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
const auto is_relocatable = is_dll || has_dynamic_base;
if (!is_relocatable || !emu.allocate_memory(binary.image_base, binary.size_of_image,
memory_permission::read))
if (!is_relocatable || !emu.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::read))
{
throw std::runtime_error("Memory range not allocatable");
}
@@ -238,8 +233,7 @@ mapped_module map_module_from_data(emulator& emu, const std::span<const uint8_t>
binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint;
const auto* header_buffer = buffer.get_pointer_for_range(0, optional_header.SizeOfHeaders);
emu.write_memory(binary.image_base, header_buffer,
optional_header.SizeOfHeaders);
emu.write_memory(binary.image_base, header_buffer, optional_header.SizeOfHeaders);
map_sections(emu, binary, buffer, nt_headers, nt_headers_offset);

View File

@@ -3,8 +3,7 @@
#include <x64_emulator.hpp>
#include "mapped_module.hpp"
mapped_module map_module_from_data(emulator& emu, std::span<const uint8_t> data,
std::filesystem::path file);
mapped_module map_module_from_data(emulator& emu, std::span<const uint8_t> data, std::filesystem::path file);
mapped_module map_module_from_file(emulator& emu, std::filesystem::path file);
bool unmap_module(emulator& emu, const mapped_module& mod);

View File

@@ -283,7 +283,7 @@ struct process_context;
class moved_marker
{
public:
public:
moved_marker() = default;
moved_marker(const moved_marker& copy) = default;
@@ -313,13 +313,13 @@ public:
return this->was_moved_;
}
private:
private:
bool was_moved_{false};
};
class emulator_thread : ref_counted_object
{
public:
public:
emulator_thread(x64_emulator& emu)
: emu_ptr(&emu)
{
@@ -471,7 +471,7 @@ public:
buffer.read_vector(this->last_registers);
}
private:
private:
void setup_registers(x64_emulator& emu, const process_context& context) const;
void release()
@@ -503,11 +503,11 @@ private:
struct process_context
{
process_context(x64_emulator& emu)
: base_allocator(emu)
, peb(emu)
, process_params(emu)
, kusd(emu, *this)
, mod_manager(emu)
: base_allocator(emu),
peb(emu),
process_params(emu),
kusd(emu, *this),
mod_manager(emu)
{
}

View File

@@ -214,7 +214,7 @@ void hive_key::parse(std::ifstream& file)
}
hive_parser::hive_parser(const std::filesystem::path& file_path)
: file_(file_path, std::ios::binary)
, root_key_(parse_root_block(file_, file_path))
: file_(file_path, std::ios::binary),
root_key_(parse_root_block(file_, file_path))
{
}

View File

@@ -15,11 +15,11 @@ struct hive_value
class hive_key
{
public:
public:
hive_key(const int subkey_block_offset, const int value_count, const int value_offsets)
: subkey_block_offset_(subkey_block_offset)
, value_count_(value_count)
, value_offsets_(value_offsets)
: subkey_block_offset_(subkey_block_offset),
value_count_(value_count),
value_offsets_(value_offsets)
{
}
@@ -44,7 +44,7 @@ public:
const hive_value* get_value(std::ifstream& file, const std::string_view name);
private:
private:
struct raw_hive_value : hive_value
{
bool parsed{false};
@@ -65,7 +65,7 @@ private:
class hive_parser
{
public:
public:
explicit hive_parser(const std::filesystem::path& file_path);
[[nodiscard]] hive_key* get_sub_key(const std::filesystem::path& key)
@@ -96,7 +96,7 @@ public:
return sub_key->get_value(this->file_, name);
}
private:
private:
std::ifstream file_{};
hive_key root_key_;
};

View File

@@ -29,8 +29,8 @@ namespace
return true;
}
void register_hive(registry_manager::hive_map& hives,
const std::filesystem::path& key, const std::filesystem::path& file)
void register_hive(registry_manager::hive_map& hives, const std::filesystem::path& key,
const std::filesystem::path& file)
{
hives[canonicalize_path(key)] = std::make_unique<hive_parser>(file);
}

View File

@@ -31,7 +31,7 @@ struct registry_value
class registry_manager
{
public:
public:
using hive_ptr = std::unique_ptr<hive_parser>;
using hive_map = std::unordered_map<std::filesystem::path, hive_ptr>;
@@ -45,14 +45,13 @@ public:
registry_manager(const registry_manager&) = delete;
registry_manager& operator=(const registry_manager&) = delete;
void serialize(utils::buffer_serializer& buffer) const;
void deserialize(utils::buffer_deserializer& buffer);
std::optional<registry_key> get_key(const std::filesystem::path& key);
std::optional<registry_value> get_value(const registry_key& key, std::string name);
private:
private:
std::filesystem::path hive_path_{};
hive_map hives_{};
std::unordered_map<std::filesystem::path, std::filesystem::path> path_mapping_{};

View File

@@ -2,32 +2,32 @@
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable: 4005)
#pragma warning(disable: 4127)
#pragma warning(disable: 4201)
#pragma warning(disable: 4244)
#pragma warning(disable: 4245)
#pragma warning(disable: 4324)
#pragma warning(disable: 4458)
#pragma warning(disable: 4471)
#pragma warning(disable: 4505)
#pragma warning(disable: 4702)
#pragma warning(disable: 4996)
#pragma warning(disable: 5054)
#pragma warning(disable: 6011)
#pragma warning(disable: 6297)
#pragma warning(disable: 6385)
#pragma warning(disable: 6386)
#pragma warning(disable: 6387)
#pragma warning(disable: 26110)
#pragma warning(disable: 26451)
#pragma warning(disable: 26444)
#pragma warning(disable: 26451)
#pragma warning(disable: 26489)
#pragma warning(disable: 26495)
#pragma warning(disable: 26498)
#pragma warning(disable: 26812)
#pragma warning(disable: 28020)
#pragma warning(disable : 4005)
#pragma warning(disable : 4127)
#pragma warning(disable : 4201)
#pragma warning(disable : 4244)
#pragma warning(disable : 4245)
#pragma warning(disable : 4324)
#pragma warning(disable : 4458)
#pragma warning(disable : 4471)
#pragma warning(disable : 4505)
#pragma warning(disable : 4702)
#pragma warning(disable : 4996)
#pragma warning(disable : 5054)
#pragma warning(disable : 6011)
#pragma warning(disable : 6297)
#pragma warning(disable : 6385)
#pragma warning(disable : 6386)
#pragma warning(disable : 6387)
#pragma warning(disable : 26110)
#pragma warning(disable : 26451)
#pragma warning(disable : 26444)
#pragma warning(disable : 26451)
#pragma warning(disable : 26489)
#pragma warning(disable : 26495)
#pragma warning(disable : 26498)
#pragma warning(disable : 26812)
#pragma warning(disable : 28020)
#pragma warning(pop)
#endif

View File

@@ -23,7 +23,6 @@ void syscall_dispatcher::deserialize(utils::buffer_deserializer& buffer)
this->add_handlers();
}
void syscall_dispatcher::setup(const exported_symbols& ntdll_exports, std::span<const std::byte> ntdll_data,
const exported_symbols& win32u_exports, std::span<const std::byte> win32u_data)
{
@@ -68,7 +67,6 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
const auto address = emu.read_instruction_pointer();
const auto syscall_id = emu.reg<uint32_t>(x64_register::eax);
const syscall_context c{win_emu, emu, context, true};
try
@@ -94,9 +92,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
if (mod != context.ntdll && mod != context.win32u)
{
win_emu.log.print(color::blue, "Executing inline syscall: %s (0x%X) at 0x%" PRIx64 " (%s)\n",
entry->second.name.c_str(),
syscall_id,
address, mod ? mod->name.c_str() : "<N/A>");
entry->second.name.c_str(), syscall_id, address, mod ? mod->name.c_str() : "<N/A>");
}
else
{
@@ -108,8 +104,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
win_emu.log.print(color::dark_gray,
"Executing syscall: %s (0x%X) at 0x%" PRIx64 " via 0x%" PRIx64 " (%s)\n",
entry->second.name.c_str(),
syscall_id, address, return_address, mod_name);
entry->second.name.c_str(), syscall_id, address, return_address, mod_name);
}
else
{
@@ -117,10 +112,8 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
win_emu.log.print(color::blue,
"Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64
" (%s)\n",
entry->second.name.c_str(),
syscall_id,
address, mod ? mod->name.c_str() : "<N/A>", context.previous_ip,
previous_mod ? previous_mod->name.c_str() : "<N/A>");
entry->second.name.c_str(), syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
context.previous_ip, previous_mod ? previous_mod->name.c_str() : "<N/A>");
}
}

View File

@@ -3,7 +3,7 @@
#include "process_context.hpp"
struct syscall_context;
using syscall_handler = void(*)(const syscall_context& c);
using syscall_handler = void (*)(const syscall_context& c);
struct syscall_handler_entry
{
@@ -15,7 +15,7 @@ class windows_emulator;
class syscall_dispatcher
{
public:
public:
syscall_dispatcher() = default;
syscall_dispatcher(const exported_symbols& ntdll_exports, std::span<const std::byte> ntdll_data,
const exported_symbols& win32u_exports, std::span<const std::byte> win32u_data);
@@ -33,7 +33,7 @@ public:
return this->handlers_.at(id).name;
}
private:
private:
std::map<uint64_t, syscall_handler_entry> handlers_{};
static void add_handlers(std::map<std::string, syscall_handler>& handler_mapping);

View File

@@ -78,9 +78,8 @@ inline std::map<uint64_t, std::string> find_syscalls(const exported_symbols& exp
if (!entry.empty())
{
throw std::runtime_error(
"Syscall with id " + std::to_string(*id) + ", which is mapping to " + symbol.name +
", was already mapped to " + entry);
throw std::runtime_error("Syscall with id " + std::to_string(*id) + ", which is mapping to " +
symbol.name + ", was already mapped to " + entry);
}
entry = symbol.name;
@@ -90,8 +89,7 @@ inline std::map<uint64_t, std::string> find_syscalls(const exported_symbols& exp
return syscalls;
}
inline void map_syscalls(std::map<uint64_t, syscall_handler_entry>& handlers,
std::map<uint64_t, std::string> syscalls)
inline void map_syscalls(std::map<uint64_t, syscall_handler_entry>& handlers, std::map<uint64_t, std::string> syscalls)
{
for (auto& [id, name] : syscalls)
{
@@ -99,8 +97,7 @@ inline void map_syscalls(std::map<uint64_t, syscall_handler_entry>& handlers,
if (!entry.name.empty())
{
throw std::runtime_error(
"Syscall with id " + std::to_string(id) + ", which is mapping to " + name +
throw std::runtime_error("Syscall with id " + std::to_string(id) + ", which is mapping to " + name +
", was previously mapped to " + entry.name);
}
@@ -168,11 +165,8 @@ void forward_syscall(const syscall_context& c, NTSTATUS (*handler)(const syscall
const auto ip = c.emu.read_instruction_pointer();
size_t index = 0;
std::tuple<const syscall_context&, Args...> func_args
{
c,
resolve_indexed_argument<std::remove_cv_t<std::remove_reference_t<Args>>>(c.emu, index)...
};
std::tuple<const syscall_context&, Args...> func_args{
c, resolve_indexed_argument<std::remove_cv_t<std::remove_reference_t<Args>>>(c.emu, index)...};
(void)index;
@@ -183,10 +177,7 @@ void forward_syscall(const syscall_context& c, NTSTATUS (*handler)(const syscall
template <auto Handler>
syscall_handler make_syscall_handler()
{
return +[](const syscall_context& c)
{
forward_syscall(c, Handler);
};
return +[](const syscall_context& c) { forward_syscall(c, Handler); };
}
template <typename T, typename Traits>
@@ -214,8 +205,8 @@ inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_poin
const auto relative_time = -delay_interval.QuadPart;
const auto relative_ticks_in_ms = relative_time / 10;
const auto relative_fraction_ns = (relative_time % 10) * 100;
const auto relative_duration = std::chrono::microseconds(relative_ticks_in_ms) +
std::chrono::nanoseconds(relative_fraction_ns);
const auto relative_duration =
std::chrono::microseconds(relative_ticks_in_ms) + std::chrono::nanoseconds(relative_fraction_ns);
return std::chrono::steady_clock::now() + relative_duration;
}
@@ -226,13 +217,11 @@ inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_poin
const auto delay_seconds_since_1970 = delay_seconds_since_1601 - EPOCH_DIFFERENCE_1601_TO_1970_SECONDS;
const auto target_time =
std::chrono::system_clock::from_time_t(delay_seconds_since_1970) +
std::chrono::nanoseconds(delay_fraction_ns);
std::chrono::system_clock::from_time_t(delay_seconds_since_1970) + std::chrono::nanoseconds(delay_fraction_ns);
const auto now_system = std::chrono::system_clock::now();
const auto duration_until_target = std::chrono::duration_cast<
std::chrono::microseconds>(target_time - now_system);
const auto duration_until_target = std::chrono::duration_cast<std::chrono::microseconds>(target_time - now_system);
return std::chrono::steady_clock::now() + duration_until_target;
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,8 @@ namespace
emulator_object<T> allocate_object_on_stack(x64_emulator& emu)
{
const auto old_sp = emu.reg(x64_register::rsp);
const auto new_sp = align_down(old_sp - sizeof(CONTEXT64),
std::max(alignof(CONTEXT64), alignof(x64_emulator::pointer_type)));
const auto new_sp =
align_down(old_sp - sizeof(CONTEXT64), std::max(alignof(CONTEXT64), alignof(x64_emulator::pointer_type)));
emu.reg(x64_register::rsp, new_sp);
return {emu, new_sp};
@@ -42,10 +42,7 @@ namespace
uint64_t value;
};
const msr_value value{
IA32_GS_BASE_MSR,
allocator.get_base()
};
const msr_value value{IA32_GS_BASE_MSR, allocator.get_base()};
emu.write_register(x64_register::msr, &value, sizeof(value));
}
@@ -66,8 +63,7 @@ namespace
}
ULONG copy_string_as_relative(x64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
const void* base_ptr, const uint64_t offset,
const size_t length)
const void* base_ptr, const uint64_t offset, const size_t length)
{
const auto address = copy_string(emu, allocator, base_ptr, offset, length);
if (!address)
@@ -86,17 +82,16 @@ namespace
const auto ns_entries_obj = allocator.reserve<API_SET_NAMESPACE_ENTRY>(orig_api_set_map.Count);
const auto hash_entries_obj = allocator.reserve<API_SET_HASH_ENTRY>(orig_api_set_map.Count);
api_set_map_obj.access([&](API_SET_NAMESPACE& api_set)
{
api_set_map_obj.access([&](API_SET_NAMESPACE& api_set) {
api_set = orig_api_set_map;
api_set.EntryOffset = static_cast<ULONG>(ns_entries_obj.value() - api_set_map_obj.value());
api_set.HashOffset = static_cast<ULONG>(hash_entries_obj.value() - api_set_map_obj.value());
});
const auto orig_ns_entries = offset_pointer<API_SET_NAMESPACE_ENTRY>(&orig_api_set_map,
orig_api_set_map.EntryOffset);
const auto orig_hash_entries = offset_pointer<API_SET_HASH_ENTRY>(&orig_api_set_map,
orig_api_set_map.HashOffset);
const auto orig_ns_entries =
offset_pointer<API_SET_NAMESPACE_ENTRY>(&orig_api_set_map, orig_api_set_map.EntryOffset);
const auto orig_hash_entries =
offset_pointer<API_SET_HASH_ENTRY>(&orig_api_set_map, orig_api_set_map.HashOffset);
for (ULONG i = 0; i < orig_api_set_map.Count; ++i)
{
@@ -112,8 +107,7 @@ namespace
}
const auto values_obj = allocator.reserve<API_SET_VALUE_ENTRY>(ns_entry.ValueCount);
const auto orig_values = offset_pointer<API_SET_VALUE_ENTRY>(&orig_api_set_map,
ns_entry.ValueOffset);
const auto orig_values = offset_pointer<API_SET_VALUE_ENTRY>(&orig_api_set_map, ns_entry.ValueOffset);
ns_entry.ValueOffset = static_cast<ULONG>(values_obj.value() - api_set_map_obj.value());
@@ -127,8 +121,7 @@ namespace
if (value.NameLength)
{
value.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(),
&orig_api_set_map,
value.NameOffset, value.NameLength);
&orig_api_set_map, value.NameOffset, value.NameLength);
}
values_obj.write(value, j);
@@ -211,8 +204,7 @@ namespace
context.process_params = allocator.reserve<RTL_USER_PROCESS_PARAMETERS64>();
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS64& proc_params)
{
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS64& proc_params) {
proc_params.Flags = 0x6001; //| 0x80000000; // Prevent CsrClientConnectToServer
proc_params.ConsoleHandle = CONSOLE_HANDLE.h;
@@ -251,13 +243,12 @@ namespace
const auto total_length = allocator.get_next_address() - context.process_params.value();
proc_params.Length = static_cast<uint32_t>(std::max(static_cast<uint64_t>(sizeof(proc_params)),
total_length));
proc_params.Length =
static_cast<uint32_t>(std::max(static_cast<uint64_t>(sizeof(proc_params)), total_length));
proc_params.MaximumLength = proc_params.Length;
});
context.peb.access([&](PEB64& peb)
{
context.peb.access([&](PEB64& peb) {
peb.ImageBaseAddress = nullptr;
peb.ProcessParameters = context.process_params.ptr();
peb.ApiSetMap = build_api_set_map(emu, allocator).ptr();
@@ -277,12 +268,11 @@ namespace
});
}
using exception_record_map = std::unordered_map<
const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*, emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<
Emu64>>>>;
using exception_record_map = std::unordered_map<const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*,
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>>>;
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(emulator_allocator& allocator,
const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record,
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(
emulator_allocator& allocator, const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record,
exception_record_map& record_mapping)
{
const auto record_obj = allocator.reserve<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>>();
@@ -307,8 +297,7 @@ namespace
record_mapping);
}
record_obj.access([&](EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& r)
{
record_obj.access([&](EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& r) {
r.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(nested_record_obj.ptr());
});
}
@@ -316,8 +305,8 @@ namespace
return record_obj;
}
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(emulator_allocator& allocator,
const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record)
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(
emulator_allocator& allocator, const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record)
{
exception_record_map record_mapping{};
return save_exception_record(allocator, record, record_mapping);
@@ -405,8 +394,7 @@ namespace
}
const emulator_object<machine_frame> machine_frame_obj{emu, new_sp + combined_size};
machine_frame_obj.access([&](machine_frame& frame)
{
machine_frame_obj.access([&](machine_frame& frame) {
const auto& record = *reinterpret_cast<CONTEXT64*>(pointers.ContextRecord);
frame.rip = record.Rip;
frame.rsp = record.Rsp;
@@ -467,10 +455,7 @@ namespace
// Crappy mechanism to prevent mutation while iterating.
const auto was_blocked = devices.block_mutation(true);
const auto _ = utils::finally([&]
{
devices.block_mutation(was_blocked);
});
const auto _ = utils::finally([&] { devices.block_mutation(was_blocked); });
for (auto& device : devices)
{
@@ -504,7 +489,6 @@ namespace
context.active_thread = &thread;
thread.restore(emu);
thread.setup_if_necessary(emu, context);
@@ -568,8 +552,7 @@ namespace
default:
break;
case handle_types::event:
{
case handle_types::event: {
auto* e = c.events.get(h);
if (e)
{
@@ -579,8 +562,7 @@ namespace
break;
}
case handle_types::mutant:
{
case handle_types::mutant: {
auto* e = c.mutants.get(h);
if (e)
{
@@ -590,8 +572,7 @@ namespace
break;
}
case handle_types::thread:
{
case handle_types::thread: {
const auto* t = c.threads.get(h);
if (t)
{
@@ -606,16 +587,14 @@ namespace
}
}
emulator_thread::emulator_thread(x64_emulator& emu, const process_context& context,
const uint64_t start_address,
const uint64_t argument,
const uint64_t stack_size, const uint32_t id)
: emu_ptr(&emu)
, stack_size(page_align_up(std::max(stack_size, static_cast<uint64_t>(STACK_SIZE))))
, start_address(start_address)
, argument(argument)
, id(id)
, last_registers(context.default_register_set)
emulator_thread::emulator_thread(x64_emulator& emu, const process_context& context, const uint64_t start_address,
const uint64_t argument, const uint64_t stack_size, const uint32_t id)
: emu_ptr(&emu),
stack_size(page_align_up(std::max(stack_size, static_cast<uint64_t>(STACK_SIZE)))),
start_address(start_address),
argument(argument),
id(id),
last_registers(context.default_register_set)
{
this->stack_base = emu.allocate_memory(this->stack_size, memory_permission::read_write);
@@ -627,8 +606,7 @@ emulator_thread::emulator_thread(x64_emulator& emu, const process_context& conte
this->teb = this->gs_segment->reserve<TEB64>();
this->teb->access([&](TEB64& teb_obj)
{
this->teb->access([&](TEB64& teb_obj) {
teb_obj.ClientId.UniqueProcess = 1ul;
teb_obj.ClientId.UniqueThread = static_cast<uint64_t>(this->id);
teb_obj.NtTib.StackLimit = reinterpret_cast<std::uint64_t*>(this->stack_base);
@@ -752,8 +730,7 @@ std::unique_ptr<x64_emulator> create_default_x64_emulator()
return unicorn::create_x64_emulator();
}
windows_emulator::windows_emulator(emulator_settings settings,
std::unique_ptr<x64_emulator> emu)
windows_emulator::windows_emulator(emulator_settings settings, std::unique_ptr<x64_emulator> emu)
: windows_emulator(std::move(emu))
{
this->silent_until_main_ = settings.silent_until_main && !settings.disable_logging;
@@ -764,8 +741,8 @@ windows_emulator::windows_emulator(emulator_settings settings,
}
windows_emulator::windows_emulator(std::unique_ptr<x64_emulator> emu)
: emu_(std::move(emu))
, process_(*emu_)
: emu_(std::move(emu)),
process_(*emu_)
{
this->setup_hooks();
}
@@ -781,10 +758,8 @@ void windows_emulator::setup_process(const emulator_settings& settings)
context.executable = context.mod_manager.map_module(settings.application, this->log);
context.peb.access([&](PEB64& peb)
{
peb.ImageBaseAddress = reinterpret_cast<std::uint64_t*>(context.executable->image_base);
});
context.peb.access(
[&](PEB64& peb) { peb.ImageBaseAddress = reinterpret_cast<std::uint64_t*>(context.executable->image_base); });
context.ntdll = context.mod_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->log);
context.win32u = context.mod_manager.map_module(R"(C:\Windows\System32\win32u.dll)", this->log);
@@ -858,16 +833,13 @@ void windows_emulator::on_instruction_execution(uint64_t address)
if (export_entry != binary->address_names.end())
{
log.print(is_interesting_call ? color::yellow : color::dark_gray,
"Executing function: %s - %s (0x%" PRIx64 ")\n",
binary->name.c_str(),
"Executing function: %s - %s (0x%" PRIx64 ")\n", binary->name.c_str(),
export_entry->second.c_str(), address);
}
else if (address == binary->entry_point)
{
log.print(is_interesting_call ? color::yellow : color::gray,
"Executing entry point: %s (0x%" PRIx64 ")\n",
binary->name.c_str(),
address);
log.print(is_interesting_call ? color::yellow : color::gray, "Executing entry point: %s (0x%" PRIx64 ")\n",
binary->name.c_str(), address);
}
}
@@ -878,22 +850,16 @@ void windows_emulator::on_instruction_execution(uint64_t address)
auto& emu = this->emu();
printf(
"Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64
printf("Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64
" - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n",
address,
emu.reg(x64_register::rax), emu.reg(x64_register::rbx),
emu.reg(x64_register::rcx),
emu.reg(x64_register::rdx), emu.reg(x64_register::r8),
emu.reg(x64_register::r9),
emu.reg(x64_register::rdi), emu.reg(x64_register::rsi),
binary ? binary->name.c_str() : "<N/A>");
address, emu.reg(x64_register::rax), emu.reg(x64_register::rbx), emu.reg(x64_register::rcx),
emu.reg(x64_register::rdx), emu.reg(x64_register::r8), emu.reg(x64_register::r9), emu.reg(x64_register::rdi),
emu.reg(x64_register::rsi), binary ? binary->name.c_str() : "<N/A>");
}
void windows_emulator::setup_hooks()
{
this->emu().hook_instruction(x64_hookable_instructions::syscall, [&]
{
this->emu().hook_instruction(x64_hookable_instructions::syscall, [&] {
for (const auto& hook : this->syscall_hooks_)
{
if (hook() == instruction_hook_continuation::skip_instruction)
@@ -906,16 +872,14 @@ void windows_emulator::setup_hooks()
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&]
{
this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&] {
const auto instructions = this->process().executed_instructions;
this->emu().reg(x64_register::rax, instructions & 0xFFFFFFFF);
this->emu().reg(x64_register::rdx, (instructions >> 32) & 0xFFFFFFFF);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::invalid, [&]
{
this->emu().hook_instruction(x64_hookable_instructions::invalid, [&] {
const auto ip = this->emu().read_instruction_pointer();
this->log.print(color::gray, "Invalid instruction at: 0x%" PRIx64 "\n", ip);
@@ -923,8 +887,7 @@ void windows_emulator::setup_hooks()
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_interrupt([&](const int interrupt)
{
this->emu().hook_interrupt([&](const int interrupt) {
if (interrupt == 6)
{
dispatch_illegal_instruction_violation(this->emu(), this->process().ki_user_exception_dispatcher);
@@ -942,8 +905,7 @@ void windows_emulator::setup_hooks()
});
this->emu().hook_memory_violation([&](const uint64_t address, const size_t size, const memory_operation operation,
const memory_violation_type type)
{
const memory_violation_type type) {
const auto permission = get_permission_string(operation);
const auto ip = this->emu().read_instruction_pointer();
const char* name = this->process().mod_manager.find_name(ip);
@@ -951,16 +913,12 @@ void windows_emulator::setup_hooks()
if (type == memory_violation_type::protection)
{
this->log.print(color::gray, "Protection violation: 0x%" PRIx64 " (%zX) - %s at 0x%" PRIx64 " (%s)\n",
address, size,
permission.c_str(), ip,
name);
address, size, permission.c_str(), ip, name);
}
else if (type == memory_violation_type::unmapped)
{
this->log.print(color::gray, "Mapping violation: 0x%" PRIx64 " (%zX) - %s at 0x%" PRIx64 " (%s)\n", address,
size,
permission.c_str(), ip,
name);
size, permission.c_str(), ip, name);
}
if (this->fuzzing)
@@ -976,10 +934,7 @@ void windows_emulator::setup_hooks()
this->emu().hook_memory_execution(
0, std::numeric_limits<size_t>::max(),
[&](const uint64_t address, const size_t, const uint64_t)
{
this->on_instruction_execution(address);
});
[&](const uint64_t address, const size_t, const uint64_t) { this->on_instruction_execution(address); });
}
void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count)
@@ -1043,15 +998,9 @@ void windows_emulator::serialize(utils::buffer_serializer& buffer) const
void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
{
buffer.register_factory<x64_emulator_wrapper>([this]
{
return x64_emulator_wrapper{this->emu()};
});
buffer.register_factory<x64_emulator_wrapper>([this] { return x64_emulator_wrapper{this->emu()}; });
buffer.register_factory<windows_emulator_wrapper>([this]
{
return windows_emulator_wrapper{*this};
});
buffer.register_factory<windows_emulator_wrapper>([this] { return windows_emulator_wrapper{*this}; });
buffer.read(this->use_relative_time_);
@@ -1070,7 +1019,7 @@ void windows_emulator::save_snapshot()
this->process_snapshot_ = serializer.move_buffer();
// TODO: Make process copyable
//this->process_snapshot_ = this->process();
// this->process_snapshot_ = this->process();
}
void windows_emulator::restore_snapshot()
@@ -1085,5 +1034,5 @@ void windows_emulator::restore_snapshot()
utils::buffer_deserializer deserializer{this->process_snapshot_};
this->process_.deserialize(deserializer);
//this->process_ = *this->process_snapshot_;
// this->process_ = *this->process_snapshot_;
}

View File

@@ -24,10 +24,9 @@ struct emulator_settings
class windows_emulator
{
public:
public:
windows_emulator(std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(emulator_settings settings,
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(emulator_settings settings, std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(windows_emulator&&) = delete;
windows_emulator(const windows_emulator&) = delete;
@@ -112,7 +111,7 @@ public:
return this->use_relative_time_;
}
private:
private:
bool use_relative_time_{false};
bool silent_until_main_{false};
std::unique_ptr<x64_emulator> emu_{};
@@ -123,7 +122,7 @@ private:
syscall_dispatcher dispatcher_;
std::vector<std::byte> process_snapshot_{};
//std::optional<process_context> process_snapshot_{};
// std::optional<process_context> process_snapshot_{};
void setup_hooks();
void setup_process(const emulator_settings& settings);