脚本混淆
⑴ 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所以,安全是相对来说的。。。