如何通过代码混淆绕过苹果机审,解决APP被拒问题

目录

iOS代码混淆

功能分析

实现流程

类名修改

方法名修改

生成垃圾代码

替换png等静态资源MD5

info.plist文件添加垃圾字段

功能分析

实现流程

类名修改

方法名修改

生成垃圾代码

替换png等静态资源MD5

info.plist文件添加垃圾字段

混淆前后对比


iOS代码混淆

目前公司产品线中存在大量功能类似的APP,按照模块化方式开发项目,核心模块业务代码是复用的,使用同一个开发者账号下iOS上架流程中有些APP在苹果机审过程中惨遭被拒的下场,通过更改部分页面UI效果也无济于事,于是采用代码混淆的方式也就是马甲包方案去绕过机审;

功能分析

  • 二进制不同,图标,包名,工程名,代码,静态资源等的修改。
  • 差异化UI风格,产品功能,页面布局等的修改

实现流程

  • 核心模块类名修改

  • 核心方法名修改

  • 加入垃圾代码

  • 替换png等静态资源MD5

  • info.plist文件添加垃圾字段

    image.png

类名修改

  • 遍历查找需要替换的核心模块目录 (主工程\Pods目录)
  • 找到所有需要替换的类名(项目专用前缀),将其存放到数组中
  • 遍历查找整个工程的所有目录,查找所有.h、.m、.xib、.string文件,逐行扫描文件,找到需要替换的类名关键字替换成别的名字前缀
  • 如发现.h、.m、.xib、.string文件的文件名包含需要替换的类名,替换之(xcodeproj工程需要重新引入文件,通过脚本动态引入)
  • 遇到有"+"号的分类文件,筛选出"+"号前面的类名然后替换之
applescript复制代码#遍历查找所有.h、.m、.xib、.strings文件,逐行扫描文件,找到需要替换的类名关键字替换成别的名字前缀
def do_replace_file_name(dir_path,need_name_list)Dir.foreach(dir_path) do |file|if file != "." and file != ".."file_path = dir_path + "/" + fileif File.directory? file_pathdo_replace_file_name(file_path,need_name_list)elseif file.end_with?(".h") or file.end_with?(".m") or file.end_with?(".xib") or file.end_with?(".strings") #只查找.h .m .xib .strings文件批量修改aFile = File.new(file_path, "r")if aFilefile_content = aFile.read()aFile.closelength = need_name_list.length - 1for i in 0..length doneed_name = need_name_list[i]file_content = split_file_content(file_content,need_name)endaFile = File.new(file_path, "w")aFile.syswrite(file_content)aFile.rewindendend#如.h、.m、.xib、.string文件的文件名包含需要替换的类名,替换之if file.include?".h" or file.include?".m" or file.include?".xib" or file.include?".strings"file_suffix = file.split(".")[1]need_name_list.each { |need_name|need_file_name = need_name + "." + file_suffixif file.start_with?(need_file_name)new_file_name = new_file_name(file)new_file_path = dir_path + "/" + new_file_nameFile.rename(file_path, new_file_path) #文件名称替换end}endendendend
end

方法名修改

  • 获取系统文件关键字并缓存,主要是获取iOS SDK中Frameworks所有方法名和参数名作为忽略关键字
  • 遍历查找整个工程的所有.h、.m、.mm文件,提取关键字,主要提取方法名和参数名
  • 将系统关键字、IBAction方法的关键字、属性property的关键字(防止懒加载方法名造成冲突)去除
  • 将剩余的关键字进行方法混淆,混淆方案是将名字用#define宏定义方式替换名称,方法不能替换成随机字符串,这样任然不能通过机审,应替换成规律的单词拼接方法名
  • 将替换后方法名关键字宏名称写入到全局pch文件,xcodeproj动态引入
