用dumpdecrypted给App砸壳

以下部分内容摘自《iOS应用逆向工程》第二版,以iOS 8为环境编写,应该也支持iOS 7和9,请大家注意。

在《iOS应用逆向工程》4.6.2节中,我们曾推荐使用iPhoneCake源的AppCrackr 1.7版给App砸壳。这种方式简单粗暴,省时省力,但正是因为它过于方便有木有,导致几乎所有iDevice用户都可轻松上手,随便亵玩,所以不少用户都拿它来■■程序,而不是学习《iOS应用逆向工程》,简直可以说是婶可忍叔不可忍!这也导致了iOS越狱开发社区普遍认为这个软件助长了盗版的气焰,没有脱离低级趣味,对iPhoneCake源进行了强烈谴责,责令其限期整改。迫于压力,iPhoneCake在前段时间将AppCrackr下架,而书中提到的xsellize源中的AppCrackr则是1.5旧版,已不能在高级系统中使用。所以,为了响应业界反盗版的呼声,提倡毛主席“自己动手丰衣足食”的革命精神,让“砸壳”这件事恢复单纯的研究目的,在这里我们会使用更偏geek一些的dumpdecrypted方式来给App砸壳,不再推荐AppCrackr、Clutch、Crackulous等纯UI方式。由于dumpdecrypted刚经历过一次大升级,目前网上可以找到的使用教程均已过期,所以这里我们以一个虚构的TargetApp.app为例,手把手带大家进行一次完整的“砸壳 + class-dump”,请大家准备板凳瓜子汽水,开始围观。如果能对着电脑,边看边做,善莫大焉!楼猪才疏学浅,如有纰漏,敬请斧正,洗耳恭听,污言秽语,免开尊口,感谢支持!

下载dumpdecrypted的源码

源码下载地址是“https://github.com/stefanesser/dumpdecrypted/archive/master.zip”,下载后请将其解压至你习惯的位置,例如楼猪为/Users/snakeninny/Code/,解压后生成/Users/snakeninny/Code/dumpdecrypted-master/

编译源码

