# -*- coding: utf-8 -*- ''' 一键Dump iOS加密MachO至A64Dbg与之对应的缓存目录。 ''' # https://gitee.com/geekneo/A64Dbg/blob/master/python3/adpdef.py # 引入adp基础定义,比如error/event定义 from adpdef import * # https://gitee.com/geekneo/A64Dbg/blob/master/python3/adp.py # 引入adp所有python api from adp import * import os import platform import struct # 开发模式则只使用源代码,不使用adc二进制模块 dev_mode = False # 将unpack得到的字符串字节数组转为字符串 def simplify_strbuff(tmps): result = '' for c in tmps: if c > 0: result += chr(c) else: break return result # 远程adcpp代码将会发送数据至该接口 # adcpp_ios_dump是adcpp api str2py/buf2py的第一个字符串参数,用于发送数据到该函数 ''' // 文件传输协议字段 struct dump_info { char filename[64]; char min_version[12]; int filesize; char filebuff[0]; }; ''' def adcpp_ios_dump(data): # MachO文件名称 filename = simplify_strbuff(struct.unpack_from('64s', data, 0)[0]) # MachO文件要求的最低系统版本号 min_version = simplify_strbuff(struct.unpack_from('12s', data, 64)[0]) # MachO大小 filesize = struct.unpack_from('i', data, 76)[0] # MachO数据 filebuff = struct.unpack_from('%ds' % (filesize), data, 80)[0] print('Received %s, %s, %d.' % (filename, min_version, filesize)) # 保存至A64Dbg与之对应的缓存目录 usrdir = os.path.expanduser('~') cachedir = usrdir + '/A64Dbg/decache/iOS/arm64-apple-ios' versioneddir = cachedir + min_version # 创建目录 if not os.path.exists(cachedir): os.mkdir(cachedir) if not os.path.exists(versioneddir): os.mkdir(versioneddir) # 保存解密后的MachO文件 filepath = cachedir + '/' + filename print('Saved to %s.' % (filepath)) with open(filepath, 'wb') as fp: fp.write(filebuff) # 创建软连接至带版本后缀的目录,lldb模式需要访问这个目录中的MachO文件 versionedpath = versioneddir + '/' + filename print('Linked to %s.' % (versionedpath)) if platform.system() == 'Windows': os.system('mklink "%s" "%s"' % (versionedpath, filepath)) else: os.system('ln -s -f "%s" "%s"' % (filepath, versionedpath)) # a64dbg插件入口 def adp_on_event(args): # 获取当前的事件码 event = args[adp_inkey_type] # 用户执行了插件主菜单命令 if event == adp_event_main_menu: # 判断当前目标平台是否是remote_unicornvm_ios plat = curPlatform() if plat == adp_remote_unicornvm_ios: plugdir = os.path.dirname(__file__) adcppfile = plugdir + '/adcpp-ios-dump.adc' if not os.path.exists(adcppfile) or dev_mode: # macOS平台可以直接使用脚本源码 # 开发模式只使用源代码 if platform.system() == 'Darwin' or dev_mode: adcppfile = plugdir + '/adcpp-ios-dump.mm' if os.path.exists(adcppfile): # 将窗口焦点切换为Log窗口 focusLog() # 在远程iOS进程执行该脚本代码进行Dump操作 # 需要预先利用远程iOS虚拟化调试模式Attach目标进程,否则该脚本执行会报错 runadc(adcppfile) else: print('Missing %s.' % (adcppfile)) return success() else: print('adcpp-ios-dump插件只支持iOS虚拟化调试模式remote_unicornvm_ios.') return failed(adp_err_unsupport) # 插件框架向插件询问主菜单名称 if event == adp_event_menuname: return success('adcpp-ios-dump') # 插件框架向插件询问插件版本和简介 if event == adp_event_adpinfo: return success(('0.1.1', "一键Dump iOS加密MachO至A64Dbg与之对应的缓存目录。")) return failed(adp_err_unimpl)