def patch(): ea = idc.find_binary(0, idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE, PATTERN) start_addr = None pattern_len = _pattern_len(PATTERN) while not (ea == ida_idaapi.BADADDR or idc.get_segm_name(ea) != '.text'): # If we don't have start address saved, save it and search for the next pattern match if not start_addr: start_addr = ea # If start address was saved before, we got end address. It's time to patch else: # Remove marker patterns to prevent re-encryption on the next script run fill_with_nops(start_addr, start_addr + pattern_len) fill_with_nops(ea, ea + pattern_len) # Decrypt the code between markers for addr in range(start_addr + pattern_len, ea): ida_bytes.patch_byte(addr, ~idc.get_wide_byte(addr)) print('[0x%08X..0x%08X] Region patched' % (start_addr, ea + pattern_len)) start_addr = None ea = idc.find_binary( ea, idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE, PATTERN) print('[PATCHING FINISHED]')
def checksig(sig): count = 0 addr = 0 addr = idc.find_binary(addr, idc.SEARCH_DOWN | idc.SEARCH_NEXT, sig) while addr != idc.BADADDR: count = count + 1 addr = idc.find_binary(addr, idc.SEARCH_DOWN | idc.SEARCH_NEXT, sig) return count
def is_good_sig(sig): count = 0 addr = 0 addr = idc.find_binary(addr, idc.SEARCH_DOWN | idc.SEARCH_NEXT, sig) while count <= 2 and addr != idc.BADADDR: count = count + 1 addr = idc.find_binary(addr, idc.SEARCH_DOWN | idc.SEARCH_NEXT, sig) return count == 1
def main(): print('[*] start debfuscation') for s in get_code_segments(): print('[*] try to deobfuscate {} section'.format( ida_segment.get_segm_name(s))) if s.use32(): junk_patterns = junk_patterns_x86 elif s.use64(): junk_patterns = junk_patterns_x64 else: print('[!] unsupported arch') print('[*] replace junk code to nop') for pattern, pattern_len in junk_patterns: addr_from = idc.find_binary(s.start_ea, ida_search.SEARCH_DOWN, pattern) while addr_from != idaapi.BADADDR and addr_from < s.end_ea: ida_bytes.patch_bytes(addr_from, '\x90' * pattern_len) addr_from = idc.find_binary(addr_from + pattern_len, ida_search.SEARCH_DOWN, pattern) print('[*] hide nop code') addr_from = ida_search.find_text( s.start_ea, 0, 0, 'nop', ida_search.SEARCH_CASE | ida_search.SEARCH_DOWN) while addr_from != idaapi.BADADDR and addr_from < s.end_ea: func_offset = idc.get_func_off_str(addr_from) if type(func_offset) == str and func_offset.find('+') == -1: addr_from = ida_search.find_text( idc.next_head(addr_from), 0, 0, 'nop', ida_search.SEARCH_CASE | ida_search.SEARCH_DOWN) else: i = 0 while True: if ida_bytes.get_byte(addr_from + i) == 0x90: i += 1 else: break if i >= 3: idc.add_hidden_range(addr_from, addr_from + i, 'nop', None, None, 0xFFFFFFFF) print("%08X" % addr_from) addr_from = ida_search.find_text( idc.next_head(addr_from + i), 0, 0, 'nop', ida_search.SEARCH_CASE | ida_search.SEARCH_DOWN) #print('[*] renanlyze') #idc.del_items(s.start_ea, size=s.size()) #time.sleep(1) #idc.plan_and_wait(s.start_ea, s.end_ea) print('[*] done')
def _get_bytes(self, location, size=None, code_page=None): """ Extracts bytes from given location. :param location: Location to pull bytes :param size: Number of bytes to pull (determines size by looking for terminator if not provided) :param code_page: Known code_page used to determine terminator. :return: bytes or None """ # Determine size by looking for terminator. # (Use provided encoding to determine terminator width.) if size is None: width = 1 if code_page: if '16' in code_page: width = 2 elif '32' in code_page: width = 4 end_location = idc.find_binary(location, idc.SEARCH_DOWN, "00 " * width) if end_location == idc.BADADDR: logger.warning('Failed to extract bytes from 0x{:08X}'.format(location)) return None size = end_location - location while size % width: # ensure unicode strings are a valid length size += 1 # Pull size amount of bytes from IDA. data = idc.get_bytes(location, size) if data is None: logger.warning('Failed to extract {} bytes from 0x{:08X}'.format(size, location)) return data
def main(): tid = get_guid_tid() for type_name, type_prefix, filepath in GUID_LIST: print('[*] scanning {}'.format(type_name)) fp = open(filepath, 'r') for line in fp.readlines(): line = line.strip() if line == "": continue guid, guid_name = line.split(' ') guid_name = type_prefix + guid_name binary_pattern = make_binary_pattern(guid) ea = 0 while True: ea = idc.find_binary( ea, ida_search.SEARCH_DOWN | ida_search.SEARCH_NEXT | ida_search.SEARCH_NOSHOW, binary_pattern) if ea == idaapi.BADADDR: break idc.del_items(ea, 16, 0) ida_bytes.create_struct(ea, ida_struct.get_struc_size(tid), tid) if idc.set_name(ea, guid_name, ida_name.SN_NOWARN) != 1: for i in range(0, 100): if idc.set_name(ea, guid_name + "_" + str(i), ida_name.SN_NOWARN) == 1: break else: print("[!] 0x{:X}: failed to apply {}".format( ea, guid_name)) print("[*] 0x{:X}: {}".format(ea, guid_name)) print("[*] finished")
def find_binary_instruction_start( search_start_location, search_direction, target, min_location=idc.get_inf_attr(idc.INF_MIN_EA), max_location=idc.get_inf_attr(idc.INF_MAX_EA)): """ Description: Given a starting location, target, and direction, find an instruction starting with the target bytes. Input: search_start_location - The EA to start searching at search_direction - either idc.SEARCH_UP or idc.SEARCH_DOWN target - The target as space separated bytes (i.e. '55' for 'push ebp') min_location - The minimum EA to accept results for (default: idc.get_inf_attr(idc.INF_MIN_EA)) max_location - The maximum EA to accept results for (default: idc.get_inf_attr(idc.INF_MAX_EA)) Output: Returns the first matching location if found, otherwise idc.BADADDR """ target = target.upper() while search_start_location < max_location: ea = idc.find_binary(search_start_location, search_direction, target) if (min_location <= ea < max_location and ea == idc.get_item_head(ea) and idc.get_bytes( ea, idc.get_item_size(ea)).encode('hex').upper().startswith( target.replace(' ', ''))): return ea else: search_start_location = ea + (1 if search_direction == idc.SEARCH_DOWN else -1) return idc.BADADDR
def FindFunctionByPatternStartEA(pattern): address = idc.find_binary(0, SEARCH_DOWN, pattern) if address == BADADDR: return BADADDR try: return idaapi.get_func(address).start_ea except Exception: return -1
def FindFunctionFirstXRef(name): address = idc.find_binary(0, SEARCH_DOWN, "\"" + name + "\"") dword = BADADDR if address == BADADDR: return BADADDR xrefs = XrefsTo(address) for xref in xrefs: dword = xref.frm try: return idaapi.get_func(dword).startEA except Exception: return -1
def FindFunctionAddr(name, offset, operandValue): address = idc.find_binary(0, SEARCH_DOWN, "\"" + name + "\"") dword = -1 if address == BADADDR: return BADADDR xrefs = XrefsTo(address) for xref in xrefs: dword = xref.frm + offset if dword == BADADDR: return BADADDR return idc.get_operand_value(dword, operandValue)
def patch(): for patterns, patch_function in PATCH_DATA: anything_patched = True while anything_patched: anything_patched = False for pattern in patterns: ea = -_pattern_len(pattern) while True: ea += _pattern_len(pattern) ea = idc.find_binary(ea, idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE, pattern) if ea == ida_idaapi.BADADDR or idc.get_segm_name(ea) != '.text': break patched = bool(patch_function(ea)) anything_patched |= patched if patched: print('[0x%08X] Code patched (%s)' % (ea, patch_function.__name__)) print('[PATCHING FINISHED]')
def process_cond(cond_type, cond_value, start_addr): """ Args: cond_type: The condition type. cond_value: The value for the condition. start_addr: The starting address for searching. Returns: A tuple of (<frozen_set_of_found_addr>,<next_search_addr>). """ search_flag = ida_search.SEARCH_DOWN | ida_search.SEARCH_NEXT found_addr = start_addr if(cond_type == "refStr"): found_addr = ida_search.find_text(start_addr, 0, 0, cond_value, search_flag) start_addr = idc.next_head(found_addr) found_addr_set = frozenset(idautils.DataRefsTo(found_addr)) print("hasStr matched!!! found_addr: {0} found_addr_set: {1}, start_addr: {2} cond_value: {3}".format(found_addr, found_addr_set, start_addr, cond_value)) elif(cond_type == "hasBytes"): found_addr = idc.find_binary(start_addr, search_flag, cond_value) start_addr = found_addr found_addr_set = frozenset([found_addr]) elif(cond_type == "addr"): found_addr_set = frozenset(int(cond_value, 16)) # note that cond_value is a string else: print("Condition type: {0} is not supported!".format(cond_type)) exit(1) return (found_addr_set, start_addr)
def main(): print("[*] League of Legends Client Update Tool") print("[*] By Dencelle for unknowncheats.me") print("[*] Started at: %s" % datetime.datetime.now()) print("----------------------------") # Functions that need to be sorted MakeEnum("Functions", [ [ "GetNextObject", FindFunctionByPatternStartEA("8B 44 24 04 56 8B 71 18") ], [ "GameVersion", FindFuncCall( "E8 ? ? ? ? 50 68 ? ? ? ? 6A 00 6A 01 6A 02 E8 ? ? ? ? E8 ? ? ? ?" ) ], [ "GetFirstObject", FindFuncCall("E8 ? ? ? ? 8B F0 85 F6 74 21 0F 1F 44 00 ?") ], [ "WorldToScreen", FindFunctionByPatternStartEA("83 EC 10 56 E8 ? ? ? ? 8B 08") ], [ "CastSpell", FindFunctionFirstXRef("ERROR: Client Tried to cast a spell from") ], [ "DrawCircle", FindFunctionByPatternStartEA( "33 C4 89 84 24 ? ? ? ? F3 0F 10 84 24 ? ? ? ? 8D 0C") ], [ "GetBasicAttack", FindFunctionByPatternStartEA("53 8B D9 B8 ? ? ? ? 8B 93") ], [ "GetAttackCastDelay", FindFunctionByPatternStartEA("83 EC 0C 53 8B 5C 24 14 8B CB 56") ], ["GetAttackDelay", FindFunctionByPatternStartEA("8B 44 24 04 51 F3")], ["GetPing", FindFunctionByPatternStartEA("55 8B EC 83 EC 08 0F B6")], ["GetSpellState", FindFuncCall("E8 ? ? ? ? 8B F8 8B CB 89")], [ "IsTargetable", FindFunctionByPatternStartEA("56 8B F1 E8 ? ? ? ? 84 C0 74 2E 8D") ], [ "IsAlive", FindFunctionByPatternStartEA( "56 8B F1 8B 06 8B 80 ? ? ? ? FF D0 84 C0 74 19") ], [ "IsBaron", FindFunctionByPatternStartEA("56 81 C1 ? ? ? ? E8 ? ? ? ? 68") ], ["IsTurret", FindFuncCall("E8 ? ? ? ? 83 C4 04 84 C0 75 ?")], ["IsInhib", FindFuncCall("E8 ? ? ? ? 55 88 44 24 1F")], ["IsHero", FindFuncCall("E8 ? ? ? ? 83 C4 04 84 C0 74 52")], ["IsMinion", FindFuncCall("E8 ? ? ? ? 83 C4 04 80 7F 26 06")], [ "IsDragon", FindFunctionByPatternStartEA( "83 EC 10 A1 ? ? ? ? 33 C4 89 44 24 0C 56 81") ], ["IsMissile", FindFuncCall("E8 ? ? ? ? 83 C4 04 84 C0 74 3F")], ["IsNexus", FindFuncCall("E8 ? ? ? ? 55 88 44 24 20")], [ "IsNotWall", FindFunctionByPatternStartEA( "85 FF 0F 48 C3 0F AF C8 8B 86 ? ? ? ? 5F 5E 5B 03 CA 8D") ], [ "IsTroy", FindFuncCall( "E8 ? ? ? ? 33 C9 83 C4 04 84 C0 0F 45 4C 24 ? 8B C1 C3 CC CC CC CC CC CC CC CC FF 74 24 04 E8 ? ? ? ? 33 C9 83 C4 04 84 C0 0F 45 4C 24 ? 8B C1 C3 CC CC CC CC CC CC CC CC 56" ) ], [ "IssueOrder", FindFuncCall( "E8 ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B 84 ?? ?? ?? ?? ?? 8B CF F3 0F 7E 00" ) ], ["PrintChat", FindFuncCall("E8 ? ? ? ? 8B 77 40 8A 47 48")], ["SendChat", FindFunctionByPatternStartEA("A1 ? ? ? ? 56 6A FF")], [ "GetTimerExpiry", FindFuncCall("E8 ? ? ? ? 51 D9 1C 24 E8 ? ? ? ? 8B") ], [ "HealthBarPosition", FindFuncCall( "E8 ?? ?? ?? ?? 8B 4E ?? 8D 54 ?? ?? 52 8B 01 FF ?? ?? 5E 83 ?? ?? C3" ) ], [ "BaseDrawPosition", FindFunctionByPatternStartEA( "30 44 14 10 42 3B D1 72 F0 8B 74 24 14 83 7C 24 ? ? 74") ], [ "Hud_OnDisconnect", FindFunctionFirstXRef("game_messagebox_caption_disconnect") ], [ "Hud_OnAfk", FindFunctionFirstXRef("game_messagebox_text_afkwarningcaption") ], [ "OnCreateObject", FindFuncCall("E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 ?? 32 C9 EB") ], ["oOnDeleteObject", FindFuncCall("E8 ? ? ? ? 8B 4E 20 85 C9 74 0F")], [ "translateString_UNSAFE_DONOTUSE", FindFuncCall("E8 ? ? ? ? 8B 0D ? ? ? ? 83 C4 04 8B F0 6A 0B") ], [ "CharacterDataStack__Push", FindFunctionByPatternStartEA("83 EC 4C 53 57") ], [ "CharacterDataStack__Update", FindFunctionByPatternStartEA("83 EC 18 53 56 57 8D 44 24 20") ], ["GetOwnerObject", FindFuncCall("E8 ? ? ? ? 39 44 24 1C 5F")], [ "CharacterData__GetCharacterPackage", FindFunctionByPatternStartEA( "81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 56 8B B4 24 ? ? ? ? 8B C6" ) ], [ "GetAiManager", FindFuncCall( "E8 ?? ?? ?? ?? 50 8B CE E8 ?? ?? ?? ?? 80 BB ?? ?? ?? ?? ??") ], [ "SetBaseCharacterData", FindFuncCall( "E8 ?? ?? ?? ?? 8B 54 ?? ?? 83 ?? ?? 72 ?? 8B 4C ?? ?? 42 8B C1 81 ?? ?? ?? ?? ?? 72 ?? 8B 49 ?? 83 ?? ?? 2B C1 83 ?? ?? 83 ?? ?? 0F ?? ?? ?? ?? ?? 52 51 E8 ?? ?? ?? ?? 83 ?? ?? 8B 06 8B CE FF ?? ?? ?? ?? ?? 8B CE F3 0F" ) ], [ "OnprocessSpell", FindFuncCall( "E8 ?? ?? ?? ?? 8B CE E8 ?? ?? ?? ?? 80 BE ?? ?? ?? ?? ?? D8") ], [ "OnNewPath", FindFunctionByPatternStartEA("83 EC 18 56 8B 74 24 20 8B CE 57") ], [ "Riot__Renderer__MaterialRegistry__GetSingletonPtr", FindFunctionByPatternStartEA( "A1 ? ? ? ? 85 C0 75 0B 8B 0D ? ? ? ? 8B 01 FF 60 14") ], ["GetGoldRedirectTarget", FindFuncCall("E8 ? ? ? ? 39 44 24 1C 5F")], [ "SummonerEmoteUserComponent__GetSummonerEmoteData", FindFunctionByPatternStartEA( "81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 56 FF B4 24 ? ? ? ? 8D 44 24 14" ) ], [ "SummonerEmoteUserComponent__SetEmoteIdForSlot", FindFunctionByPatternStartEA("83 EC 08 56 57 FF 74 24 14") ], ]) # Offsets that need to be sorted MakeEnum("Offsets", [ [ "RetAddr", idc.find_binary(0, SEARCH_DOWN, "E8 ? ? ? ? 83 C4 1C C3 E8 ? ? ? ?") + 0x8 ], ["DrawCircleRetAddr", idc.find_binary(0, SEARCH_DOWN, "83 C4 1C C3")], [ "NetClient", FindOffsetPattern( "8B 0D ? ? ? ? 85 C9 74 07 8B 01 6A 01 FF 50 08 8B", 1) ], [ "PingInstance", FindOffsetPattern( "8B 0D ? ? ? ? 85 C9 74 07 8B 01 6A 01 FF 50 08 8B", 1) ], [ "ChatClientPtr", FindOffsetPattern( "8B 35 ? ? ? ? 8D 44 24 14 53 8B 1D ? ? ? ? 8B CF", 1) ], ["ObjManager", FindOffsetPattern("8B 0D ? ? ? ? 89 74 24 14", 1)], ["ZoomClass", FindOffsetPattern("A3 ? ? ? ? 83 FA 10 72 32", 0)], ["GameInfo", FindOffsetPattern("A1 ? ? ? ? 83 78 08 02 0F 94", 1)], [ "HudInstance", FindOffsetPattern( "8B 0D ? ? ? ? 6A 00 8B 49 34 E8 ? ? ? ? B0 01 C2", 1) ], ["Renderer", FindOffsetPattern("8B 15 ? ? ? ? 83 EC 08", 1)], ["UnderMouseObject", FindOffsetPattern("8B 0D ? ? ? ? 89 0D", 1)], [ "D3DRenderer", FindOffsetPattern("A1 ? ? ? ? 68 ? ? ? ? 8B 70 08 E8", 1) ], [ "LocalPlayer", FindOffsetPattern( "A1 ?? ?? ?? ?? 85 C0 74 07 05 ?? ?? ?? ?? EB 02 33 C0 56", 1) ], ["GameTime", FindOffsetPattern("F3 0F 11 05 ? ? ? ? 8B 49", 0)], ["MenuGUI", FindOffsetPattern("8B 0D ? ? ? ? 6A 00 E8 ? ? ? ? C7", 1)], [ "ChampionManager", FindOffsetPattern("89 1D ?? ?? ?? ?? 56 8D 4B 04", 0) ], [ "ManagerTemplate_AIMinionClient_", FindOffsetPattern("A1 ?? ?? ?? ?? 53 55 8B 6C 24 1C", 1) ], [ "ManagerTemplate_AIHero_", FindOffsetPattern("8B 0D ?? ?? ?? ?? 50 8D 44 24 18", 1) ], [ "IsLaneMinion", FindOffsetPattern("8A 87 ? ? ? ? 88 4C 24 0B", 1) - 1 ], [ "CharacterDataStack", FindOffsetPattern( "8D 8E ? ? ? ? 89 44 24 28 C7 44 24 ? ? ? ? ? C6 44 24 ? ? E8 ? ? ? ? FF 30 8D 44 24 2C 68 ? ? ? ?", 1) ], [ "SkinId", FindOffsetPattern( "80 BF ? ? ? ? ? 75 50 0F 31 33 C9 66 C7 87 ? ? ? ? ? ?", 0) ], ["Riot__g_window", FindOffsetPattern("3B 05 ? ? ? ? 75 72", 1)], ["GfxWinMsgProc", FindOffsetPattern("A1 ? ? ? ? 55 57 53", 1)], ["GameClient", FindOffsetPattern("A1 ? ? ? ? 68 ? ? ? ? 8B 70 08", 1)], ["D3DDevice", FindOffsetPattern("8B 86 ? ? ? ? 89 4C 24 08", 1)], ["SwapChain", FindOffsetPattern("8B 8E ? ? ? ? 52 57", 1)], [ "oObjPerk1", FindOffsetPattern("8D 8E ? ? ? ? E8 ? ? ? ? 8B CE E8 ? ? ? ? A1", 1) ], ])
def FindFuncCall(Pattern): # Find's Func. by Pattern to a Call addr = idc.find_binary(0, SEARCH_DOWN, Pattern) if addr == BADADDR: return 0 return idc.get_operand_value(addr, 0)
def FindOffsetPattern(Pattern, Operand): addr = idc.find_binary(0, SEARCH_DOWN, Pattern) if addr == BADADDR: return 0 return idc.get_operand_value(addr, Operand)
def ida_find_all(payload): ea = idc.find_binary(0, idc.SEARCH_DOWN | idc.SEARCH_REGEX, payload) while ea != idc.BADADDR: yield ea ea = idc.find_binary(ea + 1, idc.SEARCH_DOWN | idc.SEARCH_REGEX, payload)