Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
asuto15 committed Oct 25, 2023
0 parents commit 0d1dcd2
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "readelf-rs"
version = "0.1.0"
edition = "2021"
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ELF Header Reader in Rust
This program is a simple utility written in Rust that reads and displays the ELF (Executable and Linkable Format) header of a given binary. The tool mimics the behavior of the readelf -h command, showing basic details about the ELF file.

## Features
- Displays the magic bytes of the ELF header.
- Describes the type of the ELF (e.g., REL, EXEC, DYN, CORE).
- Describes the machine type (e.g., i386, X86_64).
- Shows other pertinent details such as version, entry point address, program headers' start and size, section headers' start and size, and more.

## Usage
To use the program, simply compile it and then run:

```
> cargo run
// or
> cargo run /bin/wc
```
If you don't specify the path to the target file, the program defaults to reading the header of /bin/ls.

### Sample Output
The output might look something like:

```
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Type: EXEC (Executable file)
Machine: X86_64 (AMD x86-64 architecture)
Version: 0x1
Entry point address: 0x400080
Start of program headers: 64
Start of section headers: 123456
Flags: 0x0
Size of this header: 64(bytes)
Size of program headers: 56(bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 29
```

## Implementation Details
The program is written in Rust and uses the standard libraries for file I/O and command-line argument parsing but no crates. The ELF header structure and constants are based on the ELF64 specification.
96 changes: 96 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use std::env;
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom};

const EI_NIDENT: usize = 16;

#[repr(C)]
#[derive(Debug)]
struct Elf64_Ehdr {
e_ident: [u8; EI_NIDENT],
e_type: u16,
e_machine: u16,
e_version: u32,
e_entry: u64,
e_phoff: u64,
e_shoff: u64,
e_flags: u32,
e_ehsize: u16,
e_phentsize: u16,
e_phnum: u16,
e_shentsize: u16,
e_shnum: u16,
e_shstrndx: u16,
}

fn describe_type(e_type: u16) -> &'static str {
match e_type {
0 => "NONE (No file type)",
1 => "REL (Relocatable file)",
2 => "EXEC (Executable file)",
3 => "DYN (Shared object file)",
4 => "CORE (Core file)",
_ => "UNKNOWN",
}
}

fn describe_machine(e_machine: u16) -> &'static str {
match e_machine {
0 => "NONE (No machine)",
3 => "i386 (Intel 80386)",
62 => "X86_64 (AMD x86-64 architecture)",
_ => "UNKNOWN",
}
}

fn main() -> io::Result<()> {
let default_path = "/bin/ls";
let path = env::args().nth(1).unwrap_or(default_path.to_string());
let mut file = File::open(&path)?;

let mut ehdr = Elf64_Ehdr {
e_ident: [0; EI_NIDENT],
e_type: 0,
e_machine: 0,
e_version: 0,
e_entry: 0,
e_phoff: 0,
e_shoff: 0,
e_flags: 0,
e_ehsize: 0,
e_phentsize: 0,
e_phnum: 0,
e_shentsize: 0,
e_shnum: 0,
e_shstrndx: 0,
};

file.seek(SeekFrom::Start(0))?;
file.read_exact(unsafe { std::slice::from_raw_parts_mut(&mut ehdr as *mut _ as *mut u8, std::mem::size_of::<Elf64_Ehdr>()) })?;
print_elf_header(ehdr);

Ok(())
}

fn print_elf_header(ehdr: Elf64_Ehdr) {
println!("ELF Header:");
println!(" Magic: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}",
ehdr.e_ident[0], ehdr.e_ident[1], ehdr.e_ident[2], ehdr.e_ident[3],
ehdr.e_ident[4], ehdr.e_ident[5], ehdr.e_ident[6], ehdr.e_ident[7],
ehdr.e_ident[8], ehdr.e_ident[9], ehdr.e_ident[10], ehdr.e_ident[11],
ehdr.e_ident[12], ehdr.e_ident[13], ehdr.e_ident[14], ehdr.e_ident[15]);
println!(" Type: {}", describe_type(ehdr.e_type));
println!(" Machine: {}", describe_machine(ehdr.e_machine));
println!(" Version: 0x{:x}", ehdr.e_version);
println!(" Entry point address: 0x{:x}", ehdr.e_entry);
println!(" Start of program headers: {}", ehdr.e_phoff);
println!(" Start of section headers: {}", ehdr.e_shoff);
println!(" Flags: 0x{:x}", ehdr.e_flags);
println!(" Size of this header: {}(bytes)", ehdr.e_ehsize);
println!(" Size of program headers: {}(bytes)", ehdr.e_phentsize);
println!(" Number of program headers: {}", ehdr.e_phnum);
println!(" Size of section headers: {} (bytes)", ehdr.e_shentsize);
println!(" Number of section headers: {}", ehdr.e_shnum);
println!(" Section header string table index: {}", ehdr.e_shstrndx);

}

0 comments on commit 0d1dcd2

Please sign in to comment.