From 078a4e6af433040545a26914560d154bfac34695 Mon Sep 17 00:00:00 2001 From: johannes Date: Sat, 1 Jun 2024 23:15:42 +0200 Subject: [PATCH] Initial commit --- .github/workflows/rust.yml | 18 ++++++++++++ .gitignore | 1 + Cargo.toml | 12 ++++++++ README.md | 27 ++++++++++++++++++ src/main.rs | 56 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+) create mode 100644 .github/workflows/rust.yml create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/main.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..c008716 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,18 @@ +name: Rust + +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose 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..0c14575 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "one_byte_wallhack" +version = "0.1.0" +edition = "2021" +license = "MIT" + +[dependencies] +bcrl-rs = { git = "https://github.com/Sumandora/bcrl-rs.git", version = "0.1.0" } +byteorder = "1.5.0" +lde = "0.3.0" +procfs = "0.16.0" +signature_scanner = { git = "https://github.com/Sumandora/sigscan-rs", version = "0.1.1" } diff --git a/README.md b/README.md new file mode 100644 index 0000000..dacc695 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Counter-Strike: 2 - One-Byte-Wallhack + +Extremely simple wall-hack achieved by patching a single byte. +**LINUX ONLY: THIS WILL NOT WORK ON ANYTHING BUT LINUX.** + +## How it works + +Patching the test instruction, in the IsOtherEnemy function, results in returning false for every call. +The game treats every player as a friendly. This means the game shows the overhead indicator and spectator glow on enemies. +IsOtherEnemy (at least this one) is not used by any other relevant functions so the game does not break because of this. + +``` +bool IsOtherEnemy(C_BaseEntity* player1, C_BaseEntity* player2) + 31 c0 XOR EAX,EAX ; clears return value + 48 85 f6 TEST RSI,RSI ; check if player2 is null + 0f 84 85 JZ LABEL_EXIT_EARLY ; return cleared return value => return false; + 00 00 00 + 55 PUSH RBP ; Normal function prologue + 48 89 e5 MOV RBP,RSP + 41 54 PUSH R12 + 49 89 fc MOV R12,RDI + 53 PUSH RBX + ; and so on... + + LABEL_EXIT_EARLY: + c3 RET +``` \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7f54cc6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,56 @@ +use std::{fs::OpenOptions, os::unix::fs::FileExt}; + +use bcrl_rs::{BcrlFactory, SearchConstraints}; +use byteorder::NativeEndian; +use procfs::process::all_processes; +use signature_scanner::Signature; + +fn main() { + let process = all_processes() + .expect("Couldn't read processes") + .filter_map(|p| p.ok()) + .find(|p| p.status().map(|s| s.name == "cs2").unwrap_or(false)) + .expect("No self-process?"); + let mem_file = OpenOptions::new() + .read(true) + .write(true) + .open("/proc/".to_owned() + &process.pid().to_string() + "/mem") + .expect("Could't open mem file"); + let factory = BcrlFactory::from_files( + &process.maps().expect("Couldn't open maps file"), + &mem_file, + false, + ) + .expect("Couldn't create bcrl factory"); + + let ptr = factory + .signature( + Signature::string("mp_dogtag_pickup_rule", true), + SearchConstraints::everything() + .thats_readable() + .with_name("libclient.so".to_owned()), + ) + .find_all_references::( + 4, + SearchConstraints::everything() + .thats_executable() + .with_name("libclient.so".to_owned()), + ) + .next_occurrence( + Signature::ida("4c 89 e6 4c 89 ef"), + SearchConstraints::everything() + .thats_readable() + .thats_executable() + .with_name("libclient.so".to_owned()), + ) + .step_forwards(6) + .step_forwards(1) + .relative_to_absolute::() + .step_forwards(2) + .get_pointer() + .expect("Couldn't find IsOtherEnemy"); + + mem_file + .write_at(&[0xc3], ptr as u64) + .expect("Couldn't write to offset"); +}