前言:内容大幅度参考了网上一些博客 + 亲自实践。若文末忘记注明出处,请见谅,留言修改。
一、为什么制作马甲?
防止app因为违规被苹果下架后”一无所有”。付费视频类,彩票类的app多少都会违反苹果的一些规范有被下架的风险,马甲包可以在app被下架的时候顶上去,那什么情况下会被下架呢?
- 之前审核的时候用到开关,审核过了之后APP的内容和审核时的内容差异较大,苹果复查的时候发现被下架
- 用户举报,被下架
- 竞品方举报,被下架
为主app导入流量,因为马甲包一般和主app用的是同一套后台,用户数据上是互通的,可以通过在马甲包里添加跳转链接等方式引导用户去下载使用主app,往主app里导入流量
广撒网,增加收入。
之前做过付费视频APP,其实那个时候付费视频的黄金期已经快过了,上架的第一个APP通过做aso优化,一天的用户充值可以达到15000左右,但是再想提高充值就很难了(针对我们当时APP的情况)。但是再上架一个功能一样马甲包,通过aso优化很轻松就能做到日充值10000左右,可以脑洞大开一下如果上架100个马甲包会是一种怎样的体验。其实一般的小公司能做上架七八个就很够用了,日流水近10万,很可观了
其实苹果2018年5月份之前对马甲包的审核力度还不是很大,但是七月份之后苹果对马甲包的审核处理力度增大了很多。是因为在这期间世界杯的到来,很多博彩类的app马甲包上架,这种情况也被央视报道,说苹果审核不够严谨,应用市场上充斥着大量的马甲包,导致应用市场混乱,引起了苹果的重视,大量下架了这类app,理所应当马甲包的上架审核也严格了很多。
在这之后马甲包上架就更加困难了,苹果对代码层面的审核也严格了很多,所以马甲包的代码混淆就要比之前力度更大,包括资源文件,费代码,混淆都要尽量多的添加和修改。马甲包的功能也要尽可能的完善丰富起来(功能单一容易被2.1大礼包),而且这些功能不能太大众化,同类产品也很用可能用类似的马甲。
二、解决两个问题
2.1 : 说是违反了一个或多个应用市场规则,一旦跟马甲包、棋牌、彩票等扯上关系(比如关键词含有赌博、竞彩等),都将会上标记,进入机审流程,最后以2.1理由批量拒绝。
4.3 : 应用程序提供了与提交给App Store的其他应用程序相同的特性集;它只是内容或语言不同,这被认为是垃圾邮件的一种形式
2.1 脚本混淆
注意:添加混淆作用的头文件(这个文件名是脚本confuse.sh中定义的)
#import "codeObfuscation.h"
需要自己手动addFileTo…
被拒,苹果新规:不允许使用这种脚本混淆了。违反了2.3.1,说有隐藏功能,base64加密API肯定不能再使用了,苹果都说了,加密特征太过明显。
1 | ### Guideline 2.3.1 - Performance |
2.2 手动混淆
2.2.1 思路
切断当前马甲包与以往马甲包的所有相似性关联;
包括分项细述:
ipa包特征。包括有
- 代码相似性:
- 已有代码的混淆
- 改项目名:参考链接:iOS 最新修改项目名称
- 改文件、类、函数、宏、全局变量名
- 新增属性、属性使用,函数以及函数调用
- 改项目配置、plist文件等
- 添加一些无用的代码, 切记一定要调用, 这是重点;
- 删注释是没用的,因为注释是不会被编译进包里
- 改文件夹或者文件名应该是不太靠谱的,编译的时候会根据路径来引用查找,编译之后应该是根据在包里的相对内存地址来查找类和函数,跟你编译时的文件名称和路径关系应该不大。不过为了方便和代码的统一,更换时可以顺便换了。
- 已有代码的混淆
- 资源相似性:
- 资源改名如图片、音效;
- 适当添加一些无用的资源
- 代码相似性:
开发者帐号:两个马甲包不要关联到同一个开发者帐号的信息;比如打包时关联。
打包电脑:有条件的最好用不同的MAC来打包(每台MAC上最好打包马甲包不要超过5个)
上传IP:上传马甲包时,IP不要跟其他马甲包的IP相同
材料相似:
- ituns后台材料如宣传图,icon,版权人不要出现相同;
- 应用内部UI最好也做调整,规避人工4.3问题。
修改名称时,不要生成随机的md5编码数据格式串的名字,不管是代码还是图片资源,会被苹果认定在刻意隐藏一些功能。
2.2.2 KLGenerateSpamCode
KLGenerateSpamCode 是一个应对苹果对重复应用的审核(Guideline 4.3 Design Spam)的工具,用于避免苹果机审检测概率。
主要功能有:
- 修改工程名
- 修改类名前缀
- 扫描工程中的代码,生成同等数量的 Category 文件,文件中及是同等方法数量的垃圾代码。
- 修改 xxx.xcassets 文件夹中的 png 资源文件名。
- 删除代码中的所有注释和空行(这个貌似没什么必要)。
三、审核流程
3.1 机审
- APP工程重命名
- 文件夹名、文件名重命名:类前缀
- API(方法名、属性):方法名前缀
- 添加大量的垃圾文件(只添加,不引用好像也不行,可以创建一些view/model 不添加显示)
- 往之前的代码中添加废代码,进行混淆(记住添加注释是没有用的,)
- 资源文件的属性进行修改,就是md5编码与之前的资源文件不同(其实很简单,让ui把素材放入ps中再重新导出就可以了)
由此可见:+类前缀、方法名前缀是有多重要…
3.2 人审
- UI界面尽量跟之前有大的区别(这里可以做开关)
- 修改截图,icon,logo,ui,ue,url,界面风格,配色
- 马甲包功能不能太简单容易被苹果送上2.1大礼包
说起来简单:就是代码尽量多的混淆,跟之前包的代码有大的区别。马甲包内容尽量与众不同,功能尽量完善
做起来难:做一个完美的马甲包其实跟做了一个新的App差不多了
3.3 审核被拒处理
第一种机器审核(主要是App代码上、App相关资料方面)
被拒信息一般都是:
1 | Guideline4.3 - Design - Spam(找技术改代码) |
这种主要是对App进行扫描,就和我们毕业论文查重一样,针对关键性信息进行匹配,当这个匹配度超过一定的比例,苹果就会认为重复应用。
在代码层级上来查,现在苹果应该是已经达到全面扫描二进制文件,从中提取技术特征,有种查杀病毒的赶脚。比较明显的就是现在游戏App如果接入了某宝或者某信的支付SDK,那么这种包体必定会被拒,这就是苹果预先对一些带有第三方支付的sdk采集技术特征,然后机器扫描你是否接入了这个SDK。
如果是资料的话,无非是苹果的两个开发者后台(http://developer.apple.com/和http://itunesconnect.apple.com/)上的信息,这种和代码层上排重差不多,同样是提取特征值。
具体是上面那种原因被拒,根据我上包的经验来看,如果是从提交审核到拒审的时间间隔较短,那么很大可能就是资料上的重复导致。这种情况下,我们需要对我们的资料进行排查了。如果间隔时间较长,那么这种就一定是代码的问题,我们就需要在对代码进行混淆、垃圾代码等操作,反正必须改变特征比例。
第二种人工审核(对APP的内容、功能进行核验,防止APP有bug,防止APP模仿其他应用,内容与其他APP重复)
被拒信息一般都是
1 | Guideline4.3 - Design - Spam (改UI) |
这种在我看来,就是界面、功能、app名称等,和其他的App太相似了,审核人员一看就觉得是个马甲包;另外一种就是审核人员可能只是怀疑,这种我们就稍微进行假页面的添加、修改下前期的UI界面,如果这种还被审核人员查到了,就需要申诉,说明我们不一样。
第三种 名字等相似度过高
名字相似度太高,很多产品或运营同学经常是这个账号被拒太多次之后,就转移到另一个账号去上,同时又没有将原来账号里的APP作废,这样就导致4.3问题的出现。要记得,如果是要重新在其他账号上架,一定要关注名字、icon以及代码的问题。
关于审核时间**:**
- 只要出现4.3或2.1 全都出现了审核延迟,大概7-10天左右再会审核的。所以花了这么长时间,而创建了新的应用,就不会延时。基本上当天晚上就会审(周未除外)
关于应用相似度
- 应用全是做电商类的,原生代码都是封装了第三方的,也都一样,因为是外包公司,底层都一样,一个框架开发出来的。前端UI及JS方面。50%差不多,每款应用都有进行了修改,一般改动的是30%-50%。
其它说明
- 我们的应用也不属于马甲包吧,外包公司,制定了一套模块或是封装了一些代码,拿来重用,界面部分都是定制的。苹果要死认定是我是重复应用,我这也是百口莫辨,无奈只有不断提交上次,不断尝试。 实在上架不了,技术也要另寻高就了。为了糊口也没有办法。
结论:
旧应用进行更新上架,两次是100%一晚通过, 新应用,只要当前账户有被拒了4.3 再创建了新的,也会被拒4.3。比较危险的情况是:一个开发者账号下,存在过一直因为4.3的原因审核被拒,再在这个账号上提交马甲包,很容易被推迟审核或则再次因为4.3被拒,最好放弃这个账号,采用新账号去提交审核。
四、App配置多个马甲包的环境
在一个工程中,动态配置马甲包的bundle id、appicon、lanuchImage等:iOS app配置多环境变量和制作马甲包
附一篇实操文章
功能已经过时,但思路挺全面的
1. 马甲包
1.1 什么是马甲包?
马甲包是利用 App store 的规则漏洞,通过技术手段,多次上架同一款产品的方法。马甲包和主产品包拥有基本一致的内容和功能,项目代码基本都是完全复用的,除了图标,应用名称,包名等不一致,其他基本一致。
1.2 为什么做马甲包,以及马甲包的好处
AB 测试
可以测试跨度大的新功能,好的功能就在主包上迭代,不好的也无所谓,不影响主包的使用体验,避免用户流失。导流
主包和马甲包同属一个平台,用户信息可以共享;通过弹窗,广告,Push等引导用户到App Store下载主App;有一部份App接了网盟相互导流。增加关键词覆盖
App Store关键词长度上限是100个字符,据了解人为正常优化的极限是关键词覆盖数在4000左右,那些覆盖数在8000+的都是利用了苹果漏洞。所以,多做一个马甲,也就意味着覆盖的关键词可以更多。刷榜
积分墙、真机、机刷等。用马甲包来刷排名,抵抗主包风险。
1.3 马甲包制作注意事项
二进制不同
应用名称,图标,包名,工程名,打包电脑,代码,静态资源等的修改。差异化
整体UI,产品功能,页面布局等的修改
1.4 实践
KLGenerateSpamCode 是一个应对苹果对重复应用的审核(Guideline 4.3 Design Spam)的工具,用于避免苹果机审检测概率。
主要功能有:
- 修改工程名
- 修改类名前缀
- 扫描工程中的代码,生成同等数量的 Category 文件,文件中及是同等方法数量的垃圾代码。
- 修改 xxx.xcassets 文件夹中的 png 资源文件名。
- 删除代码中的所有注释和空行。
示例:
1 | # 1. 项目名地址,注意不是项目文件夹地址 |
修改工程名后,如果包含 pod,需要到文件夹下重新执行 pod update
1.5 优化图片大小,修改图片 hash 值
-
mac 下无损压缩图片工具,将包含图片的文件夹拖入工具,会自动扫描文件夹下的所有文件,自动选择最优算法进行优化。一般第一次优化项目时,会有几M到10几M的优化效果。
-
ImageMagick: 是一款创建、编辑、合成,转换图像的命令行工具。
通过
brew
安装imagemagick
1
brew install imagemagick
压缩文件夹下所有 png 文件,会修改 hash 值
1
find . -iname "*.png" -exec echo {} \; -exec convert {} {} \;
更多
imagemagick
命令以及使用方法
图像处理 - ImageMagick 简单介绍与案例
2. 逆向基础,以及为什么要做混淆
当我们用 Xcode 构建一个程序的过程时,编译器会把源文件 (.m 和 .h) 文件转换为一个可执行文件。这个可执行文件中包含的字节码会将被 CPU 执行,虽然不能直接从这些字节码中查看我们的核心代码,但是黑客可以通过一些反汇编的逆向工具来分析我们的程序,找到漏洞进行破解。
可执行文件格式
EXE Windows
下可直接执行的文件扩展名
ELF Linux
下的可执行文件
Mach-O MacOS/iOS
下主要的可执行文件
2.1 Mach 与 Mach-O
Mac 是苹果电脑 Macintosh 的简称,而 Mach 则是一种操作系统内核。Mach 内核被 NeXT 公司的NeXTSTEP 操作系统使用。在Mach上,一种可执行的文件格是就是 Mach-O(Mach Object file format)。1996年,乔布斯将 NeXTSTEP 带回苹果,成为了OS X的内核基础。所以虽然 MacOS X 是 Unix 的“后代”,但所主要支持的可执行文件格式是 Mach-O。
2.2 iOS 可执行文件
通常我们通过 Xcode 打包或者从应用商店下载的 APP 都是 ipa
包(iPhone Application)。这是一个变相的 zip 压缩包,可以通过 unzip
命令进行解压。
解压之后,会有一个 Payload 目录,而 Payload 里则是一个 .app 文件,而这个实际上又是一个目录,或者说是一个完整的 App Bundle。
在这个目录中,里面体积最大的文件通常就是和 ipa 包同名的一个二进制文件。通过 file
命令可以查看该文件的类型
1 | xx: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64] |
这里可以看出,这是一个支持 armv7 和 armv7s 两种处理器架构的通用程序包,里面包含的两部分都是 Mach-O 格式。
i386 模拟器32位处理器
x86_64 模拟器64位处理器
armv7,armv7s 真机32位处理器
arm64 真机64位处理器
Mach-O 的文件结构:
从这张图上来看,Mach-O文件的数据主体可分为三大部分,分别是头部(Header)、加载命令(Load commands)、和最终的数据(Data)。
2.3 class-dump
class-dump 是一个利用 Objective-C 语言的 runtime 特性,将存储在 Mach-O 文件结构里 data 部分的类属性和方法等信息提取出来,并生成对应的 .h 文件的工具。注意: 必须是脱壳后的可执行文件。(比如通过越狱手机或者第三方应用下载渠道)
2.4 安装使用
在 class-dump 官网下载 dmg,将 dmg 里面的 class-dump
拷贝到 /usr/local/bin
文件夹下,然后就可以在终端中使用 class-dump
命令了。
简单使用:
1 | class-dump -H [需要被导出的 Mach-O 文件路径] -o [头文件输出目录地址] |
也可以可以查看导出后的头文件目录:
2.5 hopper
Hopper 是一种适用于 OS X 和 Linux 的逆向工程工具,可以用于反汇编、反编译和调试 32位/64位英特尔处理器的 Mac、Linux、Windows 和 iOS 可执行程序。
将 Mach-O 文件拖入 hopper 可以查看。
通过以上的方式,别人可以对照应用的功能来分析代码逻辑,从而进行针对性的破解。所以对项目的核心的代码进行混淆就是非常有必要的了。
3. 代码混淆
常规的混淆思路:
- 花代码花指令,即随意往程序中加入迷惑人的代码指令
- 易读字符替换
防止被 class-dump 后,被人分析核心代码逻辑。可以对关键,已读的字符串进行替换,比如 ad
, vip
等关键词。
3.1 替换字符串混淆
但是我们又不想替换成不想关的字符串后给自己调试带来麻烦,这里我们可以使用 HSKConfuse 的 shell 脚本,通过在Build Phrase 中设定在编译之前进行方法名的字符串替换,从而在不影响自己编写代码的基础上,对编译后的二进制包进行混淆。
首先在项目中新建文件:
1 | confuse.sh: 存放混淆的脚本 |
confuse.sh
1 | #!/usr/bin/env bash |
以上的 shell 脚本运行后会自动获取 .h
, m
文件中以 vhl_
开头的方法写到到该文件。如果需要自定义的话,可以不执行以上那句命令,然后换成自己的规则写入 func.list 中。例如:
1 | vhl_isVIP |
然后在 Build Phases
中,左上角加号添加 run script
填入地址
3.2 查看编译结果
成功编译后,会在指定目录下生成一个 codeObfuscation.h
文件。这里可以看到,在编译过程中会执行 shell 脚本,对相关字符串进行替换
添加 .pch
文件,并在 Build Setttings
> Prefix Header
中链接该 .pch
文件,在 .pch
文件中导入 codeObfuscation.h
,此时项目中指定的方法都被替换成了codeObfuscation.h
中的宏定义。
运行成功后将 Products 中的二进制文件拖入到 hopper 中查看
此时,方法已经被混淆了。
注意:这个不要大面积的使用,会有被审核拒绝的风险,拒绝原因是说你程序里面可能包含有隐藏功能,因为 apple 无法从这些混淆后的方法获取到有用的信息。
4. 编译混淆
以上我们虽然对关键字符串进行了混淆,但是实际代码的执行逻辑等并没有改变。黑客仍然可以通过分析代码逻辑或者伪代码来寻找程序的漏洞。那有没有可能改变编译后的代码逻辑,从而让别人无法分析我们的程序呢。
4.1 iOS 是如何编译的
Objective C采用 Clang 作为前端,而 Swift 则采用 swift() 作为前端,二者都是用 LLVM(Low level vritual machine) 作为编译器后端。
编译命令地址
1 | # Objective-C |
Xcode 编译过程:
4.2 编译器
4.2.1 相关名词
GCC:(GNU Compiler Collection)缩写,一个编程语言编译器,是GNU(自由软件理事会)的关键部分。也是GNU工具链的一部分。GCC常被认为是跨平台编译器的事实标准,特别是它的C语言编译器。GCC原本只能处理C语言。但是面对Clang的竞争,很快作出了扩展,现在已经可以处理C++,Fortran、Pascal、Object-C、Java、Ada,以及Go语言。许多操作系统,包括许多Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。MacOSX也是采用这个编译器。
LLVM:是Low Level Virtual Machine的简称。这个库提供了与编译器相关的支持,能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。可以作为多种语言编译器的后台来使用。
Clang:Clang 是 LLVM 的子项目,是 C,C++ 和 Objective-C 编译器,目的是提供惊人的快速编译,比 GCC 快3倍,其中的 clang static analyzer 主要是进行语法分析,语义分析和生成中间代码,当然这个过程会对代码进行检查,出错的和需要警告的会标注出来。
前端编译器:编译器前端的任务是进行:语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。
- 后端编译器:编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化。iOS的编译过程,后端的处理如下
LVVM 优化器会进行 BitCode 的生成,链接期优化等等。
LLVM机器码生成器会针对不同的架构,比如arm64等生成不同的机器码。
2000年,伊利诺伊大学厄巴纳-香槟分校(University of Illinois at Urbana-Champaign 简称UIUC)这所享有世界声望的一流公立研究型大学的 Chris Lattner(他的 twitter @clattner_llvm ) 开发了一个叫作 Low Level Virtual Machine 的编译器开发工具套件,后来涉及范围越来越大,可以用于常规编译器,JIT编译器,汇编器,调试器,静态分析工具等一系列跟编程语言相关的工作,于是就把简称 LLVM 这个简称作为了正式的名字。Chris Lattner 后来又开发了 Clang,使得 LLVM 直接挑战 GCC 的地位。2012年,LLVM 获得美国计算机学会 ACM 的软件系统大奖,和 UNIX,WWW,TCP/IP,Tex,JAVA 等齐名。
Chris Lattner 生于 1978 年,2005年加入苹果,将苹果使用的 GCC 全面转为 LLVM。2010年开始主导开发 Swift 语言。
iOS 开发中 Objective-C 是 Clang / LLVM 来编译的。
4.3 Hikari
Hikari 是一个基于 Obfuscator-LLVM 对 Xcode9的适配。
OLLVM 是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对 LLVM 的代码混淆工具,以增加对逆向工程的难度。目前,OLLVM已经支持LLVM-4.0版本。
4.3.1 安装
下载 github 提供的 pkg 安装文件并双击安装
1 | https://github.com/HikariObfuscator/Hikari/releases |
然后重启 Xcode 就能看到已经有 Kikari 编译工具
4.3.2 使用
Xcode
->Toolchains
->Hikari
将混淆工具和项目关联- 将所有与要运行的 target 相关的 target(包括pod进来的库)
Enable Index-While-Building
的值改为 NO。 Optimization Level
的值设置为None[-O0]
- 在
Build Settings
->Other C Flags
中加入混淆标记
1 | -mllvm -enable-bcfobf 启用伪控制流 |
重新编译就会使用 Hikari 在编译器后端对项目进行编译了。
将编译后的二进制文件拖入 hopper 中进行对比
发现代码已经被混淆过了。
最新的 Xcode10 通过非官方默认的 Toolchains 编译后的的 ipa 是拒绝提交审核的。
总结
以上是对 iOS 下马甲包,代码混淆,编译混淆的一些学习实践,实际使用中需要根据自己的实际需求进行调整尝试。
demo 地址:iOSObfuscator
加密与破解,编译与反编译永远都是在不停攻防的。没有一堵绝对安全的墙,也没有绝对完美的银弹。只有在开发成本与安全成本中找个一个平衡,才是可持续发展的选择。