Skip to content

Instantly share code, notes, and snippets.

@ezterry
Created September 24, 2011 17:38
Show Gist options
  • Save ezterry/1239615 to your computer and use it in GitHub Desktop.
Save ezterry/1239615 to your computer and use it in GitHub Desktop.
A python library to provide some insight into the internals of the dex/odex files; just a start to allow checking of the checksums and sha signatures, may grow to have additional functions
#!/usr/bin/python
import struct
import zlib
import hashlib
class dexOptHeader:
def __init__(self,fp,dexFile):
"""Load the header data structure
sets attributes:
magic,dexOffset,Length,depsOffset,depsLength,
optOffset,optLength,flags,checksum
This operation reads from the dex file"""
(self.magic,
self.dexOffset,
self.dexLength,
self.depsOffset,
self.depsLength,
self.optOffset,
self.optLength,
self.flags,
self.checksum) = struct.unpack("<8s8l",fp.read(40))
self.dexFile=dexFile
self._fp=fp
self.odex=True
if self.magic[4:] == '035\x00':
#we have a classes.dex file
self.dexOffset=0
self.dexLength=self.flags
self.depsOffset=0
self.depsLength=0
self.optLength=0
self.optOffset=0
self.flags=0
self.odex=False
def calculateChecksum(self):
"""Calculate the actual adler32 checksum from the file"""
assert(self.odex)
self._fp.seek(self.depsOffset)
data = self._fp.read(self.optOffset+self.optLength-self.depsOffset)
true_checksum=zlib.adler32(data)
return true_checksum;
def verifyChecksum(self):
"""Verify if the file data matches the checksum
Note: this will read from the dexfile"""
assert(self.odex)
true_checksum=self.calculateChecksum()
return true_checksum == self.checksum
class dexHeader:
def __init__(self,fp,dexFile):
self._fp=fp
self.dexFile = dexFile
dexOptHdr=self.dexFile.getDexOptHeader()
fp.seek(dexOptHdr.dexOffset)
(self.magic,
self.checksum,
self.signature,
self.fileSize,
self.headerSize,
self.endianTag,
self.linkSize,
self.linkOff,
self.mapOff,
self.stringIdsSize,
self.stringIdsOff,
self.typeIdsSize,
self.typeIdsOff,
self.protoIdsSize,
self.protoIdsOff,
self.fieldIdsSize,
self.fieldIdsOff,
self.methodIdsSize,
self.methodIdsOff,
self.classDefsSize,
self.classDefsOff,
self.dataSize,
self.dataOff) = struct.unpack("<8sl20s20l",fp.read(112))
def calculateChecksum(self):
"""Calculate the actual check sum from the file"""
skip_nonsum = 8 + 4 #skip 8b magic + 4b checksum
dexOptHdr=self.dexFile.getDexOptHeader()
self._fp.seek(dexOptHdr.dexOffset + skip_nonsum)
data=self._fp.read(self.fileSize - skip_nonsum)
true_checksum=zlib.adler32(data)
return true_checksum
def verifyChecksum(self):
"""Verify if the file data matches the checksum
Note: this will read from the dexfile"""
true_checksum=self.calculateChecksum()
return true_checksum == self.checksum
def calculateSignature(self):
"""Calculate the SHA signature from the file"""
skip_nonsum = 8 + 4 + 20 #skip 8b magic + 4b checksum + sha1
dexOptHdr=self.dexFile.getDexOptHeader()
self._fp.seek(dexOptHdr.dexOffset + skip_nonsum)
data=self._fp.read(self.fileSize - skip_nonsum)
sha1=hashlib.new('sha1')
sha1.update(data)
return sha1.digest()
def verifySignature(self):
"""Verify the sha1 signature"""
true_sig = calculateSignature(self)
return true_sig == self.signature
class dexFile:
def __init__(self,fp):
self._fp=fp
self.dexOptHeader=None
self.dexHeader=None
self.odexDeps=None
def getDexOptHeader(self):
"""Get the dexopt header object, either the existing instance
or load a new instance"""
if(self.dexOptHeader is not None):
return self.dexOptHeader
self._fp.seek(0)
self.dexOptHeader=dexOptHeader(self._fp,self)
return self.dexOptHeader
def getDexHeader(self):
"""Get the dex header object, either the existing instance or
load a new instace"""
if(self.dexHeader is not None):
return self.dexHeader
self.dexHeader=dexHeader(self._fp,self)
return self.dexHeader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment