Last active
February 25, 2024 13:58
-
-
Save ceramicwhite/84997e386bb40d063aee680fa6440c21 to your computer and use it in GitHub Desktop.
Steam Family Share Patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // For Rust 2021 | |
| use std::fs; | |
| use std::iter::zip; | |
| static STEAMCLIENT_FILE_PATH: &str = "./steamclient.so"; | |
| static FUNCTION_OFFSETS_STRING: &str = "SharedLibraryLockStatus: | |
| 00244530: 55 89 e5 57 56 8d .. .. .. .. .. 53 e8 .. .. .. | |
| 00244540: .. 81 c3 .. .. .. .. 81 ec c4 00 00 00 89 bd 48 | |
| SharedLibraryStopPlaying: | |
| 002485d0: 55 89 e5 57 56 e8 .. .. .. .. 81 c6 .. .. .. .. | |
| 002485e0: 53 81 ec e4 00 00 00 8b 45 08 8b 7d 0c 89 85 50 | |
| IsSubscribedApp: | |
| 0096b9d0: 57 b8 01 00 00 00 53 e8 .. .. .. .. 81 c3 .. .. | |
| 0096b9e0: .. .. 83 ec 44 8b 54 24 54 85 d2 78 30 8d 7c 24"; | |
| fn hex_char_to_byte(character: char) -> u8 { | |
| let byte = character as u8; | |
| match byte { | |
| b'0'..=b'9' => byte - b'0', | |
| b'a'..=b'f' => byte - b'a' + 10, | |
| b'A'..=b'F' => byte - b'A' + 10, | |
| _ => unreachable!(), | |
| } | |
| } | |
| fn hex_string_to_byte(hex_string: &str) -> Option<u8> { | |
| assert!(hex_string.len() == 2); | |
| if hex_string == ".." { | |
| return None; | |
| } | |
| let upper_nibble = hex_char_to_byte(hex_string.chars().next().unwrap()); | |
| let lower_nibble = hex_char_to_byte(hex_string.chars().nth(1).unwrap()); | |
| Some(upper_nibble << 4 | lower_nibble) | |
| } | |
| fn parse_pattern_string() -> Vec<Vec<Option<u8>>> { | |
| let mut byte_patterns: Vec<Vec<Option<u8>>> = Vec::new(); | |
| for line in FUNCTION_OFFSETS_STRING.split('\n') { | |
| if line.ends_with(':') { | |
| byte_patterns.push(Vec::new()); | |
| } else if line == " " { | |
| continue; | |
| } else { | |
| let line = &line[10..]; | |
| for hex_byte in line.split_whitespace() { | |
| let last_index = byte_patterns.len() - 1; | |
| byte_patterns[last_index].push(hex_string_to_byte(hex_byte)); | |
| } | |
| } | |
| } | |
| byte_patterns | |
| } | |
| fn main() { | |
| let patterns = parse_pattern_string(); | |
| let file = fs::read(STEAMCLIENT_FILE_PATH) | |
| .unwrap_or_else(|_| panic!("A '{}' file should exist", STEAMCLIENT_FILE_PATH)); | |
| let mut locations_to_patch: Vec<usize> = Vec::new(); | |
| let mut iter = file.windows(32); | |
| let mut current_index: usize = 0; | |
| while let Some(word) = iter.next() { | |
| for pattern in &patterns { | |
| let mut matches = true; | |
| for (actual, pattern_byte) in zip(word, pattern) { | |
| if pattern_byte.is_none() { | |
| continue; | |
| } | |
| if pattern_byte.unwrap() != *actual { | |
| matches = false; | |
| } | |
| } | |
| if matches { | |
| locations_to_patch.push(current_index); | |
| } | |
| } | |
| current_index += 16; | |
| for _ in 0..15 { | |
| iter.next(); | |
| } | |
| } | |
| if locations_to_patch.is_empty() { | |
| print!("echo \"No matches found\""); | |
| return; | |
| } | |
| let mut command: String = "echo -e \"".to_string(); | |
| let mut iter = locations_to_patch.iter().peekable(); | |
| while let Some(location) = iter.next() { | |
| if iter.peek().is_some() { | |
| command += &format!("00{location:x}: 31c040c3\\n"); | |
| } else { | |
| command += &format!("00{location:x}: 31c040c3\""); | |
| } | |
| } | |
| command += &format!(" | xxd -r - {STEAMCLIENT_FILE_PATH}"); | |
| print!("{}", command); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Check for Rust installation and install it if not present | |
| if ! command -v cargo &> /dev/null | |
| then | |
| echo "Rust is not installed. Installing Rust..." | |
| curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y | |
| source "$HOME/.cargo/env" | |
| else | |
| echo "Rust is installed." | |
| fi | |
| # Check for 'cc' (C Compiler) | |
| if ! command -v cc &> /dev/null | |
| then | |
| echo "'cc' (C Compiler) is not installed. Installing 'base-devel'." | |
| sudo pacman -Sy base-devel | |
| fi | |
| # Check for 'xxd' | |
| if ! command -v xxd &> /dev/null | |
| then | |
| echo "'xxd' is not installed. Installing 'vim'." | |
| sudo pacman -Sy vim | |
| fi | |
| # Define the steamclient.so file path | |
| steamclient_path="/home/$USER/.steam/bin32/steamclient.so" | |
| # Backup the original steamclient.so file | |
| if [ -f "$steamclient_path" ]; then | |
| echo "Backing up steamclient.so to steamclient.so.bk" | |
| cp "$steamclient_path" "${steamclient_path}.bk" | |
| else | |
| echo "Error: steamclient.so does not exist at the specified path." | |
| exit 1 | |
| fi | |
| steamclient_sum=$(sha256sum "$steamclient_path" | awk '{print $1}') | |
| # Ensure the Rust project directory exists and navigate to it | |
| rust_project_dir="/home/$USER/steam-patch" | |
| if [ ! -d "$rust_project_dir" ]; then | |
| mkdir "$rust_project_dir" | |
| fi | |
| cd "$rust_project_dir" | |
| # Ensure main.rs exists in the project directory | |
| if [ ! -f "main.rs" ]; then | |
| curl https://gist.githubusercontent.com/ceramicwhite/84997e386bb40d063aee680fa6440c21/raw/a28de8c328fcc029735dc2dd4786f5ce71c3af71/main.rs > main.rs | |
| fi | |
| # Initialize a new Cargo project if Cargo.toml does not exist | |
| if [ ! -f "Cargo.toml" ]; then | |
| cargo init --name steam-patch . | |
| fi | |
| # Copy steamclient.so to the project directory | |
| cp "$steamclient_path" . | |
| # Run the Rust program and capture the output | |
| patch_command=$(cargo run | tail -n 1) | |
| # Check if cargo run was successful and patch_command is not empty | |
| if [ $? -eq 0 ] && [ ! -z "$patch_command" ]; then | |
| patch_command=${patch_command//.\//$rust_project_dir\/} | |
| # Execute the patch command | |
| echo "Command to patch steamclient.so:" | |
| echo "" | |
| echo $patch_command | |
| echo "" | |
| echo "Patching steamclient.so..." | |
| eval $patch_command | |
| if [[ "$steamclient_sum" == $(sha256sum "steamclient.so" | awk '{print $1}') ]]; then | |
| echo "" | |
| echo "steamclient.so has not been patched." | |
| echo "" | |
| exit 1 | |
| fi | |
| # Move the patched steamclient.so back to its original location | |
| mv "steamclient.so" "$steamclient_path" | |
| echo "" | |
| echo "Original sha256:$steamclient_sum" | |
| echo "" | |
| echo "New sha256:$(sha256sum "$steamclient_path" | awk '{print $1}')" | |
| echo "" | |
| echo "steamclient.so has been patched and moved back." | |
| else | |
| echo "Failed to run the Rust program or no patch command was generated." | |
| exit 1 | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment