腳本混淆
⑴ android如何將混淆代碼還原
當混淆後的代碼輸出一個堆棧信息時,方法名是不可識別的,這使得調試變得很困難,甚至是不可能的。幸運的是,當ProGuard運行時,它都會輸出一個<project_root>/bin/proguard/mapping.txt文件,而這個文件中包含了原始的類,方法和欄位名被映射成的混淆名字。
retrace.bat腳本(Window)或retrace.sh腳本(linux,Mac OS X)可以將一個被混淆過的堆棧跟蹤信息還原成一個可讀的信息。它位於<sdk_root>/tools/proguard文件夾中。執行retrace工具的語法如下:
retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
例如:
retrace.bat -verbose mapping.txt obfuscated_trace.txt
如果你沒有指定<stacktrace_file>,retrace工具會從標准輸入讀取。
⑵ lua代碼暴力混淆--shell腳本
#! /usr/local/bin/bash
####################################### skip define ##########################################
skipFolderArr=("src/cocos" "src/packages")
skipFileArr=("src/main.lua" "src/gm.lua" "src/config.lua" "src/app/MyApp.lua" "src/app/Utils.lua" "src/app/dataModel/name.lua" "src/app/views/Huodong/TwoTip.lua" "src/app/views/activity/Activity01.lua" "src/app/views/activity/Activity02.lua" "src/app/views/activity/Activity03.lua")
####################################### skip define ##########################################
# define rootPath
rootPath=$1
rootPathLength=${#rootPath}
newProffix="new/"
newProffixLength=${#newProffix}
newRootPath=${newProffix}${rootPath}
newRootPathLength=${#newRootPath}
folderReflactFile="folder-reflact.txt"
fileReflactFile="file-reflact.txt"
####################################### some handler ##########################################
# clear old files
#rm -rf src
rm -rf ${newRootPath} ${folderReflactFile} ${fileReflactFile}
mkdir -p ${newRootPath}
#tar -zxvf src.tar.gz
####################################### some handler ##########################################
# mv map
# origin file path name -> target file path name
declare -A fileNameMap
declare -A filePathNameMap
####################################### utils function ##########################################
# upper string's first letter
function first_letter_upper(){
temp=`echo ${1:0:1} | tr '[a-z]' '[A-Z]'`${1:1}
echo $temp
}
# random switch 0 orn 1
function random_switch(){
temp=$(($RANDOM%2))[圖片]
echo $temp
}
# random string with length
name_string_arr=(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)
function random_string(){
str=""
for ((i=0; i < $1; i++));do str="$str${name_string_arr[$RANDOM%26]}";done
echo $str
}
####################################### utils function ##########################################
# random folder name, length=5.
function randomFolderName(){
echo $(random_string 5)
}
# random file name, length=10.
function randomFileName(){
str=$(random_string 10)
str=$(first_letter_upper $str)
echo $str
}
# check if string in array
# $1 string
function checkFolderIn(){
exist=false
for str in ${skipFolderArr[@]}
do
if [ $1 == $str ]; then
exist=true
break
fi
done
echo $exist
}
# check if string in array
# $1 string
function checkFileIn(){
exist=false
for str in ${skipFileArr[@]}
do
if [ $1 == $str ]; then
exist=true
break
fi
done
echo $exist
}
# handle file path name map save
function handleMapSave(){
# key rece length
krl=${rootPathLength}+1
# value rece length
vrl=${newRootPathLength}+1
saveKey=${1:${krl}}
saveKey2=${saveKey//'/'/'.'}
saveValue=${2:${vrl}}
filePathNameMap[${saveKey}]=${saveValue}
filePathNameMap[${saveKey2}]=${saveValue}
}
function writeFolderReflactToFile(){
echo -e ${1}"-----------mkdir----------"${2} >> ${folderReflactFile}
}
function writeFileReflactToFile(){
echo -e ${1}"-----------file path name----------"${2} >> ${fileReflactFile}
}
# traverse folders to collect folders and files
function skipFolderTraverse(){
for file in `ls $1`
do
if [ -d $1"/"$file ]; then
# traverse folder
oldPath=$1"/"${file}
mkdirPath=${newRootPath}${1:${rootPathLength}}"/"${file}
echo ${oldPath}"-----------mkdir----------"${mkdirPath}
writeFolderReflactToFile ${oldPath} ${mkdirPath}
mkdir -p ${mkdirPath}
skipFolderTraverse ${oldPath}
else
# define filePathName -> newFilePathName
filePathName=${1}"/"${file}
newFilePathName=${newRootPath}${1:${rootPathLength}}"/"${file}
echo ${filePathName}"-----------file path name----------"${newFilePathName}
writeFileReflactToFile ${filePathName} ${newFilePathName}
cp ${filePathName} ${newFilePathName}
fi
done
}
# traverse folders to confuse folders and files
function confuseFolderTraverse(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
oldPath=$1"/"${file}
newFolder=$(randomFolderName)
newPath=$2"/"${newFolder}
mkdirPath=${newRootPath}${1:${rootPathLength}}"/"${file}
# folder "cocos" and "package" are con't fixed.
if [ $(checkFolderIn ${oldPath}) == true ]; then
echo ${oldPath}"-----------mkdir----------"${mkdirPath}
writeFolderReflactToFile ${oldPath} ${mkdirPath}
mkdir -p ${mkdirPath}
skipFolderTraverse ${oldPath}
continue
fi
mkdirPath=${newRootPath}${2}"/"${newFolder}
echo ${oldPath}"-----------mkdir----------"${mkdirPath}
writeFolderReflactToFile ${oldPath} ${mkdirPath}
mkdir -p ${mkdirPath}
# traverse folder
confuseFolderTraverse ${oldPath} ${newPath}
else
# get file suffix
fileSuffix="."${file##*.}
# echo "-----------file suffix-----------"${fileSuffix}
# define fileName -> newFileName
fileName=$(basename ${file} ${fileSuffix})
newFileName=$(randomFileName)
# echo ${fileName}"-----------file name----------"${newFileName}
# define file -> newFile
newFile=$newFileName$fileSuffix
# echo $file"-----------file----------"$newFile
# define filePathName -> newFilePathName
filePathName=${1}"/"${file}
newFilePathName=${newRootPath}${2}"/"${newFile}
if [ $(checkFileIn ${filePathName}) == true ]; then
newFilePathName=${newRootPath}${2}"/"${file}
echo ${filePathName}"-----------file path name----------"${newFilePathName}
writeFileReflactToFile ${filePathName} ${newFilePathName}
handleMapSave ${filePathName//${fileSuffix}/''} ${newFilePathName//${fileSuffix}/''}
cp ${filePathName} ${newFilePathName}
continue
fi
echo ${filePathName}"-----------file path name----------"${newFilePathName}
writeFileReflactToFile ${filePathName} ${newFilePathName}
handleMapSave ${filePathName//${fileSuffix}/''} ${newFilePathName//${fileSuffix}/''}
cp ${filePathName} ${newFilePathName}
sed -i "s|${fileName}|${newFileName}|g" $newFilePathName
fileNameMap[${fileName}]=${newFileName}
fi
done
}
function replace(){
for file in `ls $1`
do
if [ -d ${1}"/"$file ]
then
oldPath=${1}"/"${file}
#echo ${oldPath}
echo ${oldPath:${newProffixLength}}
if [ $(checkFolderIn ${oldPath:${newProffixLength}}) == true ]; then
continue
fi
replace ${oldPath}
else
filePathName=${1}"/"$file
for key in ${!filePathNameMap[@]};do
value=${filePathNameMap[${key}]}
echo "sed -i 's|${key}|${value}|g' $filePathName"
sed -i "s|${key}|${value}|g" $filePathName
done
for key in ${!fileNameMap[@]};do
value=${fileNameMap[${key}]}
echo "sed -i 's|${key}|${value}|g' $filePathName"
sed -i "s|${key}|${value}|g" $filePathName
done
fi
done
}
function handler(){
# traverse folder to handle files
confuseFolderTraverse ${rootPath}
echo "-----------------------------------------------------------------------------------------------------------------"
echo "-----------------------------------------------------------------------------------------------------------------"
echo "----------------------------------------------------traverse-----------------------------------------------------"
echo "-----------------------------------------------------------------------------------------------------------------"
echo "-----------------------------------------------------------------------------------------------------------------"
replace ${newRootPath}
}
handler
⑶ python程序代碼混淆、編譯、打包、運行(桌面程序防破解向)
像Python這種解釋性的語言,要想私有化部署的同時又保護好源碼,就像是對於魚和熊掌的追求。
雖然做不到盡善盡美,但是對代碼進行混淆,增加一點破解的難度,或許能規避一些泄露的風險。
本次演示環境:linux
確保要發布的包根目錄("demo")中有__main__.py文件,這個是程序執行入口。
編譯
批量改名.pyc文件
移動.pyc文件
清理.py文件
清理__pycache__文件夾
打包成zip
運行時只要將zip文件作為參數即可
最終整合腳本
調用方式
對於在變數和函數名上的混淆有點小兒科,而對於跨文件的類名的混淆又太容易實現。
所以對於混淆程度的取捨,要視工程的規模而定。
2.1 混淆工具pyminifier
在原來的工具 pyminifier上修復了幾個bug。
安裝:
python3 安裝
或者clone下來,自行安裝
使用例子
2.2 源碼變更
不同的配置對於源碼的要求不同,以下是筆者踩過的坑。
其他混淆想法
結合混淆、編譯和打包,嘗試出以下發布腳本。
主要的思路 :創建一個工作目錄tmp,然後在此目錄下混淆、編譯python代碼,完成後把內容打包成pyc文件,再將pyc文件和其他配置文件移動到dist,發布dist即可。
混淆的目的是最大程度保護源碼,在發布到客戶端後不被輕易破解。
⑷ android 代碼混淆演算法有哪些
根據 SDK 的版本不同有 2 中不同的代碼混淆方式,以上的 proguard.cfg 參數詳解中所涉及到的信息是在較低版本 SDK 下的混淆腳本,事實上在高版本的 SDK 下混淆的原理和參數也與低版本的相差無幾,只是在不同 SDK 版本的環境下引入混淆腳本的方式有所不同。具體方法如下:
低版本 SDK 下,項目中同時包含 proguard.cfg 和 project.properties 文件,則只需在 project.properties 文件末尾添加 proguard.config=proguard.cfg 再將項目 Export 即可。
高版本 SDK 下,項目中同時包含 proguard-project.txt 和 project.properties 文件,這時需要在 proguard-project.txt 文件中進行如下信息的配置,然後再將項目 Export 即可。下面以真實的文件進行演示說明。
復制代碼
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-16
復制代碼
以上的配置信息即是 project.properties 文件中內容,藍色文字為我們在代碼混淆過程中需要添加的配置信息,其中:sdk.dir 為你在當前機器上 SDK 的安裝路徑。如果想保留某個包下的文件不被混淆,可以在 proguard-project.txt 文件中加入保留對應包名的語句即可。
復制代碼
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
-dontwarn com.cnki.android.cnkireader.**
-keep class com.cnki.android.cnkireader.** { *; }
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the javaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
復制代碼
⑸ JS加密混淆後安全嗎
嚴格不能叫加密只是混淆替換了所有的變數名。腳本語言混淆只是可讀性變差了。但是高手會用chrome或者ff的console去調試你的JS所以,安全是相對來說的。。。