Files
OpenFUT/fifa17-recon/tools/ghidra_queries/q_md_v1_A.py
T

65 lines
2.5 KiB
Python

"""ADVERSARIAL VERIFY Dimension 1: userInfo.feature restriction vocabulary.
Attacks:
D1.1 feature loop recognises EXACTLY one sub-key (trade 0x330), all else value-SKIP.
D1.2 trade uses INT getter FUN_1801c79d0, writes +0xa4 only when ==1.
D1.3 massinfo root FUN_180174630: at END_OBJECT the SOLE `cmp byte[reg+disp],0` site
is +0x17c -> zero [reg+0x50]; nothing else zeroes a settings field from a feature byte.
Control: 0x330 MUST appear in the feature loop and map to +0xa4 (param_1+0x29). If the
massinfo case that calls the feature parser is not +0xd8, the +0x17c arithmetic is wrong.
"""
import traceback
try:
FEAT = 0x18013ec10
MASS = 0x180174630
src = dec(FEAT, 300)
print("=== FEATURE FUN_18013ec10 decompile=%d chars ===" % len(src))
print(src)
# enumerate every integer constant compared in the loop (dispatch forms)
print("\n=== raw instructions in feature parser: CMP/immediates + calls ===")
f = func(FEAT)
it = listing.getInstructions(f.getBody(), True)
cnt = 0
while it.hasNext():
ins = it.next()
m = ins.getMnemonicString()
s = str(ins)
if m in ("CMP", "SUB", "LEA") and ("0x330" in s or "0x11c" in s):
print(" %#x %s" % (ins.getAddress().getOffset(), s))
if m == "CALL":
print(" %#x %s" % (ins.getAddress().getOffset(), s))
cnt += 1
print(" (total insns=%d)" % cnt)
print("\n=== MASSINFO root FUN_180174630: scan for cmp byte[reg+disp],0x0 ===")
fm2 = func(MASS)
it = listing.getInstructions(fm2.getBody(), True)
hits = []
n = 0
prev = []
while it.hasNext():
ins = it.next()
n += 1
m = ins.getMnemonicString()
s = str(ins)
# cmp byte ptr [reg + disp], 0
if m == "CMP" and "byte ptr" in s and s.rstrip().endswith(",0x0"):
hits.append((ins.getAddress().getOffset(), s))
# any MOV of 0 into [reg+0x50]
if m == "MOV" and "dword ptr" in s and "0x50]" in s and s.rstrip().endswith(",0x0"):
print(" ZERO-WRITE %#x %s" % (ins.getAddress().getOffset(), s))
print(" cmp byte[reg+disp],0 sites: %d" % len(hits))
for a, s in hits:
print(" %#x %s" % (a, s))
print(" (massinfo total insns=%d)" % n)
# confirm which case calls the feature parser and at what struct offset
print("\n=== calls to FUN_18013ec10 (feature) from anywhere ===")
for frm, typ, fn, ent in xrefs_to(FEAT):
print(" %#x %s in %s" % (frm, typ, fn))
except Exception:
traceback.print_exc()