安卓脚本开发代码保护

安卓脚本代码混淆防破解实战:javascript-obfuscator 配置详解

安卓脚本怎么防破解?javascript-obfuscator 安装、obfuscator.json 逐项配置(控制流平坦化、字符串数组、RC4 编码)、混淆时机与常见坑。

约 7 分钟

做安卓脚本变现,常碰到脚本被扒走、卡密被绕过、逻辑被改完再传出去。前一篇讲的是网络验证卡密。这篇讲编译期的代码混淆:代码被拖走之后,读起来要费很多劲。

混淆是什么,怎么装

混淆是在 js 编译期间对代码做花指令、流程更改。功能不变,阅读变难。控制流平坦化把顺序执行打乱成状态机跳转,执行路径不好还原。字符串数组把明文字符串打散到数组里,运行时再取回,直接搜关键词不好定位。死代码注入会插入永远不会执行、看起来像真代码的干扰项。RC4 编码对字符串数组做加密,静态分析时看到的是密文。

EasyClick 授权管理界面展示卡密生成、绑定与防破解配置

工具链要两样:Node.js(javascript-obfuscator 跑在 Node 上)和 javascript-obfuscator(npm 全局安装的混淆库)。在 cmd 或 powershell 中执行:

npm install -g javascript-obfuscator
npm install -g class-validator

装完后,用 npm root -g 查看全局安装路径,后面配置会用到。

obfuscator.json 逐项解析,开发关发布开

EC 的 IDEA 开发工具升级到 9.4.0 后,会在工程模块下自动创建一个 obfuscator.json 文件。默认不开启混淆,把 json 里的 binPath(也就是 obfuscatorBinPath)设对之后才会工作。官方默认配置(测试过可运行):

{
  "nodeBinPath": "D:\\programe\\nodejs\\node.exe",
  "obfuscatorBinPath": "C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\javascript-obfuscator\\bin\\javascript-obfuscator",
  "target": "node",
  "compact": false,
  "log": true,
  "optionsPreset": "high-obfuscation",
  "deadCodeInjection": false,
  "simplify": false,
  "seed": 10,
  "controlFlowFlattening": true,
  "controlFlowFlatteningThreshold": 1,
  "unicodeEscapeSequence": false,
  "stringArray": true,
  "stringArrayRotate": false,
  "stringArrayShuffle": false,
  "stringArrayThreshold": 1,
  "stringArrayWrappersCount": 5,
  "stringArrayEncoding": ["rc4"],
  "stringArrayCallsTransform": false,
  "selfDefending": false,
  "splitStrings": false,
  "splitStringsChunkLength": 1
}

注意:配置里的 // 注释是方便解释用的,使用时记得删掉,不然会报错。

路径配置(必须):

属性 作用
nodeBinPath node.exe 的路径
obfuscatorBinPath javascript-obfuscator 可执行文件的路径

安装 Node.js 后,全局安装路径一般是 C:\Users\<用户名>\AppData\Roaming\npm\node_modules,在 node_modules 里找到 javascript-obfuscator 的全路径复制过来即可。混淆强度(重点):

属性 默认值 作用
optionsPreset high-obfuscation 混淆程度预设
controlFlowFlattening true 控制流平坦化,打乱执行顺序
controlFlowFlatteningThreshold 1 平坦化比例,1 = 全部代码
deadCodeInjection false 死代码注入,可开可关
simplify false 代码简化(和混淆相反的方向,保持 false)

字符串保护(重点):

属性 默认值 作用
stringArray true 把字符串提取到数组中
stringArrayEncoding ["rc4"] 字符串数组编码方式,RC4 加密后静态分析只见密文
stringArrayThreshold 1 字符串进数组的比例,1 = 全部
stringArrayWrappersCount 5 包装函数数量,越多越难还原
stringArrayRotate / stringArrayShuffle false 是否轮转/洗牌数组

其他控制项:

属性 默认值 作用
compact false 是否压缩代码
log true 编译期间展示混淆详细信息,便于确认混淆生效
seed 10 随机种子,固定种子保证每次混淆结果可复现
unicodeEscapeSequence false 是否转义为 unicode
selfDefending false 自防御:被格式化就失效(需谨慎开启,易误伤)
splitStrings false 拆分长字符串

混淆什么时候发生:obfuscator.json 里 obfuscatorBinPath 配了、而且文件存在,编译时就会混淆,js 模式和 dex 模式都包括。删掉 obfuscatorBinPath 的值,或者直接删掉 obfuscator.json,编译期间就不混淆。混淆比较吃电脑资源。平时调试关掉,发布、打包的时候再开。开发期开着,每次编译都慢,混淆后的代码也不好调试。

和卡密、指纹一起用

混淆单独用,挡不住下决心的人。官方的建议是几样一起上。网络验证卡密:卡密绑定设备、心跳验证,没有卡就跑不起来。关键代码再混淆,比如授权校验和核心算法,不必整包都混淆。包名、apk、脚本指纹验证每次打包要上传记录,用来防换壳和篡改。关键业务还可以放到远程变量和远程 js 里,发现被破解就换远程代码、停掉脚本。有人还会在远程变量里放破坏性代码,比如格式化 sdcard、删除联系人,触发之前要想清楚后果。

nodeBinPath 和 obfuscatorBinPath 两个路径配好就会生效,其余参数按上面的表调。默认的高强度方案是控制流平坦化、字符串数组、RC4 编码。开发期关、发布期开。混淆抬高的是阅读成本,不能保证永远破不开。

想要真实跑起来?

本文介绍的方案均可基于 EasyClick 能力在 iEasyClick 落地。官网提供完整文档、开发工具与自动化产品,免费体验。

访问 iEasyClick 官网 →