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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#!/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
|