pgsql复制代码    # 生成混淆文件@staticmethoddef create_confuse_file(output_file, confused_dict):log_info("Start creating confuse file, file fullpath is {0}".format(os.path.realpath(output_file)), 2, True)f = open(output_file, 'wb')f.write(bytes('#ifndef NEED_CONFUSE_h\n', encoding='utf-8'))f.write(bytes('#define NEED_CONFUSE_h\n', encoding='utf-8'))f.write(bytes('// 生成时间: {0}\n'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')), encoding='utf-8'))for (key, value) in confused_dict.items():f.write(bytes('#define {0} {1}\n'.format(key, value), encoding='utf-8'))f.write(bytes('#endif', encoding='utf-8'))f.close()

生成垃圾代码

  • 遍历查找整个工程的所有.m、.mm文件
  • 为避免和混淆后的方法重名,添加垃圾方法的时候使用 随机前缀 + "_" + 规律单词 作为方法名,随意在方法中添加日志代码
  • 在文件结尾@end前插入这些方法
haxe复制代码#oc代码以@end结尾,在其前面添加text
def appendTextToOCFile(file_path, text):with open(file_path, "r") as fileObj:old_text = fileObj.read()fileObj.close()end_mark_index = old_text.rfind("@end")if end_mark_index == -1:print "\t非法的结尾格式: " + file_pathreturnnew_text = old_text[:end_mark_index]new_text = new_text + text + "\n"new_text = new_text + old_text[end_mark_index:]with open(file_path, "w") as fileObj:fileObj.write(new_text)#处理单个OC文件,添加垃圾函数。确保其对应头文件存在于相同目录
def dealWithOCFile(filename, file_path):global target_ios_folder,create_func_min,create_func_max,funcname_setfuncname_set.clear()end_index = file_path.rfind(".")pre_name = file_path[:end_index]header_path = pre_name + ".h"if not os.path.exists(header_path):print "\t相应头文件不存在:" + file_pathreturnnew_func_num = random.randint(create_func_min, create_func_max)print "\t给%s添加%d个方法" %(filename, new_func_num)prefix_list = ['btt_', 'gym_', 'muut_', 'ora_', 'vend_', 'enyt_', 'qotb_', 'ldt_', 'zndy_', 'tim_', 'yar_', 'toa_', 'rewwy_', 'twof_', 'theg_', 'guis_', 'dui_' ]random_index_list = random.sample(range(0,new_func_num), new_func_num)for i in range(new_func_num):prefix = prefix_list[random_index_list[i]]header_text = getOCHeaderFuncText(prefix)# print "add %s to %s" %(header_text, header_path.replace(target_ios_folder, ""))appendTextToOCFile(header_path, header_text + ";\n")funcText = getOCFuncText(header_text)appendTextToOCFile(file_path, funcText)

替换png等静态资源MD5

livecodeserver复制代码        if file_type == ".png":text = "".join(random.sample(string.ascii_letters, 11))elif file_type == ".jpg":text = "".join(random.sample(string.ascii_letters, 20))elif file_type == ".lua":text = "\n--#*" + "".join(random.sample(string.ascii_letters, 10)) + "*#--"else:text = " "*random.randint(1, 100)fileObj.write(text)fileObj.close()

info.plist文件添加垃圾字段

在info.plist中插入规律英文单词(已排除系统专用字段),值为随机字符串

scss复制代码def addPlistField(plist_file):global create_field_min,create_field_max,word_name_listcreate_field_num = random.randint(create_field_min, create_field_max)random_index_list = random.sample(word_name_list, create_field_num)tree = ET.parse(plist_file)root = tree.getroot()root_dict = root.find("dict")for i in range(create_field_num):key_node = ET.SubElement(root_dict,"key")key_node.text = random_index_list[i]string_node = ET.SubElement(root_dict,"string")string_node.text = getOneName()tree.write(plist_file,"UTF-8")

目前公司产品线中存在大量功能类似的APP,按照模块化方式开发项目,核心模块业务代码是复用的,使用同一个开发者账号下iOS上架流程中有些APP在苹果机审过程中惨遭被拒的下场,通过更改部分页面UI效果也无济于事,于是采用代码混淆的方式也就是马甲包方案去绕过机审;

