Last active
July 23, 2022 00:20
-
-
Save sekaiwish/fb216073763ae2f9d9c084d9aaa1a05d to your computer and use it in GitHub Desktop.
MHF Packet Decrypter
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
# Monster Hunter Frontier packet decryption PoC. | |
import socket | |
import struct | |
import sys | |
from hexdump import hexdump | |
ENCRYPT_KEY = b'\x90\x51\x26\x25\x04\xBF\xCF\x4C\x92\x02\x52\x7A\x70\x1A\x41\x88\x8C\xC2\xCE\xB8\xF6\x57\x7E\xBA\x83\x63\x2C\x24\x9A\x67\x86\x0C\xBE\x72\xFD\xB6\x7B\x79\xB0\x22\x5A\x60\x5C\x4F\x49\xE2\x0E\xF5\x3A\x81\xAE\x11\x6B\xF0\xA1\x01\xE8\x65\x8D\x5B\xDC\xCC\x93\x18\xB3\xAB\x77\xF7\x8E\xEC\xEF\x05\x00\xCA\x4E\xA7\xBC\xB5\x10\xC6\x6C\xC0\xC4\xE5\x87\x3F\xC1\x82\x29\x96\x45\x73\x07\xCB\x43\xF9\xF3\x08\x89\xD0\x99\x6A\x3B\x37\x19\xD4\x40\xEA\xD7\x85\x16\x66\x1E\x9C\x39\xBB\xEE\x4A\x03\x8A\x36\x2D\x13\x1D\x56\x48\xC7\x0D\x59\xB2\x44\xA3\xFE\x8B\x32\x1B\x84\xA0\x2E\x62\x17\x42\xB9\x9B\x2B\x75\xD8\x1C\x3C\x4D\x76\x27\x6E\x28\xD3\x33\xC3\x21\xAF\x34\x23\xDD\x68\x9F\xF1\xAD\xE1\xB4\xE7\xA6\x74\x15\x4B\xFA\x3D\x5F\x7C\xDA\x2F\x0A\xE3\x7D\xC8\xB7\x12\x6F\x9E\xA9\x14\x53\x97\x8F\x64\xF4\xF8\xA2\xA4\x2A\xD2\x47\x9D\x71\xC5\xE9\x06\x98\x20\x54\x80\xAA\xF2\xAC\x50\xD6\x7F\xD9\xC9\xCD\x69\x46\x6D\x30\xB1\x58\x0B\x55\xD1\x5D\xD5\xBD\x31\xDE\xA5\xE4\x91\x0F\x61\x38\xDF\xA8\xE6\x3E\x1F\x35\xED\xDB\x94\xEB\x09\x5E\x95\xFB\xFC\xE0\x78\xFF' | |
DECRYPT_KEY = b'\x48\x37\x09\x76\x04\x47\xCC\x5C\x61\xF8\xB3\xE0\x1F\x7F\x2E\xEB\x4E\x33\xB8\x7A\xBC\xAB\x6E\x8C\x3F\x68\x0D\x87\x93\x7B\x70\xF2\xCE\x9D\x27\xA0\x1B\x03\x02\x97\x99\x58\xC5\x90\x1A\x79\x8A\xB2\xDD\xE6\x86\x9B\x9F\xF3\x78\x67\xED\x72\x30\x66\x94\xAE\xF1\x55\x6A\x0E\x8D\x5E\x82\x5A\xDB\xC7\x7D\x2C\x75\xAC\x07\x95\x4A\x2B\xD4\x01\x0A\xBD\xCF\xE1\x7C\x15\xDF\x80\x28\x3B\x2A\xE3\xF9\xAF\x29\xEC\x8B\x19\xC0\x39\x6F\x1D\xA2\xDA\x65\x34\x50\xDC\x98\xB9\x0C\xC9\x21\x5B\xAA\x91\x96\x42\xFE\x25\x0B\x24\xB0\xB5\x16\xD6\xD0\x31\x57\x18\x88\x6D\x1E\x54\x0F\x62\x77\x85\x10\x3A\x44\xBF\x00\xEA\x08\x3E\xF6\xFA\x59\xBE\xCD\x64\x1C\x8F\x71\xC8\xBA\xA3\x89\x36\xC3\x83\xC4\xE8\xA9\x4B\xEF\xBB\xD1\x41\xD3\xA5\x32\x9E\x26\xDE\x81\x40\xA7\x4D\x23\xB7\x13\x8E\x17\x73\x4C\xE5\x20\x05\x51\x56\x11\x9C\x52\xCA\x4F\x7E\xB6\xD8\x49\x5D\x3D\xD9\x12\x06\x63\xE2\xC6\x9A\x69\xE4\xD5\x6C\x92\xD7\xB1\xF5\x3C\xA1\xE7\xEE\xFD\xA6\x2D\xB4\xE9\x53\xF0\xA8\x38\xCB\x6B\xF7\x45\xF4\x74\x46\x35\xA4\xD2\x60\xC1\x2F\x14\x43\xC2\x5F\xAD\xFB\xFC\x22\x84\xFF' | |
SHARED_CRYPT_KEY = b'\xDD\xA8\x5F\x1E\x57\xAF\xC0\xCC\x43\x35\x8F\xBB\x6F\xE6\xA1\xD6\x60\xB9\x1A\xAE\x20\x49\x24\x81\x21\xFE\x86\x2B\x98\xB7\xB3\xD2\x91\x01\x3A\x4C\x65\x92\x1C\xF4\xBE\xDD\xD9\x08\xE6\x81\x98\x1B\x8D\x60\xF3\x6F\xA1\x47\x24\xF1\x53\x45\xC8\x7B\x88\x80\x4E\x36\xC3\x0D\xC9\xD6\x8B\x08\x19\x0B\xA5\xC1\x11\x4C\x60\xF8\x5D\xFC\x15\x68\x7E\x32\xC0\x50\xAB\x64\x1F\x8A\xD4\x08\x39\x7F\xC2\xFB\xBA\x6C\xF0\xE6\xB0\x31\x10\xC1\xBF\x75\x43\xBB\x18\x04\x0D\xD1\x97\xF7\x23\x21\x83\x8B\xCA\x25\x2B\xA3\x03\x13\xEA\xAE\xFE\xF0\xEB\xFD\x85\x57\x53\x65\x41\x2A\x40\x99\xC0\x94\x65\x7E\x7C\x93\x82\xB0\xB3\xE5\xC0\x21\x09\x84\xD5\xEF\x9F\xD1\x7E\xDC\x4D\xF5\x7E\xCD\x45\x3C\x7F\xF5\x59\x98\xC6\x55\xFC\x9F\xA3\xB7\x74\xEE\x31\x98\xE6\xB7\xBE\x26\xF4\x3C\x76\xF1\x23\x7E\x02\x4E\x3C\xD1\xC7\x28\x23\x73\xC4\xD9\x5E\x0D\xA1\x80\xA5\xAA\x26\x0A\xA3\x44\x82\x74\xE6\x3C\x44\x27\x51\x0D\x5F\xC7\x9C\xD6\x63\x67\xA5\x27\x97\x38\xFB\x2D\xD3\xD6\x60\x25\x83\x4D\x37\x5B\x40\x59\x11\x77\x51\x11\x14\x18\x07\x63\xB1\x34\x3D\xB8\x60\x13\xC2\xE8\x13\x82' | |
PACKET_HEADER_SIZE = 14 | |
OPCODES = ["MSG_HEAD","MSG_SYS_reserve01","MSG_SYS_reserve02","MSG_SYS_reserve03","MSG_SYS_reserve04","MSG_SYS_reserve05","MSG_SYS_reserve06","MSG_SYS_reserve07","MSG_SYS_ADD_OBJECT","MSG_SYS_DEL_OBJECT","MSG_SYS_DISP_OBJECT","MSG_SYS_HIDE_OBJECT","MSG_SYS_reserve0C","MSG_SYS_reserve0D","MSG_SYS_reserve0E","MSG_SYS_EXTEND_THRESHOLD","MSG_SYS_END","MSG_SYS_NOP","MSG_SYS_ACK","MSG_SYS_TERMINAL_LOG","MSG_SYS_LOGIN","MSG_SYS_LOGOUT","MSG_SYS_SET_STATUS","MSG_SYS_PING","MSG_SYS_CAST_BINARY","MSG_SYS_HIDE_CLIENT","MSG_SYS_TIME","MSG_SYS_CASTED_BINARY","MSG_SYS_GET_FILE","MSG_SYS_ISSUE_LOGKEY","MSG_SYS_RECORD_LOG","MSG_SYS_ECHO","MSG_SYS_CREATE_STAGE","MSG_SYS_STAGE_DESTRUCT","MSG_SYS_ENTER_STAGE","MSG_SYS_BACK_STAGE","MSG_SYS_MOVE_STAGE","MSG_SYS_LEAVE_STAGE","MSG_SYS_LOCK_STAGE","MSG_SYS_UNLOCK_STAGE","MSG_SYS_RESERVE_STAGE","MSG_SYS_UNRESERVE_STAGE","MSG_SYS_SET_STAGE_PASS","MSG_SYS_WAIT_STAGE_BINARY","MSG_SYS_SET_STAGE_BINARY","MSG_SYS_GET_STAGE_BINARY","MSG_SYS_ENUMERATE_CLIENT","MSG_SYS_ENUMERATE_STAGE","MSG_SYS_CREATE_MUTEX","MSG_SYS_CREATE_OPEN_MUTEX","MSG_SYS_DELETE_MUTEX","MSG_SYS_OPEN_MUTEX","MSG_SYS_CLOSE_MUTEX","MSG_SYS_CREATE_SEMAPHORE","MSG_SYS_CREATE_ACQUIRE_SEMAPHORE","MSG_SYS_DELETE_SEMAPHORE","MSG_SYS_ACQUIRE_SEMAPHORE","MSG_SYS_RELEASE_SEMAPHORE","MSG_SYS_LOCK_GLOBAL_SEMA","MSG_SYS_UNLOCK_GLOBAL_SEMA","MSG_SYS_CHECK_SEMAPHORE","MSG_SYS_OPERATE_REGISTER","MSG_SYS_LOAD_REGISTER","MSG_SYS_NOTIFY_REGISTER","MSG_SYS_CREATE_OBJECT","MSG_SYS_DELETE_OBJECT","MSG_SYS_POSITION_OBJECT","MSG_SYS_ROTATE_OBJECT","MSG_SYS_DUPLICATE_OBJECT","MSG_SYS_SET_OBJECT_BINARY","MSG_SYS_GET_OBJECT_BINARY","MSG_SYS_GET_OBJECT_OWNER","MSG_SYS_UPDATE_OBJECT_BINARY","MSG_SYS_CLEANUP_OBJECT","MSG_SYS_reserve4A","MSG_SYS_reserve4B","MSG_SYS_reserve4C","MSG_SYS_reserve4D","MSG_SYS_reserve4E","MSG_SYS_reserve4F","MSG_SYS_INSERT_USER","MSG_SYS_DELETE_USER","MSG_SYS_SET_USER_BINARY","MSG_SYS_GET_USER_BINARY","MSG_SYS_NOTIFY_USER_BINARY","MSG_SYS_reserve55","MSG_SYS_reserve56","MSG_SYS_reserve57","MSG_SYS_UPDATE_RIGHT","MSG_SYS_AUTH_QUERY","MSG_SYS_AUTH_DATA","MSG_SYS_AUTH_TERMINAL","MSG_SYS_reserve5C","MSG_SYS_RIGHTS_RELOAD","MSG_SYS_reserve5E","MSG_SYS_reserve5F","MSG_MHF_SAVEDATA","MSG_MHF_LOADDATA","MSG_MHF_LIST_MEMBER","MSG_MHF_OPR_MEMBER","MSG_MHF_ENUMERATE_DIST_ITEM","MSG_MHF_APPLY_DIST_ITEM","MSG_MHF_ACQUIRE_DIST_ITEM","MSG_MHF_GET_DIST_DESCRIPTION","MSG_MHF_SEND_MAIL","MSG_MHF_READ_MAIL","MSG_MHF_LIST_MAIL","MSG_MHF_OPRT_MAIL","MSG_MHF_LOAD_FAVORITE_QUEST","MSG_MHF_SAVE_FAVORITE_QUEST","MSG_MHF_REGISTER_EVENT","MSG_MHF_RELEASE_EVENT","MSG_MHF_TRANSIT_MESSAGE","MSG_SYS_reserve71","MSG_SYS_reserve72","MSG_SYS_reserve73","MSG_SYS_reserve74","MSG_SYS_reserve75","MSG_SYS_reserve76","MSG_SYS_reserve77","MSG_SYS_reserve78","MSG_SYS_reserve79","MSG_SYS_reserve7A","MSG_SYS_reserve7B","MSG_SYS_reserve7C","MSG_CA_EXCHANGE_ITEM","MSG_SYS_reserve7E","MSG_MHF_PRESENT_BOX","MSG_MHF_SERVER_COMMAND","MSG_MHF_SHUT_CLIENT","MSG_MHF_ANNOUNCE","MSG_MHF_SET_LOGINWINDOW","MSG_SYS_TRANS_BINARY","MSG_SYS_COLLECT_BINARY","MSG_SYS_GET_STATE","MSG_SYS_SERIALIZE","MSG_SYS_ENUMLOBBY","MSG_SYS_ENUMUSER","MSG_SYS_INFOKYSERVER","MSG_MHF_GET_CA_UNIQUE_ID","MSG_MHF_SET_CA_ACHIEVEMENT","MSG_MHF_CARAVAN_MY_SCORE","MSG_MHF_CARAVAN_RANKING","MSG_MHF_CARAVAN_MY_RANK","MSG_MHF_CREATE_GUILD","MSG_MHF_OPERATE_GUILD","MSG_MHF_OPERATE_GUILD_MEMBER","MSG_MHF_INFO_GUILD","MSG_MHF_ENUMERATE_GUILD","MSG_MHF_UPDATE_GUILD","MSG_MHF_ARRANGE_GUILD_MEMBER","MSG_MHF_ENUMERATE_GUILD_MEMBER","MSG_MHF_ENUMERATE_CAMPAIGN","MSG_MHF_STATE_CAMPAIGN","MSG_MHF_APPLY_CAMPAIGN","MSG_MHF_ENUMERATE_ITEM","MSG_MHF_ACQUIRE_ITEM","MSG_MHF_TRANSFER_ITEM","MSG_MHF_MERCENARY_HUNTDATA","MSG_MHF_ENTRY_ROOKIE_GUILD","MSG_MHF_ENUMERATE_QUEST","MSG_MHF_ENUMERATE_EVENT","MSG_MHF_ENUMERATE_PRICE","MSG_MHF_ENUMERATE_RANKING","MSG_MHF_ENUMERATE_ORDER","MSG_MHF_ENUMERATE_SHOP","MSG_MHF_GET_EXTRA_INFO","MSG_MHF_UPDATE_INTERIOR","MSG_MHF_ENUMERATE_HOUSE","MSG_MHF_UPDATE_HOUSE","MSG_MHF_LOAD_HOUSE","MSG_MHF_OPERATE_WAREHOUSE","MSG_MHF_ENUMERATE_WAREHOUSE","MSG_MHF_UPDATE_WAREHOUSE","MSG_MHF_ACQUIRE_TITLE","MSG_MHF_ENUMERATE_TITLE","MSG_MHF_ENUMERATE_GUILD_ITEM","MSG_MHF_UPDATE_GUILD_ITEM","MSG_MHF_ENUMERATE_UNION_ITEM","MSG_MHF_UPDATE_UNION_ITEM","MSG_MHF_CREATE_JOINT","MSG_MHF_OPERATE_JOINT","MSG_MHF_INFO_JOINT","MSG_MHF_UPDATE_GUILD_ICON","MSG_MHF_INFO_FESTA","MSG_MHF_ENTRY_FESTA","MSG_MHF_CHARGE_FESTA","MSG_MHF_ACQUIRE_FESTA","MSG_MHF_STATE_FESTA_U","MSG_MHF_STATE_FESTA_G","MSG_MHF_ENUMERATE_FESTA_MEMBER","MSG_MHF_VOTE_FESTA","MSG_MHF_ACQUIRE_CAFE_ITEM","MSG_MHF_UPDATE_CAFEPOINT","MSG_MHF_CHECK_DAILY_CAFEPOINT","MSG_MHF_GET_COG_INFO","MSG_MHF_CHECK_MONTHLY_ITEM","MSG_MHF_ACQUIRE_MONTHLY_ITEM","MSG_MHF_CHECK_WEEKLY_STAMP","MSG_MHF_EXCHANGE_WEEKLY_STAMP","MSG_MHF_CREATE_MERCENARY","MSG_MHF_SAVE_MERCENARY","MSG_MHF_READ_MERCENARY_W","MSG_MHF_READ_MERCENARY_M","MSG_MHF_CONTRACT_MERCENARY","MSG_MHF_ENUMERATE_MERCENARY_LOG","MSG_MHF_ENUMERATE_GUACOT","MSG_MHF_UPDATE_GUACOT","MSG_MHF_INFO_TOURNAMENT","MSG_MHF_ENTRY_TOURNAMENT","MSG_MHF_ENTER_TOURNAMENT_QUEST","MSG_MHF_ACQUIRE_TOURNAMENT","MSG_MHF_GET_ACHIEVEMENT","MSG_MHF_RESET_ACHIEVEMENT","MSG_MHF_ADD_ACHIEVEMENT","MSG_MHF_PAYMENT_ACHIEVEMENT","MSG_MHF_DISPLAYED_ACHIEVEMENT","MSG_MHF_INFO_SCENARIO_COUNTER","MSG_MHF_SAVE_SCENARIO_DATA","MSG_MHF_LOAD_SCENARIO_DATA","MSG_MHF_GET_BBS_SNS_STATUS","MSG_MHF_APPLY_BBS_ARTICLE","MSG_MHF_GET_ETC_POINTS","MSG_MHF_UPDATE_ETC_POINT","MSG_MHF_GET_MYHOUSE_INFO","MSG_MHF_UPDATE_MYHOUSE_INFO","MSG_MHF_GET_WEEKLY_SCHEDULE","MSG_MHF_ENUMERATE_INV_GUILD","MSG_MHF_OPERATION_INV_GUILD","MSG_MHF_STAMPCARD_STAMP","MSG_MHF_STAMPCARD_PRIZE","MSG_MHF_UNRESERVE_SRG","MSG_MHF_LOAD_PLATE_DATA","MSG_MHF_SAVE_PLATE_DATA","MSG_MHF_LOAD_PLATE_BOX","MSG_MHF_SAVE_PLATE_BOX","MSG_MHF_READ_GUILDCARD","MSG_MHF_UPDATE_GUILDCARD","MSG_MHF_READ_BEAT_LEVEL","MSG_MHF_UPDATE_BEAT_LEVEL","MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING","MSG_MHF_READ_BEAT_LEVEL_MY_RANKING","MSG_MHF_READ_LAST_WEEK_BEAT_RANKING","MSG_MHF_ACCEPT_READ_REWARD","MSG_MHF_GET_ADDITIONAL_BEAT_REWARD","MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE","MSG_MHF_GET_BBS_USER_STATUS","MSG_MHF_KICK_EXPORT_FORCE","MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD","MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD","MSG_MHF_GET_EARTH_STATUS","MSG_MHF_LOAD_PARTNER","MSG_MHF_SAVE_PARTNER","MSG_MHF_GET_GUILD_MISSION_LIST","MSG_MHF_GET_GUILD_MISSION_RECORD","MSG_MHF_ADD_GUILD_MISSION_COUNT","MSG_MHF_SET_GUILD_MISSION_TARGET","MSG_MHF_CANCEL_GUILD_MISSION_TARGET","MSG_MHF_LOAD_OTOMO_AIROU","MSG_MHF_SAVE_OTOMO_AIROU","MSG_MHF_ENUMERATE_GUILD_TRESURE","MSG_MHF_ENUMERATE_AIROULIST","MSG_MHF_REGIST_GUILD_TRESURE","MSG_MHF_ACQUIRE_GUILD_TRESURE","MSG_MHF_OPERATE_GUILD_TRESURE_REPORT","MSG_MHF_GET_GUILD_TRESURE_SOUVENIR","MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR","MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE","MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE","MSG_MHF_LOAD_DECO_MYSET","MSG_MHF_SAVE_DECO_MYSET","MSG_MHF_reserve010F","MSG_MHF_LOAD_GUILD_COOKING","MSG_MHF_REGIST_GUILD_COOKING","MSG_MHF_LOAD_GUILD_ADVENTURE","MSG_MHF_REGIST_GUILD_ADVENTURE","MSG_MHF_ACQUIRE_GUILD_ADVENTURE","MSG_MHF_CHARGE_GUILD_ADVENTURE","MSG_MHF_LOAD_LEGEND_DISPATCH","MSG_MHF_LOAD_HUNTER_NAVI","MSG_MHF_SAVE_HUNTER_NAVI","MSG_MHF_REGIST_SPABI_TIME","MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER","MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT","MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER","MSG_MHF_GET_TOWER_INFO","MSG_MHF_POST_TOWER_INFO","MSG_MHF_GET_GEM_INFO","MSG_MHF_POST_GEM_INFO","MSG_MHF_GET_EARTH_VALUE","MSG_MHF_DEBUG_POST_VALUE","MSG_MHF_GET_PAPER_DATA","MSG_MHF_GET_NOTICE","MSG_MHF_POST_NOTICE","MSG_MHF_GET_BOOST_TIME","MSG_MHF_POST_BOOST_TIME","MSG_MHF_GET_BOOST_TIME_LIMIT","MSG_MHF_POST_BOOST_TIME_LIMIT","MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE","MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE","MSG_MHF_GET_RAND_FROM_TABLE","MSG_MHF_GET_CAFE_DURATION","MSG_MHF_GET_CAFE_DURATION_BONUS_INFO","MSG_MHF_RECEIVE_CAFE_DURATION_BONUS","MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED","MSG_MHF_GET_GACHA_POINT","MSG_MHF_USE_GACHA_POINT","MSG_MHF_EXCHANGE_FPOINT_2_ITEM","MSG_MHF_EXCHANGE_ITEM_2_FPOINT","MSG_MHF_GET_FPOINT_EXCHANGE_LIST","MSG_MHF_PLAY_STEPUP_GACHA","MSG_MHF_RECEIVE_GACHA_ITEM","MSG_MHF_GET_STEPUP_STATUS","MSG_MHF_PLAY_FREE_GACHA","MSG_MHF_GET_TINY_BIN","MSG_MHF_POST_TINY_BIN","MSG_MHF_GET_SENYU_DAILY_COUNT","MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM","MSG_MHF_GET_BOOST_RIGHT","MSG_MHF_START_BOOST_TIME","MSG_MHF_POST_BOOST_TIME_QUEST_RETURN","MSG_MHF_GET_BOX_GACHA_INFO","MSG_MHF_PLAY_BOX_GACHA","MSG_MHF_RESET_BOX_GACHA_INFO","MSG_MHF_GET_SEIBATTLE","MSG_MHF_POST_SEIBATTLE","MSG_MHF_GET_RYOUDAMA","MSG_MHF_POST_RYOUDAMA","MSG_MHF_GET_TENROUIRAI","MSG_MHF_POST_TENROUIRAI","MSG_MHF_POST_GUILD_SCOUT","MSG_MHF_CANCEL_GUILD_SCOUT","MSG_MHF_ANSWER_GUILD_SCOUT","MSG_MHF_GET_GUILD_SCOUT_LIST","MSG_MHF_GET_GUILD_MANAGE_RIGHT","MSG_MHF_SET_GUILD_MANAGE_RIGHT","MSG_MHF_PLAY_NORMAL_GACHA","MSG_MHF_GET_DAILY_MISSION_MASTER","MSG_MHF_GET_DAILY_MISSION_PERSONAL","MSG_MHF_SET_DAILY_MISSION_PERSONAL","MSG_MHF_GET_GACHA_PLAY_HISTORY","MSG_MHF_GET_REJECT_GUILD_SCOUT","MSG_MHF_SET_REJECT_GUILD_SCOUT","MSG_MHF_GET_CA_ACHIEVEMENT_HIST","MSG_MHF_SET_CA_ACHIEVEMENT_HIST","MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS","MSG_MHF_USE_KEEP_LOGIN_BOOST","MSG_MHF_GET_UD_SCHEDULE","MSG_MHF_GET_UD_INFO","MSG_MHF_GET_KIJU_INFO","MSG_MHF_SET_KIJU","MSG_MHF_ADD_UD_POINT","MSG_MHF_GET_UD_MY_POINT","MSG_MHF_GET_UD_TOTAL_POINT_INFO","MSG_MHF_GET_UD_BONUS_QUEST_INFO","MSG_MHF_GET_UD_SELECTED_COLOR_INFO","MSG_MHF_GET_UD_MONSTER_POINT","MSG_MHF_GET_UD_DAILY_PRESENT_LIST","MSG_MHF_GET_UD_NORMA_PRESENT_LIST","MSG_MHF_GET_UD_RANKING_REWARD_LIST","MSG_MHF_ACQUIRE_UD_ITEM","MSG_MHF_GET_REWARD_SONG","MSG_MHF_USE_REWARD_SONG","MSG_MHF_ADD_REWARD_SONG_COUNT","MSG_MHF_GET_UD_RANKING","MSG_MHF_GET_UD_MY_RANKING","MSG_MHF_ACQUIRE_MONTHLY_REWARD","MSG_MHF_GET_UD_GUILD_MAP_INFO","MSG_MHF_GENERATE_UD_GUILD_MAP","MSG_MHF_GET_UD_TACTICS_POINT","MSG_MHF_ADD_UD_TACTICS_POINT","MSG_MHF_GET_UD_TACTICS_RANKING","MSG_MHF_GET_UD_TACTICS_REWARD_LIST","MSG_MHF_GET_UD_TACTICS_LOG","MSG_MHF_GET_EQUIP_SKIN_HIST","MSG_MHF_UPDATE_EQUIP_SKIN_HIST","MSG_MHF_GET_UD_TACTICS_FOLLOWER","MSG_MHF_SET_UD_TACTICS_FOLLOWER","MSG_MHF_GET_UD_SHOP_COIN","MSG_MHF_USE_UD_SHOP_COIN","MSG_MHF_GET_ENHANCED_MINIDATA","MSG_MHF_SET_ENHANCED_MINIDATA","MSG_MHF_SEX_CHANGER","MSG_MHF_GET_LOBBY_CROWD","MSG_SYS_reserve180","MSG_MHF_GUILD_HUNTDATA","MSG_MHF_ADD_KOURYOU_POINT","MSG_MHF_GET_KOURYOU_POINT","MSG_MHF_EXCHANGE_KOURYOU_POINT","MSG_MHF_GET_UD_TACTICS_BONUS_QUEST","MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS","MSG_MHF_GET_UD_TACTICS_REMAINING_POINT","MSG_SYS_reserve188","MSG_MHF_LOAD_PLATE_MYSET","MSG_MHF_SAVE_PLATE_MYSET","MSG_SYS_reserve18B","MSG_MHF_GET_RESTRICTION_EVENT","MSG_MHF_SET_RESTRICTION_EVENT","MSG_SYS_reserve18E","MSG_SYS_reserve18F","MSG_MHF_GET_TREND_WEAPON","MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG","MSG_SYS_reserve192","MSG_SYS_reserve193","MSG_SYS_reserve194","MSG_MHF_SAVE_RENGOKU_DATA","MSG_MHF_LOAD_RENGOKU_DATA","MSG_MHF_GET_RENGOKU_BINARY","MSG_MHF_ENUMERATE_RENGOKU_RANKING","MSG_MHF_GET_RENGOKU_RANKING_RANK","MSG_MHF_ACQUIRE_EXCHANGE_SHOP","MSG_SYS_reserve19B","MSG_MHF_SAVE_MEZFES_DATA","MSG_MHF_LOAD_MEZFES_DATA","MSG_SYS_reserve19E","MSG_SYS_reserve19F","MSG_MHF_UPDATE_FORCE_GUILD_RANK","MSG_MHF_RESET_TITLE","MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD","MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD","MSG_SYS_reserve204","MSG_SYS_reserve205","MSG_SYS_reserve206","MSG_SYS_reserve207","MSG_SYS_reserve208","MSG_SYS_reserve209","MSG_SYS_reserve20A","MSG_SYS_reserve20B","MSG_SYS_reserve20C","MSG_SYS_reserve20D","MSG_SYS_reserve20E","MSG_SYS_reserve20F"] | |
class PacketHeader(object): | |
def __init__(self, data): | |
(pf0, key_rot_delta, pkt_num, pkt_data_size, pf4, check0, check1, check2) = struct.unpack('>BBHHHHHH', data) | |
self.pf0 = pf0 | |
self.key_rot_delta = key_rot_delta | |
self.pkt_num = pkt_num | |
self.pkt_data_size = pkt_data_size | |
self.pf4 = pf4 | |
self.check0 = check0 | |
self.check1 = check1 | |
self.check2 = check2 | |
class Packet(object): | |
def __init__(self, header, data): | |
self.header = header | |
self.data = data | |
class PacketStreamContext(object): | |
"""PacketStreamContext is a helper class for packet IO and crypto. | |
""" | |
def __init__(self, data_stream): | |
self._read_key_rot = 995117 | |
self._ds = data_stream | |
def _decrypt(self, data, rot_key, override_byte_key=None): | |
unk_cryptkey_rot_arg = ((rot_key >> 1) % 999983) & 0xFF | |
if override_byte_key is not None: | |
unk_cryptkey_rot_arg = override_byte_key | |
unk_derived_cryptkey_rot = (len(data) * (unk_cryptkey_rot_arg+1)) & 0xFFFFFFFF | |
shared_buf_idx = 1 | |
accumulator_0 = 0 | |
accumulator_1 = 0 | |
accumulator_2 = 0 | |
i = 0 | |
output_data = bytearray() | |
if len(data) > 0: | |
while(True): | |
old_shared_buf_idx = shared_buf_idx | |
t_idx = data[i] ^ SHARED_CRYPT_KEY[shared_buf_idx] | |
v15 = DECRYPT_KEY[t_idx] | |
shared_buf_idx = ((unk_derived_cryptkey_rot >> 10) ^ v15) & 0xFF | |
# Yikes. | |
accumulator_0 = (accumulator_0 + ((t_idx << (i & 7)) & 0xFFFFFFFF)) | |
accumulator_1 = (accumulator_1 + v15) & 0xFFFFFFFF | |
accumulator_2 = (accumulator_2 + ((old_shared_buf_idx * shared_buf_idx)&0xFFFFFFFF)) & 0xFFFFFFFF | |
output_data.append(shared_buf_idx) | |
# Update the key pos for next iteration. | |
unk_derived_cryptkey_rot = (0x4FD * (unk_derived_cryptkey_rot + 1)) & 0xFFFFFFFF | |
#End | |
i += 1 | |
if i >= len(data): | |
break | |
unk_output_field = accumulator_1 + (accumulator_0 >> 1) + (accumulator_2 >> 2) | |
check_0 = (accumulator_0 ^ ((accumulator_0&0xFFFF0000)>>16)) & 0xFFFF | |
check_1 = (accumulator_1 ^ ((accumulator_1&0xFFFF0000)>>16)) & 0xFFFF | |
check_2 = (accumulator_2 ^ ((accumulator_2&0xFFFF0000)>>16)) & 0xFFFF | |
return (output_data, unk_output_field, check_0, check_1, check_2) | |
def read_packet(self, bruteforce_encryption=False, out='output.txt'): | |
# Read the header. | |
header = PacketHeader(self._ds.read(PACKET_HEADER_SIZE)) | |
# Update the rolling key index. | |
if header.key_rot_delta != 0: | |
self._read_key_rot = (header.key_rot_delta * (self._read_key_rot + 1)) & 0xFFFFFFFF | |
# Read the encrypted packet body data. | |
encrypted_data = self._ds.read(header.pkt_data_size) | |
# Decrypt the data | |
if not bruteforce_encryption: | |
(output_data, unk_output_field, check0, check1, check2) = self._decrypt(encrypted_data, self._read_key_rot) | |
else: | |
#print("Bruteforcing... Original data:") | |
#hexdump(encrypted_data) | |
# Loop over all the 256 possibilities until the checksums match. | |
for i in range(256): | |
(output_data, unk_output_field, check0, check1, check2) = self._decrypt(encrypted_data, 0, i) | |
if check0 == header.check0 and check1 == header.check1 and check2 == header.check2: | |
break | |
pass | |
with open(out, 'a') as f: | |
while True: | |
try: | |
opcode = OPCODES[int.from_bytes(output_data[0:2], 'big')] | |
if opcode == 'MSG_SYS_EXTEND_THRESHOLD': | |
output_data = output_data[2:] | |
continue | |
else: | |
break | |
except IndexError: | |
opcode = 'UNKNOWN' | |
break | |
f.write(f'OPCODE: {opcode}\n') | |
f.write(f'ACKHANDLE:{output_data[2:6].hex()}\n') | |
for line in hexdump(output_data, result='generator'): | |
f.write(line+'\n') | |
return Packet(header, output_data) | |
if __name__ == '__main__': | |
for file in sys.argv[1:]: | |
open(file+'.txt', 'w').close() | |
with open(file, 'rb') as f: | |
print(f'Decrypting \'{file}\'...') | |
ps = PacketStreamContext(f) | |
while f != '': | |
try: | |
pkt = ps.read_packet(bruteforce_encryption=True, out=file+'.txt') | |
except struct.error: | |
break |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment