diff --git a/example/dllmain.cpp b/example/dllmain.cpp
index fd1a3cc..d27ee11 100644
--- a/example/dllmain.cpp
+++ b/example/dllmain.cpp
@@ -3,5 +3,7 @@
void main(pimage_data this_image)
{
MessageBoxA(NULL, "Hello World!", "INFO", NULL);
+
+ // only use this inside of main...
ZERO_DLL(this_image->image_base, this_image->image_size);
}
\ No newline at end of file
diff --git a/injector/injector.vcxproj b/injector/injector.vcxproj
new file mode 100644
index 0000000..8c71839
--- /dev/null
+++ b/injector/injector.vcxproj
@@ -0,0 +1,151 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {50e65491-59af-43f8-a045-e66ae0676298}
+ injector
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp17
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/injector/injector.vcxproj.filters b/injector/injector.vcxproj.filters
new file mode 100644
index 0000000..707cf08
--- /dev/null
+++ b/injector/injector.vcxproj.filters
@@ -0,0 +1,23 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/injector/injector.vcxproj.user b/injector/injector.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/injector/injector.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/injector/main.cpp b/injector/main.cpp
new file mode 100644
index 0000000..54f1627
--- /dev/null
+++ b/injector/main.cpp
@@ -0,0 +1,12 @@
+#include
+#include "nozzle.hpp"
+
+int main()
+{
+ nozzle::injector injector("example.dll", nozzle::util::get_pid(L"notepad.exe"));
+ const auto module_base = injector.inject();
+ const auto thread_handle = injector.call_entry();
+
+ std::printf("[+] module base => 0x%p, thread handle => 0x%x\n", module_base, thread_handle);
+ std::getchar();
+}
\ No newline at end of file
diff --git a/nozzle.hpp b/injector/nozzle.hpp
similarity index 70%
rename from nozzle.hpp
rename to injector/nozzle.hpp
index 37bddbd..0f5c688 100644
--- a/nozzle.hpp
+++ b/injector/nozzle.hpp
@@ -34,117 +34,109 @@
#include
#include
#include
-
#pragma comment(lib, "Dbghelp.lib")
-#define FIND_NT_HEADER(x) reinterpret_cast( uint64_t(x) + reinterpret_cast(x)->e_lfanew )
-#define RET_CHK(x)\
-if (!x)\
-{\
-LOG_LAST_ERROR();\
-return false;\
-}\
-
-//
-// coded by paracord.
-// see: https://github.com/haram/splendid_implanter/blob/master/splendid_implanter/win_utils.hpp
-//
-namespace util
+
+namespace nozzle
{
- using uq_handle = std::unique_ptr;
- inline void open_binary_file(const std::string& file, std::vector& data)
+ //
+ // coded by paracord.
+ // see: https://github.com/haram/splendid_implanter/blob/master/splendid_implanter/win_utils.hpp
+ //
+ namespace util
{
- std::ifstream fstr(file, std::ios::binary);
- fstr.unsetf(std::ios::skipws);
- fstr.seekg(0, std::ios::end);
-
- const auto file_size = fstr.tellg();
+ using uq_handle = std::unique_ptr;
+ inline void open_binary_file(const std::string& file, std::vector& data)
+ {
+ std::ifstream fstr(file, std::ios::binary);
+ fstr.unsetf(std::ios::skipws);
+ fstr.seekg(0, std::ios::end);
- fstr.seekg(NULL, std::ios::beg);
- data.reserve(static_cast(file_size));
- data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator());
- }
+ const auto file_size = fstr.tellg();
- inline uint32_t get_process_id(const std::wstring_view process_name)
- {
- // open a system snapshot of all loaded processes
- uq_handle snap_shot{ CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0), &CloseHandle };
-
- if (snap_shot.get() == INVALID_HANDLE_VALUE)
- return NULL;
+ fstr.seekg(NULL, std::ios::beg);
+ data.reserve(static_cast(file_size));
+ data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator());
+ }
- PROCESSENTRY32W process_entry{ sizeof(PROCESSENTRY32W) };
+ inline uint32_t get_pid(const std::wstring_view process_name)
+ {
+ // open a system snapshot of all loaded processes
+ uq_handle snap_shot{ CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0), &CloseHandle };
- // enumerate through processes
- for (Process32FirstW(snap_shot.get(), &process_entry); Process32NextW(snap_shot.get(), &process_entry); )
- if (std::wcscmp(process_name.data(), process_entry.szExeFile) == NULL)
- return process_entry.th32ProcessID;
+ if (snap_shot.get() == INVALID_HANDLE_VALUE)
+ return NULL;
- return NULL;
- }
+ PROCESSENTRY32W process_entry{ sizeof(PROCESSENTRY32W) };
- inline std::pair get_module_data(HANDLE process_handle, const std::wstring_view module_name)
- {
- auto loaded_modules = std::make_unique(64);
- DWORD loaded_module_sz = 0;
+ // enumerate through processes
+ for (Process32FirstW(snap_shot.get(), &process_entry); Process32NextW(snap_shot.get(), &process_entry); )
+ if (std::wcscmp(process_name.data(), process_entry.szExeFile) == NULL)
+ return process_entry.th32ProcessID;
- // enumerate all modules by handle, using size of 512 since the required size is in bytes, and an HMODULE is 8 bytes large.
- if (!EnumProcessModules(process_handle, loaded_modules.get(), 512, &loaded_module_sz))
- return {};
+ return NULL;
+ }
- for (auto i = 0u; i < loaded_module_sz / 8u; i++)
+ inline std::pair get_module_data(HANDLE process_handle, const std::wstring_view module_name)
{
- wchar_t file_name[MAX_PATH] = L"";
+ auto loaded_modules = std::make_unique(64);
+ DWORD loaded_module_sz = 0;
- // get the full working path for the current module
- if (!GetModuleFileNameExW(process_handle, loaded_modules.get()[i], file_name, _countof(file_name)))
- continue;
+ // enumerate all modules by handle, using size of 512 since the required size is in bytes, and an HMODULE is 8 bytes large.
+ if (!EnumProcessModules(process_handle, loaded_modules.get(), 512, &loaded_module_sz))
+ return {};
- // module name returned will be a full path, check only for file name sub string.
- if (std::wcsstr(file_name, module_name.data()) != nullptr)
- return { loaded_modules.get()[i], file_name };
- }
+ for (auto i = 0u; i < loaded_module_sz / 8u; i++)
+ {
+ wchar_t file_name[MAX_PATH] = L"";
- return {};
- }
+ // get the full working path for the current module
+ if (!GetModuleFileNameExW(process_handle, loaded_modules.get()[i], file_name, _countof(file_name)))
+ continue;
- inline std::vector get_file_data(const HANDLE file_handle, const std::wstring_view file_path)
- {
- const auto file_size = std::filesystem::file_size(file_path);
- std::vector file_bytes{};
- file_bytes.resize(file_size);
+ // module name returned will be a full path, check only for file name sub string.
+ if (std::wcsstr(file_name, module_name.data()) != nullptr)
+ return { loaded_modules.get()[i], file_name };
+ }
- DWORD bytes_read = 0;
- if (!ReadFile(file_handle, file_bytes.data(), static_cast(file_size), &bytes_read, nullptr))
return {};
+ }
- return file_bytes;
- }
+ inline std::vector get_file_data(const HANDLE file_handle, const std::wstring_view file_path)
+ {
+ const auto file_size = std::filesystem::file_size(file_path);
+ std::vector file_bytes{};
+ file_bytes.resize(file_size);
- inline bool enable_privilege(const std::wstring_view privilege_name)
- {
- HANDLE token_handle = nullptr;
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
- return false;
+ DWORD bytes_read = 0;
+ if (!ReadFile(file_handle, file_bytes.data(), static_cast(file_size), &bytes_read, nullptr))
+ return {};
- LUID luid{};
- if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid))
- return false;
+ return file_bytes;
+ }
+
+ inline bool enable_privilege(const std::wstring_view privilege_name)
+ {
+ HANDLE token_handle = nullptr;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
+ return false;
- TOKEN_PRIVILEGES token_state{};
- token_state.PrivilegeCount = 1;
- token_state.Privileges[0].Luid = luid;
- token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ LUID luid{};
+ if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid))
+ return false;
- if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
- return false;
+ TOKEN_PRIVILEGES token_state{};
+ token_state.PrivilegeCount = 1;
+ token_state.Privileges[0].Luid = luid;
+ token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- CloseHandle(token_handle);
- return true;
+ if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
+ return false;
+
+ CloseHandle(token_handle);
+ return true;
+ }
}
-}
-namespace nozzle
-{
//
// class programmed by wlan
// link: https://github.com/not-wlan/drvmap/blob/master/drvmap/drv_image.hpp
@@ -223,47 +215,43 @@ namespace nozzle
bool pe_image::process_relocation(uintptr_t image_base_delta, uint16_t data, uint8_t* relocation_base)
{
#define IMR_RELOFFSET(x) (x & 0xFFF)
-
switch (data >> 12 & 0xF)
{
- case IMAGE_REL_BASED_HIGH:
- {
- const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
- *raw_address += static_cast(HIWORD(image_base_delta));
- break;
- }
- case IMAGE_REL_BASED_LOW:
- {
- const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
- *raw_address += static_cast(LOWORD(image_base_delta));
- break;
- }
- case IMAGE_REL_BASED_HIGHLOW:
- {
- const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
- *raw_address += static_cast(image_base_delta);
- break;
- }
- case IMAGE_REL_BASED_DIR64:
- {
- auto UNALIGNED raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
- *raw_address += image_base_delta;
- break;
- }
- case IMAGE_REL_BASED_ABSOLUTE: // No action required
- case IMAGE_REL_BASED_HIGHADJ: // no action required
- {
- break;
- }
- default:
- {
- throw std::runtime_error("gay relocation!");
- return false;
- }
-
+ case IMAGE_REL_BASED_HIGH:
+ {
+ const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
+ *raw_address += static_cast(HIWORD(image_base_delta));
+ break;
+ }
+ case IMAGE_REL_BASED_LOW:
+ {
+ const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
+ *raw_address += static_cast(LOWORD(image_base_delta));
+ break;
+ }
+ case IMAGE_REL_BASED_HIGHLOW:
+ {
+ const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
+ *raw_address += static_cast(image_base_delta);
+ break;
+ }
+ case IMAGE_REL_BASED_DIR64:
+ {
+ auto UNALIGNED raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data));
+ *raw_address += image_base_delta;
+ break;
+ }
+ case IMAGE_REL_BASED_ABSOLUTE: // No action required
+ case IMAGE_REL_BASED_HIGHADJ: // no action required
+ {
+ break;
+ }
+ default:
+ {
+ return false;
+ }
}
#undef IMR_RELOFFSET
-
return true;
}
@@ -345,11 +333,9 @@ namespace nozzle
class injector
{
public:
- injector()
- {};
injector(void* pe_image, std::size_t size, unsigned pid);
injector(std::vector image_buffer, unsigned pid);
- injector(char* path, unsigned pid);
+ injector(const char* path, unsigned pid);
void* inject();
HANDLE call_entry();
@@ -394,7 +380,7 @@ namespace nozzle
target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
{}
- injector::injector(char* path, unsigned pid)
+ injector::injector(const char* path, unsigned pid)
:
target_pid(pid),
target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
@@ -420,13 +406,6 @@ namespace nozzle
//
static const auto _get_module = [](std::string_view module_name) -> std::uintptr_t
{
- assert(
- !stricmp(module_name, "kernel32.dll") ||
- !stricmp(module_name, "user32.dll") ||
- !stricmp(module_name, "ntdll.dll"),
- "import from dll %s is invalid, only globally mapped dlls can be resolved!",
- module_name
- );
return reinterpret_cast(LoadLibraryA(module_name.data()));
};
@@ -504,7 +483,7 @@ namespace nozzle
void injector::set_target(std::wstring proc_name)
{
- target_pid = util::get_process_id(proc_name);
+ target_pid = util::get_pid(proc_name);
}
void* injector::get_pe_image() const