From d0bd1dd4055bdc7492dd954e2d11dc80fd0ae78f Mon Sep 17 00:00:00 2001 From: DrFrugal Date: Sun, 16 Jul 2023 15:18:23 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 ++ Cargo.toml | 8 ++++++ laa_toggle.iml | 12 ++++++++ src/main.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 Cargo.toml create mode 100644 laa_toggle.iml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index 3ca43ae..1246f29 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb +# IntelliJ IDEA +.idea \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8bada2c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "laa_toggle" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/laa_toggle.iml b/laa_toggle.iml new file mode 100644 index 0000000..2fecef3 --- /dev/null +++ b/laa_toggle.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..69b990d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,76 @@ +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_DOS_HEADER_E_LFANEW: u64 = 0x3C; + const IMAGE_FILE_LARGE_ADDRESS_AWARE: u8 = 0x20; + const IMAGE_FILE_MACHINE_AMD64: u16 = 0x8664; + const IMAGE_FILE_MACHINE_I386: u16 = 0x14C; + 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, IMAGE_DOS_HEADER_E_LFANEW) { + abort("Failed to read e_lfanew of MS DOS stub", Some(&error)); + } + let address_coff_machine = (u32::from_le_bytes(buffer4) + 0x4) as u64; // real data starts after "PE\0\0" string + if let Err(error) = file.seek_read(&mut buffer2, address_coff_machine) { + abort("Failed to read Machine of PE header", Some(&error)); + } + let machine = u16::from_le_bytes(buffer2); + match machine { + IMAGE_FILE_MACHINE_I386 => {}, + IMAGE_FILE_MACHINE_AMD64 => abort("This binary is 64 bit - LAA is not needed", None), + _ => abort(&*format!("Unsupported machine type: {}", machine), None) + } + let address_coff_characteristics = address_coff_machine + 0x12; + if let Err(error) = file.seek_read(&mut buffer2, address_coff_characteristics) { + abort("Failed to read Characteristics from PE 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(); +}