def get_ch_str(self, startea): """ Attempt to grab a full string (currently \x00 terminated) and return a tuple of the ending address and the string encoded as UTF-8. Decoding occurs here and may need to be adjusted, but we default to GB2312. Returning an ending address of -1 signifies that the """ CHUNKSIZE = 2048 # hopefully your string fits in here... STRTERM = "\x00" # and ends with this... ENCODING = "gb2312" # and is encoded this way... ch_str = "" endea = -1 chunk = None while chunk is None: CHUNKSIZE = CHUNKSIZE >> 1 chunk = GetManyBytes(startea, CHUNKSIZE) if CHUNKSIZE == 0: print("[!] Failed to grab any bytes.") return (endea, ch_str) end_idx = chunk.find(STRTERM) if end_idx != -1: ch_str = chunk[:end_idx] endea = startea + end_idx try: ch_str = ch_str.decode(ENCODING).encode("utf8") except UnicodeDecodeError: print("[!] String does not appear to be %s encoded." % ENCODING) endea = -1 return (endea, ch_str)
def read_unicode_string(startea): CHUNKSIZE = 2048 # hopefully your string fits in here... STRTERM = "\x00\x00" ch_str = "" endea = -1 chunk = None while chunk is None: CHUNKSIZE = CHUNKSIZE >> 1 chunk = GetManyBytes(startea, CHUNKSIZE) if CHUNKSIZE == 0: print("[!] Failed to grab any bytes.") return (endea, ch_str) end_idx = chunk.find(STRTERM) if end_idx != -1: ch_str = chunk[:end_idx] endea = startea + end_idx if len(ch_str) % 2 != 0: ch_str += '\x00' ch_str += '\x00\x00' try: ch_str.decode('ascii') return None except UnicodeDecodeError: pass return ch_str
def run(self, args): file_path = idaapi.get_input_file_path() if not file_path: print('Input file path was not found') return try: fd = open(file_path, "rb") elf = ELFFile(fd) except Exception as x: print(x) return eh_frame_phdr = next( (segment for segment in elf.iter_segments() if describe_p_type(segment['p_type']) == 'GNU_EH_FRAME'), None) if not eh_frame_phdr: print("[-] Executable was not compiled with exception unwinding information") return eh_frame_hdr_data = EhFrameHdr(eh_frame_phdr, elf) fde_count = eh_frame_hdr_data.decode_pointer(eh_frame_hdr_data.fde_count_enc, eh_frame_hdr_data.fde_count, pc=eh_frame_phdr['p_vaddr'] + 8) block_map = [] for i in range(0, fde_count): (initial_loc, fde_entry_offset) = unpack("2I", GetManyBytes(eh_frame_hdr_data.fde_table_vaddr + 8 * i, 8)) (function_vaddr, function_size) = eh_frame_hdr_data.decode_pointer(eh_frame_hdr_data.table_enc, initial_loc, fde_entry_offset) block_map.append({'function_address': function_vaddr, 'function_size': function_size}) block_form = BlockForm0(block_map) block_form.Show('GNU_EH_FRAME functions')
def decode_pointer(self, encoding_byte, target_entry, pc=None): encoding_byte = EncodedByte(encoding_byte) value_size = fmt = result = None elf_class = self._elf.header['e_ident']['EI_CLASS'] if encoding_byte.value == DW_EH_PE_omit or encoding_byte.encoding == DW_EH_PE_omit: return elif encoding_byte.value == DW_EH_PE_uleb128: return get_uleb128(target_entry) elif encoding_byte.value == DW_EH_PE_sleb128: return get_sleb128(target_entry) else: if encoding_byte.value == DW_EH_PE_absptr: value_size = 8 if elf_class == EI_CLASS64 else 4 fmt = "<q" if elf_class == EI_CLASS64 else "<i" elif encoding_byte.value == DW_EH_PE_udata2 or encoding_byte.value == DW_EH_PE_sdata2: value_size = 2 fmt = "<b" elif encoding_byte.value == DW_EH_PE_udata4 or encoding_byte.value == DW_EH_PE_sdata4: value_size = 4 fmt = "<i" elif encoding_byte.value == DW_EH_PE_udata8 or encoding_byte.value == DW_EH_PE_sdata8: value_size = 8 fmt = "<q" if not value_size and not fmt: return if encoding_byte.encoding == DW_EH_PE_pcrel: result = unpack(fmt, GetManyBytes(pc + target_entry, value_size))[0] elif encoding_byte.encoding == DW_EH_PE_absptr: result = target_entry elif encoding_byte.encoding == DW_EH_PE_datarel: if target_entry > 0x7fffffff: target_entry -= 0x100000000 function_vaddr = self._phdr['p_vaddr'] + target_entry function_size = \ unpack(fmt, GetManyBytes(self.fde_table_vaddr + pc, value_size))[0] result = (function_vaddr, function_size) elif encoding_byte.encoding == DW_EH_PE_textrel or encoding_byte.encoding == DW_EH_PE_funcrel: # These encoding schemes are not implemented. I have read they are not longer supported return if encoding_byte.encoding & DW_EH_PE_indirect: result = unpack(fmt, GetManyBYtes(result, value_size))[0] return result
def get_hex_bytes_from_ea(ea, length): """ returns a list of hex bytes from an address :param ea: :param length: :return: """ return ['{:02x}'.format(ord(x)) for x in GetManyBytes(ea, length)]
def _getOriginData(self, address, size): res = [] for offset in xrange(0, size, 64): tmp = GetManyBytes(address + offset, 64) if tmp == None: res.extend([pack("<Q", Qword(address + offset + i)) for i in range(0, 64, 8)]) else: res.append(tmp) res = "".join(res) return res[:size]
def __init__(self, ea, info, cs): """Initialization function.""" # Init the node structure node_t.__init__(self) # Check if it's a code instruction try: is_c = is_code(get_flags(ea)) except: is_c = isCode(GetFlags(ea)) if not is_c: raise CodeException # # fill node_t struct # # NodeInfo self.info = NodeInfo() inst_elements = [] try: size = create_insn(ea) bytes = get_bytes(ea, size) except: size = MakeCode(ea) bytes = GetManyBytes(ea, size) (address, size, mnemonic, op_str) = cs.disasm_lite(bytes, ea, count=1).next() self.info.opcode = mnemonic.encode("ascii", "ignore") op_str_ascci = op_str.encode("ascii", "ignore") self.info.inst_str = self.info.opcode + " " + op_str_ascci splitted = op_str_ascci.split(", ") self.info.nargs = 0 if len(splitted) >= 1: self.info.arg1 = splitted[0] self.info.nargs += 1 if len(splitted) >= 2: self.info.arg2 = splitted[1] self.info.nargs += 1 if len(splitted) >= 3: self.info.arg3 = splitted[2] self.info.nargs += 1 # No node will be root but this is acceptable for CFGs self.info.is_root = False self.info.address = ea self.info.has_address = True # node_t self.node_id = self._genid()
def __init__(self, phdr, elf): self._elf = elf self._phdr = phdr self.vaddr = self._phdr['p_vaddr'] self.fde_table_vaddr = self.vaddr + 12 self.file_bytes = GetManyBytes(self._phdr['p_vaddr'], self._phdr['p_filesz']) (self.version, self.eh_frame_ptr_enc, self.fde_count_enc, self.table_enc, self.eh_frame_ptr, self.fde_count) = unpack_from('4c2I', self.file_bytes, 0)
def get_ch_str(self, startea): CHUNKSIZE = 2048 # hopefully your string fits in here... STRTERM = "\x00\x00" ch_str = "" endea = -1 chunk = None while chunk is None: CHUNKSIZE = CHUNKSIZE >> 1 chunk = GetManyBytes(startea, CHUNKSIZE) if CHUNKSIZE == 0: print("[!] Failed to grab any bytes.") return (endea, ch_str) end_idx = chunk.find(STRTERM) if end_idx != -1: ch_str = chunk[:end_idx] endea = startea + end_idx if len(ch_str) % 2 != 0: ch_str += '\x00' endea += 1 foundEncodingFlag = False for encoding in ENCODING_LIST: try: test_str1 = ch_str.decode(encoding) test_str2 = test_str1.encode('euc-kr') foundEncodingFlag = True print '[ ' + encoding + ' string ] ' self.korean_strings_view.set_encoding(encoding) break except: #print("[!] String does not appear to be %s encoded." % encoding) continue if foundEncodingFlag == False: endea = -1 return (endea, ch_str.decode(encoding))
def findPatchString(config): patchStringByteArray = [] for funcAddr in Functions(): if GetFunctionName(funcAddr) == config['srcFnName']: print('found ea for ' + config['name']) break for byteIndex in xrange(0, config['patchLength']): func_byte_char = GetManyBytes(funcAddr + config['offset'] + byteIndex, 1) if func_byte_char is not None: patchStringByteArray.append('{:02x}'.format(ord(func_byte_char))) PATCH_STRING = ' '.join(patchStringByteArray) print('patch found for ' + config['name'] + ' >> ' + PATCH_STRING) return PATCH_STRING
int('10', 16), 'Redirect from UnitUiCtrl$$updatePlayerSkill', '01 20 A0 E3 ' + # MOV R2, #1 flag this jump as player's # NOTE: Always check if this code moves. # BL UnitCtrl$$JudgeSkillReadyAndIsMyTurn might move getARMBLHexString(call_fb_start_ea + 4, update_player_ea + int('14', 16)) + ' ' + '') ### # Remove FB Graph API lol v2 ### speed_offset = '{:02x}'.format( ord( GetManyBytes( get_ea_from_binary(SET_RECAST_TIME_SIGNATURE) + ATK_RECAST_TIME_OFFSET, 1 ) ) ) patch(call_fb_start_ea, int('0', 16), 'Remove FB Graph API lol v2', # Original FB code patched to exit early '1e ff 2f e1 ' + # BX lr # # UnitUiCtrl$$updatePlayerSkill redirects here # Init phase to set objects we need 'F0 4D 2D E9 ' + # STMFD sp!, {r4-r8, r10, r11, lr} '04 60 A0 E1 ' + # MOV r6, r4 (set UnitUICtrl to r6) '00 40 A0 E1 ' + # MOV R4, R0 (set the unitCtrl to r4) '00 f0 20 e3 ' + # NOP for now until we know how to get move rate
def __init__(self, ea, cs, IDA_inst, IDA_inst_size, IDA_inst_string): """Initialization function, to disassemble with Capstone""" # Init the node structure node_t.__init__(self) # Check if it's a code instruction try: is_c = is_code(get_flags(ea)) except: is_c = isCode(GetFlags(ea)) if not is_c: raise CodeException # # fill node_t struct # # NodeInfo self.info = NodeInfo() inst_elements = [] if cs is not None: try: size = create_insn(ea) bytes = get_bytes(ea, size) except: size = MakeCode(ea) bytes = GetManyBytes(ea, size) (address, size, mnemonic, op_str) = next(cs.disasm_lite(bytes, ea, count=1)) else: address = ea size = IDA_inst_size splitted = IDA_inst_string.split(" ") mnemonic = splitted[0] op_str = " ".join(splitted[1:]) self.info.opcode = mnemonic self.info.inst_str = self.info.opcode + " " + op_str splitted = op_str.split(", ") self.info.nargs = 0 if len(splitted) >= 1: self.info.arg1 = splitted[0] self.info.nargs += 1 if len(splitted) >= 2: self.info.arg2 = splitted[1] self.info.nargs += 1 if len(splitted) >= 3: self.info.arg3 = splitted[2] self.info.nargs += 1 # No node will be root but this is acceptable for CFGs self.info.is_root = False self.info.address = ea self.info.has_address = True # node_t self.node_id = self._genid()
from patchUtil import patchList, get_ea_from_binary, zero_ex, patch from patchUtil import getARMBLHexString, getFuncEA from idc import GetManyBytes ### # fix wait times # always make one of our players have the next turn # by making sure each enemy has a wait time of 100 # and our units get a wait time of 1 ### # GET_UNIT_TYPES_SIGNATURE = 'A0 01 1E FF 2F E1 ? ? 90 E5' GET_UNIT_TYPES_SIGNATURE = 'AC 00 90 E5 1E FF 2F E1 70 4C 2D E9' GET_UNIT_TYPES_EA_OFFSET = 0 UNIT_TYPE_BYTES = [ '{:02x}'.format(ord(char)) for char in GetManyBytes( get_ea_from_binary(GET_UNIT_TYPES_SIGNATURE) + GET_UNIT_TYPES_EA_OFFSET, 1) ] # FIX_WAIT_TIMES_SIGNATURE = '10 4A 00 EE 00 60 A0 E1 00 00 56 E3 C0 8A B8 EE' # 1.4.2 changes moved the target function as a separate name # "BattleManager:calcWaitValue" """ FIX_WAIT_TIMES_SIGNATURE = '00 A0 A0 E3 00 00 A0 E3 07 10 A0 E1 05 20 A0 E1' FIX_WAIT_TIMES_OFFSET = int('-84', 16) patch( get_ea_from_binary(FIX_WAIT_TIMES_SIGNATURE), FIX_WAIT_TIMES_OFFSET, 'fix wait times', '{} 50 90 e5 '.format(' '.join(UNIT_TYPE_BYTES)) + # example: 'a4 50 90 e5' # LDR r5, [r0, 0xa4] (check battleUnit.getUnitType)