osslsigncode/misc/pagehash.py
Per Allansson 9152c925c0 Page hash verification now works
Had it right from the start, but messed up the python script...
2013-03-12 20:43:54 +01:00

140 lines
3.1 KiB
Python

#!/usr/bin/python
import struct
import sys
import hashlib
from pyasn1.type import univ
from pyasn1.codec.ber import encoder, decoder
f = open(sys.argv[1], 'rb')
filehdr = f.read(1024)
if filehdr[0:2] != 'MZ':
print "Not a DOS file."
sys.exit(0)
pepos = struct.unpack('<I', filehdr[60:64])[0]
if filehdr[pepos:pepos+4] != 'PE\0\0':
print "Not a PE file."
sys.exit(0)
pepos += 4
nsections = struct.unpack('<H', filehdr[pepos+2:pepos+4])[0]
print "#sections", nsections
magic = struct.unpack('<H', filehdr[pepos+20:pepos+22])[0]
pe32plus = 0
if magic == 0x20b:
pe32plus = 1
elif magic == 0x10b:
pe32plus = 0
else:
print "Unknown magic", magic
sys.exit(0)
sectoralign = struct.unpack('<I', filehdr[pepos+52:pepos+56])[0]
print "Sector alignment", sectoralign
pos = pepos + 112 + pe32plus*16
nrvas = struct.unpack('<I', filehdr[pos:pos+4])[0]
print "#rvas", nrvas
pos += 4
tpos = pos
rvas = []
for i in range(0, nrvas):
(p1,p2) = struct.unpack('<II', filehdr[pos:pos+8])
rvas.append((p1,p2))
pos += 8
sections = []
for i in range(0, nsections):
(vsize,vaddr,rsize,raddr) = struct.unpack('<IIII', filehdr[pos+8:pos+24])
pos += 40
sections.append((vsize,vaddr,rsize,raddr))
hdrend = pos
print "End of headers", pos
print rvas
print sections
sigpos,siglen = rvas[4]
if sigpos == 0:
print "No signature found"
sys.exit(0)
f.seek(sigpos)
sigblob = f.read(siglen)
cid_page_hash = "\xa6\xb5\x86\xd5\xb4\xa1\x24\x66\xae\x05\xa2\x17\xda\x8e\x60\xd6"
oid_ph_v1 = "\x06\x01\x04\x01\x82\x37\x02\x03\x01"
oid_ph_v2 = "\x06\x01\x04\x01\x82\x37\x02\x03\x02"
p = sigblob.find(cid_page_hash)
if p == -1:
print "No page hash present"
sys.exit(0)
p += len(cid_page_hash)
sha1 = True
i = sigblob.find(oid_ph_v1)
if i == -1:
i = sigblob.find(oid_ph_v2)
if i == -1:
print "No page hash found"
sys.exit(0)
sha1 = False
p = i + len(oid_ph_v1)
blob = str(decoder.decode(sigblob[p:])[0].getComponentByPosition(0))
ph = []
i = 0
hashlen = 20
if not sha1:
hashlen = 24
while i < len(blob):
offset = struct.unpack('<I', blob[i:i+4])[0]
i += 4
data = blob[i:i+hashlen]
ph.append((offset,data.encode("hex")))
i += hashlen
if sha1:
md = hashlib.sha1()
else:
md = hashlib.sha256()
b = filehdr[0:pepos+84]
b += filehdr[pepos+88:tpos+4*8]
b += filehdr[tpos+5*8:1024]
b += '\0'*(4096-1024)
md.update(b)
digest = md.hexdigest()
print ""
print "Checking page hash..."
print ""
nph = [(0,digest)]
lastpos = 0
pagesize = sectoralign # ???
for vs,vo,rs,ro in sections:
l = 0
while l < rs:
f.seek(ro+l)
howmuch = pagesize
if rs - l < pagesize:
howmuch = rs - l
b = f.read(howmuch)
if howmuch < pagesize:
b = b + '\0' * (pagesize - (rs - l))
if sha1:
d = hashlib.sha1(b).hexdigest()
else:
d = hashlib.sha256(b).hexdigest()
nph.append((ro+l, d))
l += pagesize
lastpos = ro + rs
nph.append((lastpos,'0'*(2*hashlen)))
for i in range(0,len(nph)):
x=ph[i]
y=nph[i]
if x[0] != y[0] or x[1] != y[1]:
print "Not matching:", x, "!=", y