aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrFrugal <drfrugal@vmi2238186.contaboserver.net>2024-12-29 15:33:28 +0100
committerDrFrugal <drfrugal@vmi2238186.contaboserver.net>2024-12-29 15:33:28 +0100
commitbca32a698039330ed7daaa86bbbe8ba82d8bf95c (patch)
tree3a706da45e8ef6320e5da114c8edab5e07f4258f
init
-rw-r--r--.gitignore1
-rw-r--r--Cargo.toml8
-rw-r--r--LICENSE9
-rw-r--r--README.md7
-rw-r--r--src/main.rs63
5 files changed, 88 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..ef03938
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "laa_toggle"
+version = "0.1.2"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..91078c7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) 2023 DrFrugal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..44d867f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# laa_toggle
+
+Rust console app to analyze/modify the LAA flag in Windows PE-binaries.
+With LAA enabled, 32bit apps can allocate up to 4GiB of memory, instead of only 2GiB (on modern 64bit systems).
+
+Requires 1 argument: the path to the EXE file.
+The simplest way is to just drag the app you want to analyze/modify onto this one.
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..e3cbd3f
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,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();
+}