CasualX / pelite

Lightweight, memory-safe, zero-allocation library for reading and navigating PE binaries.
MIT License
288 stars 42 forks source link

Add pelite::Wrap to the top level crate documentation #250

Open C0D3-M4513R opened 3 years ago

C0D3-M4513R commented 3 years ago

First of all: Thank you for your crate. I failed miserably, to read the export table of a dll. I was just not smart enough.

In using this crate, I stumbled across the traits, mentioned in the title. I have noticed, that the functions in the traits are almost identical.

So my question: Could this library just detect the bitness, of a dll/binary, and use the required functions as needed? For me parsing the DOS and NT -Headers was no problem, using the bindings of winapi. That worked on x64 and x86 dlls.

This is my current implementation, of reading all exports, of a dll. The branches cannot be merged, because the types differ. Due to what I am trying to accomplish, with this, I need both branches. The code below could be reduced, to 50%, of it's size, if there was a trait/type, which would hide the different types, from the user.

An Example
if dll_is_x64 {
            let dll = result!(pelite::pe64::PeFile::from_bytes(k32.as_slice()));
            let exports = result!(dll.exports());
            let name = result!(result!(exports.dll_name()).to_str());
            debug!("dll name is {}",name);
            let fns = result!(exports.functions());
            let names = result!(exports.names());
            for name in names{
                if let Ok(name_c_str) = dll.derva_c_str(*name){
                    if let Ok(name_str) = name_c_str.to_str(){
                        info!("got {} as function",name_str)
                    }else{
                        debug!("get {} as function", String::from_utf8_lossy(name_c_str.to_vec().as_slice()))
                    }
                }else{
                    error!("Couldn't read specified rva");
                }
            }
        }else{
            let dll = result!(pelite::pe32::PeFile::from_bytes(k32.as_slice()));
            let exports = result!(dll.exports());
            let name = result!(result!(exports.dll_name()).to_str());
            debug!("dll name is {}",name);
            let fns=result!(exports.functions());
            let names=result!(exports.names());
            for name in names{
                if let Ok(name_c_str) = dll.derva_c_str(*name){
                    if let Ok(name_str) = name_c_str.to_str(){
                        info!("got {} as function",name_str)
                    }else{
                        debug!("get {} as function", String::from_utf8_lossy(name_c_str.to_vec().as_slice()))
                    }
                }else{
                    error!("Couldn't read specified rva");
                }
            }
        }
CasualX commented 3 years ago

Hi, thanks for taking your time to using my library!

There is a type exposed to work with both 32-bit and 64-bit Pe types: Wrap which is aliased as PeFile. From which you can get exports() and continue from there.

There is also GetProcAddress but it does not appear to work with the wrapped pefile types.

C0D3-M4513R commented 3 years ago

GetProcAddress is not exposed via Wrap. get_export_by_name is an exellent alternative.

To avoid having issues like this, please add Wrap as an alternative, in the crate documentation here:

https://github.com/CasualX/pelite/blob/1efbb8ee9af31ff6151fb2539b1ea44d4b005cdc/src/lib.rs#L6

I opened this issue, because it said, that it was only possible , to inspect EITHER pe64 or pe32.