use std::env; use std::error::Error; use std::fs::OpenOptions; use std::io::stdin; use std::os::windows::fs::FileExt; use std::process::{Command, exit}; fn pause() { // call pause command to keep the console open, so the user can read infos/errors Command::new("cmd").args(&["/C", "pause"]).spawn().expect("failed to execute pause command"); } fn abort(message: &str, error: Option<&dyn Error>) -> ! { if let Some(error) = error { println!("{:}", error); } println!("{}. Abort!", message); pause(); exit(1); } fn main() { const IMAGE_FILE_LARGE_ADDRESS_AWARE: u8 = 0x20; let mut buffer2 = [0u8; 2]; let mut buffer4 = [0u8; 4]; let args= env::args().collect::>(); let path = match args.get(1) { None => abort("Didn't receive path to EXE as argument", None), Some(path) => path }; if !path.to_lowercase().ends_with(".exe") { abort("Argument is not an EXE", None); } println!("Working on: {}", path); let file = match OpenOptions::new().read(true).write(true).open(path) { Ok(file) => file, Err(error) => abort("Failed to open EXE in read/write mode", Some(&error)) }; if let Err(error) = file.seek_read(&mut buffer4, 0x3C) { abort("Failed to read e_lfanew of MS-DOS stub", Some(&error)); } let address_coff_characteristics = (u32::from_le_bytes(buffer4) + 0x4 + 0x12) as u64; // real data starts after "PE\0\0" string (first 4 Bytes) if let Err(error) = file.seek_read(&mut buffer2, address_coff_characteristics) { abort("Failed to read Characteristics from COFF file header", Some(&error)); } let is_laa_enabled = buffer2[0] & IMAGE_FILE_LARGE_ADDRESS_AWARE != 0; println!("LAA currently enabled: {}\nDo you want to change that [y/n]?", is_laa_enabled); let mut input = String::new(); if let Err(error) = stdin().read_line(&mut input) { abort("Failed to read user input from stdin", Some(&error)); } match input.to_lowercase().trim() { "y" => {}, "n" => return, _ => abort("Invalid input", None) } buffer2[0] ^= IMAGE_FILE_LARGE_ADDRESS_AWARE; // flip bit if let Err(error) = file.seek_write(buffer2.as_slice(), address_coff_characteristics) { abort("Failed to write modification back to file", Some(&error)); } println!("Modification written to disk."); pause(); }