fix(inject): add debug flags to process

This commit is contained in:
es3n1n
2025-05-13 18:38:25 +09:00
parent 33202c4c8f
commit 73a3633b4e
2 changed files with 32 additions and 6 deletions

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include <format>
#include <stdexcept> #include <stdexcept>
#include <Windows.h> #include <Windows.h>
@@ -13,13 +14,22 @@ namespace native {
static_assert(offsetof(PEB, read_image_file_exec_options) == 1); static_assert(offsetof(PEB, read_image_file_exec_options) == 1);
inline PEB* get_peb() { template <typename Ty>
static auto function = reinterpret_cast<PEB* (*)()>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetCurrentPeb")); inline Ty get_system_routine(const std::string_view module_name, const std::string_view function_name) {
const auto mod = GetModuleHandleA(module_name.data());
if (function == nullptr) { if (mod == nullptr) {
throw std::runtime_error("no RtlGetCurrentPeb"); throw std::runtime_error(std::format("unable to find module {}", module_name));
} }
auto function = reinterpret_cast<Ty>(GetProcAddress(mod, function_name.data()));
if (function == nullptr) {
throw std::runtime_error(std::format("unable to obtain {} from {}", module_name, function_name));
}
return function;
}
inline PEB* get_peb() {
static auto function = get_system_routine<PEB*(__stdcall*)()>("ntdll.dll", "RtlGetCurrentPeb");
static auto result = function(); static auto result = function();
if (result == nullptr) [[unlikely]] { if (result == nullptr) [[unlikely]] {
throw std::runtime_error("no peb"); throw std::runtime_error("no peb");
@@ -27,5 +37,15 @@ namespace native {
return result; return result;
} }
inline bool debug_set_process_kill_on_exit(const bool value) {
static auto function = get_system_routine<BOOL(__stdcall*)(BOOL)>("kernel32.dll", "DebugSetProcessKillOnExit");
return static_cast<bool>(function(static_cast<BOOL>(value)));
}
inline bool debug_active_process_stop(const std::uint32_t process_id) {
static auto function = get_system_routine<BOOL(__stdcall*)(DWORD)>("kernel32.dll", "DebugActiveProcessStop");
return static_cast<bool>(function(process_id));
}
} // namespace native } // namespace native
#pragma pack(pop) #pragma pack(pop)

View File

@@ -21,14 +21,20 @@ namespace loader {
.bInheritHandle = TRUE, .bInheritHandle = TRUE,
}; };
/// By setting ReadImageFileExecOptions to FALSE and attaching ourselves as a debugger we can skip the IFEO
/// \xref: https://github.com/es3n1n/defendnot/issues/7#issuecomment-2874903650 /// \xref: https://github.com/es3n1n/defendnot/issues/7#issuecomment-2874903650
native::get_peb()->read_image_file_exec_options = 0; native::get_peb()->read_image_file_exec_options = 0;
std::println("** booting {}", proc_name); std::println("** booting {}", proc_name);
if (!CreateProcessA(nullptr, const_cast<char*>(proc_name.data()), &sa, &sa, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si, &pi)) { const auto process_flags = CREATE_SUSPENDED | DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
if (!CreateProcessA(nullptr, const_cast<char*>(proc_name.data()), &sa, &sa, FALSE, process_flags, nullptr, nullptr, &si, &pi)) {
throw std::runtime_error(std::format("unable to create process: {}", GetLastError())); throw std::runtime_error(std::format("unable to create process: {}", GetLastError()));
} }
/// Detach
native::debug_set_process_kill_on_exit(false);
native::debug_active_process_stop(pi.dwProcessId);
defer->void { defer->void {
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
/// Not closing hProcess because we return it /// Not closing hProcess because we return it