功能分析

  • 二进制不同,图标,包名,工程名,代码,静态资源等的修改。
  • 差异化UI风格,产品功能,页面布局等的修改

实现流程

  • 核心模块类名修改

  • 核心方法名修改

  • 加入垃圾代码

  • 替换png等静态资源MD5

  • info.plist文件添加垃圾字段

    image.png

类名修改

  • 遍历查找需要替换的核心模块目录 (主工程\Pods目录)
  • 找到所有需要替换的类名(项目专用前缀),将其存放到数组中
  • 遍历查找整个工程的所有目录,查找所有.h、.m、.xib、.string文件,逐行扫描文件,找到需要替换的类名关键字替换成别的名字前缀
  • 如发现.h、.m、.xib、.string文件的文件名包含需要替换的类名,替换之(xcodeproj工程需要重新引入文件,通过脚本动态引入)
  • 遇到有"+"号的分类文件,筛选出"+"号前面的类名然后替换之
applescript复制代码#遍历查找所有.h、.m、.xib、.strings文件,逐行扫描文件,找到需要替换的类名关键字替换成别的名字前缀
def do_replace_file_name(dir_path,need_name_list)Dir.foreach(dir_path) do |file|if file != "." and file != ".."file_path = dir_path + "/" + fileif File.directory? file_pathdo_replace_file_name(file_path,need_name_list)elseif file.end_with?(".h") or file.end_with?(".m") or file.end_with?(".xib") or file.end_with?(".strings") #只查找.h .m .xib .strings文件批量修改aFile = File.new(file_path, "r")if aFilefile_content = aFile.read()aFile.closelength = need_name_list.length - 1for i in 0..length doneed_name = need_name_list[i]file_content = split_file_content(file_content,need_name)endaFile = File.new(file_path, "w")aFile.syswrite(file_content)aFile.rewindendend#如.h、.m、.xib、.string文件的文件名包含需要替换的类名,替换之if file.include?".h" or file.include?".m" or file.include?".xib" or file.include?".strings"file_suffix = file.split(".")[1]need_name_list.each { |need_name|need_file_name = need_name + "." + file_suffixif file.start_with?(need_file_name)new_file_name = new_file_name(file)new_file_path = dir_path + "/" + new_file_nameFile.rename(file_path, new_file_path) #文件名称替换end}endendendend
end

方法名修改

  • 获取系统文件关键字并缓存,主要是获取iOS SDK中Frameworks所有方法名和参数名作为忽略关键字
  • 遍历查找整个工程的所有.h、.m、.mm文件,提取关键字,主要提取方法名和参数名
  • 将系统关键字、IBAction方法的关键字、属性property的关键字(防止懒加载方法名造成冲突)去除
  • 将剩余的关键字进行方法混淆,混淆方案是将名字用#define宏定义方式替换名称,方法不能替换成随机字符串,这样任然不能通过机审,应替换成规律的单词拼接方法名
  • 将替换后方法名关键字宏名称写入到全局pch文件,xcodeproj动态引入
pgsql复制代码    # 生成混淆文件@staticmethoddef create_confuse_file(output_file, confused_dict):log_info("Start creating confuse file, file fullpath is {0}".format(os.path.realpath(output_file)), 2, True)f = open(output_file, 'wb')f.write(bytes('#ifndef NEED_CONFUSE_h\n', encoding='utf-8'))f.write(bytes('#define NEED_CONFUSE_h\n', encoding='utf-8'))f.write(bytes('// 生成时间: {0}\n'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')), encoding='utf-8'))for (key, value) in confused_dict.items():f.write(bytes('#define {0} {1}\n'.format(key, value), encoding='utf-8'))f.write(bytes('#endif', encoding='utf-8'))f.close()

生成垃圾代码

  • 遍历查找整个工程的所有.m、.mm文件
  • 为避免和混淆后的方法重名,添加垃圾方法的时候使用 随机前缀 + "_" + 规律单词 作为方法名,随意在方法中添加日志代码
  • 在文件结尾@end前插入这些方法
