mirror of
https://github.com/vivisect/vivisect
synced 2026-06-08 18:04:23 +00:00
80de840881
A lot of cleanup things in prep for a python 3 transition. Getting rid of the old exception syntax, converting prints over to logging, cutting random scraps of code to be proper unit tests, cut away some older bits of code, etc. This still works in python2. It's just a lot of tidying up. There are no major functionality changes.
204 lines
7.9 KiB
Python
204 lines
7.9 KiB
Python
import vstruct
|
|
|
|
from vstruct.primitives import *
|
|
|
|
|
|
#const tag descriptions from wikipedia
|
|
#Tag byte Additional bytes Description of constant
|
|
#1 2+x bytes utf-8 string
|
|
#3 4 bytes Integer: a signed 32-bit two's complement number in big-endian format
|
|
#4 4 bytes Float: a 32-bit single-precision IEEE 754 floating-point number
|
|
#5 8 bytes Long: a signed 64-bit two's complement number in big-endian format (takes two slots in the constant pool table)
|
|
#6 8 bytes Double: a 64-bit double-precision IEEE 754 floating-point number (takes two slots in the constant pool table)
|
|
#7 2 bytes Class reference: an index within the constant pool to a UTF-8 string containing the fully qualified class name (in internal format)
|
|
#8 2 bytes String reference: an index within the constant pool to a UTF-8 string
|
|
#9 4 bytes Field reference: two indexes within the constant pool, the first pointing to a Class reference, the second to a Name and Type descriptor.
|
|
#10 4 bytes Method reference: two indexes within the constant pool, the first pointing to a Class reference, the second to a Name and Type descriptor.
|
|
#11 4 bytes Interface method reference: two indexes within the constant pool, the first pointing to a Class reference, the second to a Name and Type descriptor.
|
|
#12 4 bytes Name and type descriptor: two indexes to UTF-8 strings within the constant pool, the first representing a name (identifier) and the second a specially encoded type descriptor.
|
|
|
|
class ConstPoolStr(vstruct.VStruct):
|
|
def __init__(self):
|
|
vstruct.VStruct.__init__(self)
|
|
self.size = v_uint16(bigend=True)
|
|
self.strbytes = v_wstr(encode='utf8')
|
|
|
|
def pcb_size(self):
|
|
self.vsGetField('strbytes').vsSetLength( self.size )
|
|
|
|
tag_classes = {
|
|
1: ConstPoolStr,
|
|
3: v_uint32,
|
|
4: v_uint32,
|
|
5: v_uint64,
|
|
6: v_uint64,
|
|
7: v_uint16,
|
|
8: v_uint16,
|
|
9: v_uint32,
|
|
10: v_uint32,
|
|
11: v_uint32,
|
|
12: v_uint32,
|
|
}
|
|
|
|
# Constant Tag Types
|
|
CONSTANT_Utf8 = 1
|
|
CONSTANT_Integer = 3
|
|
CONSTANT_Float = 4
|
|
CONSTANT_Long = 5
|
|
CONSTANT_Double = 6
|
|
CONSTANT_Class = 7
|
|
CONSTANT_String = 8
|
|
CONSTANT_Fieldref = 9
|
|
CONSTANT_Methodref = 10
|
|
CONSTANT_InterfaceMethodref = 11
|
|
CONSTANT_NameAndType = 12
|
|
CONSTANT_MethodHandle = 15
|
|
CONSTANT_MethodType = 16
|
|
CONSTANT_InvokeDynamic = 18
|
|
|
|
# Access Flags Values
|
|
ACC_PUBLIC = 0x0001 # Declared public; may be accessed from outside its package.
|
|
ACC_PRIVATE = 0x0002 # Declared private; usable only within the defining class.
|
|
ACC_PROTECTED = 0x0004 # Declared protected; may be accessed within subclasses.
|
|
ACC_STATIC = 0x0008 # Declared static.
|
|
ACC_FINAL = 0x0010 # Declared final; never directly assigned to after object construction.
|
|
ACC_VOLATILE = 0x0040 # Declared volatile; cannot be cached.
|
|
ACC_TRANSIENT = 0x0080 # Declared transient; not written or read by a persistent object manager.
|
|
ACC_SYNTHETIC = 0x1000 # Declared synthetic; not present in the source code.
|
|
ACC_ENUM = 0x4000 # Declared as an element of an enum.
|
|
|
|
class ConstPoolInfo(vstruct.VStruct):
|
|
def __init__(self):
|
|
vstruct.VStruct.__init__(self)
|
|
self.tag = v_uint8()
|
|
self.data = vstruct.VStruct()
|
|
|
|
def pcb_tag(self):
|
|
cls = tag_classes.get(self.tag)
|
|
if cls is None:
|
|
raise Exception('Unknown ConstPoolInfo Tag: %s' % self.tag )
|
|
self.data.tagval = cls()
|
|
|
|
class AttributeInfo(vstruct.VStruct):
|
|
|
|
def __init__(self):
|
|
vstruct.VStruct.__init__(self)
|
|
self.attribute_name_index = v_uint16(bigend=True)
|
|
self.attribute_length = v_uint32(bigend=True)
|
|
self.attribute = v_bytes()
|
|
|
|
def pcb_attribute_length(self):
|
|
self.vsGetField('attribute').vsSetLength( self.attribute_length )
|
|
|
|
class FieldInfo(vstruct.VStruct):
|
|
|
|
def __init__(self):
|
|
vstruct.VStruct.__init__(self)
|
|
self.access_flags = v_uint16(bigend=True)
|
|
self.name_index = v_uint16(bigend=True)
|
|
self.descriptor_index = v_uint16(bigend=True)
|
|
self.attributes_count = v_uint16(bigend=True)
|
|
self.attributes = vstruct.VArray()
|
|
|
|
def pcb_attributes_count(self):
|
|
self.attributes.vsAddElements( self.attributes_count, AttributeInfo )
|
|
|
|
class MethodInfo(vstruct.VStruct):
|
|
|
|
def __init__(self):
|
|
vstruct.VStruct.__init__(self)
|
|
self.access_flags = v_uint16(bigend=True)
|
|
self.name_index = v_uint16(bigend=True)
|
|
self.descriptor_index = v_uint16(bigend=True)
|
|
self.attributes_count = v_uint16(bigend=True)
|
|
self.attributes = vstruct.VArray()
|
|
|
|
def pcb_attributes_count(self):
|
|
self.attributes.vsAddElements( self.attributes_count, AttributeInfo )
|
|
|
|
class JavaClass(vstruct.VStruct):
|
|
def __init__(self):
|
|
vstruct.VStruct.__init__(self)
|
|
self.magic = v_uint32(bigend=True)
|
|
self.minor_versino = v_uint16(bigend=True)
|
|
self.major_version = v_uint16(bigend=True)
|
|
|
|
self.const_pool_cnt = v_uint16(bigend=True)
|
|
self.const_pool = vstruct.VArray()
|
|
|
|
self.access_flags = v_uint16(bigend=True)
|
|
self.this_class = v_uint16(bigend=True)
|
|
self.super_class = v_uint16(bigend=True)
|
|
|
|
self.interface_cnt = v_uint16(bigend=True)
|
|
self.interfaces = vstruct.VArray()
|
|
|
|
self.fields_cnt = v_uint16(bigend=True)
|
|
self.fields = vstruct.VArray()
|
|
|
|
self.methods_cnt = v_uint16(bigend=True)
|
|
self.methods = vstruct.VArray()
|
|
|
|
self.attributes_cnt = v_uint16(bigend=True)
|
|
self.attributes = vstruct.VArray()
|
|
|
|
def pcb_const_pool_cnt(self):
|
|
# Count is off by one according to the spec
|
|
self.const_pool.vsAddElements( self.const_pool_cnt - 1, ConstPoolInfo )
|
|
|
|
def pcb_interface_cnt(self):
|
|
for i in range( self.interface_cnt ):
|
|
self.interfaces.vsAddElement( v_uint16( bigend=True ) )
|
|
|
|
def pcb_fields_cnt(self):
|
|
self.fields.vsAddElements( self.fields_cnt, FieldInfo )
|
|
|
|
def pcb_methods_cnt(self):
|
|
self.methods.vsAddElements( self.methods_cnt, MethodInfo )
|
|
|
|
def pcb_attributes_cnt(self):
|
|
self.attributes.vsAddElements( self.attributes_cnt, AttributeInfo )
|
|
|
|
def getClassName(self):
|
|
return self.const_pool[ self.this_class ].data.tagval.strbytes
|
|
|
|
def getSuperClassName(self):
|
|
return self.const_pool[ self.super_class ].data.tagval.strbytes
|
|
|
|
def getClassFields(self):
|
|
'''
|
|
Get the fields defined by this class as a tuple of
|
|
( fieldname, fieldtype, attribs ) where attribs is a dict.
|
|
'''
|
|
ret = []
|
|
for fname,fieldinfo in self.fields:
|
|
|
|
fieldname = self.const_pool[ fieldinfo.name_index - 1 ].data.tagval.strbytes
|
|
descname = self.const_pool[ fieldinfo.descriptor_index - 1 ].data.tagval.strbytes
|
|
|
|
attrs = {}
|
|
for afield, attrinfo in fieldinfo.attributes:
|
|
attrname = self.const_pool[ attrinfo.attribute_name_index - 1 ].data.tagval.strbytes
|
|
attrs[ attrname ] = attrinfo.attribute
|
|
|
|
ret.append( (fieldname, descname, attrs) )
|
|
return ret
|
|
|
|
def getClassMethods(self):
|
|
ret = []
|
|
for fname,methinfo in self.methods:
|
|
methname = self.const_pool[ methinfo.name_index - 1 ].data.tagval.strbytes
|
|
attrs = {}
|
|
for afield, attrinfo in methinfo.attributes:
|
|
attrname = self.const_pool[ attrinfo.attribute_name_index - 1 ].data.tagval.strbytes
|
|
attrs[ attrname ] = attrinfo.attribute
|
|
ret.append( (methname, attrs) )
|
|
return ret
|
|
|
|
def getClassAttributes(self):
|
|
attrs = {}
|
|
for afield, attrinfo in self.attributes:
|
|
attrname = self.const_pool[ attrinfo.attribute_name_index - 1 ].data.tagval.strbytes
|
|
attrs[ attrname ] = attrinfo.attribute
|
|
return attrs
|