memflow icon indicating copy to clipboard operation
memflow copied to clipboard

Wrong address size populated for win32 x86 process

Open AlexDoh opened this issue 1 year ago • 5 comments

Hello! Using memlow-ffi and reading x32 process inside Win10x64 VM, so every pointer is an actually a DWORD(uint). So reading a c++ structure object with pointers, which are being read by memflow read_raw as x32 pointers (ulong) so it is impossible to normally read a structure data after any pointer inside a structure. Could someone please add a fix or feature for supporting reading pointers as x86? I saw there is a feature for original Rust implementation for reading x32 addresses like "read_addr32", but probably it is only for an address or it supports the structures too, nit sure. Please add possibility for reading pointers as x32 for a pointer type if reading into a structure. Or at least please point me to the place where it could be added/updated, maybe I could contribute and add this.

Thanks!

AlexDoh avatar Apr 03 '24 05:04 AlexDoh

Hey there, thanks for your first issue! Im not sure if i understood the request correctly though. The read_addr32 and read_addr64 as well as read_addr_arch functions are still present. However they are not exported to the C layer due to constraints in the implementation. You can easily re-implement them in your C code however by reading a uint32_t or uint64_t respectively and then put this into an address.

They are currently implemented like this: https://github.com/memflow/memflow/blob/99889b649f9c71120fa99561acce21b0a7414e93/memflow/src/mem/memory_view/mod.rs#L222

In case you want to read into a struct directly then of course pointers will not be sufficient as they the struct will have the pointer widths of the architecture you compile it for. To circumvent that you could for example either replace the pointers in the structs with uint32_t values or uint64_t values respectively and then read the struct they are pointing to.

Having raw points in a struct that you read with memflow will point to invalid memory anyways (in the context of your application). Currently there is no way to resolve raw pointers in a way that would work for this use case. However in Rust we support 2 distinct pointer types that you can use in structs, here is an example:

#[repr(C)]
#[derive(Copy, Clone, Pod)]
pub struct Prop {
    pub table: Pointer64<Table>, // table_t *
    pub name: Pointer64<ReprCString>, // const char *
}

#[repr(C)]
#[derive(Default, Copy, Clone, Pod)]
pub struct Table {
    //
}

// ...

let virt_mem = &mut process.forward_mut();
let prop_name = prop.name.read_string(virt_mem)?.to_string();

// ...

let mut table = Table::default();
prop.table.read_into(virt_mem, &mut table)?;

Hope that helped.

ko1N avatar Apr 03 '24 10:04 ko1N

@ko1N Thank you for the clarification! Unfortunately I have to stick to the C implementation of memflow because I don't want to rewrite all the C structures, which are provided by the app SDK, which is written in C++ and there are a lot of classes/structures/types....

"In case you want to read into a struct directly then of course pointers will not be sufficient as they the struct will have the pointer widths of the architecture you compile it for" I have thought about that, but this is what I have got where there was a try to build with the x32 arch ("-m32" flag in Cmake file):

/usr/bin/ld: i386:x86-64 architecture of input file /home/alex/repo/dma/lib/memflow/target/release/libmemflow_ffi.a(serde_json-33b935d647617e68.serde_json.efd370de48e8361e-cgu.04.rcgu.o)' is incompatible with i386 output /usr/bin/ld: i386:x86-64 architecture of input file /home/alex/repo/dma/lib/memflow/target/release/libmemflow_ffi.a(serde_json-33b935d647617e68.serde_json.efd370de48e8361e-cgu.11.rcgu.o)' is incompatible with i386 output /usr/bin/ld: i386:x86-64 architecture of input file /home/alex/repo/dma/lib/memflow/target/release/libmemflow_ffi.a(coarsetime-be883958c8d90051.coarsetime.2930bd6dd2e35a34-cgu.0.rcgu.o)' is incompatible with i386 output /usr/bin/ld: i386:x86-64 architecture of input file /home/alex/repo/dma/lib/memflow/target/release/libmemflow_ffi.a(coarsetime-be883958c8d90051.coarsetime.2930bd6dd2e35a34-cgu.1.rcgu.o)' is incompatible with i386 output /usr/bin/ld: i386:x86-64 architecture of input file /home/alex/repo/dma/lib/memflow/target/release/libmemflow_ffi.a(compiler_builtins-1088ecd7666b60f4.compiler_builtins.3b448df83059ed2c-cgu.007.rcgu.o)' is incompatible with i386 output /usr/bin/ld: i386:x86-64 architecture of input file /home/alex/repo/dma/lib/memflow/target/release/libmemflow_ffi.a(time-e8f3324299bc6e2b.time.d1c83796c831e0dd-cgu.03.rcgu.o)' is incompatible with i386 output

Is it possible to have x32 memflow-ffi build?

AlexDoh avatar Apr 03 '24 19:04 AlexDoh

The current solution would be to manually build memflow-ffi as a 32bit target.

You could try compiling the main repo for i686. Something like this could work:

rustup target add i686-pc-windows-msvc
cargo build --target i686-pc-windows-msvc --release --all-features --workspace

Edit: I will try and see if we could add a test case to the ci for this.

ko1N avatar Apr 03 '24 19:04 ko1N

Thanks @ko1N! But it showed this error:

alex@fedora:~/repo/memflow$ cargo build --target i686-pc-windows-msvc --release --all-features --workspace warning: unused #[macro_use] import --> memflow/src/lib.rs:232:1 | 232 | #[macro_use] | ^^^^^^^^^^^^ | = note: #[warn(unused_imports)] on by default warning: memflow (lib) generated 1 warning Compiling memflow-ffi v0.2.0 (/home/alex/repo/memflow/memflow-ffi) error: linker link.exe not found | = note: No such file or directory (os error 2) note: the msvc targets depend on the msvc linker but link.exe was not found note: please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option. note: VS Code is a different product, and is not sufficient. error: could not compile memflow-ffi (lib) due to 1 previous error

Does this build expects WinOS to be running on? I am using Fedora as host Os and Win10 as guest Os I have also tried to run with target "stable-i686-pc-windows-gnu", but it showed even more compilation errors

AlexDoh avatar Apr 03 '24 19:04 AlexDoh

Then you probably want to use something like i686-unknown-linux-gnu instead. Please refer to the rustup docs on how to setup different targets: https://rust-lang.github.io/rustup/cross-compilation.html

ko1N avatar Apr 03 '24 19:04 ko1N

Since this issue is quite old im gonna close it. Feel free to re-open if you still have questions.

ko1N avatar Aug 21 '24 18:08 ko1N