haxe复制代码#oc代码以@end结尾,在其前面添加text
def appendTextToOCFile(file_path, text):with open(file_path, "r") as fileObj:old_text = fileObj.read()fileObj.close()end_mark_index = old_text.rfind("@end")if end_mark_index == -1:print "\t非法的结尾格式: " + file_pathreturnnew_text = old_text[:end_mark_index]new_text = new_text + text + "\n"new_text = new_text + old_text[end_mark_index:]with open(file_path, "w") as fileObj:fileObj.write(new_text)#处理单个OC文件,添加垃圾函数。确保其对应头文件存在于相同目录
def dealWithOCFile(filename, file_path):global target_ios_folder,create_func_min,create_func_max,funcname_setfuncname_set.clear()end_index = file_path.rfind(".")pre_name = file_path[:end_index]header_path = pre_name + ".h"if not os.path.exists(header_path):print "\t相应头文件不存在:" + file_pathreturnnew_func_num = random.randint(create_func_min, create_func_max)print "\t给%s添加%d个方法" %(filename, new_func_num)prefix_list = ['btt_', 'gym_', 'muut_', 'ora_', 'vend_', 'enyt_', 'qotb_', 'ldt_', 'zndy_', 'tim_', 'yar_', 'toa_', 'rewwy_', 'twof_', 'theg_', 'guis_', 'dui_' ]random_index_list = random.sample(range(0,new_func_num), new_func_num)for i in range(new_func_num):prefix = prefix_list[random_index_list[i]]header_text = getOCHeaderFuncText(prefix)# print "add %s to %s" %(header_text, header_path.replace(target_ios_folder, ""))appendTextToOCFile(header_path, header_text + ";\n")funcText = getOCFuncText(header_text)appendTextToOCFile(file_path, funcText)

替换png等静态资源MD5

livecodeserver复制代码        if file_type == ".png":text = "".join(random.sample(string.ascii_letters, 11))elif file_type == ".jpg":text = "".join(random.sample(string.ascii_letters, 20))elif file_type == ".lua":text = "\n--#*" + "".join(random.sample(string.ascii_letters, 10)) + "*#--"else:text = " "*random.randint(1, 100)fileObj.write(text)fileObj.close()

info.plist文件添加垃圾字段

在info.plist中插入规律英文单词(已排除系统专用字段),值为随机字符串

scss复制代码def addPlistField(plist_file):global create_field_min,create_field_max,word_name_listcreate_field_num = random.randint(create_field_min, create_field_max)random_index_list = random.sample(word_name_list, create_field_num)tree = ET.parse(plist_file)root = tree.getroot()root_dict = root.find("dict")for i in range(create_field_num):key_node = ET.SubElement(root_dict,"key")key_node.text = random_index_list[i]string_node = ET.SubElement(root_dict,"string")string_node.text = getOneName()tree.write(plist_file,"UTF-8")

混淆前后对比

代码混淆前

img

Hopper查看混淆前

img

代码混淆后

img

Hopper查看混淆后

img

假如你不知道如何代码混淆和如何创建文件混淆,你可以参考下面这个教程来使用我们平台代码混淆和文件混淆以及重签名:怎么保护苹果手机移动应用程序ios ipa中的代码 | ipaguard使用教程

Ipa Guard是一款功能强大的ipa混淆工具,不需要ios app源码,直接对ipa文件进行混淆加密。可对IOS ipa 文件的代码,代码库,资源文件等进行混淆保护。 可以根据设置对函数名、变量名、类名等关键代码进行重命名和混淆处理,降低代码的可读性,增加ipa破解反编译难度。可以对图片,资源,配置等进行修改名称,修改md5。只要是ipa都可以,不限制OC,Swift,Flutter,React Native,H5类app。

总结

