十年网站开发经验+多家企业客户+靠谱的建站团队
量身定制+运营维护+专业推广+无忧售后,网站问题一站解决
通过本文你能了解iOS逆向的基本知识,对iOSApp的安全有一定了解。然后能举一反三,在自家App找到危险漏洞加以预防,保证用户数据安全。
在安全领域,攻与防永远存在。哪怕是iPhone有着强大的安全防护机制,也挡不住那些极客们一次又一次的好奇,开发了很多强大且便利的工具。本文就是在这些极客们提供的工具的基础上完成的!
按下Option键,同时点击Mac菜单栏上的无线网Icon,能看到当前电脑的IP地址。或在终端输入ifconfigen0也可查看。
保证手机和电脑在同一WIFI下,在手机上,点击“设置->无线局域网->连接的WiFi”,设置HTTP代理:
端口:8888
在电脑端,打开Charles。使手机发生网络请求,Charles会弹出一个询问的对话框
点击“Allow”允许,Charles会出现手机的HTTP请求记录列表。
安装SSL证书到手机设备。点击Help->SSLProxying->InstallCharlesRootCertificateonaMobileDevice
出现弹窗得到地址chls.pro/ssl
在手机Safari浏览器输入地址chls.pro/ssl,出现证书安装页面,点击安装,手机设置有密码的输入密码进行安装
Charles设置Proxy。选择Proxy->SSLProxyingSettings...
勾选EnableSSLProxying,点击Add
Host设置要抓取的HTTPS接口,Port填写443。
让手机重新发送HTTPS请求,可看到抓包。
注意:不抓包请关闭手机HTTP代理,否则断开与电脑连接后会连不上网!
从AppStore直接下载的ipa,苹果公司对其做了FairPlayDRM技术进行加密保护,无法直接使用class-dump工具获取头文件。但是如果是通过development打包出来的话的App的话,是可以直接使用class-dump查看所有头文件的,此部分介绍就是通过此情况来说明如何获取.h文件的。
此处不再介绍class-dump工具的安装过程,具体步骤请直接百度。
进入到appName.ipa所在目录,修改扩展名为.zip,然后解压文件,得到appName.app。
然后执行:
class-dump-HappName.app-o./headers/
命令执行完成后,会在当前目录下的headers目录里看到app所有头文件。
如果添加参数-A-S会在头文件里标记处类方法和属性的IMP地址(模块偏移前基地址)。
class-dump-H-A-SappName.app-o./headers/
在你的越狱手机上使用Cydia应用市场安装OpenSSH,并保证Mac和iPhone处于同一个WIFI下,在MAC终端输入:
sshroot@IP,IP替换为iPhone的IP地址
输入默认密码:alpine
即可进入iPhone终端。
取得debugserver有两种方式。
进入路径/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/8.3/DeveloperDiskImage.dmg(其中路径里8.3,代表iOS系统版本,需与准备的越狱手机系统版本保持一致)。双击DeveloperDiskImage.dmg,将目录里的usr/bin/debugserver复制到指定文件夹中。
如果手机连接过手机并通过XCode调试过app,会在手机里的/Developer/usr/bin/目录下生成一个debugserver文件。通过iFunbox导出至Mac桌面。或使用scp命令cpoy出来。
重签名debugserver
即给debugserver添加task_for_pid权限
创建entitlements.plist,添加如下四个key:
com.apple.springboard.debugapplicationsget-task-allowtask_for_pid-allowrun-unsigned-codekey对应的value都设为设为ture
将entitlements.plist和debugserver放在同一个目录下,执行以下命令:
codesign-s---entitlementsentitlements.plist-fdebugserver
此命令会重新签名debugserver,将签名后的debugserver拷贝至手机系统的/usr/bin/目录下。
注意:不要将debugserver拷贝至/Developer/usr/bin/路径下
通过命令Clutch-i,列出所有的可被Clutch的应用。
使用上文【拿到.h头文件】介绍的方法拿到脱壳后的App头文件和并记下要打断点的方法的IMP地址。
本文动态调试用到的调试器是lldb。
进入/usr/bin/执行./debugserverIP:port-aPID|appProjectName。其中第一个参数IP可以替换为Mac电脑IP地址,或者使用*通配符,允许所有IP调试;第二个参数port随便写一个就行。第四个参数可以指定要调试App的PID或项目名称。比如要调试的PID为6019的搜狗输入法项目名称为SogouInput,则命令即为:
./debugserver*:1234-a6019或./debugserver*:1234-a‘SogouInput’
此命令执行完成后,app会进入等到挂载状态,app会被卡住点击无反应。正常现象!
如果此命令报错,如出现Segmentationfault:11等情况,说明App做了反动态调试保护。遇到此种情况,需先确定App采用了哪种保护方案,然后进一步找到对应措施,干掉它的反动态调试保护。
重新打开一个Mac终端执行lldb进入lldb调试状态。然后输入
processconnectconnect://iPhoneIP:port
iPhoneIP替换为iPhone的IP地址;port改为刚才指定的端口,即1234。
待命令执行完成后,App即进入挂载状态。
ASLR偏移量其实就是虚拟内存的地址相对于模块基地址的偏移量。有两个概念需要熟悉一下:
在lldb调试器模式下,执行imgelist-o-f
模块偏移后的基地址=ASLR偏移量+模块偏移前基地址(方法的IMP地址)
上面这个公式是尤为重要的,因为Class-dump中显示的都是“模块偏移前基地址”,而lldb要操作的都是“模块偏移后的基地址”。所以从Class-dump到lldb要做一个地址偏移量的转换。
至此,已得到了App的ASLR偏移量和方法的IMP地址。
在lldb模式下执行,brs-a'ASLR偏移量+IMP',然后执行c,使App跑起来,触发一个方法调用,就会进入断点模式。输入po$arg1打印第一个参数。
然后,配合着抓包工具Charles(比如分析网络请求加密逻辑)和Class-dump(比如修改某个类的方法返回值)等工具,你就可以随意动态调试App了,就像在XCode里调试一样!
br命令说明
brdis1--禁用(disable)编号为1的断点
bren1--启用(enable)编号为1的断点
brdis--禁用所有断点
bren--启用所有断点
brdel1--删除(delete)编号为1的断点
brdel--删除所有断点
brlist--列出所有断点
dumpdecrypted脱壳工具的原理是:将应用程序运行起来(iOS系统会先解密程序再启动),然后将内存中的解密结果dump写入文件中,得到一个新的可执行程序。
在终端进入到下载后的目录中,cddumpdecrypted-master,然后执行make,即可生成dumpdecrypted.dylib
将第一步生成的dumpdecrypted.dylib拷贝到第二步得到的.../Documents/路径下,命令如下:scp~/dumpdecrypted.dylibroot@IP:/var/mobile/Containers/Data/Application/2B4C6281-C015-4FF3-A8EC-5E5C7554D447/Documents(将路径里的UDID替换为你的要破壳的App的UDID)
进入Documents目录下,执行DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib/var/mobile/Containers/Bundle/Application/BFED82A3-3238-4F41-B797-C1CB584CBE05/appProjectName.app/appProjectName(将路径里的UDID替换为你的要破壳的App的UDID;将appProjectName替换为要破壳App的项目名称)
待命令执行完,会在当前目录生成一个名为appProject.decrypted的文件,这个就是破壳后的App可执行文件,要的就是它!使用Class-dump即可得到头文件。或使用Hopper或IDAPro进行反编译。
为了方便应用软件的开发和调试,从Unix的早期版本开始就提供了一种对运行中的进程进行跟踪和控制的手段,那就是系统调用ptrace()。通过ptrace可以对另一个进程实现调试跟踪,同时ptrace还提供了一个非常有用的参数那就是PT_DENY_ATTACH,这个参数用来告诉系统,阻止调试器依附。
所以最常用的反调试方案就是通过调用ptrace来实现反调试。
当一个进程被调试的时候,该进程会有一个标记来标记自己正在被调试,所以可以通过sysctl去查看当前进程的信息,看有没有这个标记位即可检查当前调试状态。
检测到调试器就退出,或者制造崩溃,或者隐藏工程,当然也可以定时去查看有没有这个标记。
为从实现从用户态切换到内核态,系统提供了一个系统调用函数syscall,上面讲到的ptrace也是通过系统调用去实现的。
在KernelSyscalls27这里可以找到ptrace对应的编号。
26.ptrace801e812cT
所以如下的调用等同于调用ptrace:
syscall(26,31,0,0,0);
arm
syscall是通过软中断来实现从用户态到内核态,也可以通过汇编svc调用来实现。