diff --git a/badeye/badeye/main.cpp b/badeye/badeye/main.cpp index bb83b4f..0f25458 100644 --- a/badeye/badeye/main.cpp +++ b/badeye/badeye/main.cpp @@ -1,3 +1,4 @@ +#include #include "nozzle.hpp" int main(const int argc, const char** argv) @@ -17,4 +18,5 @@ int main(const int argc, const char** argv) 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 index 74facec..3a0243e 100644 --- a/badeye/badeye/nozzle.hpp +++ b/badeye/badeye/nozzle.hpp @@ -50,6 +50,46 @@ return false;\ // namespace util { + inline void write(HANDLE target_handle, void* addr, void* buffer, std::size_t size) + { + SIZE_T bytes_written; + ::WriteProcessMemory( + target_handle, + addr, + buffer, + size, + &bytes_written + ); + } + + inline void read(HANDLE target_handle, void* addr, void* buffer, std::size_t size) + { + SIZE_T bytes_read; + ::ReadProcessMemory( + target_handle, + addr, + buffer, + size, + &bytes_read + ); + } + + template + inline T read(HANDLE target_handle, void* addr) + { + if (!addr) return {}; + T buffer; + read(target_handle, addr, static_cast(&buffer), sizeof(T)); + return buffer; + } + + template + inline void write(HANDLE target_handle, void* addr, const T& data) + { + if (!addr) return; + write(target_handle, addr, static_cast(&data), sizeof(T)); + } + using uq_handle = std::unique_ptr; inline void open_binary_file(const std::string& file, std::vector& data) { @@ -365,25 +405,20 @@ namespace nozzle 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 {}; + if (!addr) return {}; T buffer; - read(addr, &buffer, sizeof(T)); + read(target_handle, addr, static_cast(&buffer), sizeof(T)); return buffer; } template void write(void* addr, const T& data) { - if (!addr) - return; - write(addr, (void*)&data, sizeof(T)); + if (!addr) return; + write(target_handle, addr, static_cast(&data), sizeof(T)); } }; @@ -400,9 +435,8 @@ namespace nozzle 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")); + 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) @@ -446,7 +480,7 @@ namespace nozzle image.fix_imports(_get_module, _get_function); image.map(); image.relocate(reinterpret_cast(alloc_base)); - write(alloc_base, image.data(), image.size()); + util::write(this->target_handle, alloc_base, image.data(), image.size()); return alloc_base; } @@ -457,7 +491,7 @@ namespace nozzle 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)); + util::write(this->target_handle, rtl_alloc_heap, jmp_rip, sizeof(jmp_rip)); } void* injector::get_allocated_base() const @@ -484,28 +518,4 @@ namespace nozzle { 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/bedaisy.hpp b/badeye/inside/bedaisy.hpp new file mode 100644 index 0000000..149ab15 --- /dev/null +++ b/badeye/inside/bedaisy.hpp @@ -0,0 +1,129 @@ +#pragma once +#include +#include +#include + +// would use std::pair but that requires #include which causes unresolved externals... +using ioctl_data = struct { HANDLE drv_handle; void* return_addr; }; +#define READ_IOCTL 0x0222000 +#define WRITE_IOCTL 0x0222004 + +namespace bedaisy +{ + struct beioctl + { + void* ret_addr; + void* handle; + std::uintptr_t base_addr; + void* buffer; + size_t buffer_size; + size_t* bytes_read; + }; + + inline ioctl_data get_ioctl_data() + { + const auto wpm = + reinterpret_cast( + GetProcAddress(GetModuleHandleA("ntdll.dll"), + "NtWriteVirtualMemory")); + + // ensure inline jump is installed... + if (*reinterpret_cast(wpm) == 0xFF) + { + // + 6 into jump code is the address of where the jump goes to. + const auto shellcode_ptr = *reinterpret_cast(wpm + 6); + // + 50 into the shellcode is the HARDCODED file handle used for DeviceIoControl... + const auto ioctl_handle = *reinterpret_cast(shellcode_ptr + 0x50); + + // return address should be landing in this module + // (its not actually spoofing return address, just informational, used in ioctl data...) + const auto lsasrv = + reinterpret_cast( + GetModuleHandleA("lsasrv.dll")); + + // 0f 1f 44 00 ? 8b f0 48 8b 0d ? ? ? ? 49 3b cd (proper return) + return { ioctl_handle, reinterpret_cast(lsasrv + 0x36E3B) }; // windows 10 2004 RVA you will need to update for your winver! :) + } + return { {}, {} }; + } + + inline void read(HANDLE proc_handle, std::uintptr_t addr, void* buffer, std::size_t size) + { + if (!addr || !buffer || !size) + return; + + const auto [daisy_handle, return_addr] = get_ioctl_data(); + const beioctl ioctl_data + { + return_addr, + proc_handle, + addr, + buffer, + size, + nullptr + }; + + DWORD bytes_read; + DeviceIoControl + ( + daisy_handle, + READ_IOCTL, + (void*)&ioctl_data, + sizeof ioctl_data, + nullptr, + NULL, + &bytes_read, + nullptr + ); + } + + void write(HANDLE proc_handle, std::uintptr_t addr, void* buffer, std::size_t size) + { + if (!proc_handle || !addr) + return; + + const auto [daisy_handle, return_addr] = get_ioctl_data(); + const beioctl ioctl_data + { + return_addr, + proc_handle, + addr, + buffer, + size, + nullptr + }; + + DWORD bytes_read; + DeviceIoControl + ( + daisy_handle, + WRITE_IOCTL, + (void*)&ioctl_data, + sizeof ioctl_data, + nullptr, + NULL, + &bytes_read, + nullptr + ); + } + + template + inline T read(HANDLE proc_handle, std::uintptr_t addr) + { + if (!addr || !proc_handle) + return {}; + + T buffer{}; + read(proc_handle, addr, static_cast(&buffer), sizeof(T)); + return buffer; + } + + template + inline void write(HANDLE proc_handle, std::uintptr_t addr, const T& data) + { + if (!proc_handle || !addr) + return; + + write(proc_handle, addr, static_cast(&data), sizeof(T)); + } +} \ No newline at end of file diff --git a/badeye/inside/dllmain.cpp b/badeye/inside/dllmain.cpp index 417c0e9..a98fa63 100644 --- a/badeye/inside/dllmain.cpp +++ b/badeye/inside/dllmain.cpp @@ -1,128 +1,31 @@ -#include -#include -#include +#include "bedaisy.hpp" +#include "utils.hpp" -// would use std::pair but that requires #include which causes unresolved externals... -using ioctl_data = struct { HANDLE drv_handle; void* return_addr; }; -#define READ_IOCTL 0x0222000 -#define WRITE_IOCTL 0x0222004 - -namespace bedaisy +void read_demo() { - struct beioctl - { - void* ret_addr; - void* handle; - std::uintptr_t base_addr; - void* buffer; - size_t buffer_size; - size_t* bytes_read; - }; - - inline ioctl_data get_ioctl_data() - { - const auto wpm = - reinterpret_cast( - GetProcAddress(GetModuleHandleA("ntdll.dll"), - "NtWriteVirtualMemory")); - - // ensure inline jump is installed... - if (*reinterpret_cast(wpm) == 0xFF) - { - const auto shellcode_ptr = *reinterpret_cast(wpm + 6); - const auto ioctl_handle = *reinterpret_cast(shellcode_ptr + 0x50); - - const auto lsasrv = - reinterpret_cast( - GetModuleHandleA("lsasrv.dll")); - - // 0f 1f 44 00 ? 8b f0 48 8b 0d ? ? ? ? 49 3b cd (proper return) - return { ioctl_handle, reinterpret_cast(lsasrv + 0x36E3B) }; // windows 10 2004 RVA you will need to update for your winver! :) - } - return { {}, {} }; - } - - template - inline T read(HANDLE proc_handle, std::uintptr_t addr) - { - if (!addr || !proc_handle) - return {}; - - T buffer; - const auto [daisy_handle, return_addr] = get_ioctl_data(); - const beioctl ioctl_data - { - return_addr, - proc_handle, - addr, - &buffer, - sizeof(T), - nullptr - }; - - DWORD bytes_read; - DeviceIoControl - ( - daisy_handle, - READ_IOCTL, - (void*)&ioctl_data, - sizeof ioctl_data, - nullptr, - NULL, - &bytes_read, - nullptr + OutputDebugStringA("[lsass] main thread created!"); + const auto rust_handle = + OpenProcess( + PROCESS_QUERY_INFORMATION, FALSE, + utils::get_pid(L"RustClient.exe") ); - return buffer; - } - template - inline void write(HANDLE proc_handle, std::uintptr_t addr, const T& data) + if (rust_handle) { - if (!proc_handle || !addr) - return; - - const auto [daisy_handle, return_addr] = get_ioctl_data(); - const beioctl ioctl_data - { - return_addr, - proc_handle, - addr, - (void*)&data, - sizeof(T), - nullptr - }; - - DWORD bytes_read; - DeviceIoControl - ( - daisy_handle, - WRITE_IOCTL, - (void*)&ioctl_data, - sizeof ioctl_data, - nullptr, - NULL, - &bytes_read, - nullptr - ); + const auto game_base = utils::get_proc_base(rust_handle); + if (bedaisy::read(rust_handle, game_base) == 0x5A4D) + OutputDebugStringA("[lsass] read rust MZ!"); + else + OutputDebugStringA("[lsass] didnt read rust MZ!"); + + const auto asm_base = utils::get_module_base(rust_handle, L"GameAssembly.dll"); + if (bedaisy::read(rust_handle, asm_base) == 0x5A4D) + OutputDebugStringA("[lsass] read game assembly MZ!"); + else + OutputDebugStringA("[lsass] didnt game assembly MZ!"); } } -void read_demo() -{ - OutputDebugStringA("[lsass] main thread created!"); - - // pid 4 is system process.... - const auto system_process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, 4); - - // global mapped... gunna be the same addr in system proc.... - const auto ntdll = reinterpret_cast(GetModuleHandleA("ntdll.dll")); - - if(bedaisy::read(system_process, ntdll) == 0x5A4D) - OutputDebugStringA("[lsass] read MZ!"); - else - OutputDebugStringA("[lsass] didnt read MZ!"); -} - std::atomic init = false; extern "C" NTSTATUS nt_close(void* handle) { diff --git a/badeye/inside/inside.vcxproj b/badeye/inside/inside.vcxproj index 5e638ff..6b9a20c 100644 --- a/badeye/inside/inside.vcxproj +++ b/badeye/inside/inside.vcxproj @@ -137,7 +137,7 @@ Level3 true - true + false true NDEBUG;HELLOWORLD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true @@ -156,13 +156,17 @@ false nt_close false - %(AdditionalDependencies) - true + ntdll.lib;libvcruntime.lib;libucrt.lib;%(AdditionalDependencies) + false + + + + diff --git a/badeye/inside/inside.vcxproj.filters b/badeye/inside/inside.vcxproj.filters index c728d06..bdb77d8 100644 --- a/badeye/inside/inside.vcxproj.filters +++ b/badeye/inside/inside.vcxproj.filters @@ -5,10 +5,21 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + + {daf3b77a-fcd2-4fca-bcf0-7da17ed41da6} + Source Files + + + Header Files + + + Header Files + + \ No newline at end of file diff --git a/badeye/inside/utils.hpp b/badeye/inside/utils.hpp new file mode 100644 index 0000000..18499ce --- /dev/null +++ b/badeye/inside/utils.hpp @@ -0,0 +1,101 @@ +#pragma once +#include +#include +#include +#include +#include "bedaisy.hpp" + +char print_buffer[0x1000]; +namespace utils +{ + struct nt_peb + { + std::uintptr_t res[2]; + std::uintptr_t image_base; + std::uintptr_t ldr; + std::uintptr_t proc_params; + }; + + inline uint32_t get_pid(const std::wstring_view process_name) + { + const auto handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (handle == INVALID_HANDLE_VALUE) + return !CloseHandle(handle); + + PROCESSENTRY32W process_entry{ sizeof(PROCESSENTRY32W) }; + for (Process32FirstW(handle, &process_entry); Process32NextW(handle, &process_entry); ) + { + if (std::wcscmp(process_name.data(), process_entry.szExeFile) == NULL) + { + CloseHandle(handle); + return process_entry.th32ProcessID; + } + } + CloseHandle(handle); + return NULL; + } + + inline PPEB get_process_peb(const HANDLE process_handle) + { + PROCESS_BASIC_INFORMATION process_info{}; + ULONG bytes_returned; + if (NtQueryInformationProcess + ( + process_handle, + ProcessBasicInformation, + &process_info, + sizeof(process_info), + &bytes_returned + ) != ERROR_SUCCESS) + return nullptr; + return process_info.PebBaseAddress; + } + + // could do a snapshot but i have this code handy atm... + inline std::uintptr_t get_proc_base(const HANDLE proc_handle) + { + if (!proc_handle) return {}; + const auto ppeb = reinterpret_cast(get_process_peb(proc_handle)); + const auto peb = bedaisy::read(proc_handle, ppeb); + return peb.image_base; + } + + // could do a snapshot but i have this code handy atm... + inline std::uintptr_t get_module_base(const HANDLE proc_handle, const wchar_t* module_handle) + { + const auto ppeb = reinterpret_cast(get_process_peb(proc_handle)); + const auto peb = bedaisy::read(proc_handle, ppeb); + wchar_t full_file_name[MAX_PATH]; + std::uintptr_t module_base, file_name_ptr; + + const auto module_list_entry = + bedaisy::read(proc_handle, peb.ldr); + + const auto first_entry = + reinterpret_cast( + module_list_entry.InMemoryOrderModuleList.Flink); + + auto current_entry = bedaisy::read(proc_handle, first_entry); + while (current_entry != first_entry) + { + // read full module unicode_string structure. + file_name_ptr = bedaisy::read(proc_handle, current_entry + 0x40); + + // read full file path. + bedaisy::read + ( + proc_handle, + file_name_ptr, + full_file_name, + MAX_PATH + ); + + module_base = bedaisy::read(proc_handle, current_entry + 0x20); + if (std::wcsstr(full_file_name, module_handle)) + return module_base; + + current_entry = bedaisy::read(proc_handle, current_entry); + } + return NULL; + } +} \ No newline at end of file diff --git a/battleye.8.17.2020/BattlEye/BEDaisy.sys b/battleye.8.17.2020/BattlEye/BEDaisy.sys new file mode 100644 index 0000000..592f663 Binary files /dev/null and b/battleye.8.17.2020/BattlEye/BEDaisy.sys differ