m4b / bingrep

like ~~grep~~ UBER, but for binaries

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Doesn't work on /bin/busybox

danielzgtg opened this issue · comments

bingrep errors out on /bin/busybox with the following message:

$ cargo run --release /bin/busybox
    Finished release [optimized] target(s) in 0.02s
     Running `target/release/bingrep /bin/busybox`
Malformed entity: Section 63 size (4195032) + addr (1008) is out of bounds. Overflowed: false
Environment

Built at c3516e7.

readelf /bin/busybox works fine.

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal
$ dpkg -S /bin/busybox
busybox-static: /bin/busybox
$ dpkg -s busybox-static
[...]
Version: 1:1.30.1-4ubuntu6.3
[...]
$ sha256sum /bin/busybox
6278d294297c0eb6224e4674da95a180d6c1805f17e640d0977f68553033bddb  /bin/busybox
commented

thanks for the issue! it looks like 6495cfee9ce7219e4fe1dde5953a2c73b01a8382 in goblin (m4b/goblin#243) introduced this issue.
something like this should fix it:

-                    section.check_size(bytes.len())?;
-                    let sh_relocs = RelocSection::parse(bytes, section.sh_offset as usize, section.sh_size as usize, is_rela, ctx)?;
-                    shdr_relocs.push((idx, sh_relocs));
+                    match section.check_size(bytes.len()) {
+                        Ok(_) => {
+                            let sh_relocs = RelocSection::parse(
+                                bytes,
+                                section.sh_offset as usize,
+                                section.sh_size as usize,
+                                is_rela,
+                                ctx,
+                            )?;
+                            shdr_relocs.push((idx, sh_relocs));
+                        }
+                        Err(e) => log::warn!(
+                            "Dropping shdr relocs for section #{} size for {:?}: {}",
+                            idx,
+                            shdr_strtab
+                                .get(section.sh_name)
+                                .unwrap_or(Ok("BAD_SECTION_NAME"))?,
+                            e
+                        ),
+                    }

though it still has a regression compared to 0.2.0 that can succesfully parse out some of the shdr relocs

@m4b your patch would suppress the error but also prevent parsing the relocation entry. I believe, that the section size check is wrong for relocation entries. m4b/goblin#243 added effectively checks for sh_addr + sh_size <= file_size:

            let (end, overflow) = self.sh_addr.overflowing_add(self.sh_size);
            if overflow || end > size as u64 {

I believe that comparing the virtual memory range with the physical file size is not valid in this context, and the correct patch would be:

diff --git a/src/elf/section_header.rs b/src/elf/section_header.rs
index 308606b..22cfdf2 100644
--- a/src/elf/section_header.rs
+++ b/src/elf/section_header.rs
@@ -474,7 +474,7 @@ if_alloc! {
                 return Err(error::Error::Malformed(message));
             }
             let (end, overflow) = self.sh_addr.overflowing_add(self.sh_size);
-            if overflow || end > size as u64 {
+            if overflow {
                 let message = format!("Section {} size ({}) + addr ({}) is out of bounds. Overflowed: {}",
                     self.sh_name, self.sh_addr, self.sh_size, overflow);
                 return Err(error::Error::Malformed(message));
commented

Confirmed your patch fixes, and latest goblin is released, and bingrep updated to use it with lockfile; also tagged new release :) thanks for everyone's help and involvement here, including the bug report! :D