ios 部分string颜色_iOS-代码混淆加固方案
對(duì)于iOS來說,由于系統(tǒng)是封閉的,APP上架需要通過App Store,安全性來說相當(dāng)高。但是對(duì)于大廠和知名APP而言,別人給的安全保障永遠(yuǎn)沒有自己做的來得踏實(shí)。所以對(duì)于大廠、少部分企業(yè)級(jí)和金融支付類應(yīng)用來說加固是相當(dāng)重要的。
下面是目前幾個(gè)專業(yè)加固大廠提供的加固策略
- 網(wǎng)易
- 網(wǎng)易安全三板斧:
2.第二板斧是防動(dòng)態(tài)調(diào)試、反調(diào)試和通信安全(數(shù)據(jù)加密);
- 愛加密
- safengine
- 幾維安全
- 梆梆安全
本文將針對(duì)以上幾點(diǎn)進(jìn)行實(shí)現(xiàn),對(duì)于一些不太容易實(shí)現(xiàn)的將會(huì)做方向性討論
- 字符串加密
- 代碼混淆(方法名,類名,變量名,符號(hào)表)
- 代碼邏輯混淆
- 反調(diào)試
字符串加密
對(duì)字符串加密的方式目前我所了解到掌握到的最可靠方式就是用腳本將代碼中的所有標(biāo)記需要加密的字符串進(jìn)行異或轉(zhuǎn)換,這樣代碼中就不存在明文字符串了。當(dāng)然第三方的字符串加密不可能這么簡(jiǎn)單,具體怎么做的我也不太清楚。不過為了增加字符串加密的難度復(fù)雜性,我們可以先將字符串用加密工具轉(zhuǎn)換(例如AES、base64等)后的把加字符串放在工程中,并且把解密的鑰匙放在工程中,用異或轉(zhuǎn)換,把解密鑰匙和加密后的字符串轉(zhuǎn)換,這樣就有2層保障,增加了復(fù)雜度。
- 首先 我們創(chuàng)建任意一個(gè)工程,在工程中寫入下面的代碼,并在每句打上斷點(diǎn),再選擇Xcode工具欄的Debug --> Debug Workflow --> Always Show Disassembly。這樣你就可以在斷點(diǎn)處進(jìn)入?yún)R編模式界面,最后運(yùn)行程序
你會(huì)發(fā)現(xiàn),你的字符串內(nèi)容暴露在了匯編模式中,這會(huì)導(dǎo)致別人在逆向分析你的工程時(shí)能看見你的字符串內(nèi)容,我們一般接口、域名、加解密鑰匙串、AppKey、AppId等比較重要的東西會(huì)放在客戶端用作字符串,這就很容易暴露出來。
- 步驟1 首先需要在工程代碼中進(jìn)行修改,把下面的宏和decryptConfusionCS,decryptConstString函數(shù)放入代碼中,用宏包含每個(gè)需要轉(zhuǎn)換的字符串。
- 步驟2 使用終端cd 到需要加密的工程目錄下 執(zhí)行 touch confusion.py 和 touch decrypt.py 命令,生產(chǎn)加密和解密腳本文件
- 步驟3 把下面代碼加入解密腳本confusion.py中
- 步驟4 把下面的解密代碼放入decrypt.py解密腳本中
- 步驟5 根據(jù)自己的需求修改下腳本里面的代碼 和 文件路徑。
- 步驟6 把步驟1中的宏heyujia_confusion注釋了,然后執(zhí)行加密腳本,在終端中輸入 python confusion.py ,
(1.如果報(bào)錯(cuò),請(qǐng)查看下自己Mac電腦中的python版本,如果是python3就輸入 python3 confusion.py .
(2.如果報(bào) Non-ASCII character 'xe8' in file confusion.py on line 2 相關(guān)的錯(cuò),請(qǐng)確定腳本的前面3行是
執(zhí)行完步驟6后的結(jié)果
此時(shí)字符串已被加密,運(yùn)行程序會(huì)發(fā)現(xiàn)一切正常
加密后匯編界面看不見我們的字符串內(nèi)容了,但是我們用來解密的方法還是暴露在了匯編界面,所以我們后期還需要對(duì)方法名,變量名,類命等做混淆。
- 步驟7 把步驟1中的宏heyujia_confusion取消注釋,然后執(zhí)行解密腳本,在終端中輸入 python decrypt.py
- 解密后文本又變回了原樣。
這里只是基本的異或轉(zhuǎn)換加密,讓代碼中的字符串變成看不懂的char [],實(shí)際操作中遠(yuǎn)遠(yuǎn)不止這么簡(jiǎn)單 例如:
- 首先:我們先用加密工具例如:AES.Base64等把需要轉(zhuǎn)換的字符串先加密變成加密字符串
- 然后:在用異或轉(zhuǎn)換加密的腳本把加密字符串進(jìn)行轉(zhuǎn)換(包括解密用的鑰匙串)
- 在使用的時(shí)候:先異或解密字符串,然后根據(jù)解密鑰匙串把字符串在轉(zhuǎn)為可用的字符串
ps.還有一種保護(hù)字符串的方法,就是使用NSLocalizedString字符串本地化。
雖然跟著我的步驟你確實(shí)加密成功了,但是你卻無法實(shí)際驗(yàn)證。所以要驗(yàn)證最終的混淆結(jié)果是否達(dá)到效果,你還需要學(xué)習(xí)如何破殼解密IPA如何動(dòng)態(tài)靜態(tài)逆向編程分析工程源碼,大家可以先看看我 這篇文章 。先掌握逆向分析后再來做代碼混淆,就能驗(yàn)證混淆結(jié)果是否有效
變量、方法名,類名混淆
對(duì)于混淆這一塊,網(wǎng)上真的是千篇一律,基本都是copy的念大嬸的內(nèi)容,沒有一點(diǎn)自己的創(chuàng)新和思考。網(wǎng)上的方法我也用過,但是有缺陷,只能混淆方法名或者說自己固定的內(nèi)容去替換。第一不自動(dòng),對(duì)于大項(xiàng)目而言每個(gè)方法名自己添加,太麻煩。第二變量混淆有問題,因?yàn)橹皇菃渭兊淖址鎿Q,用宏代替。當(dāng)遇到使用_ 下劃線訪問變量時(shí),就會(huì)出現(xiàn)錯(cuò)誤。
對(duì)于變量、方法名,類名的混淆,其實(shí)跟字符串混淆差不多,都是加密混淆,然后解密混淆。不同的是,變量、方法名,類名的混淆目的是為了讓別人反編譯的時(shí)候不知道你的變量、方法,類是具體用來干什么的,不會(huì)像明文那樣一目了然。增加逆向難度。混淆的內(nèi)容不需要像字符串一樣,最后程序運(yùn)行時(shí)還要轉(zhuǎn)成中文正常使用。由于本人對(duì)shell腳本語言也不是非常熟悉,想要按照自己的思路寫一套完整的混淆腳本還不行。所以這部分也是在網(wǎng)上找的,算是目前最實(shí)用最完善的混淆
- 首先 打開終端cd到需要混淆的工程目錄下,輸入
touch obConfusion.sh (加密混淆腳本文件)
touch obDecrypt.sh (解密混淆腳本文件)
生成2個(gè)腳本文件 - 然后在工程目錄以外創(chuàng)建一個(gè)文件夾,用于保存加密時(shí)生成的加密文本內(nèi)容,該內(nèi)容會(huì)在解密時(shí)用到
- 最后是在 obConfusion.sh 和 obDecrypt.sh 文件中加入腳本內(nèi)容
下面是加密混淆腳本內(nèi)容
#!/bin/sh################################### (該腳本是在https://github.com/heqingliang/CodeObfus 上找到的)# 代碼混淆腳本 heyujia 2018.03.15####################################識(shí)別含有多字節(jié)編碼字符時(shí)遇到的解析沖突問題export LC_CTYPE=Cexport LANG=C#配置項(xiàng):#項(xiàng)目路徑,會(huì)混淆該路徑下的文件ProjectPath="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項(xiàng)目/daimahunxiao"#這個(gè)路徑是混淆成功后,原文本和替換文本解密對(duì)應(yīng)的文件存放路徑(該路徑不能在項(xiàng)目目錄或其子目錄),混淆成功后會(huì)在該路徑下生成一個(gè)解密時(shí)需要的文件,根據(jù)該文件的文本內(nèi)容把混淆后的內(nèi)容更換為原文本內(nèi)容,該文件名的組成由$(date +%Y%m%d)"_"$(date +%H%M)及日期_小時(shí)組成,每分鐘會(huì)不一樣。所以解密的時(shí)候需要每次更換文件路徑SecretFile="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項(xiàng)目/tihuan"$(date +%Y%m%d)"_"$(date +%H%M)#第一個(gè)參數(shù)為項(xiàng)目路徑if [[ $1 ]]thenif [[ $1 != "_" ]]; thenProjectPath=$1fifi#第二個(gè)參數(shù)指定密鑰文件路徑及文件名if [[ $2 ]]thenif [[ $2 != "_" ]]; thenSecretFile=$2fifi###############################################################################查找文本中所有要求混淆的屬性方法類,只會(huì)替換文本中ob_開頭和_fus結(jié)尾的字符串(區(qū)分大小寫,例如oB_就不會(huì)做混淆),如果注釋內(nèi)容有該類型的字符串,也會(huì)進(jìn)行替換。對(duì)于使用 _下劃線訪問的變量屬性,不會(huì)有影響,一樣會(huì)替換成對(duì)應(yīng)_的混淆內(nèi)容。resultfiles=`grep 'ob_[A-Za-z0-9_]*_fus' -rl $ProjectPath`#查找結(jié)果為空則退出if [[ -z $resultfiles ]]thenecho "項(xiàng)目沒有需要混淆的代碼"exitelseecho "開始混淆代碼..."echo > $SecretFilefix=$(awk 'BEGIN{srand();k=0;}#隨機(jī)數(shù)生成函數(shù)function random_int(min, max) {return int( rand()*(max-min+1) ) + min;}#隨機(jī)字符串生成函數(shù)function random_string(len) {result="UCS"k;alpbetnum=split("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z", alpbet, ",");for (i=0; i 0) {tempstr=substr(x, RSTART, RLENGTH);#判斷是否有之前已經(jīng)找過的重復(fù)字符串for ( i = 0; i < k; i++ ){if (strarr[i] == tempstr){break;}}if(i $SecretFilerecordnum=1while [[ 1 == 1 ]]; dorecord=`echo $x|cut -d "|" -f$recordnum`if [[ -z $record ]]thenbreakfirecord1=`echo $record|cut -d ":" -f1`echo "原項(xiàng):"$record1record2=`echo $record|cut -d ":" -f2`echo "加密項(xiàng):"$record2#替換文件夾中所有文件的內(nèi)容(支持正則)#單引號(hào)不能擴(kuò)展sed -i '' "s/${record1}/${record2}/g" `grep $record1 -rl $ProjectPath`echo "第"$recordnum"項(xiàng)混淆代碼處理完畢"let "recordnum = $recordnum + 1"done#查找需要混淆的文件名并替換filerecordnum=1while [[ 1 == 1 ]]; dofilerecord=`echo $x|cut -d "|" -f$filerecordnum`if [[ -z $filerecord ]]thenbreakfifilerecord1=`echo $filerecord|cut -d ":" -f1`#echo "原項(xiàng):"$filerecord1filerecord2=`echo $filerecord|cut -d ":" -f2`#echo "加密項(xiàng):"$filerecord2#改文件名find $ProjectPath -name $filerecord1"*"| awk 'BEGIN{frecord1="'"$filerecord1"'";frecord2="'"$filerecord2"'";finish=1}{filestr=$0;gsub(frecord1,frecord2,filestr);print "mv " $0 " " filestr";echo 第"finish"個(gè)混淆文件處理完畢";finish++;}'|bashlet "filerecordnum = $filerecordnum + 1"done下面是解密混淆腳本的內(nèi)容
#!/bin/sh######################################## 代碼還原腳本 RyoHo 2018.03.15########################################識(shí)別含有多字節(jié)編碼字符時(shí)遇到的解析沖突問題export LC_CTYPE=Cexport LANG=C#配置項(xiàng):#已經(jīng)混淆的項(xiàng)目路徑ProjectPath="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項(xiàng)目/daimahunxiao"#這個(gè)是文件路徑而不是目錄,是混淆的時(shí)候生成的文本文件路徑,每次不一樣。所以每次加密后,解密時(shí)需要更換路徑SecretFile="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項(xiàng)目/tihuan20180315_1456"#第一個(gè)參數(shù)為項(xiàng)目路徑if [[ $1 ]]thenif [[ $1 != "_" ]]; thenProjectPath=$1fifi#第二個(gè)參數(shù)指定密鑰文件路徑及文件名if [[ $2 ]]thenif [[ $2 != "_" ]]; thenSecretFile=$2fifi###############################################################################內(nèi)容還原x=`cat $SecretFile`recordnum=1while [[ 1 == 1 ]]; dorecord=`echo $x|cut -d "|" -f$recordnum`if [[ -z $record ]]thenbreakfirecord1=`echo $record|cut -d ":" -f1`echo "原項(xiàng):"$record1record2=`echo $record|cut -d ":" -f2`echo "加密項(xiàng):"$record2#若項(xiàng)目中加密項(xiàng)與密鑰文件的加密項(xiàng)不符合則退出程序searchresult=`grep $record2 -rl $ProjectPath`if [[ -z $searchresult ]]; thenecho "指定的密鑰文件不能還原"exitfi#替換文件夾中所有文件的內(nèi)容(支持正則)#單引號(hào)不能擴(kuò)展sed -i '' "s/${record2}/${record1}/g" $searchresultecho "第"$recordnum"項(xiàng)混淆代碼還原完畢"let "recordnum = $recordnum + 1"done#文件還原filerecordnum=1while [[ 1 == 1 ]]; dofilerecord=`echo $x|cut -d "|" -f$filerecordnum`if [[ -z $filerecord ]]thenbreakfifilerecord1=`echo $filerecord|cut -d ":" -f1`#echo "原項(xiàng):"$filerecord1filerecord2=`echo $filerecord|cut -d ":" -f2`#echo "加密項(xiàng):"$filerecord2#改文件名find $ProjectPath -name $filerecord2"*"| awk 'BEGIN{frecord1="'"$filerecord1"'";frecord2="'"$filerecord2"'";finish=1;}{filestr=$0;gsub(frecord2,frecord1,filestr);print "mv " $0 " "filestr ";echo 第"finish"個(gè)混淆文件還原完畢"finish++;}'|bashlet "filerecordnum = $filerecordnum + 1"done應(yīng)大家需要把腳本源碼:https://github.com/xkftkffz/DMHXDemo 地址 放出來
建議大家看看腳本內(nèi)容,有利于學(xué)習(xí)理解。該腳本是有針對(duì)性的混淆內(nèi)容,可以自己修改腳本中的正則表達(dá)式來確定混淆的內(nèi)容。腳本中只會(huì)替換文本中ob_開頭和_fus結(jié)尾的字符串(區(qū)分大小寫,例如oB_就不會(huì)做混淆),如果注釋內(nèi)容有該類型的字符串,也會(huì)進(jìn)行替換。對(duì)于使用 _下劃線訪問的變量屬性,不會(huì)有影響,一樣會(huì)替換成對(duì)應(yīng)_的混淆內(nèi)容。
總結(jié)
以上是生活随笔為你收集整理的ios 部分string颜色_iOS-代码混淆加固方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小李飞刀:用python刷题ing...
- 下一篇: JDBC和MySQL的实现原理