在移动互联网时代,代码混淆越来越受到开发者的重视。 iOS代码混淆可以提高难度,从而防止应用程序被盗用或反编译,保护开发者的权益。但是同时也带来了一些问题,例如混淆后的函数名可能会影响代码的可维护性。因此,在使用代码混淆时需要进行合理规划。

参考资料

  1. IpaGuard文档 - 代码混淆
  2. iOS代码混淆方案
  3. iOS文件混淆方案
  4. iOS重签名与测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/804895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

南京航空航天大学-考研科目-513测试技术综合 高分整理内容资料-01-单片机原理及应用分层教程-单片机有关常识部分

系列文章目录 高分整理内容资料-01-单片机原理及应用分层教程-单片机有关常识部分 文章目录 系列文章目录前言总结 前言 单片机的基础内容繁杂,有很多同学基础不是很好,对一些细节也没有很好的把握。非常推荐大家去学习一下b站上的哈工大 单片机原理及…

开通抖音小店后下一步要干嘛?这些准备比选品更重要!新手必看!

哈喽~我是电商月月 很多入驻完抖音小店的新手朋友总以为,入驻完抖音小店后,下一步就是去选品 其实并不是!选品确实很重要,但前期这几个细节没做好,是会直接影响店铺的整体发展的 废话不多说,直接分享给你…

Linux入门攻坚——18、SELinux、Bash脚本编程续

SELinux——Secure Enhanced Linux(安全加强的Linux),工作于Linux内核中。 SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。采用委任式存取控制,是在进行程序、文件等细节权…

python批量修改替换cad图纸文本,土木狗可以有

civilpy:python进行AutoCAD绘图的两个库,土木狗可以有3 赞同 0 评论文章​编辑 civilpy:python进行AutoCAD绘图批量打印,土木狗可以有2 赞同 2 评论文章​编辑 # 导入所需库 from pyautocad import Autocad, APoint import ma…

LeetCode 94 二叉树的中序遍历

题目描述 二叉树的中序遍历 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2]示例 2: 输入:root [] 输出:[]示例 3: 输入…

hive管理之ctl方式

hive管理之ctl方式 hivehive --service clictl命令行的命令 #清屏 Ctrl L #或者 ! clear #查看数据仓库中的表 show tabls; #查看数据仓库中的内置函数 show functions;#查看表的结构 desc表名 #查看hdfs上的文件 dfs -ls 目录 #执行操作系统的命令 !命令…

WinAppDriver 自动化测试winform程序

WinAppDriver 自动化测试winform程序 前言 WinAppDriver是Windows系统上的一个应用程序驱动工具,开源免费。与Selenium工具类似,都是用来实现产品UI自动化测试的一个工具。 WinAppDriver运行时对系统是有要求的,只能运行在Windows10或Wind…

2024/4/6—力扣—简化路径

代码实现&#xff1a; // 分割/得到名字 char **split(const char *s, int *returnSize) {int n strlen(s);char **ans (char **)malloc(sizeof(char *) * n);int l 0, r 0, len 0;while (r < n) {while (r < n && s[r] /) {r;}l r;while (r < n &…

Python | 海表面温度(SST) | 长期趋势和异常分析

趋势和异常分析&#xff08;Trend and anomaly)在大气和海洋学研究中被广泛用于探测长期变化。 趋势分析&#xff08;Trend Analysis&#xff09;&#xff1a; 趋势分析是一种用于检测数据随时间的变化趋势的方法。在海洋学和大气学中&#xff0c;常见的趋势分析包括海表面温…

WeTrade众汇账户类型有哪几种?FX110网

WeTrade众汇是一个在线交易平台&#xff0c;允许用户买卖各种金融工具&#xff0c;包括交易外汇、金属、能源、指数、股票和加密货币。 WeTrade众汇不仅提供多种交易市场&#xff0c;还提供多种有竞争力的工具和服务。那么&#xff0c;WeTrade众汇账户类型有哪几种&#xff1f;…

CF938Div3(A-F)

