iOS重签名

苹果IPA包的重签名可以解决跟换一个包名、logo和IP地址后进行重新打包的工作,也避免了因为人为原因修改代码后忘记处理而导致打出的包无法使用的问题。目前市面上有的超级app或者蒲公英上宣传的企业签名所用到的就是重签名技术。

iOS签名机制

先来看一下数字签名的图


数字签名

苹果的签名机制如果简化,那也就是数字签名的流程。图的上半部分就是签名的过程,下半部分就是用户安装应用验证的过程。
苹果为了控制应用的安装和发布,除了公私钥对,还增加了Provisioning Profile(包含了APP ID、手机UDID列表、配置的功能权限信息表Entitlements以及证书),验证的流程也增加了好多层级:

  • 先用公钥验证provisioning Profile 的签名和证书的签名;
  • 认证通过后,再使用证书内的公钥验证APP的签名,APP ID和Entitlements验证APP,手机UDID列表验证手机是否包含在列表内;
  • 所有的验证通过后用户才能使用。


    苹果签名

IPA包的分析

IPA包解压后是Payload文件夹,然后显示文件夹内的包内容,可以发现(企业证书打的包)包内有一个_CodeSignature文件夹和.mobileprovision文件还有一些已经加密后的文件。其实_CodeSignature就是APP的签名文件,哪些已经加密的文件中也保存了APP的签名文件。如果有framework,它的文件内容和主文件下的差不多。

重签名

需要使用到的文件:

  • 开发者证书
  • 配置文件(entitlements)
  • Provisioning Profile文件(embedded.mobileprovision)
  • APP

步骤

  1. 找到开发者证书,可以在keychain我的证书中查找,找到证书后右键选择显示简介,拉到最底下选择SHA-1设置为常量,在重签名的时候可以通过这个哈希值找到对应的证书。
CERT_FILE = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1. 使用embedded.mobileprovision文件生成entitlements.plist文件:
def gen_entitlements(out_file_name):
    os.system('security cms -D -i "%s" > entitlement_full.plist ' % (get_mobile_provision_file()))
    os.system('/usr/libexec/PlistBuddy -x -c \'Print:Entitlements\' entitlement_full.plist > "%s" ' % (out_file_name))
  1. 解压APP的IPA包
def unzip_app(original_ipa):
    os.system('unzip -qo ./%s -d ./' % (original_ipa))
    print('unzip_app %s done!' % (original_ipa))
  1. 移除XX.app文件夹下所有_CodeSignature包括frameworks里面的
def del_code_signature():
    os.system("rm -rf ./Payload/iVMS-7880.app/_CodeSignature")
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('rm -rf ./Payload/iVMS-7880.app/"%s"/_CodeSignature' % (file))
    print('del_code_signature done!')
  1. 把准备好的embedded.mobileprovision复制到XX.app文件夹下
def replace_provision_file():
    for file in os.listdir("./"):
        if os.path.splitext(file)[1] == '.mobileprovision':
            os.system('cp "%s" ./Payload/iVMS-7880.app/embedded.mobileprovision' % (file))
  1. 重签名framework
def resign_framework():
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/frameworks/"%s"' % (file)))
            print('resign_framework "%s" done!' % (file))
  1. 重签名app执行文件
def resign_app():
    os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/iVMS-7880'))
    print('resign_app done!')
  1. 压缩Payload文件,重命名压缩文件为XX.ipa
def zip_app(f_ipa):
    os.system('zip -r %s ./Payload' % (f_ipa))
    print('zip_app done!')

到此就会有一个新的IPA包生成了,可以通过手机助手或者上传平台进行手机安装验证。

代码

#!/usr/bin/python
# -*- coding: utf-8 -*- 

import os
import sys
import json

CERT_FILE = '6BF988FC0D4993B3D48810E4D67419A2B1E81DC1'

def get_mobile_provision_file():
    file_path = ""
    for file in os.listdir("./"):
        if os.path.splitext(file)[1] == '.mobileprovision':
            file_path = os.path.join(os.getcwd(),"%s" % (file))
    return file_path

def reset_bundle_identifier(bundle_identifier):
    os.system('/usr/libexec/PlistBuddy -c \'Set:CFBundleIdentifier "%s"\' Payload/iVMS-7880.app/Info.plist' % (bundle_identifier))

def reset_bundle_version(build):
    os.system('/usr/libexec/PlistBuddy -c \'Set:CFBundleVersion "%s"\' Payload/iVMS-7880.app/Info.plist' % (build))

def unzip_app(original_ipa):
    os.system('unzip -qo ./%s -d ./' % (original_ipa))
    print('unzip_app %s done!' % (original_ipa))

def del_code_signature():
    os.system("rm -rf ./Payload/iVMS-7880.app/_CodeSignature")
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('rm -rf ./Payload/iVMS-7880.app/"%s"/_CodeSignature' % (file))
    print('del_code_signature done!')

def resign_app():
    os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/iVMS-7880'))
    print('resign_app done!')

def resign_framework():
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/frameworks/"%s"' % (file)))
            print('resign_framework "%s" done!' % (file))

def zip_app(f_ipa):
    os.system('zip -r %s ./Payload' % (f_ipa))
    print('zip_app done!')

def del_payload():
    os.system('rm -r ./Payload')

def gen_entitlements(out_file_name):
    os.system('security cms -D -i "%s" > entitlement_full.plist ' % (get_mobile_provision_file()))
    os.system('/usr/libexec/PlistBuddy -x -c \'Print:Entitlements\' entitlement_full.plist > "%s" ' % (out_file_name))


def rep_emb_file():
    os.system('cp "%s" ./Payload/iVMS-7880/embedded.mobileprovision' % (get_mobile_provision_file()))

def replace_provision_file():
    for file in os.listdir("./"):
        if os.path.splitext(file)[1] == '.mobileprovision':
            os.system('cp "%s" ./Payload/iVMS-7880.app/embedded.mobileprovision' % (file))


if __name__ == '__main__':
    gen_entitlements("entitlement.plist")

    original_ipa = input("original_ipa:")
    unzip_app(original_ipa)

    bundle_identifier = input("bundle_identifier:")
    reset_bundle_identifier(bundle_identifier)

    build = input("build_version:")
    reset_bundle_version(build)

    del_code_signature()
    replace_provision_file()
    resign_framework()
    resign_app()
    newName = input("newName:")
    zip_app(newName)
    del_payload()

复制代码存储为python文件,之前准备的文件和该文件需要在同一个根目录下,然后在终端中执行该文件,输入对应信息后就可以得到新的IPA包。输入的信息都为字符串需要用引号,否则将会没有效果。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • 最近有朋友需要帮忙用公司企业证书打包企业内侧应用,经过本人搜集、采坑,目前最简单、可靠地重签名解决方案(企业证书可...
    歌白尼阅读 9,159评论 17 16
  • 最近在工作中遇到了一些ipa重签名相关的内容,就在网上查了一些资料,做了以下整理与大家一起分享。 现在主流的重签名...
    醉雨清风阅读 6,765评论 14 32
  • 一.理解iOS签名机制 网上有很多资料,这里不展开细说,重点参考这三篇文章: https://www.objccn...
    huig游影阅读 1,045评论 0 1
  • 一.理解iOS签名机制 网上有很多资料,这里不展开细说,重点参考这三篇文章: https://www.objccn...
    huig游影阅读 1,221评论 0 0
  • 中秋之夜,望着圆圆的月亮,即使远在他乡异客,也会感到节日的欢乐。 每年到了八月十五那天,皎洁的月光像在地上...
    冯瑛蕊阅读 524评论 0 0