parent
e9ad4d7bd3
commit
7fb4f9484c
@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
|
||||
// would use std::pair but that requires #include <map> 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<std::uint8_t*>(
|
||||
GetProcAddress(GetModuleHandleA("ntdll.dll"),
|
||||
"NtWriteVirtualMemory"));
|
||||
|
||||
// ensure inline jump is installed...
|
||||
if (*reinterpret_cast<std::uint8_t*>(wpm) == 0xFF)
|
||||
{
|
||||
// + 6 into jump code is the address of where the jump goes to.
|
||||
const auto shellcode_ptr = *reinterpret_cast<std::uint8_t**>(wpm + 6);
|
||||
// + 50 into the shellcode is the HARDCODED file handle used for DeviceIoControl...
|
||||
const auto ioctl_handle = *reinterpret_cast<HANDLE*>(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<std::uintptr_t>(
|
||||
GetModuleHandleA("lsasrv.dll"));
|
||||
|
||||
// 0f 1f 44 00 ? 8b f0 48 8b 0d ? ? ? ? 49 3b cd (proper return)
|
||||
return { ioctl_handle, reinterpret_cast<void*>(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 <class T>
|
||||
inline T read(HANDLE proc_handle, std::uintptr_t addr)
|
||||
{
|
||||
if (!addr || !proc_handle)
|
||||
return {};
|
||||
|
||||
T buffer{};
|
||||
read(proc_handle, addr, static_cast<void*>(&buffer), sizeof(T));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void write(HANDLE proc_handle, std::uintptr_t addr, const T& data)
|
||||
{
|
||||
if (!proc_handle || !addr)
|
||||
return;
|
||||
|
||||
write(proc_handle, addr, static_cast<void*>(&data), sizeof(T));
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <winternl.h>
|
||||
#include <string>
|
||||
#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<std::uintptr_t>(get_process_peb(proc_handle));
|
||||
const auto peb = bedaisy::read<nt_peb>(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<std::uintptr_t>(get_process_peb(proc_handle));
|
||||
const auto peb = bedaisy::read<nt_peb>(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<PEB_LDR_DATA>(proc_handle, peb.ldr);
|
||||
|
||||
const auto first_entry =
|
||||
reinterpret_cast<std::uintptr_t>(
|
||||
module_list_entry.InMemoryOrderModuleList.Flink);
|
||||
|
||||
auto current_entry = bedaisy::read<std::uintptr_t>(proc_handle, first_entry);
|
||||
while (current_entry != first_entry)
|
||||
{
|
||||
// read full module unicode_string structure.
|
||||
file_name_ptr = bedaisy::read<ULONGLONG>(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<ULONGLONG>(proc_handle, current_entry + 0x20);
|
||||
if (std::wcsstr(full_file_name, module_handle))
|
||||
return module_base;
|
||||
|
||||
current_entry = bedaisy::read<std::uintptr_t>(proc_handle, current_entry);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in new issue