snakeninnysiMac:~ snakeninny$ cd /Users/snakeninny/Code/dumpdecrypted-master/
snakeninnysiMac:dumpdecrypted snakeninny$ 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 
`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 -dynamiclib -o dumpdecrypted.dylib dumpdecrypted.o

上面的make命令执行完毕后,会在当前目录下生成一个dumpdecrypted.dylib文件,这就是我们等下砸壳所要用到的榔头。此文件生成一次即可,以后可以重复使用,下次砸壳时无须再重新编译。

用ps命令定位待砸壳的可执行文件

在iOS 8中,来自AppStore的App全部位于/var/mobile/Containers/下,其中可执行文件位于/var/mobile/Containers/Bundle/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/Target.app/下。我们不知道X是什么,肉眼定位需要手工遍历所有目录,劳民伤财,但一个简单的小技巧就可以省时省力:首先在iOS中关掉所有App,然后打开Target,接着ssh到iOS上,打印出所有进程:

snakeninnysiMac:~ snakeninny$ ssh root@yourIP
FunMaker-5:~ root# ps -e
  PID TTY           TIME CMD
    1 ??         3:28.32 /sbin/launchd
……
5717 ??         0:00.21 /System/Library/PrivateFrameworks/MediaServices.framework/Support/mediaartworkd
 5905 ??         0:00.20 sshd: root@ttys000 
 5909 ??         0:01.86 /var/mobile/Containers/Bundle/Application/03B61840-2349-4559-B28E-0E2C6541F879/TargetApp.app/TargetApp
 5911 ??         0:00.07 /System/Library/Frameworks/UIKit.framework/Support/pasteboardd
 5907 ttys000    0:00.03 -sh
 5913 ttys000    0:00.01 ps –e

因为iOS上只打开了一个StoreApp,所以唯一的那个含有/var/mobile/Containers/Bundle/Application/字样的结果就是TargetApp可执行文件的全路径。

用Cycript找出TargetApp的Documents目录路径。

App的Documents目录位于/var/mobile/Containers/Data/Application/ YYYYYYYY-YYYY-YYYY-YYYY–YYYYYYYYYYYY/下,Y与之前的X值不同,而且这次PS也帮不上忙了。因此,需要借助强大的Cycript,让App告诉我们Documents的路径。命令如下:

FunMaker-5:~ root# cycript -p TargetApp
cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
#"file:///var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents/"

将dumpdecrypted.dylib拷贝到Documents目录下。拷贝命令如下:

snakeninnysiMac:~ snakeninny$ scp /Users/snakeninny/Code/dumpdecrypted/dumpdecrypted.dylib root@192.168.2.2:/var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents/
dumpdecrypted.dylib                                                                   100%  193KB 192.9KB/s   00:00

这里采用的是scp方式,也可以使用iFunBox等工具来操作。

开始砸壳

dumpdecrypted.dylib的用法是:

DYLD_INSERT_LIBRARIES=/path/to/dumpdecrypted.dylib /path/to/executable

实际操作起来就是:

FunMaker-5:~ root# cd /var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents/
FunMaker-5:/var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents root# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/03B61840-2349-4559-B28E-0E2C6541F879/TargetApp.app/TargetApp
mach-o decryption dumper

DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.

[+] detected 32bit ARM binary in memory.
[+] offset to cryptid found: @0x81a78(from 0x81000) = a78
[+] Found encrypted data at address 00004000 of length 6569984 bytes - type 1.
[+] Opening /private/var/mobile/Containers/Bundle/Application/03B61840-2349-4559-B28E-0E2C6541F879/TargetApp.app/TargetApp for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a plain MACH-O image
[+] Opening TargetApp.decrypted for writing.
[+] Copying the not encrypted start of the file
[+] Dumping the decrypted data into the file
[+] Copying the not encrypted remainder of the file
[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset a78
[+] Closing original file
[+] Closing dump file

当前目录下会生成TargetApp.decrypted,即砸壳后的文件:

FunMaker-5:/var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents root# ls  
TargetApp.decrypted  dumpdecrypted.dylib OtherFiles

赶紧把砸壳后的文件拷贝到OSX上备用吧,class-dump、IDA等工具已经迫不及待啦。
以上6步还算简洁明了,但可能会有朋友问,为什么要把dumpdecrypted.dylib拷贝到Documents目录下操作?
问得好。我们都知道,StoreApp对沙盒以外的绝大多数目录没有写权限。dumpdecrypted.dylib要写一个decrypted文件,但它是运行在StoreApp中的,与StoreApp的权限相同,那么它的写操作就必须发生在StoreApp拥有写权限的路径下才能成功。StoreApp一定是能写入其Documents目录的,因此我们在Documents目录下使用dumpdecrypted.dylib时,保证它能在当前目录下写一个decrypted文件,这就是把dumpdecrypted.dylib拷贝到Documents目录下操作的原因。
最后来看看如果不放在Documents目录下,可能会出现什么问题:

FunMaker-5: /var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents root# mv dumpdecrypted.dylib /var/tmp/
FunMaker-5: /var/mobile/Containers/Data/Application/D41C4343-63AA-4BFF-904B-2146128611EE/Documents root# cd /var/tmp
FunMaker-5:/var/tmp root# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /private/var/mobile/Containers/Bundle/Application/03B61840-2349-4559-B28E-0E2C6541F879/TargetApp.app/TargetApp
dyld: could not load inserted library 'dumpdecrypted.dylib' because no suitable image found.  Did find:
        dumpdecrypted.dylib: stat() failed with errno=1

Trace/BPT trap: 5

这里errno的值是1,即Operation not permitted,砸壳失败。

class-dump丫

在崭新的21世纪,App的可执行文件一般都是fat binary,也就是说一个二进制文件里包含适合多个CPU架构使用的可执行文件,虽然CPU架构是向下兼容的(也就是说armv64可以执行armv7s的指令,反之则不行),但向下兼容一般会导致一部分性能的牺牲。这样如果一个binary既包含适用于armv7架构的可执行文件,又包含armv7s的,还包含arm64的,就意味着它可以在iPhone 4(armv7),4s(armv7),5(armv7s),5s(arm64)上都发挥100%的性能。虽然除了处女座以外的其他星座用户一般是感受不到这个性能的提升的~但是,机器比处女座还要处女座,它在执行一个fat binary时,会选择最适合自己CPU的那个可执行文件,其他的可执行文件其实是没有得到执行的。因此dumpdecrypted.dylib起作用的只有实际得到执行的那一个可执行文件,举个例子,如果Victim里含有armv7和armv7s这2种架构,而我们的操作机是一台iPhone5/4,那么dumpdecrypted砸掉的是armv7s/armv7那部分的壳,armv7/armv7s部分仍是有壳的。自然地,class-dump的作用对象必须是砸掉壳的binary,所以我们要在class-dump时指定目标,在本例中,就是

class-dump --arch armv7s Target.decrypted

class-dump --arch armv7 Target.decrypted

可以明白吧?没关系,慢一点,多看几遍,理一理,还是有问题的话,在下面留言啦!

12 个赞

“DYLD_INSERT_LIBRARIES”,原来是这么用的啊

fat binary … 学习了~~

iFile找到的文件不能复制吗,终端也不能粘贴。 写了一大串路径结果找不到…

iFile也可以复制的,具体用法你搜搜看就知道了。不过建议你ssh到机器上操作,直接在手机上操作太麻烦了!

砸壳必须到iOS里吗?OSX里不能砸壳吗?

砸壳成功 +1;mobile密码不改危险大吗?dumpdecrypted.dylib发在永久存在的文件夹下有危险吗?

密码不改危险大,dylib永久存放我觉得没太大问题

class-dump --arch armv7 Victim.decrypted 这个在terminal里看到了砸开的方法,但这个会和书上开介绍class-dump 的一样生成一个.h 的文件么?

生成本地文件需要加-o /path/to/local/document/

昨天一直输出不了,按这 http://zhiwei.li/text/2010/11/objective-c-class-dump/ 一顿操作,拿到了

楼主你好,文章里面的 xcrun --sdk iphoneos–show-sdk-path
少了一个空格,应该是 xcrun --sdk iphoneos --show-sdk-path

感谢提醒,确实是写错了

学习了,感谢楼主分享,平时都用clutch,这次动手试试

很赞,不知道 dumpdecrypted 的成功率在多少?有几个地方命令缺空格。

遇到点问题:
机子是touch 6.x系统,直接在github上下载了dumpdecrypted_6.dylib,放到了/var/tmp
砸壳的时候显示:
/var/mobile/Application/xxxxxxx/xxx.app/xxx: Bad executable(or shared library)

求教是哪里不对啊

那可能是我的dylib不能用,你按照教程自己编译生成一个吧

没问题了,文件生成有些延迟~

为什么 一定要放到手机 砸啊, 直接放Mac 上不中吗?

按照楼主的方法,我砸了下淘宝客户端,结果头文件里面的内容全部在终端里面打印出来了,然后在怎么处理呢?