def debugme(debugger): utils.ILOG("start patch ptrace funtion to bypass anti debug") patch_ptrace(debugger) utils.SLOG("ptrace funtion patach done") utils.ILOG("start patch svc ins to bypass anti debug") images = utils.get_all_image_of_app() for image in images: utils.ILOG("search svc from:{}".format(image["name"])) text_addr_arr_str = get_text_segment(debugger, image["idx"]) text_addr_arr = text_addr_arr_str.strip()[1:-1].split(",") if len(text_addr_arr) < 2: utils.ELOG("failed to get text segment of image:{}" + image["name"]) continue text_start = text_addr_arr[0] text_end = text_addr_arr[1] utils.ILOG("text start:{} end:{}".format(text_start, text_end)) svc_arr_str = lookup_svc_insn(debugger, text_start, text_end) if "<object returned empty description>" in svc_arr_str: utils.ILOG("not found svc ins, so don't need patch") continue svc_arr = svc_arr_str.strip() svc_arr = svc_arr.split() if len(svc_arr) < 1: utils.ELOG("not found svc ins, so don't need patch") continue for svc_addr in svc_arr: utils.ILOG("start hook svc at address:{}".format(svc_addr)) ret = xia0Hook(debugger, svc_addr) if ret: utils.SLOG("hook svc at address:{} done".format(svc_addr)) return
def debugme(debugger): utils.ILOG("start patch ptrace funtion to bypass antiDebug") patch_ptrace(debugger) utils.SLOG("success ptrace funtion to bypass antiDebug") utils.ILOG("start patch svc ins to bypass antiDebug") # get text segment start/end address ret = get_text_segment(debugger) # remove " \n" ret = ret.strip() ret = ret[1:-1] textAddrs = ret.split(',') if len(textAddrs) < 2: utils.ELOG("failed to get text segment:" + str(textAddrs)) return textStart = ret.split(',')[0] textEnd = ret.split(',')[1] textStart = textStart.strip() textEnd = textEnd.strip() utils.SLOG("get text segment start address:{} and end address:{}".format( textStart, textEnd)) # lookup svc ins go through all text code ret = lookup_svc_insn(debugger, textStart, textEnd) if "<object returned empty description>" in ret: utils.ILOG("not found svc ins, so don't need patch") return svcAddrs = ret.strip() svcAddrs = svcAddrs.split() if len(svcAddrs) < 1: utils.ELOG("not found svc ins, so don't need patch") return for svcAddr in svcAddrs: utils.SLOG("found svc address:{}".format(svcAddr)) utils.ILOG("start hook svc at address:{}".format(svcAddr)) ret = xia0Hook(debugger, svcAddr) if ret: utils.SLOG("success hook svc at address:{}".format(svcAddr)) utils.ILOG("all patch done") return
def get_instance_method_address(class_name, method_name): frame = get_selected_frame() class_addr = frame.EvaluateExpression("(Class)NSClassFromString(@\"%s\")" % class_name).GetValueAsUnsigned() utils.SLOG('found class address:0x%x' % class_addr) if class_addr == 0: return 0 sel_addr = frame.EvaluateExpression("(SEL)NSSelectorFromString(@\"%s\")" % method_name).GetValueAsUnsigned() utils.SLOG('found selector address:0x%x' % sel_addr) has_method = frame.EvaluateExpression("(BOOL)class_respondsToSelector(%d, %d)" % (class_addr, sel_addr)).GetValueAsUnsigned() if not has_method: return 0 method_addr = frame.EvaluateExpression('(void *)class_getMethodImplementation(%d, %d)' % (class_addr, sel_addr)) return method_addr.GetValueAsUnsigned()
def croc(debugger, command, exe_ctx, result, internal_dict): command_args = shlex.split(command, posix=False) _ = exe_ctx.target _ = exe_ctx.thread utils.ILOG("going to env that can run oc script") utils.exe_cmd(debugger, "b CFBundleGetMainBundle") utils.exe_cmd(debugger, "c") utils.exe_cmd(debugger, "br del -f") utils.SLOG("now you can exe oc") # result.AppendMessage(str('usage: croc [-m moduleName, -a address, -u UserDefaults]')) return
def dumpdecrypted(debugger, modulePath=None, moduleIdx=None): # must delete all breakpoints. utils.ILOG("delete all breakpoints") utils.exe_cmd(debugger, "br de -f") main_image = utils.get_app_exe_path() images = utils.get_all_image_of_app() utils.ILOG("start to dump...\n") if modulePath and moduleIdx: print(dump_macho_to_file(debugger, moduleIdx, modulePath)) else: for image in images: if main_image == image["name"]: entryAddrStr = get_macho_entry_offset(debugger) entryAddr_int = int(entryAddrStr.strip()[1:-1], 16) utils.SLOG("fix main addr:" + hex(entryAddr_int)) print( dump_macho_to_file(debugger, image["idx"], image["name"], entryAddr_int)) continue print(dump_macho_to_file(debugger, image["idx"], image["name"])) return '[*] Developed By xia0@2019'
def patcher(debugger, ins, addr, size): if is_raw_data(ins): utils.ILOG("detect you manual set ins data:{}".format(ins)) utils.ILOG( "start patch text at address:{} size:{} to ins data:{}".format( hex(addr), size, ins)) patch_code(debugger, hex(addr), ins, size) return "[x] power by xia0@2019" supportInsList = { 'nop': '0x1f, 0x20, 0x03, 0xd5 ', 'ret': '0xc0, 0x03, 0x5f, 0xd6', 'mov0': '0x00, 0x00, 0x80, 0xd2', 'mov1': '0x20, 0x00, 0x80, 0xd2' } if ins not in supportInsList.keys(): utils.ELOG("patcher not support this ins type:{}".format(ins)) return "[x] power by xia0@2019" utils.ILOG( "start patch text at address:{} size:{} to ins:\"{}\" and data:{}". format(hex(addr), size, ins, supportInsList[ins])) # for i in range(size): # patch_code(debugger, hex(curPatchAddr), supportInsList[ins]) # utils.SLOG("current patch address:{} patch done".format(hex(curPatchAddr))) # curPatchAddr += 4 ins_data = "" for i in range(size): ins_data += supportInsList[ins] if i != size - 1: ins_data += "," build_ins_data = "{" + ins_data + "}" utils.ILOG("make ins data:\n{}".format(build_ins_data)) patch_code(debugger, hex(addr), build_ins_data, size) utils.SLOG("patch done") return "[x] power by xia0@2019"
def dumpdecrypted(debugger, modulePath=None, moduleIdx=None): # must delete all breakpoints. utils.ILOG("delete all breakpoints") utils.exe_cmd(debugger, "br de -f") #dump_macho_to_file(debugger,) if modulePath and moduleIdx: print(dump_macho_to_file(debugger, moduleIdx, modulePath)) else: mainImagePath = get_main_image_path(debugger) appDir = os.path.dirname(mainImagePath) appImagesStr = get_all_image_of_app(debugger, appDir) appImagesArr = appImagesStr.split("#") for imageInfo in appImagesArr: if not imageInfo or not "," in imageInfo: utils.ELOG("image info is null, skip image # " + imageInfo) continue utils.ILOG("now is image: " + imageInfo) info = imageInfo.split(",") if len(info) == 2: utils.ILOG("start dump [" + info[0] + "] image:" + info[1]) # print "idx:" + info[0] # print "path:" + info[1] if info[1] == mainImagePath: entryAddrStr = get_macho_entry_offset(debugger) entryAddr_int = int(entryAddrStr.strip()[1:-1], 16) utils.SLOG("fix main addr:" + hex(entryAddr_int)) print( dump_macho_to_file(debugger, info[0], info[1], entryAddr_int)) continue print(dump_macho_to_file(debugger, info[0], info[1])) return '\n\n[*] Developed By xia0@2019'
def xbr(debugger, command, result, dict): raw_args = create_command_arguments(command) command_args = shlex.split(command, posix=False) parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return # check is options? if options.address: targetAddr = options.address if targetAddr.startswith("0x"): targetAddr_int = int(targetAddr, 16) else: targetAddr_int = int(targetAddr, 10) utils.ILOG("breakpoint at address:{}".format(hex(targetAddr_int))) lldb.debugger.HandleCommand ('breakpoint set --address %d' % targetAddr_int) return if options.entryAddress: if options.entryAddress == "main": entryAddrStr = get_macho_entry_offset(debugger) entryAddr_int = int(entryAddrStr.strip()[1:-1], 16) utils.ILOG("breakpoint at main function:{}".format(hex(entryAddr_int))) lldb.debugger.HandleCommand ('breakpoint set --address %d' % entryAddr_int) elif options.entryAddress == "init": initFunAddrStr = get_macho_mod_init_first_func(debugger) initFunAddr_int = int(initFunAddrStr.strip()[1:-1], 16) utils.ILOG("breakpoint at mod int first function:{}".format(hex(initFunAddr_int))) lldb.debugger.HandleCommand ('breakpoint set --address %d' % initFunAddr_int) elif options.entryAddress == "load": ret = get_all_class_plus_load_methods(debugger) if "<object returned empty description>" in ret: utils.ILOG("not found +[* load] method") return all_load_addrs_str_arr = ret.strip().split(",") all_load_addrs = [] for addr in all_load_addrs_str_arr: if addr != "": all_load_addrs.append(int(addr, 10)) utils.ILOG("will set breakpoint at all +[* load] methold, count:{}".format(len(all_load_addrs))) for addr in all_load_addrs: lldb.debugger.HandleCommand ('breakpoint set --address %d' % addr) utils.SLOG("set br at:{}".format(hex(addr))) # utils.ILOG("load:\n{}\n".format([hex(addr) for addr in all_load_addrs])) else: utils.ELOG("you should special the -E options:[main/init/load]") return # check is arg is address ? mean auto add slide if is_just_address_cmd(args): if options.modulePath: modulePath = options.modulePath utils.ILOG("you special the module:" + modulePath) else: utils.ILOG("you not special the module, default is main module") modulePath = None targetAddr = args[0] if targetAddr.startswith("0x"): targetAddr_int = int(targetAddr, 16) else: targetAddr_int = int(targetAddr, 10) moduleSlide = get_process_module_slide(debugger, modulePath) if "error" in moduleSlide: utils.ELOG("error in oc script # " + moduleSlide.strip()) if modulePath: targetImagePath = modulePath else: mainImagePath = get_main_image_path(debugger) if "no value available" in mainImagePath or "error" in mainImagePath: ret = utils.exe_cmd(debugger, "target list") # pylint: disable=anomalous-backslash-in-string pattern = '/.*\(' match = re.search(pattern, ret) # TODO: more strict if match: found = match.group(0) found = found.split("(")[0] found = found.strip() else: utils.ELOG("failed to auto get main module, use -m option") return mainImagePath = found print("[+] use \"target list\" to get main module:" + mainImagePath) else: mainImagePath = mainImagePath.strip()[1:-1] targetImagePath = mainImagePath ret = utils.exe_cmd(debugger, "image list -o -f") pattern = '0x.*?' + targetImagePath.replace("\"", "") match = re.search(pattern, ret) # TODO: more strict if match: found = match.group(0) else: utils.ELOG("not found image:"+targetImagePath) return moduleSlide = found.split()[0] utils.ILOG("use \"image list -o -f\" cmd to get image slide:"+moduleSlide) moduleSlide = int(moduleSlide, 16) else: moduleSlide = int(moduleSlide, 10) brAddr = moduleSlide + targetAddr_int utils.ILOG("ida's address:{} module slide:{} target breakpoint address:{}".format(hex(targetAddr_int), hex(moduleSlide), hex(brAddr))) lldb.debugger.HandleCommand ('breakpoint set --address %d' % brAddr) return # check is breakpoint at all methods address(IMP) for given classname if is_br_all_cmd_x(args): classname = args[0] begin = classname.find('$') end = classname.rfind('$') classname = classname[begin+1 : end] utils.ILOG("classname:{}".format(classname)) ret = get_all_method_address_of_class(debugger, classname) addrArr = ret.split('-')[:-1] for addr in addrArr: address = int(addr) if address: lldb.debugger.HandleCommand ('breakpoint set --address %x' % address) result.AppendMessage("Set %ld breakpoints of %s" % (len(addrArr),classname)) return if is_br_all_cmd(args): classname = args[0] ret = get_all_method_address_of_class(debugger, classname) addrArr = ret.split('-')[:-1] for addr in addrArr: address = int(addr) if address: lldb.debugger.HandleCommand ('breakpoint set --address %x' % address) result.AppendMessage("Set %ld breakpoints of %s" % (len(addrArr),classname)) return if not is_command_valid(raw_args): print('please specify the param, for example: "-[UIView initWithFrame:]"') return arg_ = raw_args[0] class_name = get_class_name(arg_) method_name = get_method_name(arg_) # xlog = 'className:'+ str(class_name) + '\tmethodName:' + str(method_name) utils.ILOG("className:{} methodName:{}".format(class_name, method_name)) # print class_name, method_name address = 0 if is_class_method(arg_): address = get_class_method_address(class_name, method_name) else: address = get_instance_method_address(class_name, method_name) utils.SLOG('found method address:0x%x' % address) if address: lldb.debugger.HandleCommand ('breakpoint set --address %x' % address) else: utils.ELOG("fail, please check the arguments")