Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Sumandora committed Jun 1, 2024
0 parents commit 078a4e6
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
```
56 changes: 56 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -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::<NativeEndian>(
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::<NativeEndian>()
.step_forwards(2)
.get_pointer()
.expect("Couldn't find IsOtherEnemy");

mem_file
.write_at(&[0xc3], ptr as u64)
.expect("Couldn't write to offset");
}

0 comments on commit 078a4e6

Please sign in to comment.