1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
"""Find ADDED guards between firmware versions, using the corrected method.
The Phase-4/5 pipeline searched for raw little-endian dwords, which cannot see
Thumb `cmp.w`/`mov.w` MODIFIED IMMEDIATES -- the encoding these constants
actually use. That produced at least one false negative that read as
confirmation (see METHODOLOGY-INLINING-VS-ADDED-GUARDS.md).
Correct method:
* decode every 2-byte-aligned instruction (linear sweep misaligns)
* count immediates of comparison/bound instructions only
* report constants whose COUNT RISES in the newer build
(rising = added code; falling/equal = outlining or refactor)
"""
from capstone import *
import sys, collections
md=Cs(CS_ARCH_ARM,CS_MODE_THUMB)
CMPish={'cmp','cmp.w','cmn','cmn.w','subs','sub.w','tst','tst.w','movw','mov.w','movs'}
def census(body):
c=collections.Counter()
for off in range(0,len(body)-4,2):
ins=list(md.disasm(body[off:off+4],off))
if not ins: continue
i=ins[0]
if i.mnemonic not in CMPish: continue
if '#' not in i.op_str: continue
try: v=int(i.op_str.rsplit('#',1)[1],0)
except Exception: continue
if v<8: continue # skip trivial small constants
c[(i.mnemonic.split('.')[0],v)]+=1
return c
def delta(a,b,label):
A,B=census(open(a,'rb').read()),census(open(b,'rb').read())
gained=[(k,B[k]-A[k]) for k in set(A)|set(B) if B[k]-A[k]>0]
gained.sort(key=lambda t:-t[1])
print("=== %s ==="%label)
print(" constants whose count RISES (candidate ADDED guards):")
shown=0
for (m,v),n in gained:
if n<1: continue
print(" %-5s #%-12s +%d (%d -> %d)"%(m,hex(v),n,A[(m,v)],B[(m,v)]))
shown+=1
if shown>=18: print(" ..."); break
print()
if __name__=='__main__':
delta('versions/sos_0.49.0.51_14039a1f.bin','versions_lfw/sos_3fd1d56b0467c5ea_98944.bin','sOS .51 -> .52')
delta('versions_lfw/sos_3fd1d56b0467c5ea_98944.bin','versions/sos_0.49.0.54_3dcb63e8.bin','sOS .52 -> .54')
delta('versions/sys_drv_0.49.0.51_0e768b6a.bin','versions/sys_drv_0.49.0.54_18bd9d26.bin','SYS_DRV .51 -> .54')
|