Initial commit: RE tooling and docs for The I of the Dragon localization/HD
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import os, sys, collections, math
|
||||
|
||||
base = r"F:\steam\steamapps\common\The I of the Dragon\Data\Misc"
|
||||
files = ["Fonts.dat", "UnitDescription.dat", "AIDescription.dat"]
|
||||
|
||||
def printable_ratio(b):
|
||||
if not b: return 0
|
||||
return sum(1 for x in b if 32 <= x < 127) / len(b)
|
||||
|
||||
def score_text(b):
|
||||
# rough score: printable ratio + bonus for common english words
|
||||
r = printable_ratio(b)
|
||||
sample = bytes(b)
|
||||
kw = 0
|
||||
for w in [b"Char", b"Code", b"Font", b"SpaceWidth", b".tga", b"Shrift", b"Distance", b"Id", b"String"]:
|
||||
kw += sample.count(w)
|
||||
return r, kw
|
||||
|
||||
for f in files:
|
||||
p = os.path.join(base, f)
|
||||
data = open(p, "rb").read()
|
||||
print("="*70)
|
||||
print(f, "size", len(data))
|
||||
print("first 32:", data[:32].hex(" "))
|
||||
|
||||
# 1) single-byte xor
|
||||
best = []
|
||||
for k in range(256):
|
||||
dec = bytes(x ^ k for x in data)
|
||||
r, kw = score_text(dec)
|
||||
best.append((kw, r, k, dec[:80]))
|
||||
best.sort(key=lambda t: (-t[0], -t[1]))
|
||||
print("-- best single-byte XOR by keyword --")
|
||||
for kw, r, k, s in best[:5]:
|
||||
print(f" k=0x{k:02X} kw={kw} pr={r:.3f} {s!r}")
|
||||
|
||||
# 2) additive / subtractive
|
||||
best = []
|
||||
for k in range(256):
|
||||
dec = bytes((x - k) & 0xFF for x in data)
|
||||
r, kw = score_text(dec)
|
||||
best.append((kw, r, k, dec[:80]))
|
||||
best.sort(key=lambda t: (-t[0], -t[1]))
|
||||
print("-- best subtract key --")
|
||||
for kw, r, k, s in best[:3]:
|
||||
print(f" k=0x{k:02X} kw={kw} pr={r:.3f} {s!r}")
|
||||
|
||||
# 3) repeating-key XOR, key length 2..64, derive key from space frequency
|
||||
print("-- repeating-key XOR (key from most-common byte == space) --")
|
||||
results = []
|
||||
for L in range(2, 65):
|
||||
key = bytearray()
|
||||
for r in range(L):
|
||||
col = data[r::L]
|
||||
c = collections.Counter(col).most_common(1)[0][0]
|
||||
key.append(c ^ 0x20)
|
||||
dec = bytes(x ^ key[i % L] for i, x in enumerate(data))
|
||||
rr, kw = score_text(dec)
|
||||
results.append((kw, rr, L, bytes(key), dec[:80]))
|
||||
results.sort(key=lambda t: (-t[0], -t[1]))
|
||||
for kw, rr, L, key, s in results[:6]:
|
||||
print(f" L={L:2d} key={key.hex()} kw={kw} pr={rr:.3f} {s!r}")
|
||||
Reference in New Issue
Block a user