Created
August 31, 2020 17:05
-
-
Save danboykis/c4c9058fab7702df6b2c03f09f992842 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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