()
| 2 | use getopts::Options; |
| 3 | |
| 4 | fn main() { |
| 5 | unsafe |
| 6 | { |
| 7 | |
| 8 | let args: Vec<String> = env::args().collect(); |
| 9 | let program = args[0].clone(); |
| 10 | let mut opts = Options::new(); |
| 11 | opts.optflag("h", "help", "Print this help menu."); |
| 12 | opts.optopt("i", "input", "Input dll's path.",""); |
| 13 | opts.optopt("o", "output", "Path where the resulting dll should be written to.",""); |
| 14 | opts.optopt("f", "function", "Exported function to use as the new entry point.",""); |
| 15 | opts.optflag("e", "make_exe", "Change the dll's characteristics to those expected from an .exe file."); |
| 16 | opts.optflag("n", "nullify_callbacks", "Replace all TLS callbacks with a return (0xC3) instruction."); |
| 17 | |
| 18 | |
| 19 | let matches = match opts.parse(&args[1..]) { |
| 20 | Ok(m) => { m } |
| 21 | Err(x) => {println!("{}",x);print!("{}","[x] Invalid arguments. Use -h for detailed help."); return; } |
| 22 | }; |
| 23 | |
| 24 | if matches.opt_present("h") || !matches.opt_present("i") || !matches.opt_present("o") || (!matches.opt_present("f") && !matches.opt_present("e")){ |
| 25 | print_usage(&program, opts); |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | let input = matches.opt_str("i").unwrap(); |
| 30 | let output = matches.opt_str("o").unwrap(); |
| 31 | let mut function = String::new(); |
| 32 | if matches.opt_present("f") |
| 33 | { |
| 34 | function = matches.opt_str("f").unwrap(); |
| 35 | |
| 36 | } |
| 37 | |
| 38 | let file_content = fs::read(&input).expect("[x] Error opening the specified dll."); |
| 39 | let pe_ptr = file_content.as_ptr() as *mut u8; |
| 40 | let mapping_result = dinvoke_rs::manualmap::read_and_map_module(&input, false, false).unwrap(); |
| 41 | let mapped_pe = mapping_result.1; |
| 42 | let function_addr = dinvoke_rs::dinvoke::get_function_address(mapped_pe, &function); |
| 43 | if function_addr == 0 && function != String::new() |
| 44 | { |
| 45 | println!("[x] The dll does not export any function with name {}", function); |
| 46 | return; |
| 47 | } |
| 48 | |
| 49 | let e_lfanew: usize = *((pe_ptr as usize + 0x3C) as *const u32) as usize; |
| 50 | |
| 51 | if function != String::new() |
| 52 | { |
| 53 | println!("[-] Patching entry point at RVA 0x{:x}...", e_lfanew + 0x18 + 16); |
| 54 | let entry = (pe_ptr as usize + e_lfanew + 0x18 + 16) as *mut u32; |
| 55 | *entry = (function_addr - mapped_pe) as u32; |
| 56 | } |
| 57 | |
| 58 | if matches.opt_present("e") |
| 59 | { |
| 60 | let characteristics = (pe_ptr as usize + e_lfanew as usize + 0x4 + 0x13) as *mut u8; |
| 61 | *characteristics = 0; |
nothing calls this directly
no test coverage detected