ufrisk / MemProcFS

MemProcFS
GNU Affero General Public License v3.0
2.8k stars 352 forks source link

Rust API does not find libpdbcrust.so #249

Closed kaarposoft closed 5 months ago

kaarposoft commented 7 months ago

My usecase is: create a Rust program using memprocfs using the Rust API.

I have created workarounds for

The result is in /home/kaarposoft/mem_release_crust/ which seems to work fine on its own:

sudo mem_release_crust/memprocfs -loglevel 4 -device forensics/memdumpX64.dmp -mount /mnt
[INFODB]   INIT: SUCCESS: va=0xfffff80529800000
[SYMBOL]   Initialized symbol subsystem (Rust).
Initialized 64-bit Windows 10.0.22621
[PLUGIN]   LOAD: built-in module: '\'
...

Based on the example in https://crates.io/crates/memprocfs I have created a small rust program:

use memprocfs::Vmm;
fn main() {
    let args = vec!["-loglevel", "4", "-device", "/home/kaarposoft/forensics/memdumpX64.dmp"];
    let vmm = match Vmm::new("/home/kaarposoft/mem_release_crust/vmm.so", &args) {
        Ok(vmm) => vmm,
        Err(err) => panic!("Vmm::new failed: {err:?}")
    };
    if let Ok(process_all) = vmm.process_list() {
        for process in &*process_all {
            println!("{} : {:?}", process.pid, process.info());
        }
    }
}

This kind-of works, at it does indeed list the processes found. However, the output starts with

[INFODB]   INIT: SUCCESS: va=0xfffff80529800000
[SYMBOL]   Functionality may be limited. Extended debug information disabled.
[SYMBOL]   Partial offline fallback symbols in use.
[SYMBOL]   For additional information use startup option: -loglevel symbol:4
[SYMBOL]   Reason: Could not load PDB required file - libpdbcrust.dll/so.

So, whereas running memprocfs in /home/kaarposoft/mem_release_crust/ correctly picks up the libpdbcrust.so the small rust program does not.

strace reveals this:

9447  readlink("/proc/self/exe", "/home/kaarposoft/mem_rs/target/d"..., 256) = 43
9447  openat(AT_FDCWD, "/home/kaarposoft/mem_rs/target/debug/libpdbcrust.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

There are no other mentions of libpdbcrust.so in the strace output.

So presumably the Vmm::new tries to open the libpdbcrust.so in the directory of the executable (ie. the rust program), not the directory where vmm.so is found. This is why everything is fine when running the memprocfs program which resides in the same directory as the vmm.so and libpdbcrust.so, but not when running from a program in a different directory.

I have tried running with LD_LIBRARY_PATH=/home/kaarposoft/mem_release_crust but it does not change anything.

Workaround: If I symlink the /home/kaarposoft/mem_release_crust/libpdbcrust.so into /home/kaarposoft/mem_rs/target/debug the Rust example works:

[INFODB]   INIT: SUCCESS: va=0xfffff80529800000
[SYMBOL]   Initialized symbol subsystem (Rust).

May I suggest, that vmm.so should look for libpdbcrust.so in the directory where vmm.so is found, or failing that, in LD_LIBRARY_PATH.

ufrisk commented 7 months ago

Many thanks for this excellent bug report.

Can you please try to most recent MemProcFS version which I uploaded just a minute ago?

It should now hopefully pick up on the directly where vmm.so is located instead of the main binary itself.

kaarposoft commented 7 months ago

I am absolutely amazed by the speed of your answer!!!

And yes, https://github.com/ufrisk/MemProcFS/commit/69e1436af057fc0d860f7b025be4b7845036d385 fixes the issue!

Thank you very much!

ufrisk commented 6 months ago

Awesome and huge thanks for confirming.

I'm keeping this issue open though since its only been partly resolved.

I still would need to figure out how to distribute this in a good way. As you mentioned in the other thread having a package might be the way to go.

Another way might be to ship two libpdbcrust.so files and try to load them both I guess. If the first one fails try the 2nd one. But they are like 1.5MB each so this would be a quite wasteful approach...

ufrisk commented 5 months ago

Apologies for the slow response on this one. I forgot about it, but now it should be resolved.

I decided to ship two versions of the .so in the binary pre-built version to keep maximum backwards compatibility. This should be completely transparent to the user and no action would have to be taken.

Since the issue is now resolved I'm closing the issue. If it's still not working please let me know and I'll look into it again.