IOS 逆向开发(四)App重签名

2,482 阅读12分钟

1. 应用签名

  • 应用签名原理回顾

上一篇博客“IOS 逆向开发(三)应用签名”中详细讲解了IOS 应用签名,证书的原理。本篇博客主要以实战为主,讲解具体如果绕过苹果证书签名,给App重签名,然后可以让我们的app可以任意安装到手机。

  • 接下来,我将用3种方式来实现对app 的重签名。

2. App 重签名 3 种方式

  • 其实我们最终签名app都是使用codesign工具,苹果也是用xcode集成了这个工具而已。这个工具为我们做了很多事情,而我们只需要敲几个命令就可以完成重签名工作。一切看起来都so easy!!!
  • 那么,接下来,我们将用三种不同的方式来重签名App. 我们使用免费证书来重签名App.

2.0 签名前准备工作

  • 我们重签名APP,这里签名的App是使用我们每个人都会使用的重磅级app 微信来重签名。我使用的版本是微信7.0.8版本
  • 我们可以在mac 上面安装一个叫做PP 助手的工具,这个工具可以下载到你想要的ipa包。其他助手工具也可以,或者你直接冲网上下载。
    下载微信ipa包

下载微信7.0.8版本

  1. Mac电脑生成公钥M和私钥M
  2. 公钥M传给苹果服务器,苹果服务器的私钥A对公钥M进行加密生成证书返回给xcode
  3. Xcode下载profile等描述文件,用公钥M对app进行加密生成app签名,然后把app签名和证书以及profile文件一起打包成ipa
  4. 手机进行两次解密,手机用手机系统里的公钥A对证书进行解密得到公钥M,然后对比profile描述文件,查看权限,看是否合法;然后用公钥M对app签名进行解密
  5. 手机里的公钥A与苹果服务器私钥A相对应
    开发者调试安装app到手机的签名过程
  • 此外还需要了解一些加密和重签名相关的命令:
  1. base64加密文件:base64 test.txt -o new.txt
  2. base64解密: base64 new.txt -o abc.txt -D
  3. openssl生成私钥:openssl genrsa -out private.pem 512
  4. 由私钥生成公钥: openssl rsa -in private.pem -out public.pem -pubout
  5. 查看rsa的明文:openssl rsa -in private.pem -text -out private.text
  6. 查看csr解密信息:openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest
  7. 查看profile文件信息: /Users/mac/Library/MobileDevice/Provisioning\ Profiles 然后security cms -D -i e871987c-b4c5-4658-8338-f6e4cabaff8e.mobileprovision
  8. 查看签名信息:ipa包解压打开,进入Payload,查看.app的签名信息codesign -vv -d WeChat.app
  9. 查看所有证书:security find-identity -v -p codesigning
  10. 查看可执行文件macho的加密信息:.app显示包内容,找到同名的可执行文件otool -l WeChat | grep crypt
  11. $security find-identity -v -p codesigning 列出钥匙串里可签名的证书
  12. $Codesign –fs “证书串” 文件名 强制替换签名
  13. $Chmod +x 可执行文件 给文件添加权限
  14. $security cms -D -i ../embedded.mobileprovision 查看描述文件
  15. $codesign -fs “证书串” --no-strict --entitlements=权限文件.plist APP包
  16. $Zip –ry 输出文件 输入文件 将输入文件压缩为输出文件

2.1 利用codesign进行重签名

  • 首先,我们进入我们下载好的WeChat.app所在的目录,通过命令:codesign -v -d WeChat.app 来查看一下包的内容

下载的砸核过的越狱应用WeChat 7.0.8信息如下:

查看WeChat.app包内容

  • 我们如果要用codesign这个命令签名,需要在命令后面跟上证书信息。

  • 我们先通过命令:security find-identity -v -p codesigning 来查看mac电脑的证书信息

    查看证书信息

  • 接下来我们进入WeChat.app 查看包里面的内容:

找到我们的WeChat mach-o可执行文件

  • 我们通过otool工具来查看WeChat可执行文件内容,终端输入:otool -l WeChat
    otool查看WeChat可执行文件信息
  • 我们还可以把这些信息重定向到txt文本:终端输入命令:otool -l WeChat > ~/Desktop/123.txt

重定向输出到文本

  • 此外我们还可以直接通过命令 otool -l WeChat | grep cry 筛选出想要的cryptid内容:

otool -l WeChat 查出来的内容通过管道输出符,通过grep筛选出 “cry”开头的内容。

查看cryptid
cryptid == 0 表示没有进行加密。cryptid == 1表示加密了。这个加密是对称加密,因为需要对整个app包进行加密,是appstore对其进行加密。

  • 我们来思考一个问题,是什么时候进行解密?

是安装的时候解密还是运行的时候解密呢,为了安全,必须运行时解密,每次运行都需要重新解密一次。这样虽然会影响运行效率,但是苹果为了安全不得不在运行时每次对APP进行解密操作。

  • 没有进行加密的app 无法直接在苹果设备上安装。

没有描述文件,无法安装

2.1.1 手动进行app重签名

  • 前面讲了这么多,都是在做准备工作,现在我们真正开始重签名操作。

  • 首先,我们进入WeChat.app目录下面,找到Pluslns目录,因为普通的插件我们是无法签名的,所以必须干掉这些插件。

    找到Pluslns目录

  • 然后我们找到Watch目录。由于Watch目录下面也有插件,我们也必须干掉。

删除Watch目录

  • 接下来,我们找到Frameworks目录,需要对该目录下的所以.framework文件,用我们自己的证书进行签名操作。

    找到Frameworks目录

  • 我们通过命令行,cd 到WeChat.app/Frameworks/目录下面,通过ls命令查看,有6个framework文件如下:

    有6个framework文件

  • 接下来,我要用我自己的证书:"Apple Development: chen lin (QY73GRZ4AG)" 对 上面6个framework分别进行签名操作。使用命令:codesign -fs "Apple Development: chen lin (QY73GRZ4AG)" xx框架名称 .framework 进行签名。

codesign -fs 对框架进行签名

  • 如上图,这里系统会弹出访问秘钥的输入框,按要求输入,始终允许即可。输入你们自己电脑账号的登录密码即可。允许之后,可以看到如下,签名被替换的消息。

    在这里插入图片描述

  • 我们使用同样的命令,依次对6个framework进行签名。

    依次对6个framework进行签名

  • 接下来我们来查看一下可执行文件WeChat,那么我们怎么判断这个可执行文件有权限可以执行呢?

一般我们看这个可执行文件的颜色就可以判断,黑色是可以有执行权限的,白色是没有的。

  • 我们现在使用chmod +x WeChat 命令给整个WeChat.app增加可执行权限。

    给整个WeChat.app增加可执行权限

  • 接下来,我们还需要对WeChat.app增加描述文件。

  • 我们通过新建一个demo工程的方式来申请新的一个描述文件。描述文件无法新增,只能通过从苹果服务器申请的方式,新建一个工程,xcode会帮助我们申请。

    新建一个demo工程的方式来申请新的一个描述文件1
    新建一个demo工程的方式来申请新的一个描述文件2

  • 描述文件申请了,但是如果没有连着真机运行,实际上描述文件并没有下载保存到我们的iphone手机中,所以我们还需要command+R运行一下,在真机上联调运行一下。

    在真机上联调运行一下

  • 如果这个证书对应的描述文件是第一次在真机iphone上运行,手机系统会弹出信任对话框,让你信任一下,如果不是第一次,则不会弹框。运行完成后,我们需要的描述文件就进入到了我们的真机iphone中。

  • 我们可以从项目WeChatDemo工程的Products/WeChatDemo.app中获取生成的描述文件。

    工程的Products/WeChatDemo.app中获取生成的描述文件
    获取描述文件

  • 得到描述文件后,我们用Command + C 复制这个embedded.mobileprovision描述文件,并Command+V粘贴到微信的WeChat.app目录下面。这样我们就给微信app增加了一个我们自己的描述文件。

    给微信app增加了一个我们自己的描述文件

  • 描述文件拷贝到WeChat.app后,我们还需要修改WeChat.app里面的info.plist里面的描述文件配置,需要bundle identifier 保持一致。

    修改WeChat.app里面的info.plist里面的描述文件配置
    修改bundle id

  • 接下来,我们还需要签名整个WeChat.app包,对WeChat.app签名就需要用到我们刚刚申请的描述文件里面的授权文件了。

  • 我们先把申请的那个描述文件拷贝到WeChat.app同级目录

描述文件拷贝到WeChat.app同级目录

  • 我们通过命令行:security cms -Di embedded.mobileprovision查看一下这个描述文件:

    命令行查看描述文件:security cms -Di embedded.mobileprovision

  • 描述文件里面有一个非常重要的东西,这个就是我们权限文件的内容:

