Last active
October 11, 2018 23:36
-
-
Save WorldSEnder/c5051dff45d9f2d20da316d383f2c8ba to your computer and use it in GitHub Desktop.
Decrypts your Monster Hunter world save data
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
import sys, errno, io | |
import struct | |
import base64 | |
import blowfish | |
key = base64.b64decode(b'eGllWmpvZSNQMjEzNC0zem1hZ2hncHFvZTB6OCQzYXplcQ==') | |
cipher = blowfish.Cipher(key, byte_order="little") | |
if sys.version_info[0] == 3: | |
stdin = sys.stdin.buffer | |
stdout = sys.stdout.buffer | |
else: | |
stdin = sys.stdin | |
stdout = sys.stdout | |
CHUNK_SIZE = 2048 | |
def iter_chunks(): | |
while True: | |
buf = stdin.read(CHUNK_SIZE) | |
if not buf: break | |
yield buf | |
def decrypt_chunks(chunk_iter): | |
for chunk in chunk_iter: | |
yield b"".join(cipher.decrypt_ecb(chunk)) | |
# just a bit of pretty printing don't kill me for it | |
def wrap_in_bar(buffer_it): | |
# don't print any progress bar if we are not in a tty setting | |
if not sys.stderr.isatty(): | |
return buffer_it | |
try: | |
from progress.bar import Bar | |
from progress.spinner import Spinner | |
except ImportError: | |
# or if progress is not available | |
return buffer_it | |
# try to detect the file size. This should be same (~9MiB) but who knows | |
# what you are doing with it :) | |
if stdin.seekable(): | |
pos = stdin.tell() | |
end = stdin.seek(0, io.SEEK_END) | |
if end != pos: | |
repos = stdin.seek(0, io.SEEK_SET) | |
assert pos == repos, "couldn't seek back to the initial position in the stream" | |
bar = Bar("Processing", file=sys.stderr, max = (end - pos + CHUNK_SIZE - 1) // CHUNK_SIZE) | |
return bar.iter(buffer_it) | |
else: | |
return Spinner("Processing", file=sys.stderr).iter(buffer_it) | |
if __name__ == "__main__": | |
if stdin.isatty(): | |
print("Usage: python3 {} < SAVEDATA1000 > SAVEDATA1000.extracted.bin".format(sys.argv[0]), file=sys.stderr) | |
exit(1) | |
buffer_it = wrap_in_bar(iter_chunks()) | |
for buf in decrypt_chunks(buffer_it): | |
try: | |
stdout.write(buf) | |
except IOError as e: | |
if e.errno == errno.EPIPE: | |
break | |
# This suppresses a warning python would print if stdout is attached | |
# to a pipe instead of a file. | |
# see: https://stackoverflow.com/questions/26692284/ | |
sys.stderr.close() |
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
progress |
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
blowfish |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment