From a98aa7f3bc5f0f6c09f42188c070b8a3ba8c0ff1 Mon Sep 17 00:00:00 2001 From: Garrett Dickinson Date: Mon, 10 Apr 2023 17:09:49 -0500 Subject: [PATCH] Basic implementation of binary patching --- src/main.rs | 3 +- src/patcher.rs | 65 +++-- testing/hello_patched | Bin 0 -> 15960 bytes testing/patches/hello.patch | 6 +- testrun | 508 ++++++++++++++++++++++++++++++++++++ 5 files changed, 554 insertions(+), 28 deletions(-) create mode 100755 testing/hello_patched create mode 100644 testrun diff --git a/src/main.rs b/src/main.rs index 1b336f2..60010db 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 ); } diff --git a/src/patcher.rs b/src/patcher.rs index cd1944b..2b9aa42 100644 --- a/src/patcher.rs +++ b/src/patcher.rs @@ -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, patch_file_path: &String) { - parse_patch_file(patch_file_path); +pub fn patch_binary(binary_contents: Vec, binary_name: String, patch_file_path: &String) { - // If valid - // Apply patch - // else - // err + let patch_data: HashMap> = parse_patch_file(patch_file_path); + let mut bytes: Vec = 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>{ // 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> = 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::().unwrap(); + let address: usize = statement.next().unwrap().trim().parse::().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 = cleaned.as_bytes().to_vec(); print!("{}: ", address); @@ -56,11 +79,13 @@ 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 = util::decode_hex(&byte_str).unwrap(); + let bytes: Vec = 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 -} - - +} \ No newline at end of file diff --git a/testing/hello_patched b/testing/hello_patched new file mode 100755 index 0000000000000000000000000000000000000000..7cf478a79d2899ea750f2d1198e600eb0c70e0cd GIT binary patch literal 15960 zcmeHOYit}>6~4QU6NftS#>Ybo+K00{ zOYH*15LywnQPV%AqNpkesYn!2Bz_nvfU7_#NT3FOkP1}_6+x+Z)F}l85E;&yIp1bH zT_;inKPt_YcE5Wb-??|r+?lk~g_J&z|srtX{bgU5|C5uOVb!3s%0LF^b?8(fZEvQuxRy$Rtp#oaI}h&`TK0ny$^h$p93JZ=m) z%}1rZjn0EE`3FjRRYx{6)7R6HO|@q;`SN1>;{Lw&z8ic?>k(?YiQdZHL z&y;MdI5|F)E#$39b0*7C=W~U;L^V9us*cpXDCNI~KK#w+BC7ThVmy^wGh6wr>=WJh zAA6imLsT6gnG3FSTwjSDo_k^(FddL?fAfIE-9m++Y-ajrb`}91HP}Y2U z_x>k_t3JIqjy%JQqTfOy#xi1s7-k^MK$w9r17QZj41^g7Gw}A$z~35n|4Tpd=Q{o2 z+Lt<%(jQ#4qt1)^iJ#P+bq~(z{VJ(nci#6TK|`Bj|1?`(fA#l{kFS+fJeu*^tsoEmL z2d~=A)U`gYQ`fdS7aQ7^+3~C(`6pff-a&@F*YuNX`tyH1pg(`LMvt7+&tJ2fC_t?Q zsBGx2RkzF+(>Lld%MfGcrlOnu}@Daif z6MmC$jBt#w_lo13A>?s|LSXw^L}<1-r~MWyMwCy zj`wNO#|hQ;*y#3_Lk+jwSGTMVwBG%JeRsI83z`2(`aD5?cn8PsthecNI-uvaxSz+V zf438=k?paEqC?v@e}X#1a#+F)gc%4k5N06EK$w9r17QZj41^g7Gw?Rc0M->^9U;~T z@>)eM^&V6fE^ZS!E9(w-ij4J&yF|t_Qme>Vx5&>`TwwqEHK)MxbFxSfYYUe*vG)3U z)C*#Nho@GL3f>~vBG@bl5Sm(%^@v#O2!DS5>A2abz*tX~c2d0j5+ab1w;mLz>gRI7?5JQ?SWS6N5YI~B&c zXI1L6RN*+4>r4z^cKw?x>wMw=3{|T2f1~62t{bOGt;G@HI#!GGL)ZT{6+G|fT-vRb zb@YhxlI!16xqhI3jVjgFbJtTs;&AfeAy-d#i-b=})jgz-shyR4!rDRl#^?@(`waBG ztcT!3UE&1ePmw}6uHVtAbN+@GNTH%K1`*@tIH@BXpn({c5;q;HJUT{|$I)v?*4 z-K7<13A;IyF>G^Qk)mXm=jOCob$z+JVdsolUhrNb&s4#f&lYCPtdX({#gbu`7u9Sb zw~)1LE2VW-_uw`78N)0V%_YOi+r=d{S2S~$kt*kMOGNQW26@`+T+{p)B6Y|xMvo4R zj~F9|hYeb1Km75-1LMgdQqz70V?-CLK73Re2gi;K4vZN`Mn{j0Od68|gJUDa2rmCm zV733vR`^>f(>9fR5VB>ULgkGDloYaiI{-*nza79xl?q1M%%^y(K=KHAr80S=T(VM% zQbAwFOsOPXcTa+0(DnixB=0+@x|v}8)`s=n;S4IJm6me0IYVd{JxrrUn;xv&xOiEM(gUNOtAg+7bETxr}TFO%s9@<6E@@cDB$`tbJ z1cPivD{C@AY71FgX>K<)s%rBE61h^cW|d}JizM=hA@72ldd*797)hrn8YC}eQ5(%TO?nPAOIzjnW(qzQD!t7DS%U&?QCpaIXaSnPEO7X4e;WM!vpz4gvl~`>EKM z3+4@;q!e$L^YerIs`&qJf5H6&H5$y+$|0}{D6hF*Mfyfi{xgO+yophWN z#IO7=$nOK@>*V5=;Q9X=Y5n}T@G2-g0Dg9W&jk1hF#zGW5&yXWe?kbroAG}T;7S=yJqVh5t X@-D@^Z^HjCjbYI5 literal 0 HcmV?d00001 diff --git a/testing/patches/hello.patch b/testing/patches/hello.patch index 7d1cd92..04a869b 100644 --- a/testing/patches/hello.patch +++ b/testing/patches/hello.patch @@ -1,3 +1,3 @@ -2002 : "Hello, World!" -20041 : DE,AD,BE,EF -45620 : 00,01,02,03 \ No newline at end of file +8196 : "Hello, Patch!" +#20041 : DE,AD,BE,EF +#45620 : 00,01,02,03 \ No newline at end of file diff --git a/testrun b/testrun new file mode 100644 index 0000000..b66834f --- /dev/null +++ b/testrun @@ -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