app風靡的時代,總有一些奇葩的需求。
為了刷量,刷排名,制作殼包,為了通過蘋果爸爸審核,想到代碼混淆,垃圾代碼等策略。
作為一名程序員,怎么辦?
爬了一些文章博客??偟膩碚f有一下幾方面:
- 字符串加密:
- 類名方法名混淆
- 程序代碼混淆
- 加入安全SDK
除了這些外,還有很多方面可以做加固保護的,以上這些只是范范一談。制作殼包為了通過審核,還有注入
垃圾代碼
來解決和主包代碼重復率的問題。本文主要講解類名方法名混淆及垃圾代碼的問題。如有問題,還請大神指點!
Objective-C的方法名混淆
混淆的方法
方法名混淆其實就是字符串替換,有2個方法可以,一個是#define,一個是利用tops。
利用#define的方法有一個好處,就是可以把混淆結果合并在一個.h中,在工程Prefix.pch的最前面#import這個.h。不導入也可以編譯、導入則實現混淆。
單段的selector,如func: ,可以通過#define func 來實現字符串替換。
多段的selector,如a:b:c: ,可以通過分別#define a 、b、c 來實現字符串替換。
第一步 創建如下文件
1、工程中建立pch文件 加入以下內容
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
//添加混淆作用的頭文件(這個文件名是腳本confuse.sh中定義的)
//#import "codeObfuscation.h"
#endif
2、在工程目錄下創建confuse.sh文件
#!/usr/bin/env bash
TABLENAME=symbols
SYMBOL_DB_FILE="symbols"
STRING_SYMBOL_FILE="func.list"
HEAD_FILE="$PROJECT_DIR/$PROJECT_NAME/codeObfuscation.h"
export LC_CTYPE=C
#維護數據庫方便日后作排重
createTable()
{
echo "create table $TABLENAME(src text, des text);" | sqlite3 $SYMBOL_DB_FILE
}
insertValue()
{
echo "insert into $TABLENAME values('$1' ,'$2');" | sqlite3 $SYMBOL_DB_FILE
}
query()
{
echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE
}
ramdomString()
{
openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16
}
rm -f $SYMBOL_DB_FILE
rm -f $HEAD_FILE
createTable
touch $HEAD_FILE
echo '#ifndef Demo_codeObfuscation_h
#define Demo_codeObfuscation_h' >> $HEAD_FILE
echo "http://confuse string at `date`" >> $HEAD_FILE
cat "$STRING_SYMBOL_FILE" | while read -ra line; do
if [[ ! -z "$line" ]]; then
ramdom=`ramdomString`
echo $line $ramdom
insertValue $line $ramdom
echo "#define $line $ramdom" >> $HEAD_FILE
fi
done
echo "#endif" >> $HEAD_FILE
sqlite3 $SYMBOL_DB_FILE .dump
3、在工程目錄下創建fun.list文件,文件中存放需要混淆的方法名,類名,文件等等
didReceiveMemoryWarning
4、配置項目$PROJECT_DIR/confuse.sh
5、編譯查看結果
直接build,混淆腳本會在編譯前運行,進行字符隨機替換,并且每次build的隨機字符不同,如圖:
類名方法名混淆
此方法是參考下開源項目:ios-class-guard
操作步驟如下:
1、 安裝工具
brew install ios-class-guard
brew install --HEAD ios-class-guard # install bleeding edge version:
ios-class-guard --v #查看版本
2、下載obfuscate_project
到工程根目錄下
curl -o obfuscate_project https://raw.githubusercontent.com/Polidea/ios-class-guard/master/contrib/obfuscate_project && chmod +x obfuscate_project
效果如果:
注意點:提交的commit信息它腳本中會移除掉,包括obfuscate_project
也會被移除
WARNING: This will wipe all your not commited changes in your repository
警告:這將會移除你未提交的更改在你的倉庫中。
問題點:
需要修改腳本中的工程名,scheme,sdk等:
3、然后繼續執行:
當你每次想混淆你的項目。都應該執行此操作。存儲包含符號映射的json文件,以便在發生崩潰時獲取原始符號名稱。
bash obfuscate_project
打開工程,發現已經生成了.h
和json
文件
4、添加.pch
文件
- Create PCH file in your project's root directory. In Xcode go to
File -> New -> File -> iOS -> Other -> PCH File
. To ensure backward compatibility iOS-Class-Guard will be looking for a file matching the *-Prefix.pch
mask, as an exampleMyProject-Prefix.pch
- At the target's
Build Settings
, inApple LLVM - Language
section, setPrefix Header
to your PCH file name. - At the target's
Build Settings
, inApple LLVM - Language
section, setPrecompile Prefix Header
toYES
.
image.png
$(SRCROOT)/MyProject/MyProject-Prefxi.pch
容易犯的錯誤:
注意是:MyProject-Prefix.pch
因為腳本中pch的名字有Prefix
每次混淆之后都會刪除腳本,清理工程??梢灾苯有薷哪_本代碼
ios-class-guard
使用命令等
ios-class-guard 0.8 (64 bit)
Usage: ios-class-guard [options] <mach-o-file>
where options are:
-F <class> specify class filter for symbols obfuscator (also protocol))
-i <symbol> ignore obfuscation of specific symbol)
--arch <arch> choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64, armv6, armv7, armv7s, arm64)
--list-arches list the arches in the file, then exit
--sdk-ios specify iOS SDK version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version>.sdk
or /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version>.sdk)
--sdk-mac specify Mac OS X version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX<version>.sdk
or /Developer/SDKs/MacOSX<version>.sdk)
--sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut)
-X <directory> base directory for XIB, storyboards (will be searched recursively)
-P <path> path to project.pbxproj of Pods project (located inside Pods.xcodeproj)
-O <path> path to file where obfuscated symbols are written
-m <path> path to symbol file map (default value symbols.json)
-c <path> path to symbolicated crash dump
還有一些單獨對xib,storyboard,pods等單獨操作進行混淆的。點擊這里
腳本源碼:有興趣可以研究下腳本源碼,這才是核心根源。
#!/bin/bash
set -e
# General build options
# WORKSPACE=YourWorkspace.xcworkspace
PROJECT=test.xcodeproj
SCHEME=test
CONFIGURATION=Release
SDK=11.3
# Additional build options
XCODEBUILD_OPTS=""
CLASS_GUARD_OPTS="-i IgnoredSymbol -F !ExcludedClass"
# In case of using Xcode >= 6 and SDK >= 8
CLASS_GUARD_OPTS_SDK="--sdk-root /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$SDK.sdk"
####################################################
# BUILD SCRIPT STARTS HERE
####################################################
# Just in case
echo "WARNING: This will wipe all your not commited changes in your repository"
echo "Press Ctrl-C to Cancel or Enter to proceed."
read
function echo_and_run() {
echo "$@"
"$@"
}
# Jump to directory where obfuscate script is located
pushd $(dirname $0)
# Symbols file path
SYMBOLS_FILE="$PWD/symbols.h"
# Clean current workspace
echo_and_run git reset --hard
echo_and_run git clean -fdx
# Just in case: wipe build/
rm -rf build/
# Automatically detect PODS
[[ -f Podfile ]] && [[ ! -f Pods/Manifest.lock ]] && pod install
[[ -f Pods/Pods.xcodeproj/project.pbxproj ]] && CLASS_GUARD_OPTS="$CLASS_GUARD_OPTS -P Pods/Pods.xcodeproj/project.pbxproj"
# Build project to fetch symbols
[[ -n "$WORKSPACE" ]] && XCODEBUILD_OPTS="$XCODEBUILD_OPTS -workspace $WORKSPACE"
[[ -n "$PROJECT" ]] && XCODEBUILD_OPTS="$XCODEBUILD_OPTS -project $PROJECT"
[[ -n "$SCHEME" ]] && XCODEBUILD_OPTS="$XCODEBUILD_OPTS -scheme $SCHEME"
[[ -n "$CONFIGURATION" ]] && XCODEBUILD_OPTS="$XCODEBUILD_OPTS -configuration $CONFIGURATION"
xcodeversion=`xcodebuild -version | grep -oE '^Xcode\s+\d+' | grep -oE '\d+'`
if ((xcodeversion > 5)) || ((SDK >= 8.0))
then
[[ -n "$SDK" ]] && XCODEBUILD_OPTS="$XCODEBUILD_OPTS -sdk iphonesimulator$SDK"
else
[[ -n "$SDK" ]] && XCODEBUILD_OPTS="$XCODEBUILD_OPTS -sdk iphoneos$SDK"
[[ -n "$SDK" ]] && CLASS_GUARD_OPTS_SDK="--sdk-ios $SDK"
fi
echo_and_run xcodebuild $XCODEBUILD_OPTS \
clean build \
-derivedDataPath build
OBJROOT=build/ \
SYMROOT=build/
# Insert SYMBOLS_FILE to all .pch found in project
echo_and_run find . -name '*-Prefix.pch' -exec sed -i .bak '1i\
'"#import \"$SYMBOLS_FILE\"
" "{}" \;
# Obfuscate project
appsNumber=0;
while read app
do
if ((appsNumber > 0))
then
echo ""
echo ""
echo "You cannot use this tool when there is more than one .app file in products. Otherwise, only the first one will be used for obfuscation."
echo ""
echo ""
exit 1
fi
((appsNumber+=1))
TARGET=$(basename "$app" .app)
echo "Obfuscating $TARGET in $app..."
echo_and_run ios-class-guard \
$CLASS_GUARD_OPTS_SDK \
$CLASS_GUARD_OPTS \
-O "$SYMBOLS_FILE" \
"$app/$TARGET"
done < <(find build/ -name '*.app')
echo ""
echo ""
echo "Congratulations! Obfuscation completed. You can now build, test and archive Your project using Xcode, Xctool or Xcodebuid..."
echo ""
echo ""
工具混淆
垃圾代碼
用于應對蘋果對重復應用的審核(Guideline 4.3 Design Spam),避免蘋果機審檢測概率。
主要功能
- 修改工程名
- 修改類名前綴
- 掃描工程中的代碼,生成同等數量的 Category 文件,文件中及是同等方法數量的垃圾代碼。
- 修改 xxx.xcassets 文件夾中的 png 資源文件名。
- 刪除代碼中的所有注釋和空行。
使用步驟如下
1、下載源碼。
2、用 Xcode 打開工程并配置參數。如圖
3、運行
使用二進制文件,在終端中執行 GenerateSpamCode
- spamCodeOut 生成垃圾代碼
./GenerateSpamCode \
/Users/wangzelong/Desktop/TeamCode/cardloan \
-spamCodeOut /Users/wangzelong/Desktop/appLog AppLog
注明:appLog是一個文件夾,垃圾代碼生成到的文件夾目錄。 后面的AppLog是將要生成的垃圾代碼分類參數等可以再測試代碼中嘗試。
- deleteComments 刪除工程目錄下 .h .m .swift 文件中的注釋和空行。
./GenerateSpamCode
/Users/wangzelong/Desktop/appium
-deleteComments
坑:
1、Podfile被修改后需要手動pod install
2、如果工程項目很大。則建議導入一部分工程代碼去生成垃圾代碼,因為項目中很多文件包括依賴的三方庫等,可能是 .m 文件中實現的私有類,編譯垃圾代碼可能會報錯,刪除該垃圾代碼 .h .m 文件及可。
此外提供一個壓縮圖片的輕量工具:
使用 ImageMagick 對 png 圖片做輕量壓縮,及不損失圖片質量,又可改變圖片文件 hash 值。方法:
- 安裝 ImageMagick
brew install imagemagick
- 壓縮工程目錄下所有 png 文件
find . -iname "*.png" -exec echo {} \; -exec convert {} {} \;