Browse Source

Initial commit

nosoop 1 year ago
commit
2b9f9c48b0
4 changed files with 83 additions and 0 deletions
  1. 12 0
      LICENSE
  2. 14 0
      README.md
  3. 10 0
      str0.example.ini
  4. 47 0
      str0.py

+ 12 - 0
LICENSE

@@ -0,0 +1,12 @@
+Copyright (c) 2020 nosoop
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.

+ 14 - 0
README.md

@@ -0,0 +1,14 @@
+# \0String Patch
+
+Patches in-binary strings to start with the null terminator, primarily intended so they never
+get displayed in the server console (for things that MM:S / SM can't reach, like the Steam
+libraries).
+
+Needs a relatively recent Python 3 version.
+
+License is BSD0.  Do whatever you want with the script as long as I'm not involved.
+
+## Usage
+
+Copy `str0.example.ini` to `str0.ini`, add your sections, then run `python3 str0.py ${FILE}` to
+shut those "RecordSteamInterfaceCreation" messages up for good.

+ 10 - 0
str0.example.ini

@@ -0,0 +1,10 @@
+# patches strings in-binary
+
+# section name is the file base name; has one key 'strings' with a python list of strings as value
+[steamclient.so]
+strings = [
+            "RecordSteamInterfaceCreation (PID %d): %s / %s",
+            "Warning: failed to init SDL thread priority manager: SDL not found",
+            "CAppInfoCacheReadFromDiskThread took %lld milliseconds to initialize",
+            "CApplicationManagerPopulateThread took %lld milliseconds to initialize (will have waited on CAppInfoCacheReadFromDiskThread)",
+          ]

+ 47 - 0
str0.py

@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+
+
+"""
+Finds the location of strings and patches the first character to the null terminator,
+preventing the messages from being displayed in the server console.
+
+This can be executed while the server is running (on Linux, may not be successful on Windows).
+"""
+
+# to automatically patch after game updates use the following incron:
+# /path/to/binary IN_CLOSE_WRITE,loopable=true python3 /path/to/str0.py $@/$# -c /path/to/config.txt
+
+import argparse
+import ast
+import configparser
+import mmap
+import os
+
+def patch_to_null(mbin, target):
+	offset = mbin.find(target.encode('ascii'))
+	if offset == -1:
+		return False
+	mbin.seek(offset)
+	mbin.write_byte(0)
+	mbin.flush()
+	return True
+
+if __name__ == '__main__':
+	parser = argparse.ArgumentParser(
+			description = "Patches various strings out of the given binary")
+	
+	parser.add_argument('binary', help = "Binary file to patch", type = argparse.FileType(mode = 'rb+'))
+	
+	args = parser.parse_args()
+	
+	mbin = mmap.mmap(args.binary.fileno(), length = 0, access = mmap.ACCESS_WRITE)
+	
+	config = configparser.ConfigParser(converters = {
+		# return multiline value as an evaluated Python literal
+		'pyliteral': ast.literal_eval,
+	}, interpolation = None)
+	config.read("str0.ini", encoding = "utf8")
+	
+	for target in config.getpyliteral(os.path.basename(args.binary.name), "strings"):
+		if not patch_to_null(mbin, target):
+			print(f'{args.binary.name}: Failed to locate string "{target}"')