Add support for ELF code injection

This commit is contained in:
Garrett Dickinson 2023-04-27 11:08:54 -05:00
parent 8aa55bdb23
commit ab0f273cd9
15 changed files with 413 additions and 198 deletions

6
notes/code_injection.md Normal file
View File

@ -0,0 +1,6 @@
# ELF Code injection notes
- Locate PT_NOTE segments in binary
- Locate a suitable `.note.*` section for replacing code
- Modify the injection code section type from `SHT_NOTE` to `SHT_PROGBITS`
- Update relevant start, offset, and end addresses for new section

View File

@ -1,9 +1,9 @@
To Do # To Do
Code injection ## Code injection
- Have a script with 3 functions, (main, funcA, funcB), and replace refs to funcA with funcB - Have a script with 3 functions, (main, funcA, funcB), and replace refs to funcA with funcB
- Trampoline definitions of a function to a new modified function that gets places in memory - Trampoline definitions of a function to a new modified function that gets places in memory
-
Injected code: 0x680 Injected code: 0x680
Call: 0x1160 Call: 0x1160

View File

@ -121,8 +121,9 @@ pub struct FileHeader {
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ProgramHeader { pub struct ProgramHeader {
pub id: u16,
pub program_type: u32, pub program_type: u32,
pub flags: u32, pub flags: u32,
pub offset: u64, pub offset: u64,
@ -134,9 +135,10 @@ pub struct ProgramHeader {
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct SectionHeader { pub struct SectionHeader {
pub name: u32, pub id: u16,
pub name_idx: u32,
pub section_type: u32, pub section_type: u32,
pub flags: u64, pub flags: u64,
pub addr: u64, pub addr: u64,

View File

@ -20,7 +20,7 @@ mod patcher;
fn main() { fn main() {
// Collect our execution args // Collect our execution args
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let mut patch_mode: bool = false; let mut inject_mode: bool = false;
let mut patch_file_path: &String = &"".to_string(); let mut patch_file_path: &String = &"".to_string();
// Grab our filepath from our options // Grab our filepath from our options
@ -34,7 +34,7 @@ fn main() {
if &args.len() > &2 { if &args.len() > &2 {
if &args[2] == "-p" { if &args[2] == "-p" {
if &args.len() >= &4 { if &args.len() >= &4 {
patch_mode = true; inject_mode = true;
patch_file_path = &args[3]; patch_file_path = &args[3];
} else { } else {
util::print_help(); util::print_help();
@ -87,6 +87,7 @@ fn main() {
let shstrtab_section: elf::SectionHeader = util::build_section_header( let shstrtab_section: elf::SectionHeader = util::build_section_header(
bytes, bytes,
shstrtab_offset as usize, shstrtab_offset as usize,
file_header.shstrndx,
file_header.is_x86_64 file_header.is_x86_64
); );
@ -104,17 +105,18 @@ fn main() {
let mut section_table_count: i32 = 0; let mut section_table_count: i32 = 0;
// Iterate through number of section headers // Iterate through number of section headers
for _ in 0..file_header.shnum { for i in 0..file_header.shnum {
// Build section header data structure // Build section header data structure
let section_header: elf::SectionHeader = util::build_section_header( let section_header: elf::SectionHeader = util::build_section_header(
bytes, bytes,
section_table_offset as usize, section_table_offset as usize,
i,
file_header.is_x86_64 file_header.is_x86_64
); );
// 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_idx as usize);
util::pp_section_header(&section_header, section_table_count, &section_name); util::pp_section_header(&section_header, section_table_count, &section_name);
@ -131,19 +133,25 @@ fn main() {
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;
let mut pt_note_offset: usize = 0;
// Iterate through number of Program Headers // Iterate through number of Program Headers
for _ in 0..file_header.phnum { for i in 0..file_header.phnum {
// Build Program Header data structure // Build Program Header data structure
let program_header: elf::ProgramHeader = util::build_program_header( let program_header: elf::ProgramHeader = util::build_program_header(
bytes, bytes,
program_table_offset as usize, program_table_offset as usize,
i,
file_header.is_x86_64 file_header.is_x86_64
); );
// Parse the program name using the program type // 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);
if (program_name == "PT_NOTE") && (pt_note_offset == 0) {
pt_note_offset = program_table_offset as usize;
}
util::pp_program_header(&program_header, program_table_count, &program_name); util::pp_program_header(&program_header, program_table_count, &program_name);
// Update the program header table offset counter based on the program header size // Update the program header table offset counter based on the program header size
@ -151,6 +159,13 @@ fn main() {
program_table_count += 1; program_table_count += 1;
} }
let note_segment: elf::ProgramHeader = util::build_program_header(
bytes,
pt_note_offset,
0,
file_header.is_x86_64
);
// Now that we have all the sections, spit out the .text section and start a linear disassembly // Now that we have all the sections, spit out the .text section and start a linear disassembly
let text_section: &elf::SectionHeader = section_table_map.get(".text").unwrap(); let text_section: &elf::SectionHeader = section_table_map.get(".text").unwrap();
@ -221,14 +236,17 @@ fn main() {
} }
if patch_mode { if inject_mode {
println!("\n==== Applying Patch To Binary ====\n"); println!("\n==== Injecting Payload To Binary ====\n");
patcher::patch_binary( patcher::patch_binary(
bytes.to_vec(), bytes.to_vec(),
file_path.to_string(), file_path.to_string(),
&patch_file_path &patch_file_path,
&file_header,
section_table_map,
note_segment
); );
} }
@ -238,7 +256,7 @@ fn main() {
} }
} }
} else { } else {
println!("[Error] '{}' does not exist", file_path); println!("[Error] File '{}' does not exist", file_path);
exit(-1); exit(-1);
} }

View File

@ -4,105 +4,124 @@
// Description: Houses binary rewriting and patching functionality for chisel. // Description: Houses binary rewriting and patching functionality for chisel.
use std::path; use std::path;
use std::fs;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write; use std::io::Write;
use std::io::Error;
use crate::util; use crate::util;
use crate::elf;
pub fn patch_binary(binary_contents: Vec<u8>, binary_name: String, patch_file_path: &String) { pub fn patch_binary(
binary_contents: Vec<u8>,
binary_name: String,
patch_file_path: &String,
file_header: &elf::FileHeader,
section_header_map: HashMap<String, elf::SectionHeader>,
note_segment: elf::ProgramHeader) {
let patch_data: HashMap<usize, Vec<u8>> = parse_patch_file(patch_file_path);
let mut bytes: Vec<u8> = binary_contents;
println!("Patch data read successfully, applying..."); let patch_result: Result<Vec<u8>,Error> = read_patch_file(patch_file_path);
let patch_data: &Vec<u8> = &patch_result.as_ref().unwrap();
for patch in patch_data { let mut program_data: Vec<u8> = binary_contents;
let start_offset = patch.0;
let mut i: usize = 0;
while i < (patch.1.len()) {
bytes[(start_offset + i) as usize] = patch.1[i];
i += 1;
}
}
println!("Done!");
let patched_file_name: String = binary_name + "_patched"; // Apply patch to end of binary
println!("Patch data read successfully, injecting at end of binary...");
println!("Writing '{}' to disk...", patched_file_name); let injection_offset: usize = program_data.len();
let injection_size: usize = patch_data.len();
let injection_addr: usize = injection_offset;
let mut file = std::fs::File::create(patched_file_name) program_data.extend_from_slice(patch_data);
print!("Done!");
// Locate a note segment
println!("Pulling .note.ABI-tag segment data...");
let note_section: &elf::SectionHeader = section_header_map.get(".note.ABI-tag")
.expect("[Error] Failed to pull ABI-tag section from binary!");
print!("Done!\n");
println!("Note section address: {:#04x}", note_section.addr);
println!("Note section offset: {:#04x}", note_section.offset);
println!("Note section size: {}", note_section.size);
println!("");
println!("Injected address: {:#04x}", injection_addr);
println!("Injected section offset: {:#04x}", injection_offset);
println!("Injected section size: {}", injection_size);
// Rewrite the section header
let mut injected_section: elf::SectionHeader = elf::SectionHeader::from(note_section.clone());
injected_section.section_type = 1;
injected_section.addr = injection_addr as u64;
injected_section.offset = injection_offset as u64;
injected_section.size = injection_size as u64;
util::overwrite_section_header(
&mut program_data,
file_header.shoff as usize,
file_header.shentsize as usize,
injected_section.id as usize,
&injected_section,
file_header.is_x86_64
);
//
// Rewrite the section header
let mut injected_segment: elf::ProgramHeader = elf::ProgramHeader::from(note_segment.clone());
injected_segment.program_type = 1;
injected_segment.offset = injection_offset as u64;
injected_segment.vaddr = injection_offset as u64;
injected_segment.paddr = injection_offset as u64;
injected_segment.filesz = injection_size as u64;
injected_segment.memsz = injection_size as u64;
injected_segment.flags = 5;
injected_segment.align = 0x1000;
util::overwrite_segment_header(
&mut program_data,
file_header.shoff as usize,
file_header.shentsize as usize,
injected_section.id as usize,
&injected_section,
file_header.is_x86_64
);
util::overwrite_entrypoint(&mut program_data, injection_offset);
// Spit everything back out
let out_file_name: String = binary_name + ".patched";
println!("Writing '{}' to disk...", out_file_name);
let mut file = std::fs::File::create(out_file_name)
.expect("[Error] Could not write patched binary to disk"); .expect("[Error] Could not write patched binary to disk");
file.write_all(&bytes) file.write_all(&program_data)
.expect("[Error] Could not write to patched binary file"); .expect("[Error] Could not write to patched binary data file");
} }
fn parse_patch_file(patch_path: &String) -> HashMap<usize, Vec<u8>>{ fn read_patch_file(patch_path: &String) -> Result<Vec<u8>, std::io::Error> {
// Load the file from patch_binary() arg
// Iterate through file, if line starts with # ignore
// Otherwise, parse as such
// [ADDRESS] [SPACE] [HEX],[HEX],[HEX],....
// [ADDRESS] [SPACE] [STRING]
if path::Path::new(patch_path).exists() && patch_path.ends_with(".patch") { if path::Path::new(patch_path).exists() && patch_path.ends_with(".bin") {
println!("Patch file exists, reading '{}'...", patch_path); println!("Patch file exists, reading '{}'...", patch_path);
let contents = util::read_lines(patch_path.to_string()); let contents: Result<Vec<u8>, std::io::Error> = fs::read(patch_path);
let mut patch_data: HashMap<usize, Vec<u8>> = HashMap::new();
for line in contents { return contents;
let unwrapped = line.unwrap();
if unwrapped.trim().starts_with("#") || unwrapped.is_empty() {
//Skip
} else {
let mut statement = unwrapped.split(":");
let address: usize = util::hex_to_int(statement.next().unwrap().trim()).unwrap();
let data: &str = statement.next().unwrap().trim();
if !data.is_empty() {
if data.contains("\"") {
// Value is a string literal
let cleaned = data.replace("\"", "");
let bytes: Vec<u8> = cleaned.as_bytes().to_vec();
print!("{}: ", address);
let mut i = 0;
while i < bytes.len() {
print!("{} ", bytes[i]);
i = i + 1;
}
println!();
patch_data.insert(address, bytes);
} else {
// Data is comma seperated list or a single value
let byte_str: String = data.replace(",", "");
let bytes: Vec<u8> = util::hex_to_buff(&byte_str).unwrap();
print!("{}: ", address);
let mut i = 0;
while i < bytes.len() {
print!("{} ", bytes[i]);
i = i + 1;
}
println!();
patch_data.insert(address, bytes);
}
}
}
}
return patch_data;
} else { } else {
println!("[Error] Patch file '{}' is invalid or cannot be read, exiting...", patch_path); println!("[Error] Patch file '{}' is invalid or cannot be read, exiting...", patch_path);

111
src/patcher.rs.bak Normal file
View File

@ -0,0 +1,111 @@
// patcher.rs
// Author: Garrett Dickinson
// Created: 04/06/2023
// Description: Houses binary rewriting and patching functionality for chisel.
use std::path;
use std::collections::HashMap;
use std::io::Write;
use crate::util;
pub fn patch_binary(binary_contents: Vec<u8>, binary_name: String, patch_file_path: &String) {
let patch_data: HashMap<usize, Vec<u8>> = parse_patch_file(patch_file_path);
let mut bytes: Vec<u8> = binary_contents;
println!("Patch data read successfully, applying...");
for patch in patch_data {
let start_offset = patch.0;
let mut i: usize = 0;
while i < (patch.1.len()) {
bytes[(start_offset + i) as usize] = patch.1[i];
i += 1;
}
}
println!("Done!");
let patched_file_name: String = binary_name + "_patched";
println!("Writing '{}' to disk...", patched_file_name);
let mut file = std::fs::File::create(patched_file_name)
.expect("[Error] Could not write patched binary to disk");
file.write_all(&bytes)
.expect("[Error] Could not write to patched binary file");
}
fn parse_patch_file(patch_path: &String) -> HashMap<usize, Vec<u8>>{
// Load the file from patch_binary() arg
// Iterate through file, if line starts with # ignore
// Otherwise, parse as such
// [ADDRESS] [SPACE] [HEX],[HEX],[HEX],....
// [ADDRESS] [SPACE] [STRING]
if path::Path::new(patch_path).exists() && patch_path.ends_with(".patch") {
println!("Patch file exists, reading '{}'...", patch_path);
let contents = util::read_lines(patch_path.to_string());
let mut patch_data: HashMap<usize, Vec<u8>> = HashMap::new();
for line in contents {
let unwrapped = line.unwrap();
if unwrapped.trim().starts_with("#") || unwrapped.is_empty() {
//Skip
} else {
let mut statement = unwrapped.split(":");
let address: usize = util::hex_to_int(statement.next().unwrap().trim()).unwrap();
let data: &str = statement.next().unwrap().trim();
if !data.is_empty() {
if data.contains("\"") {
// Value is a string literal
let cleaned = data.replace("\"", "");
let bytes: Vec<u8> = cleaned.as_bytes().to_vec();
print!("{}: ", address);
let mut i = 0;
while i < bytes.len() {
print!("{} ", bytes[i]);
i = i + 1;
}
println!();
patch_data.insert(address, bytes);
} else {
// Data is comma seperated list or a single value
let byte_str: String = data.replace(",", "");
let bytes: Vec<u8> = util::hex_to_buff(&byte_str).unwrap();
print!("{}: ", address);
let mut i = 0;
while i < bytes.len() {
print!("{} ", bytes[i]);
i = i + 1;
}
println!();
patch_data.insert(address, bytes);
}
}
}
}
return patch_data;
} else {
println!("[Error] Patch file '{}' is invalid or cannot be read, exiting...", patch_path);
std::process::exit(0);
}
}

View File

@ -5,9 +5,9 @@
// functions. // functions.
use std::mem; use std::mem;
use std::io::{self, BufReader, BufRead}; // use std::io::{self, BufReader, BufRead};
use std::fs::File; // use std::fs::File;
use std::num::ParseIntError; // use std::num::ParseIntError;
use crate::elf::{self, EndianType, ArchitectureType}; use crate::elf::{self, EndianType, ArchitectureType};
@ -43,7 +43,7 @@ pub fn build_file_header(data: &Vec<u8>) -> elf::FileHeader {
} }
pub fn build_program_header(data: &Vec<u8>, phoffset: usize, is_x86_64: bool) -> elf::ProgramHeader { pub fn build_program_header(data: &Vec<u8>, phoffset: usize, id: u16, is_x86_64: bool) -> elf::ProgramHeader {
// Cast the supplied is_x86_64 bool to an array offset // Cast the supplied is_x86_64 bool to an array offset
// 0 : x86 // 0 : x86
@ -51,6 +51,7 @@ pub fn build_program_header(data: &Vec<u8>, phoffset: usize, is_x86_64: bool) ->
let arch: usize = is_x86_64.into(); let arch: usize = is_x86_64.into();
let program_header: elf::ProgramHeader = elf::ProgramHeader { let program_header: elf::ProgramHeader = elf::ProgramHeader {
id: id,
program_type: u32_from_buffer(data, phoffset + elf::PH_TYPE_OFFSET as usize), 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), 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), offset: u64_from_buffer(data, phoffset + elf::PH_OFFSET_OFFSET[arch] as usize),
@ -65,7 +66,48 @@ pub fn build_program_header(data: &Vec<u8>, phoffset: usize, is_x86_64: bool) ->
} }
pub fn build_section_header(data: &Vec<u8>, shoffset: usize, is_x86_64: bool) -> elf::SectionHeader { pub fn overwrite_segment_header(program_data: &mut Vec<u8>,
stoffset: usize,
shentsize: usize,
shentidx: usize,
new_section: &elf::SectionHeader,
is_x86_64: bool) {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
println!("stoffset {}", stoffset);
println!("shentsize {}", shentsize);
println!("shentidx {}", shentidx);
let section_addr_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_ADDR_OFFSET[arch] as usize;
let section_offset_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_OFFSET_OFFSET[arch] as usize;
let section_size_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_SIZE_OFFSET[arch] as usize;
let section_type_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_TYPE_OFFSET as usize;
program_data[section_addr_offset..section_addr_offset+8].copy_from_slice(
&new_section.addr.to_ne_bytes().to_vec());
println!("Overwriting section addr with {:#04x}", new_section.addr);
program_data[section_offset_offset..section_offset_offset+8].copy_from_slice(
&new_section.offset.to_ne_bytes().to_vec());
println!("Overwriting section offset with {:#04x}", new_section.offset as usize);
program_data[section_size_offset..section_size_offset+8].copy_from_slice(
&new_section.size.to_ne_bytes().to_vec());
println!("Overwriting section size with {:#04x}", new_section.size as usize);
program_data[section_type_offset..section_type_offset+4].copy_from_slice(
&new_section.section_type.to_ne_bytes().to_vec());
println!("Overwriting section type with {:#04x}", new_section.section_type as usize);
// return section_header;
}
pub fn build_section_header(data: &Vec<u8>, stoffset: usize, id: u16, is_x86_64: bool) -> elf::SectionHeader {
// Cast the supplied is_x86_64 bool to an array offset // Cast the supplied is_x86_64 bool to an array offset
// 0 : x86 // 0 : x86
@ -73,22 +115,74 @@ pub fn build_section_header(data: &Vec<u8>, shoffset: usize, is_x86_64: bool) ->
let arch: usize = is_x86_64.into(); let arch: usize = is_x86_64.into();
let section_header: elf::SectionHeader = elf::SectionHeader { let section_header: elf::SectionHeader = elf::SectionHeader {
name: u32_from_buffer(data, shoffset + elf::SH_NAME_OFFSET as usize), id: id,
section_type: u32_from_buffer(data, shoffset + elf::SH_TYPE_OFFSET as usize), name_idx: u32_from_buffer(data, stoffset + elf::SH_NAME_OFFSET as usize),
flags: u64_from_buffer(data, shoffset + elf::SH_FLAGS_OFFSET as usize), section_type: u32_from_buffer(data, stoffset + elf::SH_TYPE_OFFSET as usize),
addr: u64_from_buffer(data, shoffset + elf::SH_ADDR_OFFSET[arch] as usize), flags: u64_from_buffer(data, stoffset + elf::SH_FLAGS_OFFSET as usize),
offset: u64_from_buffer(data, shoffset + elf::SH_OFFSET_OFFSET[arch] as usize), addr: u64_from_buffer(data, stoffset + elf::SH_ADDR_OFFSET[arch] as usize),
size: u64_from_buffer(data, shoffset + elf::SH_SIZE_OFFSET[arch] as usize), offset: u64_from_buffer(data, stoffset + elf::SH_OFFSET_OFFSET[arch] as usize),
link: u32_from_buffer(data, shoffset + elf::SH_LINK_OFFSET[arch] as usize), size: u64_from_buffer(data, stoffset + elf::SH_SIZE_OFFSET[arch] as usize),
info: u32_from_buffer(data, shoffset + elf::SH_INFO_OFFSET[arch] as usize), link: u32_from_buffer(data, stoffset + elf::SH_LINK_OFFSET[arch] as usize),
addralign: u64_from_buffer(data, shoffset + elf::SH_ADDRALIGN_OFFSET[arch] as usize), info: u32_from_buffer(data, stoffset + elf::SH_INFO_OFFSET[arch] as usize),
entsize: u64_from_buffer(data, shoffset + elf::SH_ENTSIZE_OFFSET[arch] as usize) addralign: u64_from_buffer(data, stoffset + elf::SH_ADDRALIGN_OFFSET[arch] as usize),
entsize: u64_from_buffer(data, stoffset + elf::SH_ENTSIZE_OFFSET[arch] as usize)
}; };
return section_header; return section_header;
} }
pub fn overwrite_section_header(program_data: &mut Vec<u8>,
stoffset: usize,
shentsize: usize,
shentidx: usize,
new_section: &elf::SectionHeader,
is_x86_64: bool) {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
println!("stoffset {}", stoffset);
println!("shentsize {}", shentsize);
println!("shentidx {}", shentidx);
let section_addr_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_ADDR_OFFSET[arch] as usize;
let section_offset_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_OFFSET_OFFSET[arch] as usize;
let section_size_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_SIZE_OFFSET[arch] as usize;
let section_type_offset: usize = stoffset + (shentsize * shentidx) + elf::SH_TYPE_OFFSET as usize;
program_data[section_addr_offset..section_addr_offset+8].copy_from_slice(
&new_section.addr.to_ne_bytes().to_vec());
println!("Overwriting section addr with {:#04x}", new_section.addr);
program_data[section_offset_offset..section_offset_offset+8].copy_from_slice(
&new_section.offset.to_ne_bytes().to_vec());
println!("Overwriting section offset with {:#04x}", new_section.offset as usize);
program_data[section_size_offset..section_size_offset+8].copy_from_slice(
&new_section.size.to_ne_bytes().to_vec());
println!("Overwriting section size with {:#04x}", new_section.size as usize);
program_data[section_type_offset..section_type_offset+4].copy_from_slice(
&new_section.section_type.to_ne_bytes().to_vec());
println!("Overwriting section type with {:#04x}", new_section.section_type as usize);
// return section_header;
}
pub fn overwrite_entrypoint(program_data: &mut Vec<u8>,
new_entry_point: usize) {
let offset: usize = elf::ENTRYPOINT_OFFSET as usize;
program_data[offset..offset+8].copy_from_slice(
&new_entry_point.to_ne_bytes().to_vec()
);
}
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,
@ -339,23 +433,28 @@ pub fn print_help() {
} }
pub fn read_lines(filename: String) -> io::Lines<BufReader<File>> { // pub fn read_lines(filename: String) -> io::Lines<BufReader<File>> {
// Open the file in read-only mode. // // Open the file in read-only mode.
let file = File::open(filename).unwrap(); // let file = File::open(filename).unwrap();
// Read the file line by line, and return an iterator of the lines of the file. // // Read the file line by line, and return an iterator of the lines of the file.
return io::BufReader::new(file).lines(); // return io::BufReader::new(file).lines();
} // }
// Borrowed from the following Stack Overflow post // // Borrowed from the following Stack Overflow post
// https://stackoverflow.com/questions/52987181/how-can-i-convert-a-hex-string-to-a-u8-slice // // https://stackoverflow.com/questions/52987181/how-can-i-convert-a-hex-string-to-a-u8-slice
pub fn hex_to_buff(s: &str) -> Result<Vec<u8>, ParseIntError> { // pub fn hex_to_buff(s: &str) -> Result<Vec<u8>, ParseIntError> {
(0..s.len()) // (0..s.len())
.step_by(2) // .step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16)) // .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
.collect() // .collect()
} // }
pub fn hex_to_int(s: &str) -> Result<usize, ParseIntError> { // pub fn hex_to_usize(s: &str) -> Result<usize, ParseIntError> {
return usize::from_str_radix(s, 16) // return usize::from_str_radix(s, 16)
} // }
// pub fn usize_to_hex(i: usize) -> String {
// return format!("{:X}", i).to_string();
// }

Binary file not shown.

View File

@ -0,0 +1,32 @@
BITS 64
SECTION .text
global main
main:
push rax
push rcx
push rdx
push rsi
push rdi
push r11
mov rax,1
mov rdi,1
lea rsi,[rel $+hello-$]
mov rdx,[rel $+len-$]
syscall
pop r11
pop rdi
pop rsi
pop rdx
pop rcx
pop rax
;push 0x1060 ; jump to original entry point
; ; could be replaced dynamically?
;ret
hello: db "Calling injected code >:)",10
len: dd 26

BIN
testing/elfpatching/login Executable file

Binary file not shown.

Binary file not shown.

View File

@ -1,14 +0,0 @@
# Trampoline segment
# Pushes and returns to 0x116b
#3f80 : 48C7C00100000048C7C70100000048C7C68007000048C7C20D0000000F05686B110000C3
# No syscall
1190 : 48C7C00100000048C7C70100000048C7C6C011000048C7C20D000000686B110000C3
# String data to print from trampoline instruction
11C0 : "Hello, World!"
# Initial jump to trampoline
#1160 : 6880060000C3
#1160 : 6890110000C3
2004 : "Hello, Patch!"

View File

@ -1,12 +0,0 @@
int main() {
return 0;
}
int my_function() {
return 0;
}
int another_function() {
return 0;
}

View File

@ -1,46 +0,0 @@
.file "main.c"
.text
.section .rodata
.LC0:
.string "Hello, World!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4: