逆向Appstore应用(一)

写在前面

最近在做一些iOS启动速度优化和App瘦身相关的工作,有时候需要横向对比一下竞品的数据,免不了要对一些商店的App在许可范围内做一些手脚,下面以开源中国的iPhone客户端为例给大家简单介绍下操作步骤。

当前环境:

  • 一台越狱iPhone,系统为iOS8.3
  • mac OS X EI 10.11.5
  • iTunes 12.4

通过iTunes获取ipa

点击下载,然后到我的Apps中找到刚刚下载的开源中国.ipa文件,将后缀.ipa修改为.zip,直接解压即可。找到Payload文件夹下的iosapp包文件,查看包内容,就是开发者上传Appstore的全部内容了。里面包含有png、xib等资源文件,以及本地化语言包,签名包以及二进制文件。

使用工具解密二进制文件

逆向Appstore应用(一)_第1张图片
配图来自ifanr

App Store上的应用都使用了DRM(Digital Rights Management)数字版权加密保护技术,想更多了解DMG历史请戳这里。首先得破解加密的可执行文件,可以通过编译dumpdecrypted来解密,原理是让app预先加载一个解密的dumpdecrypted.dylib,然后在程序运行后,将代码动态解密,最后在内存中dump出来整个程序。(如果没有越狱设备,可以通过第三方市场下载未加密的ipa文件,跳过此步骤)。

找到刚才解压好的开源中国二进制,名为iosapp,运行:

otool -l iosapp_本地路径 | grep crypt
# 结果为:
     cryptoff 16384
    cryptsize 5619712
      cryptid 1
     cryptoff 16384
    cryptsize 6144000
      cryptid 1

cryptid 1代表加密,cryptid 0代表未加密。两个分别对应着armv7和arm64,也就是它们都有加密。接下来要开始编译dumpdecrypted.dylib文件了,首先clone dumpdecrypted到桌面,cd到dump decrypted目录,执行以下命令,即可生成dumpdecrypted.dylib文件了。

 make
`xcrun --sdk iphoneos --find gcc` -Os  -Wimplicit -isysroot `xcrun --sdk iphoneos --show-sdk-path` -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/Frameworks -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/PrivateFrameworks -arch armv7 -arch armv7s -arch arm64 -c -o dumpdecrypted.o dumpdecrypted.c

编译后的目录如下:

逆向Appstore应用(一)_第2张图片

如何使用dumpdecrypted.dylib文件来破解spa包中的二进制文件呢?

首先需要在已经越狱的iPhone中下载几个插件:

  • OpenSSH,用来建立与iPhone的ssh链接,传递文件用;
  • adv-cmds,在iPhone上使用ps命令查看进程,方便找到当前运行的App在iPhone中的文件目录;
  • iFile,在iPhone上建立一个web server,方便与mac传递数据;

通过Cydia安装好插件后,就要开始解密iosapp这个文件了。在iPhone设置中查找当前链接网络的ip地址,比如是:192.168.0.100,打开mac命令行,建立ssh链接:

ssh [email protected]

此时提示输入密码,默认为:alpine,无需修改。连接成功后,cd 到 /var/mobile/Containers/Bundle/Application/ 目录下,可能看到所有安装的App文件夹,在iPhone中打开开源中国App,保持前台运行。然后在mac终端执行以下命令:

ps -e | grep var

结果如下:

  143 ??         0:04.00 /usr/libexec/pkd -d/var/db/PlugInKit-Annotations
  398 ??         0:01.08 /private/var/db/stash/_.T1qNfY/Applications/MobileSafari.app/webbookmarksd
  529 ??         0:04.78 /private/var/db/stash/_.T1qNfY/Applications/Stocks.app/PlugIns/StocksWidget.appex/StocksWidget
  530 ??         0:01.77 /private/var/db/stash/_.T1qNfY/Applications/MobileCal.app/PlugIns/CalendarWidget.appex/CalendarWidget
 3490 ??         0:14.24 /var/mobile/Containers/Bundle/Application/7738D5DE-B38D-4BF1-9551-BF671978045F/CocoaPods.app/CocoaPods
 3622 ??         0:08.91 /var/mobile/Containers/Bundle/Application/B590E6C8-D5FA-4697-AF4B-EF717ADBCB90/ABC.app/ABC
 4328 ??         0:06.65 /var/mobile/Containers/Bundle/Application/86E38E63-5FF3-4EF5-AB07-D13C4CB70168/iosapp.app/iosapp
 4350 ??         0:01.47 /var/mobile/Containers/Bundle/Application/FBA32574-0453-4BB6-9F46-A87757F22325/WeChat.app/WeChat
 4394 ttys000    0:00.01 grep var

由此可见开源中国的App运行在/var/mobile/Containers/Bundle/Application/86E38E63-5FF3-4EF5-AB07-D13C4CB70168/iosapp.app/目录下,每个app目录下都有一个Info.plist。我们可以通过这个Info.plist得到app的Bundle ID:

cat /var/mobile/Containers/Bundle/Application/86E38E63-5FF3-4EF5-AB07-D13C4CB70168/iosapp.app/Info.plist

得到开源中的的Bundle ID为net.oschina.iosapp,由于App的运行会受到沙盒的限制,因此dump出来的app只能保存在data目录下,这里我们可以通过Bundle ID和一个private API得到data目录的位置:

    Class cls = NSClassFromString(@"LSApplicationWorkspace");
    id s = [(id)cls performSelector:NSSelectorFromString(@"defaultWorkspace")];
    NSArray *arr = [s performSelector:NSSelectorFromString(@"allInstalledApplications")];
    Class Proxy  = NSClassFromString(@"LSApplicationProxy");
    
    for (id proxy in arr) {
        id bundleID = [proxy valueForKey:@"applicationIdentifier"];
        if (bundleID && [bundleID isEqualToString:@"net.oschina.iosapp"]) {
            id dataUrl = [proxy valueForKey:@"dataContainerURL"];
            NSLog(@"dataUrl : %@",dataUrl);
        }
    }

打印出来的data url为file:///private/var/mobile/Containers/Data/Application/6C425F0E-217C-4051-A131-735F3A816D89,接下来在mac终端,cd到dumpdecrypted.dylib所在目录,将dumpdecrypted.dylib拷贝到开源中国的Documents目录下:

scp dumpdecrypted.dylib [email protected]:/private/var/mobile/Containers/Data/Application/6C425F0E-217C-4051-A131-735F3A816D89/Documents/dumpdecrypted.dylib

传输成功显示:

dumpdecrypted.dylib   100%  193KB 192.9KB/s   00:00

然后进入iPhone中开源中国所在根目录的Documents下,执行DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib相关的命令,即将开始编译:

DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/7202242C-DABA-4520-8D3D-81448728F587/iosapp.app/iosapp

成功后,会在Documents目录生成名为iosapp.decrypted的文件,至此就算是破解成功了,如下图所示:


逆向Appstore应用(一)_第3张图片

如果显示dumpdecrypted.dylib: stat() failed with errno=1 即“Operation not permitted”,表示操作权限不够,可以将dumpdecrypted.dylib文件sip至手机的usr/lib目录下,然后再执行DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib命令编译,此时会在usr/lib目录下生成iosapp.decrypted文件。

逆向Appstore应用(一)_第4张图片

砸壳后的app只能解密砸壳运行时的架构,可以看到在arm64架构下显示cryptid为0,已经成功解密。

解密后的文件如何使用?

在得到iosapp.decrypted后,真正的逆向App工作才刚刚开始。未完待续...

参考:

http://www.ifanr.com/473806

http://www.liuchendi.com/2015/12/23/iOS/24_dumpdecrypted/

你可能感兴趣的:(逆向Appstore应用(一))