声明:此文仅仅用于学习研究,也请大家不要用于商业或其他非法途径上~~
说明:尝试最终卡在了重签名上,安装后的应用持续闪退。目前还没找到解决方法。。。大家如果有什么好方法,欢迎回复~
之前通过对 iOS 冰与火之歌番外篇 - 在非越狱手机上进行 App Hook 走了一遍,尝试到了一点甜头。看到文中抢红包的动画是在太诱惑了,所以把微信作为目标,准备一步步自己实现同样的目标。
目标要一步一步来。与之前相比,这次真的没有源码,也没有 debug 证书打的包。因此先从给微信加 hook 开始。
步骤:
一开始打算直接用 app store 上的微信,结果发现在成功添加 hook ,成功重签并装上设备后,打开 app 还是会闪退。系统错误提示如下:
Mar 23 22:43:46 hengjie-chens-iPad SpringBoard[644] <Error>: SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]
Mar 23 22:43:47 hengjie-chens-iPad SpringBoard[644] <Error>: SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]
Mar 23 22:43:47 hengjie-chens-iPad kernel[0] <Notice>: AppleFairplayTextCrypterSession::fairplayOpen() failed, error -42022
Mar 23 22:43:47 hengjie-chens-iPad com.apple.xpc.launchd[1] (UIKitApplication:com.tencent.xin[0x7c18][1086]) <Notice>: Service exited due to signal: Killed: 9
Mar 23 22:43:47 hengjie-chens-iPad assertiond[653] <Warning>: Unable to obtain a task name port right for pid 1086: (os/kern) failure (5)
Mar 23 22:43:47 hengjie-chens-iPad SpringBoard[644] <Warning>: Unable to register for exec notifications: No such process
Mar 23 22:43:47 hengjie-chens-iPad SpringBoard[644] <Warning>: Unable to obtain a task name port right for pid 1086: (os/kern) failure (5)
Mar 23 22:43:47 hengjie-chens-iPad SpringBoard[644] <Warning>: Unable to obtain a task name port right for <FBApplicationProcess: 0x150211ac0; com.tencent.xin; pid: 1086>
Mar 23 22:43:47 hengjie-chens-iPad SpringBoard[644] <Warning>: Application 'UIKitApplication:com.tencent.xin[0x7c18]' exited abnormally via signal.
Mar 23 22:43:47 hengjie-chens-iPad SpringBoard[644] <Warning>: Application '(null)' exited for an unknown reason.
参考 iOS 冰与火之歌番外篇 - App Hook 答疑以及 iOS 9 砸壳,app store 上的应用都是加密的。若需要进行 hook 及重打包,必须获取到解密后的 app 才行。否则即使 Hook 成功,签名成功,安装成功,app 还是会闪退。
纸上说来终觉浅,我们先来验证一下 app store 上的微信是否真的加了密。
第一步,获取 ipa 文件。
方法很多,我使用的是用 itunes 下载微信,然后通过在 finder 显示文件获取到 ipa 。
第二步,解压获得二进制文件,并查看包含的架构
$ unzip WeChat_6.3.13.ipa -d wechat_6.3.13
...
$ cd wechat_6.3.13/Payload/WeChat.app/
$ file Wechat
Wechat: Mach-O universal binary with 2 architectures
Wechat (for architecture armv7): Mach-O executable arm
Wechat (for architecture arm64): Mach-O 64-bit executable
第三步,通过 otool -l
输出 app load commands ,然后查看 cryptid 标志位的值是否为 1(已加密)
$ otool -l Wechat | grep crypt
cryptoff 16384
cryptsize 38748160
cryptid 1
cryptoff 16384
cryptsize 41467904
cryptid 1
很不幸,看来两个架构都被加密了。
按照文中指示,对 armv7 架构进行砸壳是通用性最强的。通过 iossupportmatrix 找到了采用 armv7 架构的设备清单:
手上虽然有部 iPhone ,但考虑到越狱相对麻烦,这个留待下次进行。
虽然没有亲自砸壳,但还是有办法拿到砸壳后的 app 的。那就是越狱市场。
在 pp 助手上找到了越狱版微信(6.3.15)。虽然和原来的版本略有出入,但能用就好。
下载后的文件重命名为 Wechat_6.3.15.16_jailbreak_pp.ipa 。再次检查加密相关字段:
$ otool -l WeChat | grep crypt
cryptoff 16384
cryptsize 39305216
cryptid 0
cryptoff 16384
cryptsize 42057728
cryptid 0
ok,顺利完成
参照 iOS 冰与火之歌番外篇 - 在非越狱手机上进行 App Hook 。由于目前只是试验,里面先不对具体方法进行 hook ,只是在启动时加入一句 Log :
#import <Foundation/Foundation.h>
#import "CaptainHook/CaptainHook.h"
__attribute__((constructor)) static void entry()
{
NSLog(@"Chj hook begins");
}
然后 build (记得选择用真机,不要用模拟器)。build 完后的结果会放在 Xcode 项目缓存目录 ~/Library/Developer/Xcode/DerivedData
,打开这个文件夹后找到前缀和项目名一致的文件夹,找到里面的 Build/Products/Debug-iphoneos
,把 hook4wechat.dylib hook4wechat.dylib.dSYM
两个文件先拷贝出来待用。
这里参考 iOS 冰与火之歌番外篇 - 在非越狱手机上进行 App Hook 中的方法,用 yololib 来插入。
➜ WeChat.app yololib WeChat hook4wechat.dylib
2016-03-06 22:13:07.861 yololib[77851:9213874] dylib path @executable_path/hook1.dylib
2016-03-06 22:13:07.864 yololib[77851:9213874] dylib path @executable_path/hook1.dylib
Reading binary: WeChat
2016-03-06 22:13:07.864 yololib[77851:9213874] FAT binary!
2016-03-06 22:13:07.865 yololib[77851:9213874] Injecting to arch 9
2016-03-06 22:13:07.866 yololib[77851:9213874] Patching mach_header..
2016-03-06 22:13:07.866 yololib[77851:9213874] Attaching dylib..
2016-03-06 22:13:07.867 yololib[77851:9213874] Injecting to arch 0
2016-03-06 22:13:07.867 yololib[77851:9213874] 64bit arch wow
2016-03-06 22:13:07.867 yololib[77851:9213874] dylib size wow 56
2016-03-06 22:13:07.867 yololib[77851:9213874] mach.ncmds 73
2016-03-06 22:13:07.868 yololib[77851:9213874] mach.ncmds 74
2016-03-06 22:13:07.868 yololib[77851:9213874] Patching mach_header..
2016-03-06 22:13:07.868 yololib[77851:9213874] Attaching dylib..
2016-03-06 22:13:07.868 yololib[77851:9213874] size 52
2016-03-06 22:13:07.868 yololib[77851:9213874] complete!
插入后用 MachOView 打开确认
主要需要三个步骤
因为穷到没有苹果开发者账号,所以没办法在 developer center 里配置。但也有其它办法。
首先,通过 Info.plist 找到微信的 bundle id com.tencent.xin
。
然后自己创建一个使用同名 bundle id 的项目,进行编译就能找到 embedded.mobileprovision 了。
你觉得就是这么简单吗?你自己动手试试这个 bundle id 和微信一样的项目能不能正常签上名?
是的。bundle id 作为唯一标识,不能和其它应用重名,否则生成 mobileprovision 时会报错:An App ID with Identifier 'com.tencent.xin' is not available. Please enter a different string.
。所以这里直接用同名 bundle id 是不可能获取到 mobileprovision 的。
因此,这里换个 bundle id :com.tencent.xin4hook
。然后在生成的 .app 文件中获取到 embedded.mobileprovision。
可以按照文中的方法,通过 iOSOpenDev 提供的 ldid
进行解析(如果这个 ldid
用不了,可以试试这个)。此外,参考 代码签名探析 ,还有一种更方便的获取方法
$ codesign -d --entitlements - WeChat.app
...
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.team-identifier</key>
<string>88L2Q4487U</string>
<key>com.apple.developer.healthkit</key>
<true/>
<key>application-identifier</key>
<string>532LCLCWL8.com.tencent.xin</string>
<key>com.apple.external-accessory.wireless-configuration</key>
<true/>
<key>com.apple.developer.networking.HotspotHelper</key>
<true/>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
<string>app-proxy-provider</string>
<string>content-filter-provider</string>
</array>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.tencent.xin</string>
</array>
...
我一开始不知道撞了什么邪,ldid 老是报 minimal/mapping.h(54): _assert(false); errno=2
这个错误。 Google 和 Stackoverflow 都说是我的 xcode command line 没装,但我装了啊,instruments,xcodebuild 等命令都好好的。结果等到第二天再试竟然自己好了。。。
回想一下,也许是因为我重启了几次 xcode ?
好了,先跳过把。
原文说理论上要签上原 app 对应的所有 entitlement 。因此先尝试这种方式。直接把输出值放到 Entitlement.plist 文件中。
注:关于 Entitlements.plist 的 Key 和 value 含义可以参考苹果的 About Entitlements
参考蒸米的文章:
codesign -f -s "iPhone Developer: zhengmin1989@gmail.com (**********)" WeChat.app/Watch/WeChatWatchNative.app/PlugIns/WeChatWatchNativeExtension.appex
codesign -f -s "iPhone Developer: zhengmin1989@gmail.com (**********)" WeChat.app/Watch/WeChatWatchNative.app
codesign -f -s "iPhone Developer: zhengmin1989@gmail.com (**********)" WeChat.app/PlugIns/WeChatShareExtensionNew.appex
codesign -f -s "iPhone Developer: zhengmin1989@gmail.com (**********)" WeChat.app/hook2.dylib
codesign -f -s "iPhone Developer: zhengmin1989@gmail.com (**********)" --entitlements Entitlements.plist WeChat.app
由于穷,所以我用的是 XCode7 施舍的免费个人开发者证书。。。
结果在最后一步出错:
codesign -f -s "iPhone Developer: 704495442@qq.com (**********)" --entitlements Entitlements.plist WeChat.app
Entitlements.plist: cannot read entitlement data
经过搜索发现,原来这个 plist 不是单纯的文本文件,而是二进制文件,文件开头有一些特殊的二进制字符。因此用 xcode 打开然后保存一次即可。
最后一步了。操作很简单,但所有问题都会暴露在这里
$ ideviceinstaller -i WeChat.app
Uploading WeChat.app package contents... DONE.
Installing '(null)'
- CreatingStagingDirectory (5%)
- ExtractingPackage (15%)
- InspectingPackage (20%)
- TakingInstallLock (20%)
- PreflightingApplication (30%)
- InstallingEmbeddedProfile (30%)
- VerifyingApplication (40%)
- CreatingContainer (50%)
- InstallingApplication (60%)
- PostflightingApplication (70%)
- SandboxingApplication (80%)
- GeneratingApplicationMap (90%)
- Complete
嗯。安装成功了。但打开闪退。。。肯定哪里姿势不对。
重新参照了整篇文章,最大可能出问题的就是砸壳。看来还是得亲自动手啊。
幸好手上有部越狱机,iPhone4 + iOS 7。先装好 OpenSSH、Cycript 。
首先,获取需要砸壳的 app 的二进制文件地址。
# ps ax
...
536 ?? Ss 0:03.63 /var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/WeChat.app/WeChat
然后,获取 app 的 Document 目录
# cycript -p Wechat
cy# NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]
@ /var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/Documents
编译及拷贝 dumpdecrypted.dylib 文件到应用的 Document 目录:
# scp ./dumpdecrypted.dylib root@192.168.1.133:/var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/Documents/
root@192.168.1.133's password:
dumpdecrypted.dylib 100% 193KB 192.9KB/s 00:00
开始砸壳
# DYLD_INSERT_LIBRARIES=/var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/Documents/dumpdecrypted.dylib /var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/WeChat.app/WeChat
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: @0x13a4c(from 0x13000) = a4c
[+] Found encrypted data at address 00004000 of length 39305216 bytes - type 1.
[+] Opening /private/var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/WeChat.app/WeChat for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a FAT image - searching for right architecture
[+] Correct arch is at offset 16384 in the file
[+] Opening WeChat.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 4a4c
[+] Closing original file
[+] Closing dump file
把砸壳后的文件拷贝出来
scp root@192.168.1.133:/var/mobile/Applications/694EDC84-5D40-458E-956E-1041530DC7E6/Documents/WeChat.decrypted .
root@192.168.1.133's password:
WeChat.decrypted
检查是否已经被解密
otool -l WeChat.decrypted | grep crypt
WeChat.decrypted (architecture armv7):
cryptoff 16384
cryptsize 39305216
cryptid 0
WeChat.decrypted (architecture arm64):
cryptoff 16384
cryptsize 42057728
cryptid 1
可以看到,只有 armv7 被解密了。不过足够了。
然后把这个 WeChat.decrypted 重命名为 WeChat ,覆盖 Wechat.app 下同名文件,再重新加 dylib 头、加 embedded.mobileprovision,重签名。
好吧,安装后还是闪退。看来不是破壳问题。还得继续查。。。目前已购买收费个人开发者证书,准备把授权加上再尝试。
大家如果有什么好方法,欢迎回复
updated in 4.10
终于解决这个问题了。我之所以一直闪退和砸壳、换 bundle id 和换 entitlements 无关,应该是和平时使用第三方助手时会出现的闪退一个道理。具体什么道理,我也不清楚,待探究。。。
解决方案很简单:最后不要直接安装 .app ,而是使用下面的命令生成 ipa 后安装 ipa 文件:
$ xcrun -sdk iphoneos PackageApplication -v Wechat.app -o `pwd`/Wechat_resign.ipa
启动后就出现添加进去的 Hook 信息了:
重签名:
http://dev.mlsdigital.net/posts/how-to-resign-an-ios-app-from-external-developers/
http://gowithfloat.com/2011/11/re-signing-an-ios-app-without-xcode/
http://www.enterpriseios.com/forum/topic/Resigning_3rd_party_apps
https://segmentfault.com/a/1190000004144556
plist
http://stackoverflow.com/questions/15231592/error-when-trying-to-sandbox-with-codesign-command
全过程:
http://www.jianshu.com/p/189afbe3b429