Monster Hunter 4 Ultimate: Savegame De-/Encryption

Reading, editing and everything related to the files created by games to contain savegames and configurations
HenryEx
Posts: 27
Joined: Wed Aug 13, 2014 6:43 pm

Monster Hunter 4 Ultimate: Savegame De-/Encryption

Post by HenryEx »

As is traditionally the case, the Monster Hunter games employ their own added savegame encryption on top of the game system's native encryption, which is in this case the Nintendo 3DS. So if you can somehow get a decrypted MH4U save off your 3DS, you still need to remove the game's own save encryption. This is what these two scripts are for! I'm leaning heavily on svanheulen's work with this, but if you don't want to install Python just for Monster Hunter save games, then you're in luck.

The MH4U saves are called "user1", "user2" or "user3", depending on which save slot you want to decrypt. Encrypted files are 0x13E00 bytes long, decrypted ones will be 0x13DF8 bytes long.

Just use QuickBMS + decryption script + userX file to make it plain. With QuickBMS + encryption script + userX file, you can then re-import it onto your 3DS!

Here's pastebin links to the two scripts, i'll post them in full in the following posts for better readability.

Decryption: http://pastebin.com/bWCr9ZPU

Encryption: http://pastebin.com/6McrW6rw

Enjoy!
HenryEx
Posts: 27
Joined: Wed Aug 13, 2014 6:43 pm

Re: Monster Hunter 4 Ultimate: Savegame De-/Encryption

Post by HenryEx »

The decryption script:

Code: Select all

# Monster Hunter 4 Ultimate
# Script to decrypt save file data
#
# Based on information from mhef by Seth VanHeulen
# https://github.com/svanheulen/mhef
#
# Written by HenryEx
#
# script for QuickBMS http://quickbms.aluigi.org

################################################
# Preparations

print "Setup..."

# set up virtual memory file for save data
  math TMP = 0x13E00
  log MEMORY_FILE 0 0
  putvarchr MEMORY_FILE TMP 0   # improves the speed with pre-allocation
  log MEMORY_FILE 0 0           # reset the position and size of the file


# Set up default values and keys
  get FILENAME filename 0
  get FILESIZE asize 0
  set FILESTART long 0
  set SAV_MH4U string "blowfish key iorajegqmrna4itjeangmb agmwgtobjteowhv9mope"
  set DLC_MH4U_EU string "AgK2DYheaCjyHGPB"
  set DLC_MH4U_JP string "AgK2DYheaCjyHGP8"
  set DLC_MH4U_KR string "AgK2DYheaOjyHGP8"
  set DLC_MH4U_TW string "Capcom123 "
  set KEY_MUL short 0xB0
  set KEY_MOD short 0xFF53
  set SUM long 0


# get savedata in memory for decryption
  log MEMORY_FILE FILESTART FILESIZE 0  # MEMORY_FILE is encrypted save data


################################################
# Decrypt save

print "Decrypting save"

print "-> Blowfish Decryption..."
# decrypt via blowfish
  Encryption blowfish SAV_MH4U
  log MEMORY_FILE FILESTART FILESIZE MEMORY_FILE
  Encryption "" ""

print "-> XORing with save key..."
# check if file looks properly decrypted & get save key
  get SIXTEEN short MEMORY_FILE
  get KEY short MEMORY_FILE
  math FILESTART + 4
  math FILESIZE - 4

  if SIXTEEN != 16
    print "[!] Save key doesn't seem to be decrypted! Blowfish decryption may have failed! Exiting..."
    CleanExit
  endif

# advance key and XOR 16b block of the file with it
  xmath XORNUM "FILESIZE / 2"
  for i = 0 < XORNUM
    xmath POS "(i * 2) + FILESTART"  # get current file position
    if KEY == 0
      math KEY = 1
    endif
    math KEY * KEY_MUL
    math KEY % KEY_MOD

    getvarchr DATA MEMORY_FILE POS short
    math DATA u^ KEY
    putvarchr MEMORY_FILE POS DATA short
  next i

