分类目录归档:技术相关

LLDB+debugserver调试第三方应用

前言

本文主要介绍越狱手机通过LLDB、debugserver调试第三方应用,关于LLDB、debugserver的内容,前面在学习中也有提到过:LLDB调试命令、ptrace反调试

一、简介

debugserver就像是远程服务的控制台应用,主要给gdb或者lldb调试,手机设备开启debugserver服务,本地Mac通过LLDB发送指令给debugserver,debugserver在真机调试的时候被安装到手机上,可以在手机上/Developer/usr/bin/debugserver找到。日常正向开发就是Xcode内部的LLDB调起debugserver进程来调试我们自己的App。

二、debugserver命令选项

iOS端调起debugserver

debugserver host:port [program-name program-arg1 program-arg2 …]

选项 含义
-a 进程 将debugserver依附到指定进程,通过PID或可执行文件名称
-d integer 指定等待时间
-i integer 指定等待时间间隔
-l filename 日志文件。将文件名设置为stdout以记录标准输出
-t 使用task ID代替PID
-v 日志模式

三、配置debugserver

debugserver默认只能调试自己开发的应用,调试其他应用会抛异常unable to start the exception thread。默认的debugserver缺少task_for_pid()权限,因此需要给debugserver赋予task_for_pid权限。

LLDB+debugserver调试第三方应用
unable to start the exception thread异常

(一)、方法一 使用ldid赋予权限

(1)Mac端找到debugserver文件
debugserver可以在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/你越狱手机版本/DeveloperDiskImage.dmg里的usr/bin路径找到,拷贝出来。由于ldid不支持胖二进制文件,因此需要先瘦身:

lipo -thin armv7 debugserver -output ~/debugserver (注意,本文使用iPhone5测试,因此对应armv7,请自行对应架构)

LLDB+debugserver调试第三方应用
image.png

(2)新建一个xml文件

<!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.springboard.debugapplications</key>
        <true/>
        <key>get-task-allow</key>
        <true/>
        <key>task_for_pid-allow</key>
        <true/>
        <key>run-unsigned-code</key>
        <true/>
    </dict>
</plist>
LLDB+debugserver调试第三方应用
xml

(3)赋予权限

ldid -Sxml全路径 debugserver全路径
例如:ldid -S/Users/kinken_yuen/Desktop/ent.xml /Users/kinken_yuen/Desktop/debugserver

LLDB+debugserver调试第三方应用
赋予权限

(4)拷贝配置后的debugserver到手机

注意: 手机上的/Developer目录实际上是只读的,你不能直接将debugserver复制回去,放到别的地方使用,可以是:scp -P 2222 ./debugserver root@127.0.0.1:/usr/bin/debugserver
下面的方法二最后也需要如此操作

(二)、方法二 使用codesign赋予权限

(1)拷贝出debugserver
先将debugserver从手机复制到Mac

scp -P 2222 root@localhost:/Developer/usr/bin/debugserver ./

因为是从当前越狱手机拷贝,因此不需要再瘦身

LLDB+debugserver调试第三方应用
debugserver文件

(1)使用entitlements权限文件签名
新建entitlements.plist,写入内容

<?xml version="1.0" encoding="UTF-8"?>
<!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.springboard.debugapplications</key>
    <true/>
    <key>run-unsigned-code</key>
    <true/>
    <key>get-task-allow</key>
    <true/>
    <key>task_for_pid-allow</key>
    <true/>
</dict> 
</plist>

(3)赋予权限

codesign -s - --entitlements entitlements.plist -f debugserver

LLDB+debugserver调试第三方应用
签名权限

(4)拷贝配置后的debugserver到手机
参考方法一

四、附加到进程

(一)、通过WIFI连接

(1)、手机端开启debugserver

LLDB+debugserver调试第三方应用

(2)、Mac端LLDB连接debugserver

LLDB+debugserver调试第三方应用
进入lldb

process connect connect://设备IP地址:1234(对应于手机开启的端口号)

LLDB+debugserver调试第三方应用
连接debugserver

(二)、通过USB连接

(1)手机端开启debugserver(同上)
(2)Mac端

  • 先做端口转发

iproxy 1234 1234

接着

process connect connect://127.0.0.1:1234
process connect connect://localhost:1234

LLDB+debugserver调试第三方应用
USB连接

五、小结

第三方应用动态调试的方式不止一种,如重签名后用Xcode调试非越狱Cycript调试越狱Cycript调试,以及上面的lldb + debugserver调试。

dumpdecrypted砸壳

