日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ios 部分string颜色_iOS-代码混淆加固方案

發(fā)布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ios 部分string颜色_iOS-代码混淆加固方案 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

對于iOS來說,由于系統(tǒng)是封閉的,APP上架需要通過App Store,安全性來說相當(dāng)高。但是對于大廠和知名APP而言,別人給的安全保障永遠(yuǎn)沒有自己做的來得踏實(shí)。所以對于大廠、少部分企業(yè)級和金融支付類應(yīng)用來說加固是相當(dāng)重要的。
下面是目前幾個專業(yè)加固大廠提供的加固策略

  • 網(wǎng)易
  • 網(wǎng)易安全三板斧:
  • 第一板斧是防靜態(tài)分析,這里包括字符串加密、符號混淆、代碼邏輯混淆和游戲存檔加密;
  • 2.第二板斧是防動態(tài)調(diào)試、反調(diào)試和通信安全(數(shù)據(jù)加密);

  • 第三板斧是外掛檢測、加速掛、內(nèi)存修改掛和自動任務(wù)掛等
    • 愛加密
    • safengine
    • 幾維安全
    • 梆梆安全

    本文將針對以上幾點(diǎn)進(jìn)行實(shí)現(xiàn),對于一些不太容易實(shí)現(xiàn)的將會做方向性討論

    • 字符串加密
    • 代碼混淆(方法名,類名,變量名,符號表)
    • 代碼邏輯混淆
    • 反調(diào)試

    字符串加密

    對字符串加密的方式目前我所了解到掌握到的最可靠方式就是用腳本將代碼中的所有標(biāo)記需要加密的字符串進(jìn)行異或轉(zhuǎn)換,這樣代碼中就不存在明文字符串了。當(dāng)然第三方的字符串加密不可能這么簡單,具體怎么做的我也不太清楚。不過為了增加字符串加密的難度復(fù)雜性,我們可以先將字符串用加密工具轉(zhuǎn)換(例如AES、base64等)后的把加字符串放在工程中,并且把解密的鑰匙放在工程中,用異或轉(zhuǎn)換,把解密鑰匙和加密后的字符串轉(zhuǎn)換,這樣就有2層保障,增加了復(fù)雜度。

    • 首先 我們創(chuàng)建任意一個工程,在工程中寫入下面的代碼,并在每句打上斷點(diǎn),再選擇Xcode工具欄的Debug --> Debug Workflow --> Always Show Disassembly。這樣你就可以在斷點(diǎn)處進(jìn)入?yún)R編模式界面,最后運(yùn)行程序
    /* 加密NSString字符串 */ NSString *str = @"Hello World"; NSLog(@"%@",str); /* 加密char*字符串 */ char* cStr = "Super Man"; NSLog(@"%s",cStr);

    你會發(fā)現(xiàn),你的字符串內(nèi)容暴露在了匯編模式中,這會導(dǎo)致別人在逆向分析你的工程時能看見你的字符串內(nèi)容,我們一般接口、域名、加解密鑰匙串、AppKey、AppId等比較重要的東西會放在客戶端用作字符串,這就很容易暴露出來。

    • 步驟1 首先需要在工程代碼中進(jìn)行修改,把下面的宏和decryptConfusionCS,decryptConstString函數(shù)放入代碼中,用宏包含每個需要轉(zhuǎn)換的字符串。
    /* 字符串混淆解密函數(shù),將char[] 形式字符數(shù)組和 aa異或運(yùn)算揭秘 */extern char* decryptConfusionCS(char* string){ char* origin_string = string; while(*string) { *string ^= 0xAA; string++; } return origin_string;}/* 解密函數(shù),返回的是NSString類型的 */extern NSString* decryptConstString(char* string){ /* 先執(zhí)行decryptConfusionString函數(shù)解密字符串 */ char* str = decryptConfusionCS(string); /* 獲取字符串的長度 */ unsigned long len = strlen(str); NSUInteger length = [[NSString stringWithFormat:@"%lu",len] integerValue]; NSString *resultString = [[NSString alloc]initWithBytes:str length:length encoding:NSUTF8StringEncoding]; return resultString;}/* * 使用heyujia_confusion宏控制加密解密 * 當(dāng)heyujia_confusion宏被定義的時候,執(zhí)行加密腳本,對字符串進(jìn)行加密 * 當(dāng)heyujia_confusion宏被刪除或為定義時,執(zhí)行解密腳本,對字符串解密 */#define heyujia_confusion#ifdef heyujia_confusion/* heyujia_confusion 宏被定義,那么就進(jìn)行執(zhí)行解密腳本 *//* confusion_NSSTRING宏的返回結(jié)果是NSString 類型的 */#define confusion_NSSTRING(string) decryptConstString(string)/* confusion_CSTRING宏的返回結(jié)果是char* 類型的 */#define confusion_CSTRING(string) decryptConfusionCS(string)#else/* heyujia_confusion 宏沒有被定義,那么就執(zhí)行加密腳本 *//* 加密NSString類型的 */#define confusion_NSSTRING(string) @string/* 加密char *類型的 */#define confusion_CSTRING(string) string#endif@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. /* 使用confusion_NSSTRING宏包含需要加密的NSString字符串 */ NSString *str = confusion_NSSTRING("Hello World"); NSLog(@"%@",str); /* 使用confusion_NSSTRING宏包含需要加密的char*字符串 */ char* cStr = confusion_CSTRING("Super Man"); NSLog(@"%s",cStr); }
    • 步驟2 使用終端cd 到需要加密的工程目錄下 執(zhí)行 touch confusion.py 和 touch decrypt.py 命令,生產(chǎn)加密和解密腳本文件
    • 步驟3 把下面代碼加入解密腳本confusion.py中
    #!/usr/bin/env python# encoding=utf8# -*- coding: utf-8 -*-# author by heyujia# 腳本將會用于對指定目錄下的.h .m源碼中的字符串進(jìn)行轉(zhuǎn)換# 替換所有字符串常量為加密的char數(shù)組,形式((char[]){1, 2, 3, 0})import importlibimport osimport reimport sys# replace替換字符串為((char[]){1, 2, 3, 0})的形式,同時讓每個字節(jié)與0xAA異或進(jìn)行加密# 當(dāng)然可以不使用0xAA 使用其他的十六進(jìn)制也行 例如0XBB、0X22、0X11def replace(match): string = match.group(2) + 'x00' replaced_string = '((char []) {' + ', '.join(["%i" % ((ord(c) ^ 0xAA) if c != '0' else 0) for c in list(string)]) + '})' return match.group(1) + replaced_string + match.group(3)# obfuscate方法是修改傳入文件源代碼中用confusion_NSSTRING標(biāo)記的所有字符串# 使用replace函數(shù)對字符串進(jìn)行異或轉(zhuǎn)換def obfuscate(file): with open(file, 'r') as f: code = f.read() f.close() code = re.sub(r'(confusion_NSSTRING(|confusion_CSTRING()"(.*?)"())', replace, code) code = re.sub(r'//#define ggh_confusion', '#define ggh_confusion', code) with open(file, 'w') as f: f.write(code) f.close()# openSrcFile方法是讀取源碼路徑下的所有.h和.m 文件# 對每個文件執(zhí)行obfuscate函數(shù)def openSrcFile(path): print("混淆的路徑為 "+ path) # this folder is custom for parent,dirnames,filenames in os.walk(path): #case 1: # for dirname in dirnames: # print((" parent folder is:" + parent).encode('utf-8')) # print((" dirname is:" + dirname).encode('utf-8')) #case 2 for filename in filenames: extendedName = os.path.splitext(os.path.join(parent,filename)) if (extendedName[1] == '.h' or extendedName[1] == '.m'): print("處理源代碼文件: "+ os.path.join(parent,filename)) obfuscate(os.path.join(parent,filename))#這里需要修改源碼的路徑為自己工程的文件夾名稱srcPath = '../daimahunxiao'if __name__ == '__main__': print("本腳本用于對源代碼中被標(biāo)記的字符串進(jìn)行加密") if len(srcPath) > 0: openSrcFile(srcPath) else: print("請輸入正確的源代碼路徑") sys.exit()
    • 步驟4 把下面的解密代碼放入decrypt.py解密腳本中
    #!/usr/bin/env python# encoding=utf8# -*- coding: utf-8 -*-# author by heyujia# 解密腳本# 替換所有標(biāo)記過的加密的char數(shù)組為字符串常量,""import importlibimport osimport reimport sys# 替換((char[]){1, 2, 3, 0})的形式為字符串,同時讓每個數(shù)組值與0xAA異或進(jìn)行解密def replace(match): string = match.group(2) decodeConfusion_string = "" for numberStr in list(string.split(',')): if int(numberStr) != 0: decodeConfusion_string = decodeConfusion_string + "%c" % (int(numberStr) ^ 0xAA) replaced_string = '"' + decodeConfusion_string + '"' print("replaced_string = " + replaced_string) return match.group(1) + replaced_string + match.group(3)# 修改源代碼,加入字符串加密的函數(shù)def obfuscate(file): with open(file, 'r') as f: code = f.read() f.close() code = re.sub(r'(confusion_NSSTRING(|confusion_CSTRING()((char []) {(.*?)})())', replace, code) code = re.sub(r'[/]*#define ggh_confusion', '//#define ggh_confusion', code) with open(file, 'w') as f: f.write(code) f.close()#讀取源碼路徑下的所有.h和.m 文件def openSrcFile(path): print("解密路徑: "+ path) # this folder is custom for parent,dirnames,filenames in os.walk(path): #case 1: # for dirname in dirnames: # print((" parent folder is:" + parent).encode('utf-8')) # print((" dirname is:" + dirname).encode('utf-8')) #case 2 for filename in filenames: extendedName = os.path.splitext(os.path.join(parent,filename)) #讀取所有.h和.m 的源文件 if (extendedName[1] == '.h' or extendedName[1] == '.m'): print("已解密文件:"+ os.path.join(parent,filename)) obfuscate(os.path.join(parent,filename))#源碼路徑srcPath = '../daimahunxiao'if __name__ == '__main__': print("字符串解混淆腳本,將被標(biāo)記過的char數(shù)組轉(zhuǎn)為字符串,并和0xAA異或。還原代碼") if len(srcPath) > 0: openSrcFile(srcPath) else: print("請輸入正確的源代碼路徑!") sys.exit()
    • 步驟5 根據(jù)自己的需求修改下腳本里面的代碼 和 文件路徑。
    • 步驟6 把步驟1中的宏heyujia_confusion注釋了,然后執(zhí)行加密腳本,在終端中輸入 python confusion.py ,
      (1.如果報錯,請查看下自己Mac電腦中的python版本,如果是python3就輸入 python3 confusion.py .
      (2.如果報 Non-ASCII character 'xe8' in file confusion.py on line 2 相關(guān)的錯,請確定腳本的前面3行是
    #!/usr/bin/env python# encoding=utf8# -*- coding: utf-8 -*-

    執(zhí)行完步驟6后的結(jié)果

    此時字符串已被加密,運(yùn)行程序會發(fā)現(xiàn)一切正常

    加密后匯編界面看不見我們的字符串內(nèi)容了,但是我們用來解密的方法還是暴露在了匯編界面,所以我們后期還需要對方法名,變量名,類命等做混淆。

    • 步驟7 把步驟1中的宏heyujia_confusion取消注釋,然后執(zhí)行解密腳本,在終端中輸入 python decrypt.py
    • 解密后文本又變回了原樣。

    這里只是基本的異或轉(zhuǎn)換加密,讓代碼中的字符串變成看不懂的char [],實(shí)際操作中遠(yuǎn)遠(yuǎn)不止這么簡單 例如:

    • 首先:我們先用加密工具例如:AES.Base64等把需要轉(zhuǎn)換的字符串先加密變成加密字符串
    • 然后:在用異或轉(zhuǎn)換加密的腳本把加密字符串進(jìn)行轉(zhuǎn)換(包括解密用的鑰匙串)
    • 在使用的時候:先異或解密字符串,然后根據(jù)解密鑰匙串把字符串在轉(zhuǎn)為可用的字符串

    ps.還有一種保護(hù)字符串的方法,就是使用NSLocalizedString字符串本地化。

    雖然跟著我的步驟你確實(shí)加密成功了,但是你卻無法實(shí)際驗證。所以要驗證最終的混淆結(jié)果是否達(dá)到效果,你還需要學(xué)習(xí)如何破殼解密IPA如何動態(tài)靜態(tài)逆向編程分析工程源碼,大家可以先看看我 這篇文章 。先掌握逆向分析后再來做代碼混淆,就能驗證混淆結(jié)果是否有效

    變量、方法名,類名混淆

    對于混淆這一塊,網(wǎng)上真的是千篇一律,基本都是copy的念大嬸的內(nèi)容,沒有一點(diǎn)自己的創(chuàng)新和思考。網(wǎng)上的方法我也用過,但是有缺陷,只能混淆方法名或者說自己固定的內(nèi)容去替換。第一不自動,對于大項目而言每個方法名自己添加,太麻煩。第二變量混淆有問題,因為只是單純的字符串替換,用宏代替。當(dāng)遇到使用_ 下劃線訪問變量時,就會出現(xiàn)錯誤。

    對于變量、方法名,類名的混淆,其實(shí)跟字符串混淆差不多,都是加密混淆,然后解密混淆。不同的是,變量、方法名,類名的混淆目的是為了讓別人反編譯的時候不知道你的變量、方法,類是具體用來干什么的,不會像明文那樣一目了然。增加逆向難度。混淆的內(nèi)容不需要像字符串一樣,最后程序運(yùn)行時還要轉(zhuǎn)成中文正常使用。由于本人對shell腳本語言也不是非常熟悉,想要按照自己的思路寫一套完整的混淆腳本還不行。所以這部分也是在網(wǎng)上找的,算是目前最實(shí)用最完善的混淆

    • 首先 打開終端cd到需要混淆的工程目錄下,輸入
      touch obConfusion.sh (加密混淆腳本文件)
      touch obDecrypt.sh (解密混淆腳本文件)
      生成2個腳本文件
    • 然后在工程目錄以外創(chuàng)建一個文件夾,用于保存加密時生成的加密文本內(nèi)容,該內(nèi)容會在解密時用到
    • 最后是在 obConfusion.sh 和 obDecrypt.sh 文件中加入腳本內(nèi)容

    下面是加密混淆腳本內(nèi)容

    #!/bin/sh################################### (該腳本是在https://github.com/heqingliang/CodeObfus 上找到的)# 代碼混淆腳本 heyujia 2018.03.15####################################識別含有多字節(jié)編碼字符時遇到的解析沖突問題export LC_CTYPE=Cexport LANG=C#配置項:#項目路徑,會混淆該路徑下的文件ProjectPath="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項目/daimahunxiao"#這個路徑是混淆成功后,原文本和替換文本解密對應(yīng)的文件存放路徑(該路徑不能在項目目錄或其子目錄),混淆成功后會在該路徑下生成一個解密時需要的文件,根據(jù)該文件的文本內(nèi)容把混淆后的內(nèi)容更換為原文本內(nèi)容,該文件名的組成由$(date +%Y%m%d)"_"$(date +%H%M)及日期_小時組成,每分鐘會不一樣。所以解密的時候需要每次更換文件路徑SecretFile="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項目/tihuan"$(date +%Y%m%d)"_"$(date +%H%M)#第一個參數(shù)為項目路徑if [[ $1 ]]thenif [[ $1 != "_" ]]; thenProjectPath=$1fifi#第二個參數(shù)指定密鑰文件路徑及文件名if [[ $2 ]]thenif [[ $2 != "_" ]]; thenSecretFile=$2fifi###############################################################################查找文本中所有要求混淆的屬性方法類,只會替換文本中ob_開頭和_fus結(jié)尾的字符串(區(qū)分大小寫,例如oB_就不會做混淆),如果注釋內(nèi)容有該類型的字符串,也會進(jìn)行替換。對于使用 _下劃線訪問的變量屬性,不會有影響,一樣會替換成對應(yīng)_的混淆內(nèi)容。resultfiles=`grep 'ob_[A-Za-z0-9_]*_fus' -rl $ProjectPath`#查找結(jié)果為空則退出if [[ -z $resultfiles ]]thenecho "項目沒有需要混淆的代碼"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 "原項:"$record1record2=`echo $record|cut -d ":" -f2`echo "加密項:"$record2#替換文件夾中所有文件的內(nèi)容(支持正則)#單引號不能擴(kuò)展sed -i '' "s/${record1}/${record2}/g" `grep $record1 -rl $ProjectPath`echo "第"$recordnum"項混淆代碼處理完畢"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 "原項:"$filerecord1filerecord2=`echo $filerecord|cut -d ":" -f2`#echo "加密項:"$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"個混淆文件處理完畢";finish++;}'|bashlet "filerecordnum = $filerecordnum + 1"done

    下面是解密混淆腳本的內(nèi)容

    #!/bin/sh######################################## 代碼還原腳本 RyoHo 2018.03.15########################################識別含有多字節(jié)編碼字符時遇到的解析沖突問題export LC_CTYPE=Cexport LANG=C#配置項:#已經(jīng)混淆的項目路徑ProjectPath="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項目/daimahunxiao"#這個是文件路徑而不是目錄,是混淆的時候生成的文本文件路徑,每次不一樣。所以每次加密后,解密時需要更換路徑SecretFile="/Users/xieyujia/Desktop/ios/學(xué)習(xí)項目/tihuan20180315_1456"#第一個參數(shù)為項目路徑if [[ $1 ]]thenif [[ $1 != "_" ]]; thenProjectPath=$1fifi#第二個參數(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 "原項:"$record1record2=`echo $record|cut -d ":" -f2`echo "加密項:"$record2#若項目中加密項與密鑰文件的加密項不符合則退出程序searchresult=`grep $record2 -rl $ProjectPath`if [[ -z $searchresult ]]; thenecho "指定的密鑰文件不能還原"exitfi#替換文件夾中所有文件的內(nèi)容(支持正則)#單引號不能擴(kuò)展sed -i '' "s/${record2}/${record1}/g" $searchresultecho "第"$recordnum"項混淆代碼還原完畢"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 "原項:"$filerecord1filerecord2=`echo $filerecord|cut -d ":" -f2`#echo "加密項:"$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"個混淆文件還原完畢"finish++;}'|bashlet "filerecordnum = $filerecordnum + 1"done

    應(yīng)大家需要把腳本源碼:https://github.com/xkftkffz/DMHXDemo 地址 放出來

    建議大家看看腳本內(nèi)容,有利于學(xué)習(xí)理解。該腳本是有針對性的混淆內(nèi)容,可以自己修改腳本中的正則表達(dá)式來確定混淆的內(nèi)容。腳本中只會替換文本中ob_開頭和_fus結(jié)尾的字符串(區(qū)分大小寫,例如oB_就不會做混淆),如果注釋內(nèi)容有該類型的字符串,也會進(jìn)行替換。對于使用 _下劃線訪問的變量屬性,不會有影響,一樣會替換成對應(yīng)_的混淆內(nèi)容。

    總結(jié)

    以上是生活随笔為你收集整理的ios 部分string颜色_iOS-代码混淆加固方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。