Basic implementation of binary patching

This commit is contained in:
Garrett Dickinson 2023-04-10 17:09:49 -05:00
parent 8829e2803f
commit a98aa7f3bc
5 changed files with 554 additions and 28 deletions

View File

@ -226,7 +226,8 @@ fn main() {
println!("\n==== Applying Patch To Binary ====\n");
patcher::patch_binary(
bytes,
bytes.to_vec(),
file_path.to_string(),
&patch_file_path
);
}

View File

@ -4,23 +4,45 @@
// 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>, patch_file_path: &String) {
parse_patch_file(patch_file_path);
pub fn patch_binary(binary_contents: Vec<u8>, binary_name: String, patch_file_path: &String) {
// If valid
// Apply patch
// else
// err
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");
file.flush();
}
fn parse_patch_file(patch_path: &String) {
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
@ -31,6 +53,7 @@ fn parse_patch_file(patch_path: &String) {
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();
@ -38,14 +61,14 @@ fn parse_patch_file(patch_path: &String) {
} else {
let mut statement = unwrapped.split(":");
let address: i32 = statement.next().unwrap().trim().parse::<i32>().unwrap();
let address: usize = statement.next().unwrap().trim().parse::<usize>().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 = cleaned.as_bytes();
let bytes: Vec<u8> = cleaned.as_bytes().to_vec();
print!("{}: ", address);
@ -57,10 +80,12 @@ fn parse_patch_file(patch_path: &String) {
println!();
patch_data.insert(address, bytes);
} else {
// Data is comma seperated list or a single value
let byte_str: String = data.replace(",", "");
let mut bytes: Vec<u8> = util::decode_hex(&byte_str).unwrap();
let bytes: Vec<u8> = util::decode_hex(&byte_str).unwrap();
print!("{}: ", address);
@ -71,25 +96,17 @@ fn parse_patch_file(patch_path: &String) {
}
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);
}
std::process::exit(0);
}
fn apply_patch() {
// Iterate through parsed patch information
// Find the address at start of line, then apply following data to section
// Make sure within size limits of data, otherwise boundary problems
// Strings -> Iterate through characters specifically and parse them as individual ASCII chars
}

BIN
testing/hello_patched Executable file

Binary file not shown.

View File

@ -1,3 +1,3 @@
2002 : "Hello, World!"
20041 : DE,AD,BE,EF
45620 : 00,01,02,03
8196 : "Hello, Patch!"
#20041 : DE,AD,BE,EF
#45620 : 00,01,02,03

508
testrun Normal file
View File

@ -0,0 +1,508 @@
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
==== File Header ====
- Architecture: X86_64
- Endian: Little
- ABI: System V
- Type: Shared object
- ISA: AMD x86-64
- Entry Point: 0x1060
- Program Offset: 0x40
- Program Entry Size: 56
- Number Program Entries: 13
- Section Offset: 0x3698
- Section Entry Size: 64
- Number Section Entries: 31
Parsing Section Headers...
- Found .shstrtab section
==== Sections ====
[0]
- Type: SHT_NULL
- Flags: UNKNOWN
- Address: 0x00
- Offset: 0x00
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[1] .interp
- Type: SHT_PROGBITS
- Flags: SHF_ALLOC
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[2] .note.gnu.property
- Type: SHT_NOTE
- Flags: SHF_ALLOC
- Address: 0x07
- Offset: 0x07
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[3] .note.gnu.build-id
- Type: SHT_NOTE
- Flags: SHF_ALLOC
- Address: 0x07
- Offset: 0x07
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[4] .note.ABI-tag
- Type: SHT_NOTE
- Flags: SHF_ALLOC
- Address: 0x07
- Offset: 0x07
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[5] .gnu.hash
- Type: UNKNOWN
- Flags: SHF_ALLOC
- Address: 0x6ffffff6
- Offset: 0x6ffffff6
- Link Index: 6
- Info Bytes: 0
- Alignment: 0
[6] .dynsym
- Type: SHT_DYNSYM
- Flags: SHF_ALLOC
- Address: 0x0b
- Offset: 0x0b
- Link Index: 7
- Info Bytes: 1
- Alignment: 1
[7] .dynstr
- Type: SHT_STRTAB
- Flags: SHF_ALLOC
- Address: 0x03
- Offset: 0x03
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[8] .gnu.version
- Type: UNKNOWN
- Flags: SHF_ALLOC
- Address: 0x6fffffff
- Offset: 0x6fffffff
- Link Index: 6
- Info Bytes: 0
- Alignment: 0
[9] .gnu.version_r
- Type: UNKNOWN
- Flags: SHF_ALLOC
- Address: 0x6ffffffe
- Offset: 0x6ffffffe
- Link Index: 7
- Info Bytes: 1
- Alignment: 1
[10] .rela.dyn
- Type: SHT_RELA
- Flags: SHF_ALLOC
- Address: 0x04
- Offset: 0x04
- Link Index: 6
- Info Bytes: 0
- Alignment: 0
[11] .rela.plt
- Type: SHT_RELA
- Flags: UNKNOWN
- Address: 0x04
- Offset: 0x04
- Link Index: 6
- Info Bytes: 24
- Alignment: 24
[12] .init
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[13] .plt
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[14] .plt.got
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[15] .plt.sec
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[16] .text
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[17] .fini
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[18] .rodata
- Type: SHT_PROGBITS
- Flags: SHF_ALLOC
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[19] .eh_frame_hdr
- Type: SHT_PROGBITS
- Flags: SHF_ALLOC
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[20] .eh_frame
- Type: SHT_PROGBITS
- Flags: SHF_ALLOC
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[21] .init_array
- Type: SHT_INIT_ARRAY
- Flags: UNKNOWN
- Address: 0x0e
- Offset: 0x0e
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[22] .fini_array
- Type: SHT_FINI_ARRAY
- Flags: UNKNOWN
- Address: 0x0f
- Offset: 0x0f
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[23] .dynamic
- Type: SHT_DYNAMIC
- Flags: UNKNOWN
- Address: 0x06
- Offset: 0x06
- Link Index: 7
- Info Bytes: 0
- Alignment: 0
[24] .got
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[25] .data
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[26] .bss
- Type: SHT_NOBITS
- Flags: UNKNOWN
- Address: 0x08
- Offset: 0x08
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[27] .comment
- Type: SHT_PROGBITS
- Flags: UNKNOWN
- Address: 0x01
- Offset: 0x01
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[28] .symtab
- Type: SHT_SYMTAB
- Flags: UNKNOWN
- Address: 0x02
- Offset: 0x02
- Link Index: 29
- Info Bytes: 18
- Alignment: 18
[29] .strtab
- Type: SHT_STRTAB
- Flags: UNKNOWN
- Address: 0x03
- Offset: 0x03
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
[30] .shstrtab
- Type: SHT_STRTAB
- Flags: UNKNOWN
- Address: 0x03
- Offset: 0x03
- Link Index: 0
- Info Bytes: 0
- Alignment: 0
Parsing Program Segments...
==== Program Segments ====
[0] PT_PHDR
- Type: SHT_DYNAMIC
- Flags: 4
- Offset: 0x40
- Virtual Address: 0x40
- Physical Address: 0x40
- File Size: 728
- Memory Size: 728
- Alignment: 8
[1] PT_INTERP
- Type: SHT_STRTAB
- Flags: 4
- Offset: 0x318
- Virtual Address: 0x318
- Physical Address: 0x318
- File Size: 28
- Memory Size: 28
- Alignment: 1
[2] PT_LOAD
- Type: SHT_PROGBITS
- Flags: 4
- Offset: 0x00
- Virtual Address: 0x00
- Physical Address: 0x00
- File Size: 1576
- Memory Size: 1576
- Alignment: 4096
[3] PT_LOAD
- Type: SHT_PROGBITS
- Flags: 5
- Offset: 0x1000
- Virtual Address: 0x1000
- Physical Address: 0x1000
- File Size: 377
- Memory Size: 377
- Alignment: 4096
[4] PT_LOAD
- Type: SHT_PROGBITS
- Flags: 4
- Offset: 0x2000
- Virtual Address: 0x2000
- Physical Address: 0x2000
- File Size: 244
- Memory Size: 244
- Alignment: 4096
[5] PT_LOAD
- Type: SHT_PROGBITS
- Flags: 6
- Offset: 0x2db8
- Virtual Address: 0x3db8
- Physical Address: 0x3db8
- File Size: 600
- Memory Size: 608
- Alignment: 4096
[6] PT_DYNAMIC
- Type: SHT_SYMTAB
- Flags: 6
- Offset: 0x2dc8
- Virtual Address: 0x3dc8
- Physical Address: 0x3dc8
- File Size: 496
- Memory Size: 496
- Alignment: 8
[7] PT_NOTE
- Type: SHT_RELA
- Flags: 4
- Offset: 0x338
- Virtual Address: 0x338
- Physical Address: 0x338
- File Size: 48
- Memory Size: 48
- Alignment: 8
[8] PT_NOTE
- Type: SHT_RELA
- Flags: 4
- Offset: 0x368
- Virtual Address: 0x368
- Physical Address: 0x368
- File Size: 68
- Memory Size: 68
- Alignment: 4
[9] UNKNOWN
- Type: UNKNOWN
- Flags: 4
- Offset: 0x338
- Virtual Address: 0x338
- Physical Address: 0x338
- File Size: 48
- Memory Size: 48
- Alignment: 8
[10] UNKNOWN
- Type: UNKNOWN
- Flags: 4
- Offset: 0x2014
- Virtual Address: 0x2014
- Physical Address: 0x2014
- File Size: 52
- Memory Size: 52
- Alignment: 4
[11] UNKNOWN
- Type: UNKNOWN
- Flags: 6
- Offset: 0x00
- Virtual Address: 0x00
- Physical Address: 0x00
- File Size: 0
- Memory Size: 0
- Alignment: 16
[12] UNKNOWN
- Type: UNKNOWN
- Flags: 4
- Offset: 0x2db8
- Virtual Address: 0x3db8
- Physical Address: 0x3db8
- File Size: 584
- Memory Size: 584
- Alignment: 1
==== Text Section Analysis ====
0000000000001060 endbr64
0000000000001064 xor ebp,ebp
0000000000001066 mov r9,rdx
0000000000001069 pop rsi
000000000000106A mov rdx,rsp
000000000000106D and rsp,0`FFFF`FFFF`FFFF`FFF0h
0000000000001071 push rax
0000000000001072 push rsp
0000000000001073 xor r8d,r8d
0000000000001076 xor ecx,ecx
0000000000001078 lea rdi,[rel 1149h]
000000000000107F call qword [rel 3FD8h]
0000000000001085 hlt
0000000000001086 nop word [rax+rax]
0000000000001090 lea rdi,[rel 4010h]
0000000000001097 lea rax,[rel 4010h]
000000000000109E cmp rax,rdi
00000000000010A1 je short 0000`0000`0000`10B8h
00000000000010A3 mov rax,[rel 3FE0h]
00000000000010AA test rax,rax
00000000000010AD je short 0000`0000`0000`10B8h
00000000000010AF jmp rax
00000000000010B1 nop dword [rax]
00000000000010B8 ret
00000000000010B9 nop dword [rax]
00000000000010C0 lea rdi,[rel 4010h]
00000000000010C7 lea rsi,[rel 4010h]
00000000000010CE sub rsi,rdi
00000000000010D1 mov rax,rsi
00000000000010D4 shr rsi,3Fh
00000000000010D8 sar rax,3
00000000000010DC add rsi,rax
00000000000010DF sar rsi,1
00000000000010E2 je short 0000`0000`0000`10F8h
00000000000010E4 mov rax,[rel 3FF0h]
00000000000010EB test rax,rax
00000000000010EE je short 0000`0000`0000`10F8h
00000000000010F0 jmp rax
00000000000010F2 nop word [rax+rax]
00000000000010F8 ret
00000000000010F9 nop dword [rax]
0000000000001100 endbr64
0000000000001104 cmp byte [rel 4010h],0
000000000000110B jne short 0000`0000`0000`1138h
000000000000110D push rbp
000000000000110E cmp qword [rel 3FF8h],0
0000000000001116 mov rbp,rsp
0000000000001119 je short 0000`0000`0000`1127h
000000000000111B mov rdi,[rel 4008h]
0000000000001122 call 0000`0000`0000`1040h
0000000000001127 call 0000`0000`0000`1090h
000000000000112C mov byte [rel 4010h],1
0000000000001133 pop rbp
0000000000001134 ret
0000000000001135 nop dword [rax]
0000000000001138 ret
0000000000001139 nop dword [rax]
0000000000001140 endbr64
0000000000001144 jmp 0000`0000`0000`10C0h
0000000000001149 endbr64
000000000000114D push rbp
000000000000114E mov rbp,rsp
0000000000001151 lea rax,[rel 2004h]
0000000000001158 mov rdi,rax
000000000000115B mov eax,0
0000000000001160 call 0000`0000`0000`1050h
0000000000001165 mov eax,0
000000000000116A pop rbp