1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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::<Vec<String>>();
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();
}
|