Skip to content

Instantly share code, notes, and snippets.

@danboykis
Created August 31, 2020 17:05
Show Gist options
  • Save danboykis/c4c9058fab7702df6b2c03f09f992842 to your computer and use it in GitHub Desktop.
Save danboykis/c4c9058fab7702df6b2c03f09f992842 to your computer and use it in GitHub Desktop.
import sys
import binascii
const_pool_tags = {7: 'CONSTANT_Class',
9: 'CONSTANT_Fieldref',
10: 'CONSTANT_Methodref',
11: 'CONSTANT_InterfaceMethodref',
8: 'CONSTANT_String',
3: 'CONSTANT_Integer',
4: 'CONSTANT_Float',
5: 'CONSTANT_Long',
6: 'CONSTANT_Double',
12: 'CONSTANT_NameAndType',
1: 'CONSTANT_Utf8',
15: 'CONSTANT_MethodHandle',
16: 'CONSTANT_MethodType',
18: 'CONSTANT_InvokeDynamic'}
const_pool_values = {'CONSTANT_Class': 2,
'CONSTANT_Fieldref': 4,
'CONSTANT_Methodref': 4,
'CONSTANT_InterfaceMethodref': 4,
'CONSTANT_String': 2,
'CONSTANT_Integer': 4,
'CONSTANT_Float': 4,
'CONSTANT_Long': 8,
'CONSTANT_Double': 8,
'CONSTANT_NameAndType': 4,
'CONSTANT_Utf8': 3,
'CONSTANT_MethodHandle': 3,
'CONSTANT_MethodType': 2,
'CONSTANT_InvokeDynamic': 4}
def parse_int(data,count):
return int.from_bytes(data.read(count), byteorder='big', signed=False)
def parse_u1(data):
return parse_int(data,1)
def parse_u2(data):
return parse_int(data,2)
def parse_u4(data):
return parse_int(data,4)
def load_cp(data,cp_len):
constant_pool = []
for i in range(cp_len-1):
tag = parse_u1(data)
tag_name = const_pool_tags.get(tag)
if tag_name == 'CONSTANT_Utf8':
length = parse_u2(data)
utf8_data = data.read(length)
constant_pool.append({'tag_name': tag_name, 'data': utf8_data})
elif tag_name == 'CONSTANT_String':
string_index = parse_u2(data)
constant_pool.append({'tag_name': tag_name, 'string_index': string_index})
elif tag_name == 'CONSTANT_NameAndType':
name_index = parse_u2(data)
descriptor_index = parse_u2(data)
constant_pool.append({'tag_name': tag_name, 'name_index': name_index,'descriptor_index': descriptor_index})
elif tag_name in {'CONSTANT_Methodref','CONSTANT_Fieldref'}:
class_index = parse_u2(data)
name_and_type_index = parse_u2(data)
constant_pool.append({'tag_name': tag_name,'class_index': class_index, 'name_and_type_index': name_and_type_index})
elif tag_name == 'CONSTANT_Class':
name_index = parse_u2(data)
constant_pool.append({'tag_name': tag_name,'name_index': name_index})
else:
values = data.read(const_pool_values.get(tag_name))
constant_pool.append({'tag_name': tag_name,'values': values})
return constant_pool
def load_attribute_info(data,attr_count):
ai = []
for i in range(attr_count):
attribute_name_index = parse_u2(data)
attribute_length = parse_u4(data)
attributes = [parse_u1(data) for a in range(attribute_length)]
ai.append({'attribute_name_index': attribute_name_index,'attribute_length': attribute_length,'attributes': attributes})
return ai
def load_method_info(data,mi_count):
mi = []
for i in range(mi_count):
access_flags = parse_u2(data)
name_index = parse_u2(data)
descriptor_index = parse_u2(data)
attributes_count = parse_u2(data)
attr_info = load_attribute_info(data,attributes_count)
mi.append({'access_flags': access_flags, 'name_index': name_index ,'descriptor_index': descriptor_index,
'attributes_count': attributes_count, 'attr_info': attr_info})
return mi
def load(filename):
with open(filename,"rb") as data:
magic = data.read(4)
minor = parse_u2(data)
major = parse_u2(data)
cp_len = parse_u2(data) # constant pool count
print("Magic {},\n Minor Ver: {},\n Major Ver: {},\n Constant Pool Length: {}".format(binascii.hexlify(magic),minor,major,cp_len))
constant_pool = load_cp(data,cp_len)
for i,c in enumerate(constant_pool):
print("{} => {}".format(i,c))
access_flags = parse_u2(data)
this_class = parse_u2(data)
super_class = parse_u2(data)
interfaces_count = parse_u2(data)
# interfaces[interfaces_count];
fields_count = parse_u2(data)
methods_count = parse_u2(data)
print("access_flags: {}".format(hex(access_flags)))
print("this_class: {}".format(this_class))
print("super_class: {}".format(super_class))
print("interface_count: {}".format(interfaces_count))
print("fields_count: {}".format(fields_count))
print("methods_count: {}".format(methods_count))
method_info = load_method_info(data,methods_count)
for i,mi in enumerate(method_info):
print("{} => {}".format(i,mi))
attributes_count = parse_u2(data)
print("attributes_count: {}".format(attributes_count))
attributes_info = load_attribute_info(data,attributes_count)
for i,ai in enumerate(attributes_info):
print("{} => {}".format(i,ai))
if __name__ == "__main__":
load(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment