I'm writing a C++ application to connect with my driver and try to read memory from there.
First, I tried to read from this address ac_client.exe+0x0018AC00
and offset 0xEC
. It works well, I can get the data.
But, if I change the address to 0x0018AC00,0x364,0x14,0x0
with 3 offsets, it does not work and I don't know why.
Here's my code that I try:
template <class T>T read_memory_with_driver(HANDLE driver_handle, const std::uintptr_t addr) { T temp = {}; Request r; r.target = reinterpret_cast<PVOID>(addr); r.buffer = &temp; r.size = sizeof(T); if (!DeviceIoControl(driver_handle, codes::read, &r, sizeof(r), &r, sizeof(r), nullptr, nullptr)) { std::cerr << "Failed to read memory at address: " << addr << " Error: " << GetLastError() << std::endl; } return temp;}int main() { const wchar_t* process_name = L"ac_client.exe"; const DWORD pid = get_process_id(process_name); if (pid == 0) { std::cout << "[+] Failed to find process.\n"; std::cin.get(); return 1; } const HANDLE driver = CreateFile(L"\\\\.\\KevinDriver", GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (driver == INVALID_HANDLE_VALUE) { std::cout << "Failed to create our driver handle.\n"; std::cin.get(); return 1; } if (driver::attach_to_process(driver, pid)) { std::cout << "Attachment successful.\n"; const std::uintptr_t client_base = get_module_base(pid, L"ac_client.exe"); if (client_base != 0) { std::cout << "Module Base Address: " << std::hex << client_base << "\n"; std::uintptr_t first_level_address = client_base + 0x0018AC00; std::uintptr_t first_level_pointer = driver::read_memory_with_driver<std::uintptr_t>(driver, (first_level_address)); std::cout << "First-level address: " << std::hex << first_level_address << " -> First-level pointer: " << std::hex << first_level_pointer << "\n"; if (first_level_pointer == 0) { std::cerr << "First-level pointer is null, terminating chain.\n"; CloseHandle(driver); std::cin.get(); return 1; } std::uintptr_t first_level_address2 = first_level_pointer + 0x364; std::uintptr_t first_level_pointer2 = driver::read_memory_with_driver<std::uintptr_t>(driver, (first_level_address2)); std::cout << "Second-level address: " << std::hex << first_level_address2 << " -> Second-level pointer: " << std::hex << first_level_pointer2 << "\n"; if (first_level_pointer2 == 0) { std::cerr << "Second-level pointer is null, terminating chain.\n"; CloseHandle(driver); std::cin.get(); return 1; } std::uintptr_t first_level_address3 = first_level_pointer2 + 0x14; std::uintptr_t first_level_pointer3 = driver::read_memory_with_driver<std::uintptr_t>(driver, (first_level_address3)); std::cout << "Third-level address: " << std::hex << first_level_address3 << " -> Third-level pointer: " << std::hex << first_level_pointer3 << "\n"; if (first_level_pointer3 == 0) { std::cerr << "Third-level pointer is null, terminating chain.\n"; CloseHandle(driver); std::cin.get(); return 1; } std::uintptr_t first_level_address4 = first_level_pointer3 + 0x0; std::uintptr_t first_level_pointer4 = driver::read_memory_with_driver<std::uintptr_t>(driver, (first_level_address4)); std::cout << "Fourth-level address: " << std::hex << first_level_address4 << " -> Fourth-level pointer: " << std::hex << first_level_pointer4 << "\n"; } else { std::cout << "Failed to find client base address.\n"; } } CloseHandle(driver); std::cin.get(); return 0;}
And in CE it looks like this:
I'm expecting to get the correct pointer and correct value with the same in CE.
And I tried using C# memory.dll
library, and it also works as well as expected.