权限文件内容

  • 为了使用方便,我们在我们之前创建的那个demo工程里面新建一个plist文件。
    新建一个plist文件
    用SourceCode方式打开plist文件

拷贝权限文件内到新建的plist文件

拷贝后得到权限文件

  • 我们再确认一下plist文件是否拷贝正确:

    确认一下plist文件是否拷贝正确

  • 这样我们就成功从描述文件中提取出了权限文件到新增的kongyuluWechatEnt.plist文件了。

  • 然后我们把这个文件拷贝到WeChat.app同级目录下面:

    拷贝到WeChat.app同级目录下面

  • 接下来,重要的步骤来了,我们通过命令行,输入命令:codesign -fs "证书名称" --no-strict --entitlements=kongyuluWechatEnt.plist WeChat.app

codesign -fs "Apple Development: chen lin (QY73GRZ4AG)" --no-strict --entitlements=kongyuluWechatEnt.plist  WeChat.app

对WeChat.app进行签名

  • 这样我们就手动签名就大功告成了,这样处理过的WeChat.app就会让苹果手机认为我们的app 是一个正在开发阶段的app,这样就可以将我们的重签名过后的app,直接安装到我们的手机上面去了。

  • 接下来我们可以测试一下,我们重签名过后的WeChat.app是否可以安装到手机上面

  • 首先打开我们的xcode ,快捷键Command + Shift +2 调出设备页面

    快捷键Command + Shift +2 调出设备页面

  • 选择WeChat.app后,会提示是否需要覆盖安装,选择是

    覆盖安装

安装重签名包

  • 手动重签名的步骤有点多,这里再简单归纳总结一下,总共分为9步:
  1. 新建工程WeChatDemo,选择证书和真机调试
  2. 进入包内容,因为免费证书无法重签名插件,所以删除PlugIns文件夹,Watch里也有插件,也删除
  3. 对Frameworks里的framework进行重签名,有些包没有Frameworks就忽略这步: 进入Frameworks 文件夹;然后一个一个的重签名 security find-identity -v -p codesigning //查看所有证书 codesign -fs "iPhone Developer: clwmac@icloud.com (Q4M32A5HU5)" QYUniversalFramework.framework //选择和工程codesignDemo一样的证书
  4. 给可执行文件执行权限:chmod +x WeChat
  5. WeChatDemo工程里的Products里的WeChatDemo.app显示包内容,找到包内容里的embedded.mobileprovision文件,拷贝到需要重签名的爱奇艺.app包内容中
  6. WeChatDemo工程的Bundle identifier拷贝到WeChat.app的包内容中的Info.plist的Bundle identifier
  7. 找到第五步的embedded.mobileprovision文件,然后security cms -D -i embedded.mobileprovision找到Entitlements,然后把Entitlements下面的: "dict> </dict" 用Xcode生成plist文件PropertyList.plist,然后Open As -> Source Code,把刚才的拷贝进去,得到如下:
  8. 把第7步得到的plist文件,和WeChat.app放在一个文件夹new中,进行重签名
  9. 安装到手机上 打包为ipa: zip -ry WeChat.ipa new 把new文件夹打包为WeChat.ipa 安装:Xcode command+shift+2进入到设备管理,选择+号找到刚才的WeChat.ipa

2.2 利用xcode进行重签名

  • 上面详细介绍了手动重签名的过程,这里有很多小伙伴肯定会有疑惑,我们花这么大代价重签名是为的什么呢?

重签名app至少有这两个好处:

  1. 重签名后,我们可以通过xcode动态调试那些被我们重签名过后的app.
  2. 重签名后,我们还可以动态注入我们自己的代码,达到破解的目的。
  • 接下来我们将通过xcode来实现重签名。
  • (1)我们先打开xcode ,通过快捷键 :“Command + Shift + N”,创建一个新的工程名字叫做WeChat.

创建一个新的工程名字叫做WeChat

  • (2) 我们需要先连接真机iphone,将WeChat工程在真机上运行一下。“Command + Shift + R”运行一次。这样可以得到我们需要的描述文件。然后我们需要拷贝现在的官方微信版本替换掉新建工程Products中的WeChat.app

替换掉新建工程Products中的WeChat.app

Products/WeChat.app 通过右键Show Finder 可以找到在debug-iphoneos目录下面,直接替换如下图:

