Finish linear sweep implementation, add polish, update README

This commit is contained in:
Garrett Dickinson 2023-03-01 01:51:58 -06:00
parent f56400d124
commit 0d227f10af
9 changed files with 330 additions and 225 deletions

View File

@ -5,3 +5,23 @@
## Supported Binary formats ## Supported Binary formats
`chisel` supports binaries compiled to the [ELF format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) from most x86/x64 *nix systems, and __does not__ currently support macOS Mach-O or Windows PE binaries. `chisel` supports binaries compiled to the [ELF format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) from most x86/x64 *nix systems, and __does not__ currently support macOS Mach-O or Windows PE binaries.
> Due to an indexing bug, current iterations of chisel do not support 32-bit x86 applications
## Building and Installing
To build and install `chisel`, use the following steps:
```shell
$ git clone git@github.com:Gman0064/chisel.git
$ cd chisel && cargo install
```
## Usage
```shell
$ chisel [path to ELF executable]
```

View File

@ -4,9 +4,8 @@
// Description: Main entrypoint script for chisel. Contains basic procedures // Description: Main entrypoint script for chisel. Contains basic procedures
// for gathering ELF file and program data. // for gathering ELF file and program data.
use iced_x86::*; use iced_x86::{Decoder, DecoderOptions, Formatter, NasmFormatter, Instruction};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write;
use std::path; use std::path;
use std::env; use std::env;
use std::fs; use std::fs;
@ -36,53 +35,59 @@ fn main() {
let contents: Result<Vec<u8>, std::io::Error> = fs::read(file_path); let contents: Result<Vec<u8>, std::io::Error> = fs::read(file_path);
if contents.is_ok() { if contents.is_ok() {
let bytes: &Vec<u8> = &contents.expect(""); let bytes: &Vec<u8> = &contents.expect("");
let magic_num: &[u8] = &bytes[0..4]; let magic_num: &[u8] = &bytes[0..4];
// Check to see if our file contains the ELF magic number
if magic_num == elf::MAGIC_NUMBER { if magic_num == elf::MAGIC_NUMBER {
println!("Found ELF Magic Number..."); println!("Found ELF Magic Number...");
println!("Parsing File Header..."); println!("Parsing File Header...");
// Build the File Header data structure // Build the File Header data structure
let file_header: elf::FileHeader = build_file_header(bytes); let file_header: elf::FileHeader = util::build_file_header(bytes);
println!("\t- Found {} program header entries {} bytes in length", file_header.phnum, file_header.phentsize); println!("\t- Found {} program header entries {} bytes in length", file_header.phnum, file_header.phentsize);
println!("\t- Found {} section header entries {} bytes in length", file_header.shnum, file_header.shentsize); println!("\t- Found {} section header entries {} bytes in length", file_header.shnum, file_header.shentsize);
println!("\t- Found .shstrtab section at index {}", file_header.shstrndx); println!("\t- Found .shstrtab section at index {}", file_header.shstrndx);
println!("{:?}", file_header); println!("\n==== File Header ====");
util::pp_file_header(&file_header);
println!("\nParsing Section Headers..."); println!("\nParsing Section Headers...");
// Determine the shstrtab offset. // Determine the shstrtab offset.
// This is found by taking the string table index and multiplying it by the section header entry size, then // This is found by taking the string table index and multiplying it by the section header entry size, then
// adding this to the initial section header offset. // adding this to the initial section header offset.
let shstrtab_offset: u64 = file_header.shoff + (file_header.shentsize as u64 * file_header.shstrndx as u64); let shstrtab_offset: u64 = file_header.shoff + (file_header.shentsize as u64 * file_header.shstrndx as u64);
// Build a read-only version of the .shstrtab section // Build a read-only version of the .shstrtab section
let shstrtab_section: elf::SectionHeader = build_section_header( let shstrtab_section: elf::SectionHeader = util::build_section_header(
bytes, bytes,
shstrtab_offset as usize, shstrtab_offset as usize,
file_header.is_x86_64 file_header.is_x86_64
); );
// Define all of our offsets for the shstrtab, and build a u8 buffer of the data
let shstrtab_start: u64 = shstrtab_section.offset; let shstrtab_start: u64 = shstrtab_section.offset;
let shstrtab_end: u64 = shstrtab_section.offset + shstrtab_section.size; let shstrtab_end: u64 = shstrtab_section.offset + shstrtab_section.size;
let shstrtab_data: Vec<u8> = bytes[shstrtab_start as usize..shstrtab_end as usize].to_vec(); let shstrtab_data: Vec<u8> = bytes[shstrtab_start as usize..shstrtab_end as usize].to_vec();
println!("\t- Found .shstrtab section"); println!("\t- Found .shstrtab section");
println!("\n==== Sections ====");
println!("\n=== Sections ===");
let mut section_table_map: HashMap<String, elf::SectionHeader> = HashMap::new(); let mut section_table_map: HashMap<String, elf::SectionHeader> = HashMap::new();
let mut section_table_offset: u64 = file_header.shoff; let mut section_table_offset: u64 = file_header.shoff;
let mut section_table_count: i32 = 0; let mut section_table_count: i32 = 0;
// Build Section Header data structure // Iterate through number of section headers
for _ in 0..file_header.shnum { for _ in 0..file_header.shnum {
let section_header: elf::SectionHeader = build_section_header(
// Build section header data structure
let section_header: elf::SectionHeader = util::build_section_header(
bytes, bytes,
section_table_offset as usize, section_table_offset as usize,
file_header.is_x86_64 file_header.is_x86_64
@ -91,37 +96,37 @@ fn main() {
// Determine the section name for each section using the shstrtab data // Determine the section name for each section using the shstrtab data
let section_name: String = util::parse_section_name(&shstrtab_data, section_header.name as usize); let section_name: String = util::parse_section_name(&shstrtab_data, section_header.name as usize);
println!("[{}] {}", section_table_count, section_name); util::pp_section_header(&section_header, section_table_count, &section_name);
println!("{:?}", section_header);
section_table_map.insert(section_name, section_header); section_table_map.insert(section_name, section_header);
// Update the section table offset counter based on the section header size
section_table_offset += file_header.shentsize as u64; section_table_offset += file_header.shentsize as u64;
section_table_count += 1; section_table_count += 1;
} }
println!("\nParsing Program Segments..."); println!("\nParsing Program Segments...");
println!("\n=== Program Segments ==="); println!("\n==== Program Segments ====");
let mut program_table_offset = file_header.phoff; let mut program_table_offset = file_header.phoff;
let mut program_table_count: i32 = 0; let mut program_table_count: i32 = 0;
// Build Section Header data structure // Iterate through number of Program Headers
for _ in 0..file_header.phnum { for _ in 0..file_header.phnum {
// Build Program Header data structure // Build Program Header data structure
let program_header: elf::ProgramHeader = build_program_header( let program_header: elf::ProgramHeader = util::build_program_header(
bytes, bytes,
program_table_offset as usize, program_table_offset as usize,
file_header.is_x86_64 file_header.is_x86_64
); );
// Set a default section name if there's no index found in the table // Parse the program name using the program type
let program_name: String = util::parse_program_segment_type(program_header.program_type); let program_name: String = util::parse_program_segment_type(program_header.program_type);
println!("[{}] {}", program_table_count, program_name); util::pp_program_header(&program_header, program_table_count, &program_name);
println!("{:?}", program_header);
// Update the program header table offset counter based on the program header size
program_table_offset += file_header.phentsize as u64; program_table_offset += file_header.phentsize as u64;
program_table_count += 1; program_table_count += 1;
} }
@ -132,22 +137,68 @@ fn main() {
let text_section_offset: usize = text_section.offset as usize; let text_section_offset: usize = text_section.offset as usize;
let text_section_end: usize = text_section_offset + text_section.size as usize; let text_section_end: usize = text_section_offset + text_section.size as usize;
// Buffer of text section data
let text_section_buff: &[u8] = &bytes[text_section_offset..text_section_end]; let text_section_buff: &[u8] = &bytes[text_section_offset..text_section_end];
let mut decoder: Decoder = Decoder::new(64, text_section_buff, DecoderOptions::NONE); // Offsets for resizing buffer
let mut instruction: Instruction = Instruction::default(); let mut instr_start: usize = 0;
let instruction_start: u64 = 0; let mut instr_end: usize = 1;
let instruction_length: u64 = 1; let mut ip_offset: u64 = text_section.offset;
while (instruction_start + instruction_length) < text_section.size { // Define our instruction buffer
//let instruction_bytes: &[u8] = &text_section_buff[instruction_start..instruction_length]; let mut instr_bytes: &[u8] = &text_section_buff[instr_start..instr_end];
//instruction.
//decoder.decode_out(instruction) // Define our decoder and icedx86 variables
let mut decoder: Decoder = Decoder::with_ip(64, instr_bytes, text_section.offset, DecoderOptions::NONE);
let mut formatter: NasmFormatter = NasmFormatter::new();
let mut instruction: Instruction = Instruction::default();
let mut output = String::new();
// Specify options for our NASM instruction formatter
// Formatting and linear sweep pattern partially borrowed from icedx86 docs
// https://docs.rs/iced-x86/latest/iced_x86/#disassemble-decode-and-format-instructions
formatter.options_mut().set_digit_separator("`");
formatter.options_mut().set_first_operand_char_index(10);
println!("==== Text Section Analysis ====\n");
while decoder.can_decode() {
// Decode the instruction sub-buffer
decoder.decode_out(&mut instruction);
if instruction.is_invalid() {
// Instruction invalid
// Increase the buffer size by 1, then try to parse again
instr_end = instr_end + 1;
instr_bytes = &text_section_buff[instr_start..instr_end];
decoder = Decoder::with_ip(64, instr_bytes, ip_offset, DecoderOptions::NONE);
} else {
// Got a valid instruction
// Format the instruction for printing
output.clear();
formatter.format(&instruction, &mut output);
// Print the instruction to an output assembly file
println!("{:016X}\t{}", instruction.ip(), output);
// Reset the buffer start to the end of the previous buffer, then try to parse again
instr_start = instr_end;
// If the instruction end index is less than the buffer, increase it
if (instr_end + 1) < text_section_buff.len() {
instr_end = instr_end + 1;
} }
//let out_file = fs::File::create("out.s").unwrap(); // Resize the instruction buffer and parse it again
//out_file.write() instr_bytes = &text_section_buff[instr_start..instr_end];
//out_file.flush(); ip_offset = text_section.offset + instr_start as u64;
decoder = Decoder::with_ip(64, instr_bytes, ip_offset, DecoderOptions::NONE);
}
}
} else { } else {
println!("[Error] Could not find magic number, is this an ELF executable?") println!("[Error] Could not find magic number, is this an ELF executable?")
@ -160,80 +211,3 @@ fn main() {
return; return;
} }
fn build_file_header(data: &Vec<u8>) -> elf::FileHeader {
// Determine x86 or x64 architecture
// 0 : x86
// 1 : x64
let arch: usize = (data[elf::ARCH_OFFSET as usize] - 1).into();
let file_header: elf::FileHeader = elf::FileHeader {
arch: util::parse_architecture(data[elf::ARCH_OFFSET as usize]),
is_x86_64: arch != 0,
endian: util::parse_endian(data[elf::ENDIAN_OFFSET as usize]),
abi: data[elf::ABI_OFFSET as usize],
abi_str: util::parse_abi(data[elf::ABI_OFFSET as usize]),
elf_type: util::u16_from_buffer(data, elf::TYPE_OFFSET as usize),
isa: util::u16_from_buffer(data, elf::MACHINE_OFFSET as usize),
isa_str: util::parse_isa(util::u16_from_buffer(data, elf::MACHINE_OFFSET as usize)),
entryoff: util::u64_from_buffer(data, elf::ENTRYPOINT_OFFSET as usize),
phoff: util::u64_from_buffer(data, elf::PHOFF_OFFSET[arch] as usize),
shoff: util::u64_from_buffer(data, elf::SHOFF_OFFSET[arch] as usize),
ehsize: util::u16_from_buffer(data, elf::EHSIZE_OFFSET[arch] as usize),
phentsize: util::u16_from_buffer(data, elf::PHENTSIZE_OFFSET[arch] as usize),
phnum: util::u16_from_buffer(data, elf::PHNUM_OFFSET[arch] as usize),
shentsize: util::u16_from_buffer(data, elf::SHENTSIZE_OFFSET[arch] as usize),
shnum: util::u16_from_buffer(data, elf::SHNUM_OFFSET[arch] as usize),
shstrndx: util::u16_from_buffer(data, elf::SHSTRNDX_OFFSET[arch] as usize),
};
return file_header;
}
fn build_program_header(data: &Vec<u8>, phoffset: usize, is_x86_64: bool) -> elf::ProgramHeader {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
let program_header: elf::ProgramHeader = elf::ProgramHeader {
program_type: util::u32_from_buffer(data, phoffset + elf::PH_TYPE_OFFSET as usize),
flags: util::u32_from_buffer(data, phoffset + elf::PH_FLAGS_OFFSET[arch] as usize),
offset: util::u64_from_buffer(data, phoffset + elf::PH_OFFSET_OFFSET[arch] as usize),
vaddr: util::u64_from_buffer(data, phoffset + elf::PH_VADDR_OFFSET[arch] as usize),
paddr: util::u64_from_buffer(data, phoffset + elf::PH_PADDR_OFFSET[arch] as usize),
filesz: util::u64_from_buffer(data, phoffset + elf::PH_FILESZ_OFFSET[arch] as usize),
memsz: util::u64_from_buffer(data, phoffset + elf::PH_MEMSZ_OFFSET[arch] as usize),
align: util::u64_from_buffer(data, phoffset + elf::PH_ALIGN_OFFSET[arch] as usize)
};
return program_header;
}
fn build_section_header(data: &Vec<u8>, shoffset: usize, is_x86_64: bool) -> elf::SectionHeader {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
let section_header: elf::SectionHeader = elf::SectionHeader {
name: util::u32_from_buffer(data, shoffset + elf::SH_NAME_OFFSET as usize),
section_type: util::u32_from_buffer(data, shoffset + elf::SH_TYPE_OFFSET as usize),
flags: util::u64_from_buffer(data, shoffset + elf::SH_FLAGS_OFFSET as usize),
addr: util::u64_from_buffer(data, shoffset + elf::SH_ADDR_OFFSET[arch] as usize),
offset: util::u64_from_buffer(data, shoffset + elf::SH_OFFSET_OFFSET[arch] as usize),
size: util::u64_from_buffer(data, shoffset + elf::SH_SIZE_OFFSET[arch] as usize),
link: util::u32_from_buffer(data, shoffset + elf::SH_LINK_OFFSET[arch] as usize),
info: util::u32_from_buffer(data, shoffset + elf::SH_INFO_OFFSET[arch] as usize),
addralign: util::u64_from_buffer(data, shoffset + elf::SH_ADDRALIGN_OFFSET[arch] as usize),
entsize: util::u64_from_buffer(data, shoffset + elf::SH_ENTSIZE_OFFSET[arch] as usize)
};
return section_header;
}

View File

@ -9,6 +9,83 @@ use std::mem;
use crate::elf::{self, EndianType, ArchitectureType}; use crate::elf::{self, EndianType, ArchitectureType};
pub fn build_file_header(data: &Vec<u8>) -> elf::FileHeader {
// Determine x86 or x64 architecture
// 0 : x86
// 1 : x64
let arch: usize = (data[elf::ARCH_OFFSET as usize] - 1).into();
let file_header: elf::FileHeader = elf::FileHeader {
arch: parse_architecture(data[elf::ARCH_OFFSET as usize]),
is_x86_64: arch != 0,
endian: parse_endian(data[elf::ENDIAN_OFFSET as usize]),
abi: data[elf::ABI_OFFSET as usize],
abi_str: parse_abi(data[elf::ABI_OFFSET as usize]),
elf_type: u16_from_buffer(data, elf::TYPE_OFFSET as usize),
isa: u16_from_buffer(data, elf::MACHINE_OFFSET as usize),
isa_str: parse_isa(u16_from_buffer(data, elf::MACHINE_OFFSET as usize)),
entryoff: u64_from_buffer(data, elf::ENTRYPOINT_OFFSET as usize),
phoff: u64_from_buffer(data, elf::PHOFF_OFFSET[arch] as usize),
shoff: u64_from_buffer(data, elf::SHOFF_OFFSET[arch] as usize),
ehsize: u16_from_buffer(data, elf::EHSIZE_OFFSET[arch] as usize),
phentsize: u16_from_buffer(data, elf::PHENTSIZE_OFFSET[arch] as usize),
phnum: u16_from_buffer(data, elf::PHNUM_OFFSET[arch] as usize),
shentsize: u16_from_buffer(data, elf::SHENTSIZE_OFFSET[arch] as usize),
shnum: u16_from_buffer(data, elf::SHNUM_OFFSET[arch] as usize),
shstrndx: u16_from_buffer(data, elf::SHSTRNDX_OFFSET[arch] as usize),
};
return file_header;
}
pub fn build_program_header(data: &Vec<u8>, phoffset: usize, is_x86_64: bool) -> elf::ProgramHeader {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
let program_header: elf::ProgramHeader = elf::ProgramHeader {
program_type: u32_from_buffer(data, phoffset + elf::PH_TYPE_OFFSET as usize),
flags: u32_from_buffer(data, phoffset + elf::PH_FLAGS_OFFSET[arch] as usize),
offset: u64_from_buffer(data, phoffset + elf::PH_OFFSET_OFFSET[arch] as usize),
vaddr: u64_from_buffer(data, phoffset + elf::PH_VADDR_OFFSET[arch] as usize),
paddr: u64_from_buffer(data, phoffset + elf::PH_PADDR_OFFSET[arch] as usize),
filesz: u64_from_buffer(data, phoffset + elf::PH_FILESZ_OFFSET[arch] as usize),
memsz: u64_from_buffer(data, phoffset + elf::PH_MEMSZ_OFFSET[arch] as usize),
align: u64_from_buffer(data, phoffset + elf::PH_ALIGN_OFFSET[arch] as usize)
};
return program_header;
}
pub fn build_section_header(data: &Vec<u8>, shoffset: usize, is_x86_64: bool) -> elf::SectionHeader {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
let section_header: elf::SectionHeader = elf::SectionHeader {
name: u32_from_buffer(data, shoffset + elf::SH_NAME_OFFSET as usize),
section_type: u32_from_buffer(data, shoffset + elf::SH_TYPE_OFFSET as usize),
flags: u64_from_buffer(data, shoffset + elf::SH_FLAGS_OFFSET as usize),
addr: u64_from_buffer(data, shoffset + elf::SH_ADDR_OFFSET[arch] as usize),
offset: u64_from_buffer(data, shoffset + elf::SH_OFFSET_OFFSET[arch] as usize),
size: u64_from_buffer(data, shoffset + elf::SH_SIZE_OFFSET[arch] as usize),
link: u32_from_buffer(data, shoffset + elf::SH_LINK_OFFSET[arch] as usize),
info: u32_from_buffer(data, shoffset + elf::SH_INFO_OFFSET[arch] as usize),
addralign: u64_from_buffer(data, shoffset + elf::SH_ADDRALIGN_OFFSET[arch] as usize),
entsize: u64_from_buffer(data, shoffset + elf::SH_ENTSIZE_OFFSET[arch] as usize)
};
return section_header;
}
pub fn parse_endian(endian: u8) -> elf::EndianType { pub fn parse_endian(endian: u8) -> elf::EndianType {
match endian { match endian {
0x00 => return EndianType::Big, 0x00 => return EndianType::Big,
@ -113,12 +190,81 @@ pub fn parse_section_name(buff: &Vec<u8>, index: usize) -> String {
char = buff[char_ctr]; char = buff[char_ctr];
} }
let result = String::from_utf8(name).expect("Failed to parse section name!"); let result = String::from_utf8(name).expect("[Error] Failed to parse section name!");
return result; return result;
} }
pub fn parse_elf_type(elf_type: u16) -> String {
match elf_type {
0x0000 => "Unknown".to_string(),
0x0001 => "Relocatable file".to_string(),
0x0002 => "Executable file".to_string(),
0x0003 => "Shared object".to_string(),
0x0004 => "Core file".to_string(),
0xFE00 => "Reserved, operating system specific".to_string(),
0xFEFF => "Reserved, operating system specific".to_string(),
0xFF00 => "Reserved, processor specific".to_string(),
0xFFFF => "Reserved, processor specific".to_string(),
// Match unknown segment type
_ => "UNKNOWN".to_string()
}
}
pub fn parse_section_type(section_type: u32) -> String {
match section_type {
0x00000000 => "SHT_NULL".to_string(),
0x00000001 => "SHT_PROGBITS".to_string(),
0x00000002 => "SHT_SYMTAB".to_string(),
0x00000003 => "SHT_STRTAB".to_string(),
0x00000004 => "SHT_RELA".to_string(),
0x00000005 => "SHT_HASH".to_string(),
0x00000006 => "SHT_DYNAMIC".to_string(),
0x00000007 => "SHT_NOTE".to_string(),
0x00000008 => "SHT_NOBITS".to_string(),
0x00000009 => "SHT_REL".to_string(),
0x0000000A => "SHT_SHLIB".to_string(),
0x0000000B => "SHT_DYNSYM".to_string(),
0x0000000E => "SHT_INIT_ARRAY".to_string(),
0x0000000F => "SHT_FINI_ARRAY".to_string(),
0x00000010 => "SHT_PREINIT_ARRAY".to_string(),
0x00000011 => "SHT_GROUP".to_string(),
0x00000012 => "SHT_SYMTAB_SHNDX".to_string(),
0x00000013 => "SHT_NUM".to_string(),
0x60000000 => "SHT_LOOS".to_string(),
// Match unknown segment type
_ => "UNKNOWN".to_string()
}
}
pub fn parse_section_flags(flags: u64) -> String {
match flags {
0x00000001 => "SHF_WRITE".to_string(),
0x00000002 => "SHF_ALLOC".to_string(),
0x00000004 => "SHF_EXECINSTR".to_string(),
0x00000010 => "SHF_MERGE".to_string(),
0x00000020 => "SHF_STRINGS".to_string(),
0x00000040 => "SHF_INFO_LINK".to_string(),
0x00000080 => "SHF_LINK_ORDER".to_string(),
0x00000100 => "SHF_OS_NONCONFORMING".to_string(),
0x00000200 => "SHF_GROUP".to_string(),
0x00000400 => "SHF_TLS".to_string(),
0x0FF00000 => "SHF_MASKOS".to_string(),
0xF0000000 => "SHF_MASKPROC".to_string(),
0x40000000 => "SHF_ORDERED".to_string(),
0x80000000 => "SHF_EXCLUDE".to_string(),
// Match unknown segment type
_ => "UNKNOWN".to_string()
}
}
pub fn parse_program_segment_type(segment_type: u32) -> String { pub fn parse_program_segment_type(segment_type: u32) -> String {
match segment_type { match segment_type {
0x00000000 => "PT_NULL".to_string(), 0x00000000 => "PT_NULL".to_string(),
@ -138,3 +284,47 @@ pub fn parse_program_segment_type(segment_type: u32) -> String {
_ => "UNKNOWN".to_string() _ => "UNKNOWN".to_string()
} }
} }
pub fn pp_file_header(header: &elf::FileHeader) {
println!("- Architecture: {:?}", header.arch);
println!("- Endian: {:?}", header.endian);
println!("- ABI: {}", header.abi_str);
println!("- Type: {}", parse_elf_type(header.elf_type));
println!("- ISA: {}", header.isa_str);
println!("- Entry Point: {:#04x}", header.entryoff);
println!("- Program Offset: {:#04x}", header.phoff);
println!("- Program Entry Size: {}", header.phentsize);
println!("- Number Program Entries: {}", header.phnum);
println!("- Section Offset: {:#04x}", header.shoff);
println!("- Section Entry Size: {}", header.shentsize);
println!("- Number Section Entries: {}", header.shnum);
}
pub fn pp_section_header(header: &elf::SectionHeader, number: i32, name: &String) {
println!("[{}] {}", number, name);
println!("\t- Type: {}", parse_section_type(header.section_type));
println!("\t- Flags: {}", parse_section_flags(header.flags));
println!("\t- Address: {:#04x}", header.section_type);
println!("\t- Offset: {:#04x}", header.section_type);
println!("\t- Link Index: {}", header.link);
println!("\t- Info Bytes: {}", header.info);
println!("\t- Alignment: {}", header.info);
println!();
}
pub fn pp_program_header(header: &elf::ProgramHeader, number: i32, ph_type: &String) {
println!("[{}] {}", number, ph_type);
println!("\t- Type: {}", parse_section_type(header.program_type));
println!("\t- Flags: {}", header.flags);
println!("\t- Offset: {:#04x}", header.offset);
println!("\t- Virtual Address: {:#04x}", header.vaddr);
println!("\t- Physical Address: {:#04x}", header.paddr);
println!("\t- File Size: {}", header.filesz);
println!("\t- Memory Size: {}", header.memsz);
println!("\t- Alignment: {}", header.align);
println!();
}

104
test_run
View File

@ -1,104 +0,0 @@
File exists, reading 'testing/hello'...
Found ELF Magic Number...
Parsing File Header...
- Found 13 program header entries 56 bytes in length
- Found 31 section header entries 64 bytes in length
- Found .shstrtab section at index 30
FileHeader { arch: X86_64, is_x86_64: true, endian: Little, abi: 0, abi_str: "SystemV", elf_type: 3, isa: 62, isa_str: "AMD x86-64", entryoff: 4192, phoff: 64, shoff: 13976, ehsize: 64, phentsize: 56, phnum: 13, shentsize: 64, shnum: 31, shstrndx: 30 }
Parsing Section Headers...
- Found .shstrtab section
=== Sections ===
[0]
SectionHeader { name: 0, section_type: 0, flags: 0, addr: 0, offset: 0, size: 0, link: 0, info: 0, addralign: 0, entsize: 0 }
[1] .interp
SectionHeader { name: 27, section_type: 1, flags: 2, addr: 792, offset: 792, size: 28, link: 0, info: 0, addralign: 1, entsize: 0 }
[2] .note.gnu.property
SectionHeader { name: 35, section_type: 7, flags: 2, addr: 824, offset: 824, size: 48, link: 0, info: 0, addralign: 8, entsize: 0 }
[3] .note.gnu.build-id
SectionHeader { name: 54, section_type: 7, flags: 2, addr: 872, offset: 872, size: 36, link: 0, info: 0, addralign: 4, entsize: 0 }
[4] .note.ABI-tag
SectionHeader { name: 73, section_type: 7, flags: 2, addr: 908, offset: 908, size: 32, link: 0, info: 0, addralign: 4, entsize: 0 }
[5] .gnu.hash
SectionHeader { name: 87, section_type: 1879048182, flags: 2, addr: 944, offset: 944, size: 36, link: 6, info: 0, addralign: 8, entsize: 0 }
[6] .dynsym
SectionHeader { name: 97, section_type: 11, flags: 2, addr: 984, offset: 984, size: 168, link: 7, info: 1, addralign: 8, entsize: 24 }
[7] .dynstr
SectionHeader { name: 105, section_type: 3, flags: 2, addr: 1152, offset: 1152, size: 143, link: 0, info: 0, addralign: 1, entsize: 0 }
[8] .gnu.version
SectionHeader { name: 113, section_type: 1879048191, flags: 2, addr: 1296, offset: 1296, size: 14, link: 6, info: 0, addralign: 2, entsize: 2 }
[9] .gnu.version_r
SectionHeader { name: 126, section_type: 1879048190, flags: 2, addr: 1312, offset: 1312, size: 48, link: 7, info: 1, addralign: 8, entsize: 0 }
[10] .rela.dyn
SectionHeader { name: 141, section_type: 4, flags: 2, addr: 1360, offset: 1360, size: 192, link: 6, info: 0, addralign: 8, entsize: 24 }
[11] .rela.plt
SectionHeader { name: 151, section_type: 4, flags: 66, addr: 1552, offset: 1552, size: 24, link: 6, info: 24, addralign: 8, entsize: 24 }
[12] .init
SectionHeader { name: 161, section_type: 1, flags: 6, addr: 4096, offset: 4096, size: 27, link: 0, info: 0, addralign: 4, entsize: 0 }
[13] .plt
SectionHeader { name: 156, section_type: 1, flags: 6, addr: 4128, offset: 4128, size: 32, link: 0, info: 0, addralign: 16, entsize: 16 }
[14] .plt.got
SectionHeader { name: 167, section_type: 1, flags: 6, addr: 4160, offset: 4160, size: 16, link: 0, info: 0, addralign: 16, entsize: 16 }
[15] .plt.sec
SectionHeader { name: 176, section_type: 1, flags: 6, addr: 4176, offset: 4176, size: 16, link: 0, info: 0, addralign: 16, entsize: 16 }
[16] .text
SectionHeader { name: 185, section_type: 1, flags: 6, addr: 4192, offset: 4192, size: 268, link: 0, info: 0, addralign: 16, entsize: 0 }
[17] .fini
SectionHeader { name: 191, section_type: 1, flags: 6, addr: 4460, offset: 4460, size: 13, link: 0, info: 0, addralign: 4, entsize: 0 }
[18] .rodata
SectionHeader { name: 197, section_type: 1, flags: 2, addr: 8192, offset: 8192, size: 18, link: 0, info: 0, addralign: 4, entsize: 0 }
[19] .eh_frame_hdr
SectionHeader { name: 205, section_type: 1, flags: 2, addr: 8212, offset: 8212, size: 52, link: 0, info: 0, addralign: 4, entsize: 0 }
[20] .eh_frame
SectionHeader { name: 219, section_type: 1, flags: 2, addr: 8264, offset: 8264, size: 172, link: 0, info: 0, addralign: 8, entsize: 0 }
[21] .init_array
SectionHeader { name: 229, section_type: 14, flags: 3, addr: 15800, offset: 11704, size: 8, link: 0, info: 0, addralign: 8, entsize: 8 }
[22] .fini_array
SectionHeader { name: 241, section_type: 15, flags: 3, addr: 15808, offset: 11712, size: 8, link: 0, info: 0, addralign: 8, entsize: 8 }
[23] .dynamic
SectionHeader { name: 253, section_type: 6, flags: 3, addr: 15816, offset: 11720, size: 496, link: 7, info: 0, addralign: 8, entsize: 16 }
[24] .got
SectionHeader { name: 171, section_type: 1, flags: 3, addr: 16312, offset: 12216, size: 72, link: 0, info: 0, addralign: 8, entsize: 8 }
[25] .data
SectionHeader { name: 262, section_type: 1, flags: 3, addr: 16384, offset: 12288, size: 16, link: 0, info: 0, addralign: 8, entsize: 0 }
[26] .bss
SectionHeader { name: 268, section_type: 8, flags: 3, addr: 16400, offset: 12304, size: 8, link: 0, info: 0, addralign: 1, entsize: 0 }
[27] .comment
SectionHeader { name: 273, section_type: 1, flags: 48, addr: 0, offset: 12304, size: 43, link: 0, info: 0, addralign: 1, entsize: 1 }
[28] .symtab
SectionHeader { name: 1, section_type: 2, flags: 0, addr: 0, offset: 12352, size: 864, link: 29, info: 18, addralign: 8, entsize: 24 }
[29] .strtab
SectionHeader { name: 9, section_type: 3, flags: 0, addr: 0, offset: 13216, size: 477, link: 0, info: 0, addralign: 1, entsize: 0 }
[30] .shstrtab
SectionHeader { name: 17, section_type: 3, flags: 0, addr: 0, offset: 13693, size: 282, link: 0, info: 0, addralign: 1, entsize: 0 }
Parsing Program Segments...
=== Program Segments ===
[0] PT_PHDR
ProgramHeader { program_type: 6, flags: 4, offset: 64, vaddr: 64, paddr: 64, filesz: 728, memsz: 728, align: 8 }
[1] PT_INTERP
ProgramHeader { program_type: 3, flags: 4, offset: 792, vaddr: 792, paddr: 792, filesz: 28, memsz: 28, align: 1 }
[2] PT_LOAD
ProgramHeader { program_type: 1, flags: 4, offset: 0, vaddr: 0, paddr: 0, filesz: 1576, memsz: 1576, align: 4096 }
[3] PT_LOAD
ProgramHeader { program_type: 1, flags: 5, offset: 4096, vaddr: 4096, paddr: 4096, filesz: 377, memsz: 377, align: 4096 }
[4] PT_LOAD
ProgramHeader { program_type: 1, flags: 4, offset: 8192, vaddr: 8192, paddr: 8192, filesz: 244, memsz: 244, align: 4096 }
[5] PT_LOAD
ProgramHeader { program_type: 1, flags: 6, offset: 11704, vaddr: 15800, paddr: 15800, filesz: 600, memsz: 608, align: 4096 }
[6] PT_DYNAMIC
ProgramHeader { program_type: 2, flags: 6, offset: 11720, vaddr: 15816, paddr: 15816, filesz: 496, memsz: 496, align: 8 }
[7] PT_NOTE
ProgramHeader { program_type: 4, flags: 4, offset: 824, vaddr: 824, paddr: 824, filesz: 48, memsz: 48, align: 8 }
[8] PT_NOTE
ProgramHeader { program_type: 4, flags: 4, offset: 872, vaddr: 872, paddr: 872, filesz: 68, memsz: 68, align: 4 }
[9] UNKNOWN
ProgramHeader { program_type: 1685382483, flags: 4, offset: 824, vaddr: 824, paddr: 824, filesz: 48, memsz: 48, align: 8 }
[10] UNKNOWN
ProgramHeader { program_type: 1685382480, flags: 4, offset: 8212, vaddr: 8212, paddr: 8212, filesz: 52, memsz: 52, align: 4 }
[11] UNKNOWN
ProgramHeader { program_type: 1685382481, flags: 6, offset: 0, vaddr: 0, paddr: 0, filesz: 0, memsz: 0, align: 16 }
[12] UNKNOWN
ProgramHeader { program_type: 1685382482, flags: 4, offset: 11704, vaddr: 15800, paddr: 15800, filesz: 584, memsz: 584, align: 1 }

View File

@ -1,9 +0,0 @@
File exists, reading 'testing/hello32'...
Found ELF Magic Number...
Parsing File Header...
- Found 11 program header entries 32 bytes in length
- Found 29 section header entries 40 bytes in length
- Found .shstrtab section at index 28
FileHeader { arch: X86, is_x86_64: false, endian: Little, abi: 0, abi_str: "SystemV", elf_type: 3, isa: 3, isa_str: "Intel x86", entryoff: 223338303600, phoff: 59184649338932, shoff: 13780, ehsize: 52, phentsize: 32, phnum: 11, shentsize: 40, shnum: 29, shstrndx: 28 }
Parsing Section Headers...

View File

@ -1 +1,3 @@
hello world hello world
this flat file should fail
because it doesn't have the ELF magic keyword

BIN
testing/isPrime Executable file

Binary file not shown.

32
testing/src/isPrime.c Normal file
View File

@ -0,0 +1,32 @@
#include <stdio.h>
int main() {
int n, i, flag = 0;
printf("Enter a positive integer: ");
scanf("%d", &n);
// 0 and 1 are not prime numbers
// change flag to 1 for non-prime number
if (n == 0 || n == 1)
flag = 1;
for (i = 2; i <= n / 2; ++i) {
// if n is divisible by i, then n is not prime
// change flag to 1 for non-prime number
if (n % i == 0) {
flag = 1;
break;
}
}
// flag is 0 for prime numbers
if (flag == 0) {
printf("%d is a prime number.", n);
}
else {
printf("%d is not a prime number.", n);
}
}

BIN
text.out

Binary file not shown.