print "-> Comparing save checksum..."
  get CSUM long MEMORY_FILE
  math FILESTART + 4
  math FILESIZE - 4

  for i = 0 < FILESIZE
    get SBYTE byte MEMORY_FILE
    math SUM + SBYTE
  next i
  math SUM u& 0xFFFFFFFF

  if CSUM != SUM
    print "[!] Checksum mismatch! Save chksum: %CSUM% - Calculated chksum: %SUM%! Exiting..."
    CleanExit
  endif


################################################
# Save files to disk

print "Exporting decrypted save to %FILENAME%"
log FILENAME FILESTART FILESIZE MEMORY_FILE

CleanExit
HenryEx
Posts: 27
Joined: Wed Aug 13, 2014 6:43 pm

Re: Monster Hunter 4 Ultimate: Savegame De-/Encryption

Post by HenryEx »

The encryption script:

Code: Select all

# Monster Hunter 4 Ultimate
# Script to re-encrypt save file data
#
# Based on information from mhef by Seth VanHeulen
# https://github.com/svanheulen/mhef
#
# Written by HenryEx
#
# script for QuickBMS http://quickbms.aluigi.org

################################################
# Preparations

print "Setup..."

# set up virtual memory file for save data
  math TMP = 0x13E00
  log MEMORY_FILE 0 0
  putvarchr MEMORY_FILE TMP 0   # improves the speed with pre-allocation
  log MEMORY_FILE 0 0           # reset the position and size of the file

# Set up default values and keys
  get FILENAME filename 0
  get FILESIZE asize 0
  set SAV_MH4U string "blowfish key iorajegqmrna4itjeangmb agmwgtobjteowhv9mope"
  set DLC_MH4U_EU string "AgK2DYheaCjyHGPB"
  set DLC_MH4U_JP string "AgK2DYheaCjyHGP8"
  set DLC_MH4U_KR string "AgK2DYheaOjyHGP8"
  set DLC_MH4U_TW string "Capcom123 "
  set KEY_MUL short 0xB0
  set KEY_MOD short 0xFF53
  set SUM long 0

# set up savedata in memory for encryption
  put 16 short MEMORY_FILE
  put 0 short MEMORY_FILE  # space for xor key
  put 0 long MEMORY_FILE  # space for checksum
  append  # Append ON
  log MEMORY_FILE FILESTART FILESIZE 0  # MEMORY_FILE = decrypted save data
  append  # Append OFF
  math FILESTART = 8


################################################
# Encrypt save

print "Encrypting save"

print "-> Calculating save checksum..."
  for i = 0 < FILESIZE
    get SBYTE byte 0
    math SUM + SBYTE
  next i
  math SUM u& 0xFFFFFFFF
  print "Calculated checksum: %SUM%"

  putvarchr MEMORY_FILE 4 SUM long
  math FILESIZE + 4
  math FILESTART - 4

print "-> XORing with random key..."  # Well, not REALLY random...
# make pseudo-random KEY
  xmath KEY "SUM & 0xFFFF"
  xmath KEY "((KEY < 7) & 0xFFFF) | (KEY > 9)"  # 16bit rotated left 7x
  math KEY ^ 0x484D  # xor with "MH"

  putvarchr MEMORY_FILE 2 KEY short

# advance key and XOR 16b block of the file with it
  xmath XORNUM "FILESIZE / 2"
  for i = 0 < XORNUM
    xmath POS "(i * 2) + FILESTART"  # get current file position
    if KEY == 0
      math KEY = 1
    endif
    math KEY * KEY_MUL
    math KEY % KEY_MOD

    getvarchr DATA MEMORY_FILE POS short
    math DATA u^ KEY
    putvarchr MEMORY_FILE POS DATA short
  next i

  math FILESIZE + 4
  math FILESTART - 4

print "-> Blowfish Encryption..."
# encrypt via blowfish
  Encryption blowfish SAV_MH4U "" 1
  log MEMORY_FILE FILESTART FILESIZE MEMORY_FILE
  Encryption "" ""


################################################
# Save files to disk

print "Exporting encrypted save to %FILENAME%"
log FILENAME FILESTART FILESIZE MEMORY_FILE

CleanExit