def __get_section(self, section_type): mod_iter = iter(decode_module(self.module_bytecode, True)) _, _ = next(mod_iter) sections = list(mod_iter) # iterate over all section for cur_sec, cur_sec_data in sections: sec = cur_sec_data.get_decoder_meta()['types']['payload'] if isinstance(sec, section_type): return cur_sec_data return None
def enumerate_module_functions(module_bytecode): functions = list() mod_iter = iter(decode_module(module_bytecode)) _, _ = next(mod_iter) sections = list(mod_iter) type_list = None import_len = 0 function_list = None export_list = None code_data = None # iterate over all section for cur_sec, cur_sec_data in sections: sec = cur_sec_data.get_decoder_meta()['types']['payload'] if isinstance(sec, TypeSection): type_list = decode_type_section(cur_sec_data) elif isinstance(sec, ImportSection): import_len = cur_sec_data.payload.count elif isinstance(sec, FunctionSection): function_list = cur_sec_data.payload.types elif isinstance(sec, ExportSection): export_list = decode_export_section(cur_sec_data) elif isinstance(sec, CodeSection): code_data = cur_sec_data for idx, func in enumerate(code_data.payload.bodies): param_str, return_str = type_list[function_list[idx]] func_id = import_len + idx name = '$func%d %s%s' % (func_id, param_str, return_str) prefered_name = '' if export_list: for index, field_str in export_list: if index == func_id: #prefered_name = '%s %s%s' % (field_str, param_str, return_str) prefered_name = '%s' % (field_str) break instructions = EosDisassembler().disassemble(func.code.tobytes()) cur_function = Function(0, instructions[0], name=name, prefered_name=prefered_name) cur_function.instructions = instructions functions.append(cur_function) return functions
def initDataSec(file): dataSec = {} with open(file, 'rb') as raw: raw = raw.read() mod_iter = iter(decode_module(raw)) header, header_data = next(mod_iter) for cur_sec, cur_sec_data in mod_iter: if isinstance(cur_sec_data.get_decoder_meta()['types']['payload'], DataSection): for idx, entry in enumerate(cur_sec_data.payload.entries): for cur_insn in entry.offset: op = format_instruction(cur_insn) if op.split(" ")[0] == "i32.const": dataSec[op.split(" ")[1]] = entry.data.tobytes() return dataSec
def extract_functions_code(self, module_bytecode): functions = list() mod_iter = iter(decode_module(module_bytecode)) _, _ = next(mod_iter) sections = list(mod_iter) # iterate over all section for cur_sec, cur_sec_data in sections: sec = cur_sec_data.get_decoder_meta()['types']['payload'] if isinstance(sec, CodeSection): code_data = cur_sec_data if not code_data: raise ValueError('No functions/codes in the module') for idx, func in enumerate(code_data.payload.bodies): instructions = self.disassemble(func.code.tobytes()) cur_function = Function(0, instructions[0]) cur_function.instructions = instructions functions.append(cur_function) return functions
def analyze(self): """analyse the complete module & extract informations """ # src: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md # custom 0 name, .debug_str, ... # Type 1 Function signature declarations # Import 2 Import declarations # Function 3 Function declarations # Table 4 Indirect function table and other tables # Memory 5 Memory attributes # Global 6 Global declarations # Export 7 Exports # Start 8 Start function declaration # Element 9 Elements section # Code 10 Function bodies (code) # Data 11 Data segments # reset attributes self.attributes_reset() mod_iter = iter(decode_module(self.module_bytecode, True)) # decode header version - usefull in the future (multiple versions) header, header_data = next(mod_iter) self.magic, self.version = self.__decode_header(header, header_data) # # Wasm sections # for cur_sec, cur_sec_data in mod_iter: sec = cur_sec_data.get_decoder_meta()['types']['payload'] if isinstance(sec, TypeSection): self.types = self.__decode_type_section(cur_sec_data) elif isinstance(sec, ImportSection): self.imports_all, self.imports_func = \ self.__decode_import_section(cur_sec_data) elif isinstance(sec, FunctionSection): self.func_types = self.__decode_function_section(cur_sec_data) elif isinstance(sec, TableSection): self.tables = self.__decode_table_section(cur_sec_data) elif isinstance(sec, MemorySection): self.memories = self.__decode_memory_section(cur_sec_data) elif isinstance(sec, GlobalSection): # TODO not analyzed self.globals = self.__decode_global_section(cur_sec_data) elif isinstance(sec, ExportSection): self.exports = self.__decode_export_section(cur_sec_data) elif isinstance(sec, StartSection): # TODO not analyzed self.start = self.__decode_start_section(cur_sec_data) elif isinstance(sec, ElementSection): self.elements = self.__decode_element_section(cur_sec_data) elif isinstance(sec, CodeSection): self.codes = self.__decode_code_section(cur_sec_data) elif isinstance(sec, DataSection): self.datas = self.__decode_data_section(cur_sec_data) # name section elif isinstance(cur_sec, NameSubSection): self.names = self.__decode_name_section(cur_sec_data) else: self.customs.append( self.__decode_unknown_section(cur_sec_data)) # create ordered list of functions self.func_prototypes = self.get_func_prototypes_ordered() return True
def analyze(self): ''' analyse the complete module & extract informations''' # src: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md # Type 1 Function signature declarations # Import 2 Import declarations # Function 3 Function declarations # Table 4 Indirect function table and other tables # Memory 5 Memory attributes # Global 6 Global declarations # Export 7 Exports # Start 8 Start function declaration # Element 9 Elements section # Code 10 Function bodies (code) # Data 11 Data segments self.customs = list() try: mod_iter = iter(decode_module(self.module_bytecode)) header, header_data = next(mod_iter) sections = list(mod_iter) except KeyError: log.error('Module corrupted - Wasm KeyError') return -1 # # Wasm Header # self.header = self.decode_header(header, header_data) # # Wasm sections # for cur_sec, cur_sec_data in sections: sec = cur_sec_data.get_decoder_meta()['types']['payload'] if isinstance(sec, TypeSection): self.types = self.decode_type_section(cur_sec_data) elif isinstance(sec, ImportSection): self.imports, self.imports_func = \ self.decode_import_section(cur_sec_data) elif isinstance(sec, FunctionSection): self.func_types = self.decode_function_section(cur_sec_data) elif isinstance(sec, TableSection): self.tables = self.decode_table_section(cur_sec_data) elif isinstance(sec, MemorySection): self.memories = self.decode_memory_section(cur_sec_data) elif isinstance(sec, GlobalSection): # TODO not analyzed self.globals = self.decode_global_section(cur_sec_data) elif isinstance(sec, ExportSection): self.exports = self.decode_export_section(cur_sec_data) elif isinstance(sec, StartSection): # TODO not analyzed self.start = self.decode_start_section(cur_sec_data) elif isinstance(sec, ElementSection): self.elements = self.decode_element_section(cur_sec_data) elif isinstance(sec, CodeSection): self.codes = self.decode_code_section(cur_sec_data) elif isinstance(sec, DataSection): self.datas = self.decode_data_section(cur_sec_data) else: # name section if cur_sec_data.id == 0: self.names = self.decode_name_section(cur_sec_data) else: self.customs.append(cur_sec_data) # create ordered list of functions self.func_prototypes = self._create_ordered_list()