str0.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. #!/usr/bin/python3
  2. """
  3. Finds the location of strings and patches the first character to the null terminator,
  4. preventing the messages from being displayed in the server console.
  5. This can be executed while the server is running (on Linux; may not be successful on Windows).
  6. """
  7. import argparse
  8. import ast
  9. import configparser
  10. import mmap
  11. import os
  12. def patch_to_null(mbin, target, fully_zero = True):
  13. mbin.seek(0)
  14. offset = mbin.find(target.encode('ascii'))
  15. if offset == -1:
  16. return False
  17. mbin.seek(offset)
  18. # read up to the next null terminator and zero out the range if we fullclear it
  19. mbin.write(b'\0' * (mbin.find(b'\0', offset) - offset if fully_zero else 1))
  20. return True
  21. if __name__ == '__main__':
  22. parser = argparse.ArgumentParser(
  23. description = "Patches various strings out of the given binary")
  24. parser.add_argument('binary', help = "Binary file to patch", type = argparse.FileType(mode = 'rb+'))
  25. parser.add_argument('-c', '--config', help = "List of files / strings to match",
  26. action = 'append', default = [])
  27. args = parser.parse_args()
  28. mbin = mmap.mmap(args.binary.fileno(), length = 0, access = mmap.ACCESS_WRITE)
  29. config = configparser.ConfigParser(converters = {
  30. # return multiline value as an evaluated Python literal
  31. 'pyliteral': ast.literal_eval,
  32. }, interpolation = None)
  33. config.read([ "str0.ini" ] + args.config, encoding = "utf8")
  34. for target in config.getpyliteral(os.path.basename(args.binary.name), "strings"):
  35. fully_zero = config.getboolean(os.path.basename(args.binary.name), "fully_zero", fallback = False)
  36. if not patch_to_null(mbin, target, fully_zero):
  37. print(f'{args.binary.name}: Failed to locate string "{target}"')
  38. mbin.flush()