A: 买n个酸奶&#xff0c;一次一瓶a元,一次买两瓶可以优惠价b元,也可以a元,问恰好买n瓶需要多少钱. void solve() {int n, a, b;cin >> n >> a >> b;int ans min(a * n, n / 2 * b n % 2 * a);cout << ans << endl; } B: 给你一个数组,问能…

AWVS/Acunetix Premium V24.3.2403高级版漏洞扫描器

前言 Acunetix Premium 是一种 Web 应用程序安全解决方案&#xff0c;用于管理多个网站、Web 应用程序和 API 的安全。集成功能允许您自动化 DevOps 和问题管理基础架构。 Acunetix Premium&#xff1a;全面的 Web 应用程序安全解决方案 Web 应用程序对于企业和组织与客户、…

Vue 大文件切片上传实现指南包会,含【并发上传切片,断点续传,服务器合并切片,计算文件MD5,上传进度显示,秒传】等功能

Vue 大文件切片上传实现指南 背景 在Web开发中&#xff0c;文件上传是一个常见的功能需求&#xff0c;尤其是当涉及到大文件上传时&#xff0c;为了提高上传的稳定性和效率&#xff0c;文件切片上传技术便显得尤为重要。通过将大文件切分成多个小块&#xff08;切片&#xff0…

【Python 基础知识课程】Python的第一个程序

Python 简介 Python 是一种功能强大且用途广泛的编程语言&#xff0c;广泛用于数据科学、Web 开发、自动化等高需求领域。 幸运的是&#xff0c;对于初学者来说&#xff0c;它也是一种很好的学习语言&#xff0c;因为Python代码更容易阅读和编写。它的简单性使其成为初学者的完…

【Qt】:窗口

窗口 一.概述二.菜单栏1.一个简单的菜单2.添加快捷键3.嵌套子菜单4.添加下划线5.添加图标 三.工具栏1.创建一个简单的工具栏2.设置工具栏的停靠位置 四.状态栏五.浮动窗口 一.概述 Qt窗口是通过QMainWindow类来实现的。 QMainWindow是一个为用户提供主窗口程序的类&#xff0c…

Utilize webcam to capture photo with camera

1. Official Guide& my github Official course my github 2. Overcome Webcam js Error in Chrome: Could not access webcam link 直接把代码拷贝到本机的下述目录下 To ignore Chrome’s secure origin policy, follow these steps. Navigate to chrome://flags/#un…

StarRocks实战——华米科技埋点分析平台建设

目录 前言 一、原有方案及其痛点 二、引入StarRocks 三、方案改造 3.1 架构设计 3.2 数据流程 3.3 性能指标 3.4 改造收益 前言 华米科技是一家基于云的健康服务提供商&#xff0c;每天都会有海量的埋点数据&#xff0c;以往基于HBase建设的埋点计算分析项目往往效率上…

小红书APP闪退,电商ERP系统接口该如何测试呢?

大数据时代&#xff0c; 数据收集不仅是科学研究的基石&#xff0c; 更是企业决策的关键。 然而&#xff0c;如何高效地收集数据 成了摆在我们面前的一项重要任务。 本文将为你揭示&#xff0c; 一系列实时数据采集方法&#xff0c; 助你在信息洪流中&#xff0c; 找到…

OJ 栓奶牛【C】【Python】【二分算法】

题目 算法思路 要求的距离在最近木桩与最远木桩相隔距离到零之间&#xff0c;所以是二分法 先取一个中间值&#xff0c;看按照这个中间值可以栓多少奶牛&#xff0c;再与输入奶牛数比较&#xff0c;如果大于等于&#xff0c;则增大距离&#xff0c;注意这里等于也是增大距离…

苍穹外卖---文件上传-阿里OSS

一&#xff1a;开通阿里云对象存储服务oss,创建bucket&#xff0c;获得密钥 二&#xff1a;在程序中集成上传文件功能 1.连接阿里云OSS对象存储服务器 声明一个配置属性的文件用于传入连接的参数 package com.sky.properties;import lombok.Data; import org.springframewo…