diff --git a/badeye/badeye.sln b/badeye/badeye.sln
new file mode 100644
index 0000000..ef004d0
--- /dev/null
+++ b/badeye/badeye.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30406.217
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "badeye", "badeye\badeye.vcxproj", "{FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inside", "inside\inside.vcxproj", "{F449B39D-4975-4478-B873-2747CC3DD7EF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Debug|x64.ActiveCfg = Debug|x64
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Debug|x64.Build.0 = Debug|x64
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Debug|x86.ActiveCfg = Debug|Win32
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Debug|x86.Build.0 = Debug|Win32
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Release|x64.ActiveCfg = Release|x64
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Release|x64.Build.0 = Release|x64
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Release|x86.ActiveCfg = Release|Win32
+ {FAADD55D-E2C8-4E6D-BE7E-6D8B5209F4F0}.Release|x86.Build.0 = Release|Win32
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Debug|x64.ActiveCfg = Debug|x64
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Debug|x64.Build.0 = Debug|x64
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Debug|x86.ActiveCfg = Debug|Win32
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Debug|x86.Build.0 = Debug|Win32
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Release|x64.ActiveCfg = Release|x64
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Release|x64.Build.0 = Release|x64
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Release|x86.ActiveCfg = Release|Win32
+ {F449B39D-4975-4478-B873-2747CC3DD7EF}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {140A6DB5-034F-43AF-9D44-4D6FEBDFADD1}
+ EndGlobalSection
+EndGlobal
diff --git a/badeye/badeye/badeye.vcxproj b/badeye/badeye/badeye.vcxproj
new file mode 100644
index 0000000..1ef8ad8
--- /dev/null
+++ b/badeye/badeye/badeye.vcxproj
@@ -0,0 +1,154 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {faadd55d-e2c8-4e6d-be7e-6d8b5209f4f0}
+ badeye
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+ ntdll.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/badeye/badeye/badeye.vcxproj.filters b/badeye/badeye/badeye.vcxproj.filters
new file mode 100644
index 0000000..02a3f13
--- /dev/null
+++ b/badeye/badeye/badeye.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
+
+
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/badeye/badeye/badeye.vcxproj.user b/badeye/badeye/badeye.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/badeye/badeye/badeye.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/badeye/badeye/main.cpp b/badeye/badeye/main.cpp
new file mode 100644
index 0000000..bb83b4f
--- /dev/null
+++ b/badeye/badeye/main.cpp
@@ -0,0 +1,20 @@
+#include "nozzle.hpp"
+
+int main(const int argc, const char** argv)
+{
+ if (argc < 2)
+ {
+ std::perror("[-] please provide a dll path...");
+ return -1;
+ }
+
+ const auto lsass_pid = util::get_process_id(L"lsass.exe");
+ std::printf("[+] lsass_pid => %p\n", lsass_pid);
+
+ nozzle::injector inject(argv[1], lsass_pid);
+ const auto module_base = inject.inject();
+ inject.hook_entry();
+
+ std::printf("[+] module base => %p\n", module_base);
+ std::getchar();
+}
\ No newline at end of file
diff --git a/badeye/badeye/nozzle.hpp b/badeye/badeye/nozzle.hpp
new file mode 100644
index 0000000..74facec
--- /dev/null
+++ b/badeye/badeye/nozzle.hpp
@@ -0,0 +1,511 @@
+/*
+ MIT License
+
+ Copyright (c) 2020 xerox
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#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
+{
+ 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);
+
+ const auto file_size = fstr.tellg();
+
+ fstr.seekg(NULL, std::ios::beg);
+ data.reserve(static_cast(file_size));
+ data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator());
+ }
+
+ 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;
+
+ PROCESSENTRY32W process_entry{ sizeof(PROCESSENTRY32W) };
+
+ // 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;
+
+ return NULL;
+ }
+
+ 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 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 {};
+
+ for (auto i = 0u; i < loaded_module_sz / 8u; i++)
+ {
+ wchar_t file_name[MAX_PATH] = L"";
+
+ // get the full working path for the current module
+ if (!GetModuleFileNameExW(process_handle, loaded_modules.get()[i], file_name, _countof(file_name)))
+ continue;
+
+ // 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 };
+ }
+
+ return {};
+ }
+
+ 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);
+
+ DWORD bytes_read = 0;
+ if (!ReadFile(file_handle, file_bytes.data(), static_cast(file_size), &bytes_read, nullptr))
+ return {};
+
+ 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;
+
+ LUID luid{};
+ if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid))
+ return false;
+
+ TOKEN_PRIVILEGES token_state{};
+ token_state.PrivilegeCount = 1;
+ token_state.Privileges[0].Luid = luid;
+ token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ 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
+ //
+ class pe_image
+ {
+ std::vector m_image;
+ std::vector m_image_mapped;
+ PIMAGE_DOS_HEADER m_dos_header = nullptr;
+ PIMAGE_NT_HEADERS64 m_nt_headers = nullptr;
+ PIMAGE_SECTION_HEADER m_section_header = nullptr;
+
+ public:
+ pe_image() {};
+ pe_image(std::uint8_t* image, std::size_t size);
+ pe_image(std::vector image);
+ size_t size() const;
+ uintptr_t entry_point() const;
+ void map();
+ static bool process_relocation(size_t image_base_delta, uint16_t data, uint8_t* relocation_base);
+ void relocate(uintptr_t base) const;
+
+ template
+ __forceinline T* get_rva(const unsigned long offset)
+ {
+ return (T*)::ImageRvaToVa(m_nt_headers, m_image.data(), offset, nullptr);
+ }
+
+ void fix_imports(const std::function get_module, const std::function get_function);
+ void* data();
+ size_t header_size();
+ };
+
+ pe_image::pe_image(std::uint8_t* image, std::size_t size)
+ {
+ m_image = std::vector(image, image + size);
+ m_dos_header = reinterpret_cast(image);
+ m_nt_headers = reinterpret_cast((uintptr_t)m_dos_header + m_dos_header->e_lfanew);
+ m_section_header = reinterpret_cast((uintptr_t)(&m_nt_headers->OptionalHeader) + m_nt_headers->FileHeader.SizeOfOptionalHeader);
+ }
+
+ pe_image::pe_image(std::vector image)
+ : m_image(std::move(image))
+ {
+ m_dos_header = reinterpret_cast(m_image.data());
+ m_nt_headers = reinterpret_cast((uintptr_t)m_dos_header + m_dos_header->e_lfanew);
+ m_section_header = reinterpret_cast((uintptr_t)(&m_nt_headers->OptionalHeader) + m_nt_headers->FileHeader.SizeOfOptionalHeader);
+ }
+
+ size_t pe_image::size() const
+ {
+ return m_nt_headers->OptionalHeader.SizeOfImage;
+ }
+
+ uintptr_t pe_image::entry_point() const
+ {
+ return m_nt_headers->OptionalHeader.AddressOfEntryPoint;
+ }
+
+ void pe_image::map()
+ {
+
+ m_image_mapped.clear();
+ m_image_mapped.resize(m_nt_headers->OptionalHeader.SizeOfImage);
+ std::copy_n(m_image.begin(), m_nt_headers->OptionalHeader.SizeOfHeaders, m_image_mapped.begin());
+
+ for (size_t i = 0; i < m_nt_headers->FileHeader.NumberOfSections; ++i)
+ {
+ const auto& section = m_section_header[i];
+ const auto target = (uintptr_t)m_image_mapped.data() + section.VirtualAddress;
+ const auto source = (uintptr_t)m_dos_header + section.PointerToRawData;
+ std::copy_n(m_image.begin() + section.PointerToRawData, section.SizeOfRawData, m_image_mapped.begin() + section.VirtualAddress);
+ }
+ }
+
+ 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;
+ }
+
+ }
+#undef IMR_RELOFFSET
+
+ return true;
+ }
+
+ void pe_image::relocate(uintptr_t base) const
+ {
+ if (m_nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+ return;
+
+ ULONG total_count_bytes;
+ const auto nt_headers = ImageNtHeader((void*)m_image_mapped.data());
+ auto relocation_directory = (PIMAGE_BASE_RELOCATION)::ImageDirectoryEntryToData(nt_headers, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &total_count_bytes);
+ auto image_base_delta = static_cast(static_cast(base) - (nt_headers->OptionalHeader.ImageBase));
+ auto relocation_size = total_count_bytes;
+
+ void* relocation_end = reinterpret_cast(relocation_directory) + relocation_size;
+ while (relocation_directory < relocation_end)
+ {
+ auto relocation_base = ::ImageRvaToVa(nt_headers, (void*)m_image_mapped.data(), relocation_directory->VirtualAddress, nullptr);
+ auto num_relocs = (relocation_directory->SizeOfBlock - 8) >> 1;
+ auto relocation_data = reinterpret_cast(relocation_directory + 1);
+
+ for (unsigned long i = 0; i < num_relocs; ++i, ++relocation_data)
+ {
+ if (process_relocation(image_base_delta, *relocation_data, (uint8_t*)relocation_base) == FALSE)
+ return;
+ }
+ relocation_directory = reinterpret_cast(relocation_data);
+ }
+ }
+
+ template
+ __forceinline T* ptr_add(void* base, uintptr_t offset)
+ {
+ return (T*)(uintptr_t)base + offset;
+ }
+
+ void pe_image::fix_imports(const std::function get_module, const std::function get_function)
+ {
+
+ ULONG size;
+ auto import_descriptors = static_cast(::ImageDirectoryEntryToData(m_image.data(), FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size));
+
+ if (!import_descriptors)
+ return;
+
+ for (; import_descriptors->Name; import_descriptors++)
+ {
+ IMAGE_THUNK_DATA* image_thunk_data;
+ const auto module_name = get_rva(import_descriptors->Name);
+ const auto module_base = get_module(module_name);
+
+ if (import_descriptors->OriginalFirstThunk)
+ image_thunk_data = get_rva(import_descriptors->OriginalFirstThunk);
+ else
+ image_thunk_data = get_rva(import_descriptors->FirstThunk);
+
+ auto image_func_data = get_rva(import_descriptors->FirstThunk);
+ for (; image_thunk_data->u1.AddressOfData; image_thunk_data++, image_func_data++)
+ {
+ uintptr_t function_address;
+ const auto image_import_by_name = get_rva(*(DWORD*)image_thunk_data);
+ const auto name_of_import = static_cast(image_import_by_name->Name);
+ function_address = get_function(module_base, name_of_import);
+ image_func_data->u1.Function = function_address;
+ }
+ }
+ }
+
+ void* pe_image::data()
+ {
+ return m_image_mapped.data();
+ }
+
+ size_t pe_image::header_size()
+ {
+ return m_nt_headers->OptionalHeader.SizeOfHeaders;
+ }
+
+ class injector
+ {
+ public:
+ injector() {};
+ injector(void* pe_image, std::size_t size, unsigned pid);
+ injector(std::vector image_buffer, unsigned pid);
+ injector(const char* path, unsigned pid);
+
+ void* inject();
+ void hook_entry();
+ void set_target(unsigned pid);
+ void set_target(std::wstring proc_name);
+
+ void* get_pe_image() const;
+ void* get_allocated_base() const;
+ unsigned get_target() const;
+ private:
+ pe_image image;
+ unsigned target_pid;
+ std::vector image_buffer;
+ HANDLE target_handle;
+ void* alloc_base;
+
+ void write(void* addr, void* buffer, std::size_t size);
+ void read(void* addr, void* buffer, std::size_t size);
+
+ template
+ T read(void* addr)
+ {
+ if (!addr)
+ return {};
+ T buffer;
+ read(addr, &buffer, sizeof(T));
+ return buffer;
+ }
+
+ template
+ void write(void* addr, const T& data)
+ {
+ if (!addr)
+ return;
+ write(addr, (void*)&data, sizeof(T));
+ }
+ };
+
+ injector::injector(void* pe_image, std::size_t size, unsigned pid)
+ :
+ target_pid(pid),
+ target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
+ {}
+
+ injector::injector(const char* path, unsigned pid)
+ :
+ target_pid(pid)
+ {
+ std::vector image_buffer;
+ util::open_binary_file(path, image_buffer);
+ this->image_buffer = image_buffer;
+ std::printf("[+] enabled debug priv => %d\n", util::enable_privilege(L"SeDebugPrivilege"));
+ this->target_handle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+ std::printf("[+] target handle => %p\n", target_handle);
+ }
+
+ injector::injector(std::vector image_buffer, unsigned pid)
+ :
+ image_buffer(image_buffer),
+ target_pid(pid),
+ target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
+ {}
+
+ void* injector::inject()
+ {
+ image = pe_image(image_buffer);
+
+ //
+ // only resolves globally mapped dll imports.
+ //
+ static const auto _get_module = [](std::string_view module_name) -> std::uintptr_t
+ {
+ return reinterpret_cast(LoadLibraryA(module_name.data()));
+ };
+
+ //
+ // only resolves ntdll.dll, kernel32.dll, and user32.dll imports
+ //
+ static const auto _get_function = [](std::uintptr_t module_base, const char* module_name) -> std::uintptr_t
+ {
+ return reinterpret_cast(GetProcAddress(reinterpret_cast(module_base), module_name));
+ };
+
+ alloc_base = VirtualAllocEx(
+ target_handle,
+ NULL,
+ image.size(),
+ MEM_COMMIT | MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!alloc_base)
+ return NULL;
+
+ image.fix_imports(_get_module, _get_function);
+ image.map();
+ image.relocate(reinterpret_cast(alloc_base));
+ write(alloc_base, image.data(), image.size());
+ return alloc_base;
+ }
+
+ void injector::hook_entry()
+ {
+ // jmp [rip]
+ // 0xaddress of entry...
+ std::uint8_t jmp_rip[14] = { 0xff, 0x25, 0x0, 0x0, 0x0, 0x0 };
+ *reinterpret_cast(jmp_rip + 6) = reinterpret_cast(alloc_base) + image.entry_point();
+ static const auto rtl_alloc_heap = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtClose");
+ write(rtl_alloc_heap, jmp_rip, sizeof(jmp_rip));
+ }
+
+ void* injector::get_allocated_base() const
+ {
+ return alloc_base;
+ }
+
+ void injector::set_target(unsigned pid)
+ {
+ target_pid = pid;
+ }
+
+ void injector::set_target(std::wstring proc_name)
+ {
+ target_pid = util::get_process_id(proc_name);
+ }
+
+ void* injector::get_pe_image() const
+ {
+ return (void*)image_buffer.data();
+ }
+
+ unsigned injector::get_target() const
+ {
+ return target_pid;
+ }
+
+ void injector::write(void* addr, void* buffer, std::size_t size)
+ {
+ SIZE_T bytes_written;
+ ::WriteProcessMemory(
+ target_handle,
+ addr,
+ buffer,
+ size,
+ &bytes_written
+ );
+ }
+
+ void injector::read(void* addr, void* buffer, std::size_t size)
+ {
+ SIZE_T bytes_read;
+ ::ReadProcessMemory(
+ target_handle,
+ addr,
+ buffer,
+ size,
+ &bytes_read
+ );
+ }
+}
\ No newline at end of file
diff --git a/badeye/inside/dllmain.cpp b/badeye/inside/dllmain.cpp
new file mode 100644
index 0000000..90ae9b0
--- /dev/null
+++ b/badeye/inside/dllmain.cpp
@@ -0,0 +1,129 @@
+#include
+#include
+#include
+
+// would use std::pair but that requires #include