在这里插入图片描述

  • (3) 替换掉之后,我们并不能直接通过xcode运行到真机上面,我还需要完成几个步骤才行。和手动签名一样,首先我们要删除我们无法签名的插件信息,删除WeChat.app下的Watch目录和 Pluglsn目录

    删除WeChat.app下的Watch目录和 Pluglsn目录

  • (4)然后,我们还需要对Frameworks目录下面的所以framework进行重签名。

对Frameworks目录下面的所以framework进行重签名

对6个framework进行重签名

  • 这样我们就大功告成了,直接“Command + Shift + R” 运行app,这样重签名的微信就可以运行在我们的真机上面,so easy .

注意:这里我们不需要去修改原始微信.app里面的bundle Id ,xcode运行自动会帮我们改为我们新建工程的bundle id.

重签名成功后的微信

  • 这里我们对xcode重签名步骤总结一下:
  1. 新建工程WeChat,选择证书和真机调试
  2. 把WeChat.app替换WeChat工程的Products的WeChat.app
  3. 进入替换后的WeChat.app包内容中,删除PlugIns文件夹和Watch文件夹
  4. 重签名对Frameworks里的framework进行重签名,有些包没有Frameworks就忽略这步
  5. 改替换后的WeChat.app包中的Info.plist的Bundle identifier改为WeChat工程的Bundle identifier
  6. 给可执行文件执行权限:chmod +x WeChat
  7. 运行工程WeChat

注意: 这里如果新建的工程名字和你要签名的app名称不一致,会签名失败,运行的还是你新建工程的那个demo,而不是你想覆盖的微信.app。因为xcode运行时,会自动将可执行文件改为你新建工程的名称。加入我们新建的工程名称叫demo,我们用WeChat.app改名后替换了demo.app,运行的时候会自动运行demo.app而不是WeChat.app. 这样我们需要通过运行脚本的方式,来更加优雅的执行重签名操作。

  • 我们下面将讲述通过Shell脚本来重签名。

2.3 利用shell脚本进行重签名

  • 新建工程cosignAutoDemo,选择证书和真机调试,在工程根目录里新建APP和Temp文件夹:
  • xcode->Build Phases->+New Run Script Phase
  • 在Run Script的shell代码如下:
# ${SRCROOT} 它是工程文件所在的目录
TEMP_PATH="${SRCROOT}/Temp"
#资源文件夹
ASSETS_PATH="${SRCROOT}/APP"
#ipa包路径
TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"

#新建Temp文件夹
rm -rf "${SRCROOT}/Temp"
mkdir -p "${SRCROOT}/Temp"

#----------------------------------------
# 1. 解压IPA到Temp下
unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
# 拿到解压的临时的APP的路径
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# echo "路径是:$TEMP_APP_PATH"


#----------------------------------------
# 2. 将解压出来的.app拷贝进入工程下
# BUILT_PRODUCTS_DIR 工程生成的APP包的路径
# TARGET_NAME target名称
TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
echo "app路径:$TARGET_APP_PATH"

rm -rf "$TARGET_APP_PATH"
mkdir -p "$TARGET_APP_PATH"
cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"



#----------------------------------------
# 3. 删除extension和WatchAPP.个人证书没法签名Extention
rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"



#----------------------------------------
# 4. 更新info.plist文件 CFBundleIdentifier
#  设置:"Set : KEY Value" "目标文件路径"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"


#----------------------------------------
# 5. 给MachO文件上执行权限
# 拿到MachO文件的路径
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#上可执行权限
chmod +x "$TARGET_APP_PATH/$APP_BINARY"



#----------------------------------------
# 6. 重签名第三方 FrameWorks
TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
    then
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do
#签名
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
done
fi
  • 在APP文件夹下放ipa包,然后运行.这样就大功告成了,是不是更简单呢?
  • 其实,我们也可以把脚本保存成xcodeCodesign.sh文件,然后在Run Script的shell的代码处,写入xcodeCodesign.sh文件的路径;最后要chmod +x xcodeCodesign.sh,就可以运行了。
  • 下面将介绍一种更简单的方法,名字叫做第三方,第三方基本上就是傻瓜式的了,安装官方说明就可以完成了。

2.4 利用第三方工具 MonkeyDev重签名

  1. MonkeyDev安装,点击这里下载
  2. 新建MonkeyApp工程monkeyDemo
  3. 在monkeyDemo文件夹的TargetApp里放ipa包,然后运行