iOS逆向(3)-APP重签名

作者: 一缕清风扬万里 | 来源:发表于2019-03-05 18:48 被阅读600次

    本文将从原理分析,到利用原理的漏洞,再到具体过程,最后利用脚本全自动实现。

    文章首发:https://www.jianshu.com/p/4e3aa435d848

    作为一名iOS开发者肯定知道iOS开发证书,那么证书具体是什么呢?为什么到我们本地的不是证书本身,而是一个称之为描述文件的东西。而这「描述文件」又具体是什么呢?
    在知道这「描述文件」后,我们是不是可以通过将「描述文件」替换为我们自己的「描述文件」进行一些有意思的事情呢?比如这篇文章的主题,对一个APP进行重签名,让他在我们的XCode中运行起来,运用我们强大的LLDB进行调试,分析其UI和部分逻辑。当然作为一个正直的开发者,我们在这片文章肯定不会对她进「代码注入」这样让人不(兴)齿(奋)的事情的(下一篇就会 O(∩_∩)O哈哈~)。

    片头先给福利:点击下载Demo:AppReSign,使用方法详见demo的Readme

    接下来我们会从以下几点来玩一玩「APP重签名」

    • 分析Apple对App加密的需求
    • 什么是双层签名
    • 手动对APP进行重签名
    • 使用Shell脚本进行重签

    1、分析Apple对App加密的需求

    首先明确一点,对App加密肯定是用要非对称加密而不是对称加密!这我默认大家都懂了,应该不用解释。

    Step 1 安装App到手机的渠道分析

    如果所有的APP都是从App Store下载的那么,这就简单了,只需要对APP进行一层RSA加密就可以了,App Store持有私钥,我们iPhone持有公钥。那么问题就解决了。但事实上肯定不是这样,我们已知的渠道除了App Store就包括XCode打包,ADHOC证书分发,企业证书分发等等。为了解决这个问题,我们就得先了解Apple的具体需求是什么。

    Step 2 分析需求

    • App Store下载
    • XCode直接安装
    • 限制ADHoc打包的APP安装设备
    • ...等等

    2、什么是双层签名

    针对以上三种(包括但不只)场景,苹果给出「双层签名」的机制。
    什么是「双层签名」,先上一张PPT。


    双层签名流程图.png

    看不懂?没关系,下面会一步步,详细的接受双层签名的始末。

    1、向服务器申请证书
    • 什么是CSR文件
      申请过开发者证书的都知道,要申请证书,都有「Mac本地通过CSR文件向服务器」这样的一步。那么这一步到底做了写什么呢?
      先看看什么是CSR

    CSR是Certificate Signing Request的英文缩写,即证书请求文件,也就是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。

    通俗一点,就是Mac本地有一对公钥(公钥M)和私钥(私钥M)(什么是公钥私钥?),在Mac上对公钥M进行了一层包装,这包装后的新东西就是CSR。

    • 服务器通过CSR返回证书
      本地有了CSR文件之后,将CSR上传到Apple的服务器。
      Apple服务器其实也是有一对公钥(公钥A)和私钥(私钥A),在收到Mac上传过来的的CSR文件之后,取出其中的公钥M,用Apple服务器的私钥A对公钥M进行一次数字签名(什么是数字签名?)得到开发证书,然后将开发证书附入描述文件(描述文件还有哪些东西下文会有讲到),最后将描述文件传回给我们的Mac电脑。
    2、描述文件

    配置描述文件是 XML 文件,包含以下内容:设备的安全策略和限制、VPN 配置信息、无线局域网设置、电子邮件帐户和日历帐户以及可允许 iPhone、iPod touch 和 iPad 配合您的企业系统使用的鉴定凭证。配置描述文件能快速地将设置和授权信息载入到设备上。有些 VPN 和无线局域网设置只能使用配置描述文件来设定,而且如果您使用的不是 Microsoft Exchange,则将需要使用配置描述文件来设定设备密码策略。
    描述文件包括的东西,如:

    • 开发证书
    • APP的Bundle Id
    • 证书所信任的Device Id
    • 还有一些权限文件(如:Apple Pay,通知,VPN,iCloud)
    3、Mac打包APP

    在Mac本地有了描述文件之后,就可以对APP进行打包了,打包这个过程除了对APP的压缩之外,更重要的其实是指对APP的加密。
    之前本地把公钥M发送给Apple服务器,本地剩下的私钥M就是用来加密APP的,得到一个APP的签名文件,再将上一步得到的描述文件,以及MachO文件一起打包压缩,最终就得到了我们的ipa包了。
    所以ipa其实包含以下三种东西

    • MachO文件
    • APP的签名文件
    • 描述文件
    4、iPhone验证ipa文件

    上文提到的私钥A是用来加密了公钥M,与之对应的公钥A其实在我们激活iPhone的同时已经下载好了,一直躺在我们的iPhone里面。
    有了公钥M,那么一切就简单了,

    • 公钥A解开ipa中携带的描述文件中的证书得到公钥M
    • 对公钥M进行Hash,对比证书中的Hash
    • 对比通过之后,用公钥M对加密的APP进行解密,得到最终APP。

    3、手动对APP进行重签名 (如果不想看具体过程,可以跳到本节末尾,有流程总结)

    从上面可以得知,双层签名其实本质就是如下三个步骤:

    • APP的Bundle id的验证
    • 描述文件本身的验证
    • 对APP签名的验证

    注:对APP进行重新签名,前提是这个APP已经被砸壳了。
    下载已经砸壳成功的APP,以下例子用微信举例:越狱版本微信7.0.2 提取码: 2w87

    具体步骤:

    Step 1 进入WeChat目录

    解压出 Wechat7.0.2越狱 ,进入WeChat目录

    // 进入WeChat的目录
    cd /Users/dengbin/Desktop/分享/主目录/资料/Wechat7.0.2越狱/Payload
    

    Step 2 查看APP的证书情况

    codesign -d -vv「WeChat.app路径」
    
    查看APP证书情况.png

    Step 3 查看验证APP是否被加密

    进入APP的包内容可以看到其中有一个WeChat的可执行文件,也就是是MachO文件,就是要查看这个MachO文件时候被加密


    WeChat目录.png
    WeChat_MachO.png
    otool -l WeChat | grep cryp
    

    其中cryptid0代表已经砸壳,即解密,为1或者2表示以第1类或者第2类加密方案加密。

    Step 4 查看本地证书并记录需要用到的证书

    security find-identity -v -p codesigning
    
    本地证书列表.png

    Step 5 删除不可签名的插件(还有Watch中的插件)

    由于本地存在一些插件,这些插件是不可被我们重签,并且这个过程我们用不着,所以我们索性就删掉。
    其中包括:整个目录PlugIns目录和整个Watch目录(因为Watch.app中也有个PlugIns)


    PlugIns.png
    Watch.png

    Step 6 Framework重签名

    这一步就是比较繁琐的了,需要将Frameworks下的所有Framework进行重签名,运用到XCode提供的codesign指令,参数中的证书就是Step 4中的一个。具体使用哪个就看个人了

    codesign –fs 「证书串」 「文件名」
    
    Frameworks.png
    Frameworks证书重签.png

    Step 7 给MachO添加可执行权限

    由于MachO本身就有可执行权限,所以这一步跳过。

    Step 8 App重签名

    • 新建一个WeChat同名工程(下文称NewWeChat,原来的微信APP称之为WeChat)
    • Build NewWeChat工程,进入被编译出的WeChat.App目录,找到其中的embedded.mobileprovision文件,将其复制到WeChat.App(越狱微信)中


      Build后的WeChat.png
      embedded.mobileprovision文件.png
      复制后的结果.png
    • 在WeChat.App找到info.plist,并修改其中的BundleId为NewWeChat的BundleId


      更改BundleId.png
    • 查看embedded文件

    security cms -D -i 「 embedded文件路径」
    

    找到其中的entitlements字段,并且复制entitlements字段和其中的内容


    查看embedded.png
    entitlements字段.png
    • 在NewWeChat中新建entitlements.plist文件,将上一步复制得到的「entitlements字段内容」拷贝入新的entitlements.plist文件,然后将entitlements.plist复制到WeChat.app的同级目录下。


      拷贝entitlements.png
      复制entitlements.png
    • 对APP重新签名
      进入WeChat目录,对APP使用新的描述文件进行重签
    codesign -fs 「证书串」 --no-strict --entitlements=entitlements.plist
    
    对App进行重签.png
    • 压缩Playload
     zip –ry 「输出文件名」 「输入文件名」
    
    压缩Playload.png

    Step 9 安装新的ipa

    可以通过各种途径安装ipa,如Xcode,PP助手,fir,iTunes等等, 如果手机上有正版的微信,在安装完我们重签名的ipa包后会发现手机上就有两个微信啦!!!

    如果想用LLDB调试微信,可以将重签后的WeChat.app替换NewWeChat Build后的WeChat.app,然后直接运行(Run)项目,就会发现我们可以用LLDB了。

    Step 10 再次验证新的ipa是否真的重签成功

    这一步其实是重复Step 3

    codesign -d -vv「WeChat.app路径」
    

    步骤总结:

    1、cd WeChat // 进入WeChat的目录
    2、codesign -d -vv「WeChat.app路径」 // 查看APP的证书情况
    3、otool –l WeChat | grep cryp // 查看APP是否被加密
    4、security find-identity -v -p codesigning // 查看本地证书
    5、删除不可签名的插件(还有Watch中的插件)
    6、codesign –fs 「证书串」 「文件名」 // Framework重签名
    7、chmod +x 可执行文件   // 给文件添加权限
    8、App重签名
         ① 新建一个项目并且命名为 WeChat(下文称NewWeChat,原来的微信APP称之为WeChat) -> Build -> 找到APP中的权限文件 embedded.mobileprovision
         ② 复制embedded.mobileprovision到WeChat.app中
         ③ 修改WeChat.app中info.plist的BundleId
         ④ security cms -D -i 「 embedded文件路径」 //查看WeChat中的embedded文件,复制WeChat中entitlements.plist文件的entitlements字段
         ⑤ 在NewWeChat中新建entitlements.plist文件,将上一步复制得到的「entitlements字段和其中的内容」拷贝入新的entitlements.plist文件
         ⑥ codesign -fs 「证书串」 --no-strict --entitlements=entitlements.plist //复制新的entitlements到WeChat.app的同级目录,并且对APP重新签名
         ⑦ zip –ry 「输出文件名」 「输入文件名」 // 压缩Playload
    9、安装ipa 
    10、再次验证新的ipa是否真的重签成功
    
    • 注意:有些人会安装失败,或者安装成功会有Crash的问题,这是因为当前描述文件在我们的手机还不受信任,用新工程NewWeChat在手机上跑一遍,然后删除NewWeChat,在尝试安装新的ipa,问题可以解决。

    4、使用Shell脚本进行重签

    上面所有的步骤其实是固定不变的,而且所有需要操作的文件相对于ipa文件的「相对地址」也是固定的,所以就可以用脚本来代替所有的操作。
    以下脚本适用于适用XCode直接调试,点击下载Demo:AppReSign,使用方法详见demo的Readme

    附上脚本代码

    # ${SRCROOT} 它是工程文件所在的目录
    TEMP_PATH="${SRCROOT}/Temp"
    #资源文件夹,我们提前在工程目录下新建一个APP文件夹,里面放ipa包
    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(已越狱)进行重签,但其实其中有一点非常非常重要的内容在这片文章知识被一笔带过,那就是LLDB,能够用LLDB调试我们的APP意味着无限的可能。
    所以对LLDB运用,也是咱们逆向的必经之路。后续文章也会提到,待更新。

    注意!!!
    警告!!!
    警告!!!
    警告!!!
    重签后不要用自己的账号登录,有封号的危险!!!

    相关文章

      网友评论

        本文标题:iOS逆向(3)-APP重签名

        本文链接:https://www.haomeiwen.com/subject/lgljuqtx.html