Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 12141

Reading ntdll base address from the Loader Table yields an invalid address

$
0
0

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;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;            }            // THIS DOESNT PRINT, ACCESS VIOLATION IN THE PREVIOUS STEP            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");        }    }}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}

The code at:

println!("NT Headers: {:p}", nt_headers); doesn't print, the access violation occurs immediatley before this.


Viewing all articles
Browse latest Browse all 12141

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>