一、原理

动态注入可执行文件Mach-o,从内存dump出解密的内容

github : dumpdecrypted

二、编译dumpdecrypted

cd到目录 make 得到一个dumpdecrypted.dylib

PS:后面注入过程出现一个问题:

dumpdecrypted砸壳
因为没有签名dylib,注入失败

解决方案:
列出可签名证书

security find-identity -v -p codesigning

为dumpecrypted.dylib签名

codesign --force --verify --verbose --sign "iPhone Developer: xxx xxxx (xxxxxxxxxx)" dumpdecrypted.dylib

三、砸壳(解密)

1.定位目标应用的可执行文件

手机退出其他应用,只打开目标应用(以微信为例),电脑ssh到手机,使用ps -e(ps命令需要手机安装插件adv-cmds)命令查看进程:

dumpdecrypted砸壳
定位微信进程

2.获取应用沙盒目录Documents

动态库注入解密需要写到同一目录下,而应用存在沙盒中,通过BundleID调用私有API获取Documents目录:
cat /var/containers/Bundle/Application/BE4C2082-083B-4DE4-924D-EDCA98EB1701/WeChat.app/Info.plist | grep CFBundleIdentifier -A 1

dumpdecrypted砸壳
获取bundleID

3.调用私有API获取沙盒Documents目录

新建iOS工程,在目标应用设备上运行

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSString *bundleID = @"com.tencent.xin";
    NSURL *dataURL = [[NSClassFromString(@"LSApplicationProxy") performSelector:@selector(applicationProxyForIdentifier:) withObject:bundleID] performSelector:@selector(dataContainerURL)];
    NSLog(@"%@",[dataURL.absoluteString stringByAppendingString:@"/Documents"]);
    return YES;
}

控制台输出:
2018-11-08 23:13:26.751557 decrypt[623:18364] file:///private/var/mobile/Containers/Data/Application/02A7FF42-8A6B-45BA-8C25-99760F0311C7/Documents
对应Documents目录:
/var/mobile/Containers/Data/Application/02A7FF42-8A6B-45BA-8C25-99760F0311C7/Documents

4.复制dylib到Documents目录并进行解密

  • 在dumpdecrypted.dylib目录下打开终端,复制dylib使用以下命令(自行修改不同参数):
    scp ./dumpdecrypted.dylib root@192.168.10.170:/var/mobile/Containers/Data/Application/02A7FF42-8A6B-45BA-8C25-99760F0311C7/Documents

  • ssh到手机端解密
    1.cd /var/mobile/Containers/Data/Application/02A7FF42-8A6B-45BA-8C25-99760F0311C7/Documents
    2.DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/containers/Bundle/Application/BE4C2082-083B-4DE4-924D-EDCA98EB1701/WeChat.app/WeChat

    dumpdecrypted砸壳
    dump出解密文件
  • 解密文件就在Documents目录,拷贝出来玩耍吧
    Mac端:
    scp root@192.168.10.170:/var/mobile/Containers/Data/Application/02A7FF42-8A6B-45BA-8C25-99760F0311C7/Documents/WeChat.decrypted ~/desktop

  • 查看解密文件

    dumpdecrypted砸壳
    cryptid为0表示未加密

上述操作比较原始,后面会有更快的砸壳方法,庆哥的改版dumpdecrypted(试过一遍没搞懂),庆哥推荐使用 frida-ios-dump,传送门:使用frida-ios-dump快速通过越狱设备砸壳

Clutch砸壳

一、准备工作

Clutch

git clone https://github.com/KJCracks/Clutch.git

设置生成所有架构(Build Active Architecture Only – NO),Xcode编译,我遇到了编译失败,有待解决:

Clutch砸壳
Xcode编译失败

按照github README处理
终端:

killall Xcode

cp /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist ~/

sudo /usr/libexec/PlistBuddy -c "Set :DefaultProperties:CODE_SIGNING_REQUIRED NO" /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist

sudo /usr/libexec/PlistBuddy -c "Set :DefaultProperties:AD_HOC_CODE_SIGNING_ALLOWED YES" /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist

接着到项目目录、终端:

xcodebuild clean build

会有build文件夹生成,里面有编译好的可执行的Clutch,拷贝手机端:
注意:命令采用USB ssh方式,并且做了端口转发

scp -P 2222 ./build/Clutch root@localhost:/usr/bin/Clutch

二、在手机端进行砸壳

我尝试了两次对Wechat砸壳,手机都死机了,终端提示以下:

Clutch砸壳
砸壳失败

接着我又直接在手机终端上砸,同样失败,终端闪退,手机黑屏死机,又要强制重启重新越狱…

对于失败的猜测,可能是自己编译Clutch可能架构不对,无法正确使用,那么我直接使用作者Release出来的,换了个App,成功。后续学习过程了解到,Clutch会对App内部的Framework也解密,所以可能会出错,像微信、支付宝就会出错。

Clutch砸壳
换个了App砸

再砸一次WeChat,失败!

学习对比了几个砸壳的方式,个人感觉frida-ios-dump最方便,直接在Mac端拿到解密的可执行文件。

frida-ios-dump砸壳

一、越狱设备端配置

  • 安装frida
    cydia添加源:http://build.frida.re/
frida-ios-dump砸壳
安装Frida

二、Mac端配置frida

  • Mac安装frida

pip install frida-tools

PS:有可能Mac没有安装pip

sudo easy_install pip

  • 克隆frida-ios-dump并且安装依赖

git clone https://github.com/AloneMonkey/frida-ios-dump.git
sudo pip install -r requirements.txt --upgrade(需要Python2.7,Python3请检出3.x分支,github README.md有说明)

配置过程可能出现异常:

frida-ios-dump砸壳
sudo pip install -r requirements.txt –upgrade提示异常

使用sudo -H pip install -r requirements.txt --upgrade解决

  • 使用usbmuxd做端口转发

iproxy 2222 22

  • 列出Display name(应用名称)

frida-ps -U

frida-ios-dump砸壳
target:微信

三、dump出脱壳的ipa

./dump.py 微信

参数用Display name或者Bundle ID都行

PS:这一步可能会提示认证失败,原因是没有将Mac公钥传到越狱设备上,庆哥github上面也有提示。

nice~

frida-ios-dump砸壳
得到砸壳的ipa
frida-ios-dump砸壳
验证是否加密

LLDB解密(砸壳)

前言

前段时间学习过利用工具来对加密的应用ipa包砸壳,dumpdecrypted砸壳,Clutch砸壳,frida-ios-dump砸壳,这次通过LLDB自己手动操作可执行文件,dump出解密的文件(实际上dumpdecrypted就是这个原理),简单了解砸壳的原理。

一、原理

加密内容在手机启动执行加载到内存后,是解密的,可以根据Mach-O文件记录的加密内容开始偏移值以及加密内容大小,从内存中dump出已经解密的部分,再将dump出的部分写回原执行文件,这样就得到一个完整的解密的可执行文件。

二、从越狱手机拷贝出原可执行文件

以WeChat为例

LLDB解密(砸壳)
查看可执行文件路径

LLDB解密(砸壳)
拷贝

LLDB解密(砸壳)
查看可执行文件加密字段信息

LLDB解密(砸壳)
arm64架构

了解到了这两个数据信息,就可以利用LLDB进行解密,下面选择64位架构进行解密

三、使用LLDB砸壳

参考LLDB+debugserver调试第三方应用进入lldb调试界面,并且附加到目标进程,如下:

LLDB解密(砸壳)
LLDB调试

查看主模块加载地址

LLDB解密(砸壳)
image.png

我们使用的物理地址为:0x0000000100014000,先记录下来,接着根据cryptoofcryptsize字段dump出解密部分,如下:

LLDB解密(砸壳)
dump出解密部分

这样dump出的文件是没有Mach-O header,因此要将dump出文件Patch回原可执行文件(可以先备份原可执行文件),Patch之前先说个注意点:

注意:手机上拷贝出的Mach-O文件含有两种架构,因此我们在Patch的时候要找对架构起始偏移

从下面的Mach-O头信息可知,我们需要将dump出的文件写回70041600 + 16384 =70057984的位置

LLDB解密(砸壳)
架构起始偏移

Patch操作如下(过程会有点久,耐心等待):

LLDB解密(砸壳)

到这一步,原可执行文件的arm64架构文件已经解密,最后修改一下对应的加密标识cryptID即可。

提取arm64架构的文件

lipo -thin arm64 WeChat -output /Users/kinken_yuen/Desktop/WeChat_arm64

使用Mach-OView修改字段

LLDB解密(砸壳)
修改加密标识字段

最后使用class-dump能够正常dump出工程的类头文件,砸壳成功。

四、脚本调用LLDB砸壳

Github:https://github.com/BlueCocoa/dumpdecrypted-lldb

LLDB解密(砸壳)
python脚本dump

参考

使用lldb砸壳