应用签名原理
代码签名
概念性的东西:代码签名是对可执行文件或脚本进行数字签名.用 来确认软件在签名后未被修改或损坏的措施。和 数字签名原理一样,只不过签名的数据是代码而已。
在iOS出来之前,以前的主流操作系统(Mac/Windows)软件随便从哪里下载都能运行,系统安全存在隐患,盗版软件,病 毒入侵,静默安装等等.那么苹果希望解决这样的问题,要保证每一个安装到 iOS 上的 APP 都是经过苹果官方允许的,怎样 保证呢?就是通过代码签名。
如果要实现验证.其实最简单的方式就是通过苹果官方生成非对称加密的一对公私钥.在iOS的系统中内置一个公钥,私钥 由苹果后台保存,我们传APP到AppStore时,苹果后台用私钥对APP数据进行签名,iOS系统下载这个APP后,用公钥验证这个签名, 若签名正确,这个APP肯定是由苹果后台认证的,并且没有被修改过,也就达到了苹果的需求:保证安装的每一个APP都是经过苹 果官方允许的.
如果我们iOS设备安装APP只从App Store这一个入口这件事就简单解决了,没有任何复杂的东西,一个数字签名搞定. 但是实际上iOS安装APP还有其他渠道.比如对于我们开发者iOSER而言,我们是需要在开发APP时直接真机调试的.而且苹
果还开放了企业内部分发的渠道,企业证书签名的APP也是需要顺利安装的. 苹果需要开放这些方式安装APP,这些需求就无法通过简单的代码签名来办到了。
苹果需求
- 安装包不需要上传到App Store,可以直接安装到手机上.
- 苹果为了保证系统的安全性,又必须对安装的APP有绝对的控制权
• 经过苹果允许才可以安装
• 不能被滥用导致非开发APP也能被安装
所以为了实现这些需求,iOS签名的复杂度也就开始增加,苹果给出的方案,就是双层签名。
双层代码签名
iOS的双层代码签名流程简单梳理,这也不是最终的iOS签名原理.iOS的最终签名在这个基础上还要稍微加 点东西.
首先这里有两个角色.一个是iOS系统 还有一个就是我们的Mac系统.因为iOS的APP开发环境在Mac系统下.所以这 个依赖关系成为了苹果双层签名的基础.
1、在Mac系统中生成一对非对称加密算法的公钥和私钥,这里简称公钥M和私钥M。
2、苹果自己也有一对固定的公钥A和私钥A,公钥A在每个手机iOS系统中,而私钥A在苹果后台。
3、在项目打包过程中,我们第一件事,就是生成CSR文件,生成文件的时候,电脑会让我们填入相关开发者信息,这些就是所谓的信息摘要。把CSR文件(包含公钥M以及开发者信息)发送给苹果后台,苹果后台用私钥A去签名公钥M,得到了一份数据包含了公钥M以及其签名,这份数据称为证书,以及会给我们一份描述文件(通过填写设备ID、AppID、证书等信息得到的(Provisioning profile)。
4、在开发时,编译完一个APP后,用本地的私钥M(其本质就是P12文件)对这个APP进行签名,同时把第三部得到的描述文件及证书一起打包进APP里,安装到手机上。
5、在安装时,iOS系统取得证书,通过系统内置的公钥A,去验证证书的数字签名是否正确。
6、验证证书后确保了公钥M是苹果认证过的,再用公钥 M 去验证 APP 的签名,这里就间接验证了这个 APP 安装 行为是否经过苹果官方允许。(这里只验证安装行为,不验证APP 是否被改动,因为开发阶段 APP 内容总是 不断变化的,苹果不需要管。)
如果你还是不太明白,就仔细看一下下面的流程图。

有了上面的过程,已经可以保证开发者的认证,和程序的安全性了。
描述文件
描述文件(Provisioning profile)一般包括三样东
西:证书、App ID、设备。当我们在真机运行或
者打包一个项目的时候,证书用来证明我们程序
的安全性和合法性。
苹果为了解决应用滥用的问题,所以苹果又加了两个限制. 第一限制在苹果后台注册过的设备才可以安装. 第二限制签名只能针对某一个具体的APP. 并且苹果还想控制App里面的iCloud/PUSH/后台运行/调试器附加这些权限,所以苹果把这些权限开关统一称为
Entitlements(授权文件).并将这个文件放在了一个叫做Provisioning Profile(描述文件)文件中. 描述文件是在AppleDevelop网站创建的(在Xcode中填上AppleID它会代办创建),Xcode运行时会打包进入APP内. 所以我们使用CSR申请证书时,我们还要申请一个东西!! 就是描述文件!
在开发时,编译完一个 APP 后,用本地的私钥M对这个APP进行签名,同时把从苹果服务器得到的 Provisioning Profile 文件
打包进APP里,文件名为embedded.mobileprovision,把 APP 安装到手机上.最后系统进行验证。
重签名原理
codeSign
Xcode提供了签名工具,codesign,我们通过几个命令就可以完成重签名。日常我们开发中,签名的过程都是Xcode代替我们手工完成。
相关终端命令
$security find-identity -v -p codesigning //列出钥匙串里可签名的证书
$Codesign –fs “证书串” //文件名 强制替换签名
$Chmod +x 可执行文件 //给文件添加权限
$security cms -D -i ../embedded.mobileprovision //查看描述文件
$codesign -fs “证书串” --no-strict --entitlements=权限文件.plist APP包
$Zip –ry 输出文件 输入文件 将输入文件压缩为输出文件
重签步骤
说在前面的一些注意事项,因为刚开始接触逆向,所以现在pp助手下载越狱的ipa包。越狱的ipa包是非加密包,可以通过几项操作查询到该ipa包是否加密
以下我们用微信举例:
1、下载越狱版WeChat ipa包,解压后,得到WeChat.app,右键显示包内容,打开iterm2,cd到该目录下。
2、
$ otool -l WeChat | grep cry //otool查询WeChat文件信息,然后管道输出以cry开头的信息.cryptid 0 // 1代表加密算法, 0代表未加密ps:如果cryptid 1 ,证明app是经过appStore加密处理过的。此加密是对称加密,因为数据量过大,之前我们说过非对称加密适合小型数据加密。那么什么时候解密呢?是手机安装的时候对app解密,还是在运行的时候解密呢?答案是运行的时候解密,所以在appStore上下载的app,我们每次运行的时候,都会进行解密。
3、在该文件夹下删除插件和带有插件的.app包(Watch\Plugins如果有就删除)
4、在显示包内容文件夹对Frameworks文件夹下的库进行重签名
$ codesign -fs "iPhone Developer:XXX(123A456B)" abc.framework //强制替换签名,这里强调一下,如果存在多个.framework都要依次强制替换签名。5、包内容下,有个叫WeChat的可执行文件,该文件图标为白色则是无执行权限,黑色则是有可执行权限。
$ chomd +x 可执行文件 //给文件添加权限6、本地新建工程,(一定要是同名工程,避免在包内容文件夹下的可执行文件冲突,同时也是为了方便),这里新建工程是为了得到描述文件,描述文件不可生成,只能去请求,把新建项目在真机跑一遍,保证真机已信任该描述文件。
7、打开该新建工程,打开包内容,复制描述文件,然后粘贴到微信的包内容下
7、替换BundleID,在微信(WeChat.app)的包内容文件夹下找到info.plist文件,替换成新建工程的BundleID。
8、打开新建工程的描述文件、查看描述文件信息
$ cd /$ security cms -Di +描述文件<key>Entitlements</key>
<dict>
<key>xxxxx</key>
<array>xxxxx</array>
<true/>xxxx
<string>xxxx</string>
</dict>复制<dict>下所有内容,然后新建abx.plist文件,粘贴其内容,保证格式正确。
9、通过授权文件(Entilements)重签.app包,注意,上面生成的abx.plist的很重要,描述文件包含其权限文件。
$codesign -fs "iPhone Developer:XXX(123A456B)" --no-strict --entitlements=abx.plist WeChat.app
10、回到Xcode新建项目中,command + shift + R,点击+,安装WeChat.app。这时候会提示,是否要替换掉你刚才新建的项目(因为为了让手机信任描述文件,所以我们之前用真机跑过一次新建项目)。选择替换replace。
11、至此安装成功。回到Xcode中,点击debug,选择attach to process,找到WeChat。点击。直到Xcode进程栏中显示, Running WeChat on XXiPhone。成功附加,就可以lldb调试了。
说在最后面的话。以上知识点仅是重新签名的原理,日后还会更新利用Xcode快速重签名以及shell脚本重签名。
如果我哪里写的不对,还希望你能校正出来,我们共同进步,如果你喜欢此文章,就动一动小手点个赞吧。