I am trying to parse the import address table of NTDLL, I have done this previously trying to iterate over each module, but I was getting a strange base address. I scrapped that approach and have done the below, but I get the exact same base address.
For NTDLL I am getting the base address 0x217000
from the field DllBase
on the LDR_DATA_TABLE_ENTRY
struct.
I have followed all the addresses (PEB
& PEB_LDR_DATA
) and they seem right in windbg. Accessing the base address of 0x217000
gives me a memory access violation.
The value I’m reading of 0x217000
is consistent on both my attempts, so I’m lead to believe I’m reading the correct value. I also understand the address here i’snt an RVA, but the actual VA of the base address. I have tried however treating it as an offset, but that also gave me a memory access violation.
use windows::Win32::Foundation::{HANDLE, NTSTATUS, UNICODE_STRING};
use windows::Win32::System::LibraryLoader::LoadLibraryA;
use windows::Win32::System::SystemServices::{IMAGE_IMPORT_DESCRIPTOR, IMAGE_NT_SIGNATURE};
use windows::Win32::System::Threading::{PEB, PROCESS_ALL_ACCESS};
use windows::Win32::System::Diagnostics::Debug::{SetUnhandledExceptionFilter, EXCEPTION_POINTERS, IMAGE_OPTIONAL_HEADER64};
use windows::Win32::System::WindowsProgramming::LDR_DATA_TABLE_ENTRY;
unsafe fn get_peb_ptr() -> *const PEB {
let peb: *const PEB;
asm!("mov {}, gs:[0x60]", out(reg) peb);
peb
}
unsafe fn find_ntdll(peb: *const PEB) -> Option<*const LDR_DATA_TABLE_ENTRY> {
let ldr = (*peb).Ldr;
if ldr.is_null() {
return None;
}
let mut module_list = (*ldr).InMemoryOrderModuleList.Flink;
while module_list != &(*ldr).InMemoryOrderModuleList as *const _ as *mut _ {
let entry = module_list as *const LDR_DATA_TABLE_ENTRY;
let dll_name = (*entry).FullDllName.Buffer;
if !dll_name.is_null() {
let name = std::slice::from_raw_parts(dll_name.0, (*entry).FullDllName.Length as usize / 2);
if name == "ntdll.dll".encode_utf16().collect::<Vec<u16>>() {
return Some(entry);
}
}
module_list = (*module_list).Flink;
}
None
}
fn read_iat() {
unsafe {
let peb = get_peb_ptr();
if peb.is_null() {
eprintln!("Failed to get PEB");
return;
}
if let Some(ntdll_entry) = find_ntdll(peb) {
let base_address = (*ntdll_entry).DllBase as *const u8;
if base_address.is_null() {
eprintln!("Invalid base address");
return;
}
println!("Base address: {:p}", base_address);
let nt_headers_offset = *(base_address.add(0x3C) as *const u32) as usize;
let nt_headers = base_address.add(nt_headers_offset) as *const IMAGE_OPTIONAL_HEADER64;
if nt_headers.is_null() {
eprintln!("Invalid NT headers");
return;
}
println!("NT Headers: {:p}", nt_headers);
let data_directory = &(*nt_headers).DataDirectory;
let import_directory = data_directory[1]; // IMAGE_DIRECTORY_ENTRY_IMPORT is 1
if import_directory.VirtualAddress == 0 {
eprintln!("No import directory");
return;
}
let import_table = base_address.add(import_directory.VirtualAddress as usize) as *const IMAGE_IMPORT_DESCRIPTOR;
if import_table.is_null() {
eprintln!("Invalid import table");
return;
}
let mut import_descriptor = import_table;
while (*import_descriptor).Name != 0 {
let dll_name = base_address.add((*import_descriptor).Name as usize) as *const i8;
println!("Importing: {}", CStr::from_ptr(dll_name).to_str().unwrap_or("Invalid UTF-8"));
let thunk_ref = base_address.add((*import_descriptor).Anonymous.OriginalFirstThunk as usize) as *const usize;
let iat_ref = base_address.add((*import_descriptor).FirstThunk as usize) as *const usize;
if thunk_ref.is_null() || iat_ref.is_null() {
eprintln!("Invalid thunk or IAT reference");
import_descriptor = import_descriptor.add(1);
continue;
}
let mut i = 0;
while *thunk_ref.add(i) != 0 {
let func_name_ptr = base_address.add(*thunk_ref.add(i) as usize + 2) as *const i8;
println!("Imported function: {}", CStr::from_ptr(func_name_ptr).to_str().unwrap_or("Invalid UTF-8"));
i += 1;
}
import_descriptor = import_descriptor.add(1);
}
} else {
eprintln!("NTDLL.dll not found");
}
}
}
letters_and_numbers is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.