----------------------------------------分割線----------------------------------------git
今天主要想說的是iOS的代碼混淆,爲何想作代碼混淆?爲了APP的安全,爲了防止別人破殼輕易破解咱們代碼;還有就是作馬甲包了,咱們知道馬甲包的市場需求很大,可是不能花費過多的精力在開發上,畢竟只是個馬甲,不必花費太多的成本!github
網上搜了一下,開源免費的混淆都在轉載念茜大姐大的sh腳本的混淆方法,或者在念茜的腳本基礎上二次開發,你們去看過就知道念茜的這篇博客是在14年寫的,那時我剛作iOS沒多久🤗,並且那時候中國區審覈尚未那麼嚴格,若果你如今還使用那種方法進行混淆,你確定會收到蘋果的2.3.1 大禮包🤓,因此咱們仍是探索別的混淆方法吧,不要再挖墳了!swift
ZFJObsLib主要是經過Python寫的混淆工具,具體功能有方法混淆、屬性混淆、類名混淆、添加垃圾代碼、自動建立垃圾類、刪除註釋、修改資源文件Hash值、加密字符串、翻新資源名、模擬人工混淆、混淆文件名、混淆文件目錄、混淆詞庫、混淆日誌、映射列表、敏感詞過濾、圖片壓縮、爬蟲服務、修改項目名、翻新項目UUID,具體的以下:api
ZFJObsLib混淆工具全面支持OC項目工程、swift項目和u3d項目!!!👍👍👍安全
Gitee:gitee.com/zfj1128/ZFJ…bash
GitHub:github.com/zfjsyqk/ZFJ…app
連接:pan.baidu.com/s/1pqUkgU8Y… 密碼:9sll工具
ZFJObsLib軟件的主要界面以下:優化
import addRubbishCode as addCode
import cunfusionObjName as conObjN
import confusionFun as conFunc
import cunfusionProperty as conPro
import confusionLog as conLog
import deleteNotes as delNot
import updateSourceHash as updHash
import encryptString as encStr
import sourceName as soName
import missFolder
from singletonModel import ZFJPersoninfo
def start_fun(file_dir, funMap = {}):
personinfo = ZFJPersoninfo()
personinfo.isMissing = True
if len(file_dir) == 0:
return
if int(funMap['property']) > 0:
# 混淆屬性
conLog.tips('*' * 30 + 'Fun:開始混淆屬性' + '*' * 30)
conPro.startConfusionPro(file_dir)
if int(funMap['funName']) > 0:
# 混淆方法
conLog.tips('*' * 30 + 'Fun:開始混淆方法' + '*' * 30)
conFunc.startConfusionFun(file_dir)
if int(funMap['objName']) > 0:
# 混淆類名
conLog.tips('*' * 30 + 'Fun:開始混淆類名' + '*' * 30)
prefix = funMap['funNamePrefix'].replace('0', '') #-添加類名前綴
personinfo.prefix = prefix #前綴存到單利裏面
fixObjName = funMap['fixObjName'] #-自動修復過濾文件夾中引用的類名
conObjN.startObfuscatedObjName(file_dir, prefix)
if int(funMap['souHashKey']) > 0:
# 修改資源文件的hash值
conLog.tips('*' * 30 + 'Fun:修改資源HASH值' + '*' * 30)
updHash.startUpdateSourceHash(file_dir)
if int(funMap['upSouName']) > 0:
# 翻新資源文件名
conLog.tips('*' * 30 + 'Fun:翻新資源文件名' + '*' * 30)
soName.startSourceName(file_dir)
if int(funMap['encryStr']) > 0:
# 加密明文字符串
conLog.tips('*' * 30 + 'Fun:加密明文字符串' + '*' * 30)
encStr.startEncryptStr(file_dir)
if int(funMap['rubbishCode']) > 0:
# 垃圾代碼
conLog.tips('*' * 30 + 'Fun:添加垃圾代碼' + '*' * 30)
amount = int(funMap['rubbishLine']) # -添加行數
addCode.startAddRubbishCode(file_dir, amount)
if int(funMap['deleteNotes']) > 0:
# 混淆或者刪除註釋
conLog.tips('*' * 30 + 'Fun:開始刪除註釋' + '*' * 30)
delNot.startDeleteNotes(file_dir)
if int(funMap['missFolder']) > 0:
# 混淆文件夾名
conLog.tips('*' * 30 + 'Fun:開始混淆文件夾名' + '*' * 30)
missFolder.startMissFolder(file_dir)
conLog.tips('*' * 30 + 'End:混淆結束' + '*' * 30)
personinfo.isMissing = False
複製代碼
混淆的部分日誌,混淆的時候回經過import logging自動生成混淆日誌《ZFJ混淆日誌.log》,便於開發者修改部分報錯: ui
咱們在混淆的時候,不必所有進行混淆,特別是第三方庫,或者Pods管理的第三方庫;畢竟混淆的越多問題也就越多,因此我添加了混淆忽略文件📂,以下圖:
import confusionLog as conLog
ignore_Files = ['/Pods/', '/Vendor/', '/LIB/', '/Util/']
conLog.tips('已忽略的路徑 === ' + str(ignore_Files))
# 判斷是不是忽略的文件夾
def isIgnoreFiles(tmp_path):
# if '+' in tmp_path:
# return True
for item in ignore_Files:
if item in tmp_path:
return True
return False
複製代碼
✍️✍️✍️ZFJObsLib有不少功能,你們能夠根據本身的實際使用狀況自行選擇!✍️✍️✍️
垃圾代碼的調用與實現
詳細請看:👉《Python-ZFJObsLib完美生成iOS垃圾代碼》zfj1128.blog.csdn.net/article/det…
針對項目中的資源文件,咱們能夠經過修改Hash的方式來進行混淆,運行以下:
🔆Tips:已忽略的路徑 === ['/Pods/', '/Vendor/', '/LIB/', '/Util/']
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/MainWeb_Back_Icon.imageset/fanhui-4.png
🎉Infor:[UPdHash Meg] Old:dd03889c2e8647b9377d08775333557ff11425dd<->New:4a72c7b640882ae436b18868aa021331169db3fa
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/60.png
🎉Infor:[UPdHash Meg] Old:2d73347848d7168c09c48efe28a7ac5a9ec7411b<->New:551483123b5cc2c4c5ff2f5bf876db0d075261a1
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/58.png
🎉Infor:[UPdHash Meg] Old:c0c671fe3707bca8c5accdcadd8aa9f4f1f2726c<->New:d022db1c1f99c263b69bc09c09bc52dd1fa97fb5
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/120-1.png
🎉Infor:[UPdHash Meg] Old:5a6a7ec42d7489be18888828c1a9caba0da688ca<->New:8bbddfbbbed9023e4537e9e6caeed79c88ef8955
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/120.png
🎉Infor:[UPdHash Meg] Old:5a6a7ec42d7489be18888828c1a9caba0da688ca<->New:dcc4b47092bca1d6a6bb6d7bd671a0ef7ce2f4da
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/180.png
🎉Infor:[UPdHash Meg] Old:fee9220dbba52040517a0f77ffe8335e9300a64b<->New:d28a9118e1cf4a2ce9fc2805184ad42e20500c95
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/GUEG_ICON.png
🎉Infor:[UPdHash Meg] Old:07ed6c66ec7d5550bfa1e32b4848687417027c90<->New:fb780d87591cc86dd0fd24cdfa41e76a091ad657
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/80.png
🎉Infor:[UPdHash Meg] Old:ca3b3f61fc4c391515fe895d81360d15ec598049<->New:769ebf182fbb3a3fd69c46c3a595c1669c505f63
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/40.png
🎉Infor:[UPdHash Meg] Old:1bb7908a2ba1295fa69ad476a81003f2f413a3a8<->New:10793e67b27cdf5ad1ee4b9d37aecc62074b8ffc
🎉Infor:[UPdHash OK] /Users/zhangfujie/Desktop/Obfuscated/GUEG_MJ/GUEG/GUEG/Assets.xcassets/AppIcon.appiconset/87.png
......等等......
複製代碼
編譯前的代碼以下:
- (void)uiConfig{
ZFJView *zfjView = [[ZFJView alloc] initWithZFJ:@"ZFJ1128"];
zfjView.backgroundColor = [UIColor yellowColor];
zfjView.frame = CGRectMake(100, 100, 150, 150);
[zfjView setZFJViewTitleLab];
[zfjView setZFJViewTitleLab:@"aaaaaa"];
[zfjView setZFJViewTitleLab:@"aaa" efg:@"dscvdscsd"];
[zfjView setZFJViewTitleLab:@"ddscvsdv" efg:@"cdsvdfbdf" hijk:@"cdvsvbdsbdfgnfdhnhdg"];
[self.view addSubview:zfjView];
[ZFJView svdsvfdsvfdvbzdfb];
}
複製代碼
編譯後的代碼以下:
- (void)uiConfig{
ZFJView *zfjView = [[ZFJView alloc] initWithZFJ:ZFJ_NSSTRING(((char []) {240, 236, 224, 155, 155, 152, 146, 0}))];
zfjView.backgroundColor = [UIColor yellowColor];
zfjView.frame = CGRectMake(100, 100, 150, 150);
[zfjView setZFJViewTitleLab];
[zfjView setZFJViewTitleLab:ZFJ_NSSTRING(((char []) {203, 203, 203, 203, 203, 203, 0}))];
[zfjView setZFJViewTitleLab:ZFJ_NSSTRING(((char []) {203, 203, 203, 0})) efg:ZFJ_NSSTRING(((char []) {206, 217, 201, 220, 206, 217, 201, 217, 206, 0}))];
[zfjView setZFJViewTitleLab:ZFJ_NSSTRING(((char []) {206, 206, 217, 201, 220, 217, 206, 220, 0})) efg:ZFJ_NSSTRING(((char []) {201, 206, 217, 220, 206, 204, 200, 206, 204, 0})) hijk:ZFJ_NSSTRING(((char []) {201, 206, 220, 217, 220, 200, 206, 217, 200, 206, 204, 205, 196, 204, 206, 194, 196, 194, 206, 205, 0}))];
[self.view addSubview:zfjView];
[ZFJView svdsvfdsvfdvbzdfb];
}
複製代碼
加密混淆反編譯先後Hopper對好比下:
咱們能夠看到再經過Hopper看不到硬編碼了!👍👍👍找到工程中的圖片資源並翻新,而後自動替換代碼中的引用。
ZFJObsLib集成圖片壓縮工具,支持一鍵生成iOS開發三套圖標,也支持自定義壓縮尺寸,還能夠移除Alpha通道,轉成RGB圖片模式;實現邏輯可參考:zfj1128.blog.csdn.net/article/det… 具體以下圖:
教學視頻
資源爬取:連接:pan.baidu.com/s/1xa9ruF_h… 密碼:1zpg
節點爬取:連接:pan.baidu.com/s/1ebWWYtjo… 密碼:cosa
使用截圖
說明:設置混淆前綴,必定要點擊保存哦!!!✌️✌️✌️
在iOS項目開發的過程當中,若是版本迭代開發的時間比較長,那麼在不少版本開發之後或者說有多人開發參與之後,工程中不免有一些垃圾資源,未被使用卻佔據着api包的大小!
這裏我經過Python腳原本查找項目中未被使用的圖片、音頻、視頻資源,而後刪除掉;以達到減少APP包大小的目的!
詳細請看:👉《Python-一鍵查找iOS項目中未使用的圖片、音頻、視頻資源》zfj1128.blog.csdn.net/article/det…
ZFJObsLib自帶二十多萬的字典詞庫,因此不用擔憂代碼重複問題;若是你以爲取得詞庫單詞目標性不強或者無心思,你能夠自定義詞庫,自定義詞庫解學視頻以下:
由於不知道Xcode的UUID詳細生成規則,此項功能旨在從其餘項目中讀取UUID,方便建立垃圾類和修改UUID使用;在混淆的過程當中若是使用了建立垃圾類和修改UUID的功能,建議最好使用此功能讀取一個其餘項目的UUID,以達到更真實的目的;最好的使用方法是用Xcode新建一個iOS項目,而後本身隨便建立幾個類或者試圖,接着再此功能讀取該新建項目的Xcodeproj來獲取UUID;若是在混淆過程當中使用到的UUID數量大於讀取的UUID數量,則會先緊着讀取的UUID使用,當讀取的UUID使用完之後,ZFJObsLib會自動按照本身的規則建立UUID(不推薦)!
👉建議本身用Xcode建立一個項目,多建立幾個類或者試圖進行讀取!👈
翻新UUID效果對比圖
這個項目是某位羣友提供的swift項目!
做者:ZFJ_張福傑
來源:CSDN
原文:zfj1128.blog.csdn.net/article/det… (第一時間更新)