Skip to content

PE: image base silently overflows parsing PE64 on 32-bit builds #440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Tracked by #434
kkent030315 opened this issue Dec 16, 2024 · 2 comments
Closed
Tracked by #434

PE: image base silently overflows parsing PE64 on 32-bit builds #440

kkent030315 opened this issue Dec 16, 2024 · 2 comments

Comments

@kkent030315
Copy link
Contributor

kkent030315 commented Dec 16, 2024

As pointed out in this comment the goblin::pe::PE::image_base silently overflowing when parsing PE64 on 32-bit goblin.

Target Sizeof usize Sizeof u64
x86 (32-bit) 4 bytes (32-bit) 8 bytes (64-bit)
x64 (64-bit) 8 bytes (64-bit) 8 bytes (64-bit)

goblin/src/pe/mod.rs

Lines 61 to 62 in 48da3d8

/// The binary's RVA, or image base - useful for computing virtual addreses
pub image_base: usize,

The goblin::pe::PE::image_base must be defined as u64 to be compatible with 32-bit hosts.

Steps to reproduce

For convenience, patching examples\rdr.rs may improve readability specifically for this case since theres a bunch of irrelevant logs:

fn run() -> error::Result<()> {
    for (i, arg) in env::args().enumerate() {
        if i == 1 {
            let path = Path::new(arg.as_str());
            let buffer = fs::read(path)?;
            let res = goblin::Object::parse(&buffer)?;
-           //println!("{:#?}", res);
+           match res {
+              goblin::Object::PE(x) => {
+                  println!("{:#x}", x.image_base)
+              }
+              _ => {}
+           }
        }
    }
    Ok(())
}

Then run:

cargo run --target i686-pc-windows-msvc --example rdr -- "path/to/pe64-bin.exe"

If the image base of path/to/pe64-bin.exe is 0x140000000 (the default value of COFF linkers), it outputs trimmed 32-bit value 0x40000000.

This is not particular to i686-pc-windows-msvc triple but any other 32-bit builds.

@kkent030315
Copy link
Contributor Author

note: TE has no problem with this.

goblin/src/pe/header.rs

Lines 1196 to 1197 in 48da3d8

/// The image base
pub image_base: u64,

@kkent030315
Copy link
Contributor Author

kkent030315 commented Dec 16, 2024

This is also a mess. it is defined as 32-bit on both PE32/64.

/// A pointer to the entry point function, relative to the image base address.
///
/// * For executable files, this is the starting address.
/// * For device drivers, this is the address of the initialization function.
///
/// The entry point function is optional for DLLs. When no entry point is present, this member is zero.
pub address_of_entry_point: u64,

Moreover, this field should be u32 that this is RVA. Generally speaking, PE has limit of 4GB in practice.

goblin/src/pe/mod.rs

Lines 59 to 60 in 48da3d8

/// the entry point of the binary
pub entry: usize,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant