mirror of
https://gitea.tendokyu.moe/beerpsi/x.git
synced 2024-11-24 07:10:11 +01:00
fix: option versions are different; fix header metadat, formatting
This commit is contained in:
parent
8ca3bc37ba
commit
5c40c357c6
@ -9,7 +9,16 @@ import zlib
|
|||||||
from Crypto.Cipher import AES, PKCS1_OAEP
|
from Crypto.Cipher import AES, PKCS1_OAEP
|
||||||
from Crypto.Hash import HMAC, SHA1
|
from Crypto.Hash import HMAC, SHA1
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from construct import Bytes, Const, Int16ul, Int32ul, Int64ul, Int8ul, Struct
|
from construct import (
|
||||||
|
Bytes,
|
||||||
|
Const,
|
||||||
|
IfThenElse,
|
||||||
|
Int16ul,
|
||||||
|
Int32ul,
|
||||||
|
Int64ul,
|
||||||
|
Int8ul,
|
||||||
|
Struct,
|
||||||
|
)
|
||||||
|
|
||||||
# ---- Configuration
|
# ---- Configuration
|
||||||
ENCRYPTION_KEY = bytes.fromhex("")
|
ENCRYPTION_KEY = bytes.fromhex("")
|
||||||
@ -28,11 +37,7 @@ BOOTID = {
|
|||||||
"second": 43,
|
"second": 43,
|
||||||
"milli": 0,
|
"milli": 0,
|
||||||
},
|
},
|
||||||
"game_version": {
|
"game_version": b"A041",
|
||||||
"release": 0,
|
|
||||||
"minor": 30,
|
|
||||||
"major": 1,
|
|
||||||
},
|
|
||||||
"block_size": 0x40000,
|
"block_size": 0x40000,
|
||||||
"header_block_count": 8,
|
"header_block_count": 8,
|
||||||
"unk1": 0,
|
"unk1": 0,
|
||||||
@ -57,7 +62,8 @@ BOOTID = {
|
|||||||
"minor": 54,
|
"minor": 54,
|
||||||
"major": 80,
|
"major": 80,
|
||||||
},
|
},
|
||||||
"strings": b"\x00" * 0x27AC, # Depending on the app/opt/pack, this might have some text in it.
|
"strings": b"\x00"
|
||||||
|
* 0x27AC, # Depending on the app/opt/pack, this might have some text in it.
|
||||||
}
|
}
|
||||||
# ----
|
# ----
|
||||||
|
|
||||||
@ -65,7 +71,9 @@ BOOTID = {
|
|||||||
# The BootID (app/opt/pack header) encryption key and IV.
|
# The BootID (app/opt/pack header) encryption key and IV.
|
||||||
BTKEY = bytes.fromhex("09ca5efd30c9aaef3804d0a7e3fa7120")
|
BTKEY = bytes.fromhex("09ca5efd30c9aaef3804d0a7e3fa7120")
|
||||||
BTIV = bytes.fromhex("b155c22c2e7f0491fa7f0fdc217aff90")
|
BTIV = bytes.fromhex("b155c22c2e7f0491fa7f0fdc217aff90")
|
||||||
SIGKEY = bytes.fromhex("e1bdcb2d5e9ed3b5de234364dfa4d126849edff769fc6c28fba5f43bc482bd7479d676afce8188e1d3a6852f4ebce45cde46bd15e8ee5fe84d197f945a54518f")
|
SIGKEY = bytes.fromhex(
|
||||||
|
"e1bdcb2d5e9ed3b5de234364dfa4d126849edff769fc6c28fba5f43bc482bd7479d676afce8188e1d3a6852f4ebce45cde46bd15e8ee5fe84d197f945a54518f"
|
||||||
|
)
|
||||||
HEADER_META_PUBKEY = RSA.import_key("""-----BEGIN PUBLIC KEY-----
|
HEADER_META_PUBKEY = RSA.import_key("""-----BEGIN PUBLIC KEY-----
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRMLnJuczNpfoqPpHQ3o
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRMLnJuczNpfoqPpHQ3o
|
||||||
5XNkjKXO6P3ToV/45Az5dNaHVL7uEu9vPI7a2KYFQnNYgD3UUHFahfTcljzLOkcH
|
5XNkjKXO6P3ToV/45Az5dNaHVL7uEu9vPI7a2KYFQnNYgD3UUHFahfTcljzLOkcH
|
||||||
@ -107,7 +115,7 @@ BootID = Struct(
|
|||||||
"sequence_number" / Int16ul,
|
"sequence_number" / Int16ul,
|
||||||
"game_id" / Bytes(4),
|
"game_id" / Bytes(4),
|
||||||
"game_timestamp" / Timestamp,
|
"game_timestamp" / Timestamp,
|
||||||
"game_version" / Version,
|
"game_version" / IfThenElse(lambda ctx: ctx.type == 0x0201, Bytes(4), Version),
|
||||||
"block_count" / Int64ul,
|
"block_count" / Int64ul,
|
||||||
"block_size" / Int64ul,
|
"block_size" / Int64ul,
|
||||||
"header_block_count" / Int64ul,
|
"header_block_count" / Int64ul,
|
||||||
@ -120,6 +128,7 @@ BootID = Struct(
|
|||||||
"strings" / Bytes(0x27AC),
|
"strings" / Bytes(0x27AC),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_page_iv(iv: bytes, offset: int):
|
def get_page_iv(iv: bytes, offset: int):
|
||||||
return bytes(x ^ (offset >> (8 * (i % 8))) & 0xFF for (i, x) in enumerate(iv))
|
return bytes(x ^ (offset >> (8 * (i % 8))) & 0xFF for (i, x) in enumerate(iv))
|
||||||
|
|
||||||
@ -134,11 +143,27 @@ print(f"Generated IV: {iv.hex()}")
|
|||||||
filesize = os.stat(INPUT_FILE).st_size
|
filesize = os.stat(INPUT_FILE).st_size
|
||||||
BOOTID["block_count"] = ceil(filesize / BOOTID["block_size"]) + 8
|
BOOTID["block_count"] = ceil(filesize / BOOTID["block_size"]) + 8
|
||||||
|
|
||||||
header_meta = struct.pack("<Q", time.time()) + os.path.abspath(INPUT_FILE).encode("utf-8")
|
key = secrets.token_bytes(16)
|
||||||
header_meta += secrets.token_bytes(BOOTID["block_size"] - len(header_meta))
|
iv = secrets.token_bytes(16)
|
||||||
header_meta = PKCS1_OAEP.new(HEADER_META_PUBKEY).encrypt(header_meta)
|
encrypted_keypair = PKCS1_OAEP.new(HEADER_META_PUBKEY).encrypt(key + iv)
|
||||||
|
header_meta = struct.pack("<Q", int(time.time())) + os.path.abspath(INPUT_FILE).encode(
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
header_meta += secrets.token_bytes(
|
||||||
|
BOOTID["block_size"] - len(header_meta) - len(encrypted_keypair)
|
||||||
|
)
|
||||||
|
header_meta = encrypted_keypair + AES.new(key, AES.MODE_CBC, iv).encrypt(header_meta)
|
||||||
header_meta_crc32 = zlib.crc32(header_meta)
|
header_meta_crc32 = zlib.crc32(header_meta)
|
||||||
block_crc32s = [0, header_meta_crc32, header_meta_crc32, header_meta_crc32, header_meta_crc32, header_meta_crc32, header_meta_crc32, header_meta_crc32]
|
block_crc32s = [
|
||||||
|
0,
|
||||||
|
header_meta_crc32,
|
||||||
|
header_meta_crc32,
|
||||||
|
header_meta_crc32,
|
||||||
|
header_meta_crc32,
|
||||||
|
header_meta_crc32,
|
||||||
|
header_meta_crc32,
|
||||||
|
header_meta_crc32,
|
||||||
|
]
|
||||||
|
|
||||||
with open(INPUT_FILE, "rb") as fin, open(OUTPUT_FILE, "w+b") as fout:
|
with open(INPUT_FILE, "rb") as fin, open(OUTPUT_FILE, "w+b") as fout:
|
||||||
# Write the bootID.
|
# Write the bootID.
|
||||||
@ -207,7 +232,9 @@ with open(INPUT_FILE, "rb") as fin, open(OUTPUT_FILE, "w+b") as fout:
|
|||||||
|
|
||||||
# Skip the HMAC signature and the first CRC32, which we're trying to calculate.
|
# Skip the HMAC signature and the first CRC32, which we're trying to calculate.
|
||||||
_ = fout.seek(0x204, os.SEEK_CUR)
|
_ = fout.seek(0x204, os.SEEK_CUR)
|
||||||
block_0_crc32 = zlib.crc32(fout.read(BOOTID["block_size"] - 0x2800 - 0x204), block_0_crc32)
|
block_0_crc32 = zlib.crc32(
|
||||||
|
fout.read(BOOTID["block_size"] - 0x2800 - 0x204), block_0_crc32
|
||||||
|
)
|
||||||
|
|
||||||
_ = fout.seek(0x2A00)
|
_ = fout.seek(0x2A00)
|
||||||
_ = fout.write(struct.pack("<I", block_0_crc32))
|
_ = fout.write(struct.pack("<I", block_0_crc32))
|
||||||
@ -227,4 +254,3 @@ with open(INPUT_FILE, "rb") as fin, open(OUTPUT_FILE, "w+b") as fout:
|
|||||||
|
|
||||||
_ = fout.seek(0x2800)
|
_ = fout.seek(0x2800)
|
||||||
_ = fout.write(hmac.digest())
|
_ = fout.write(hmac.digest())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user