Skip to content

Commit

Permalink
Merge pull request #1 from xxxxue/mycode
Browse files Browse the repository at this point in the history
feat: 命令行参数添加 优化等级 与 禁用字符串加密
  • Loading branch information
xxxxue authored Jun 26, 2023
2 parents 2365002 + 103b824 commit 29ddcb0
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 89 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# 魔改 Rhino 1.7.14
将 js 转为 dex . 移除js源码字段, 加密所有字符串, 防止被轻易破解


`其他版本请查看其他分支`

# 环境
Expand All @@ -13,22 +12,32 @@ JDK 8

到 jar 文件的所在目录执行命令

`-f` 是想要转换的 js 文件
## 参数

`-o` 是输出的目录
必填项

`-f` 想要转换的 js 文件

`-o` 输出的目录

可选项

`-l` Rhino 优化等级 (例子: -l 5) ( 传参 -1 ~ 9 默认 9 )

`-s` 禁用字符串加密 (程序默认会加密字符串, 命令中添加 `-s` 则禁用加密字符串)

最终会生成一个 `aaa.dex` 文件.

```bash
java -jar .\rhino-Rhino1_7_14_Release-1.7.14.jar -f E:\Work\AutojsProject\autox-super-kit\out\main.js -o E:\Work\AutojsProject\autox-super-kit\out\dist\
java -jar .\rhino-Rhino1_7_14_Release-1.7.14.jar -f E:\autox-super-kit\out\main.js -o E:\autox-super-kit\out\dist\
```

![image](https://github.com/xxxxue/Autojs_Rhino_Dex/assets/32764266/518488de-f9a0-41e5-b646-4794f4e63c67)
最终会生成一个 `aaa.dex` 文件.

autojs 核心代码:
调用 dex :
```javascript
//autojs 加载 dex 并运行
// autojs 加载 dex
runtime.loadDex("/sdcard/xxx辅助/aaa.dex");
// 运行
new Packages["aaa"]()();
```
更多代码 请看底部的 热更新小例子
Expand Down
52 changes: 21 additions & 31 deletions src/defpackage/StrUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@
import org.mozilla.classfile.ByteCode;
import org.mozilla.classfile.ClassFileWriter;

public class StrUtils
{
import static org.mozilla.mycode.Main._isNoEncryptString;

public class StrUtils {

/**
* 字符串加密
*/
public static String e(String data)
{
public static String e(String data) {
byte[] b = data.getBytes();
for (int i = 0; i < b.length; i++)
{
for (int i = 0; i < b.length; i++) {
b[i] = (byte) (b[i] + 1);
}
StringBuilder hex = new StringBuilder();
for (int i2 = 0; i2 < b.length; i2++)
{
for (int i2 = 0; i2 < b.length; i2++) {
hex.append(String.format("%02X", Byte.valueOf(b[i2])));
}
return hex.toString();
Expand All @@ -27,16 +25,13 @@ public static String e(String data)
/**
* 字符串解密
*/
public static String d(String data)
{
public static String d(String data) {
int l = data.length() / 2;
byte[] b = new byte[l];
for (int i = 0; i < l; i++)
{
for (int i = 0; i < l; i++) {
b[i] = Integer.valueOf(data.substring(i * 2, (i * 2) + 2), 16).byteValue();
}
for (int i2 = 0; i2 < b.length; i2++)
{
for (int i2 = 0; i2 < b.length; i2++) {
b[i2] = (byte) (b[i2] - 1);
}
return new String(b);
Expand All @@ -45,14 +40,11 @@ public static String d(String data)
/**
* 加密,把一个字符串在原有的基础上 加一个数值
*/
public static String e2(String data)
{

public static String e2(String data) {
//把字符串转为字节数组
byte[] b = data.getBytes();
//遍历
for (int i = 0; i < b.length; i++)
{
for (int i = 0; i < b.length; i++) {
b[i] += 3;//在原有的基础上 加一个数值
}
return new String(b);
Expand All @@ -64,13 +56,11 @@ public static String e2(String data)
* @param data 加密后的字符串
* @return 返回解密后的新字符串
*/
public static String d2(String data)
{
public static String d2(String data) {
//把字符串转为字节数组
byte[] b = data.getBytes();
//遍历
for (int i = 0; i < b.length; i++)
{
for (int i = 0; i < b.length; i++) {
b[i] -= 3;//在原有的基础上 减一个数
}
return new String(b);
Expand All @@ -79,16 +69,16 @@ public static String d2(String data)
/**
* 字符串加密
*/
public static void strE(ClassFileWriter cfw, String content)
{
//System.out.println(content);
if (content.isEmpty())
{
//为空 则 不调用 解密..
public static void strE(ClassFileWriter cfw, String content) {
// 禁用加密
if (_isNoEncryptString) {
cfw.addPush(content);
return;
}
else
{
if (content.isEmpty()) {
//为空 则 不调用 解密..
cfw.addPush(content);
} else {
cfw.addPush(StrUtils.e(content));
cfw.addInvoke(ByteCode.INVOKESTATIC, "defpackage.StrUtils", "d", "(Ljava/lang/String;)" +
"Ljava/lang/String;");
Expand Down
111 changes: 61 additions & 50 deletions src/org/mozilla/mycode/main.java → src/org/mozilla/mycode/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.CharsetUtil;
import com.itranswarp.compiler.JavaStringCompiler;
import org.mozilla.javascript.CompilerEnvirons;
Expand All @@ -17,14 +16,17 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

class Main {
public class Main {

static final String JAVA_SOURCE_CODE = "" +
"package defpackage;" +
/**
* 解密函数
*/
static final String _javaSourceCode = "package defpackage;" +
"import org.mozilla.classfile.ByteCode;" +
"import org.mozilla.classfile.ClassFileWriter;" +
"public class StrUtils{" +
Expand All @@ -44,97 +46,110 @@ class Main {
" }" +
" } ";

// 工作的目录
/**
* 工作的目录
*/
public static String _outDirPath = "";

/**
* Rhino 加密等级
*/
public static Integer _level = 9;

/**
* 禁用加密
*/
public static Boolean _isNoEncryptString = false;
public static String _dxFileName = "dx-29.0.3.jar";

public static void main(String[] args) throws Exception {

// 创建 Options 对象
Options options = new Options();
options.addOption("f", "file", true, "输入文件");
options.addOption("o", "output", true, "输出的目录");

// 创建 CommandLineParser 对象
CommandLineParser parser = new DefaultParser();
options.addRequiredOption("f", "file", true, "输入文件");
options.addRequiredOption("o", "output", true, "输出的目录");
// -1 .. 9
options.addOption("l", "level", true, "Rhino 优化等级");
options.addOption("s", "string", false, "禁用字符串加密");

try {
// 解析命令行参数
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);

// 获取解析后的参数值
String inputFile = cmd.getOptionValue("f");
String outputDir = cmd.getOptionValue("o");
String inputFilePath = cmd.getOptionValue("f");
String outputDirPath = cmd.getOptionValue("o");


// 打印参数值
System.out.println("输入文件:" + inputFile);
System.out.println("输出文件夹:" + outputDir);
// 输出目录 再创建一个唯一的文件夹 (使用当前时间精确到秒)
_outDirPath = outputDir + "\\" + getTimeString() + "\\";
_outDirPath = Paths.get(outputDirPath, getTimeString()).toString();
_level = Integer.valueOf(cmd.getOptionValue('l', "9"));
_isNoEncryptString = cmd.hasOption('s');

System.out.println("===================================");
System.out.println("===================================");
System.out.println("输入文件:" + inputFilePath);
System.out.println("输出文件夹:" + outputDirPath);
System.out.println("最终的输出地址:" + _outDirPath);
System.out.println("Rhino 优化等级:" + _level);
System.out.println("禁用字符串加密:" + _isNoEncryptString);
System.out.println("===================================");
System.out.println("===================================");

// 将 当前 jar 程序中的 dx.jar 释放到 outputDir 目录
byte[] fileData = ResourceUtil.readBytes("dx-29.0.3.jar");
FileUtil.writeBytes(fileData, _outDirPath + "dx-29.0.3.jar");
byte[] fileData = ResourceUtil.readBytes(_dxFileName);
FileUtil.writeBytes(fileData, Paths.get(_outDirPath, _dxFileName).toString());

String code = FileUtil.readUtf8String(inputFilePath);

toClassFile(FileUtil.readUtf8String(inputFile));
toDexFile(code);

} catch (ParseException e) {
// 解析失败,打印错误消息
System.err.println("命令行参数解析失败: " + e.getMessage());
}

// String filePath = "E:\\Work\\AutojsProject\\autox-super-kit\\out\\main.js";
}

/**
* 获取时间 字符串
*
* @return
*/

public static String getTimeString() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss");
return formatter.format(date);
}

//这里注意传参是 js 文本数据,不是 js 路径
static void toClassFile(String script) throws Exception {
static void toDexFile(String code) throws Exception {
//创建 Rhino 编译环境 相关参数..
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.setGeneratingSource(false); //编译后,不添加 js 源码
compilerEnv.setLanguageVersion(Context.VERSION_ES6); //设置 支持es6
compilerEnv.setOptimizationLevel(9); // 优化等级改为 9 级. 如果有问题 就改成0
compilerEnv.setOptimizationLevel(_level); // 优化等级 -1..9
ClassCompiler compiler = new ClassCompiler(compilerEnv);

// compileToClassFiles 的第4个参数比较重要,它表明了js转成.class的类路径,影响到 在 autojs 调用的方法
// 不填写包名 则 默认在 defpackage 中

// auto js调用例子 (如果autojs闪退.就是抛出了异常.请使用开源的autojs 代码, 使用 AdnroidStudio 进行调试,查看异常)
// auto.js调用例子 (如果auto.js闪退.就是抛出了异常.可以使用 adb logcat 查看日志 或者 用开源的 auto.js 代码, 使用 AndroidStudio 进行调试,查看异常)
// var localDexPath= "/sdcard/辅助/aaa.dex"
// runtime.loadDex(localDexPath);
// new Packages["aaa"]()();
//
Object[] compiled = compiler.compileToClassFiles(
script,
code,
null,
1,
"aaa");

for (int j = 0; j != compiled.length; j += 2) {
//String className = (String) compiled[j];

JavaStringCompiler compiler2 = new JavaStringCompiler();

// 字符串 转为 java class 文件
Map<String, byte[]> results = compiler2.compile("StrUtils.java", JAVA_SOURCE_CODE);
JavaStringCompiler javaStringCompiler = new JavaStringCompiler();

Console.log(results);
// 字符串 转为 java class 文件
Map<String, byte[]> results = javaStringCompiler.compile("StrUtils.java", _javaSourceCode);

//解密工具类的 数据
byte[] utilsBytes = results.get("defpackage.StrUtils");

String utilsClassPath = _outDirPath + "class\\defpackage\\StrUtils.class";
String utilsClassPath = Paths.get(_outDirPath, "class", "defpackage", "StrUtils.class").toString();
File utilsFile = new File(utilsClassPath);
utilsFile.getParentFile().mkdirs(); //创建文件夹

Expand All @@ -148,10 +163,9 @@ static void toClassFile(String script) throws Exception {
e.printStackTrace();
}

//------------
String classPath = _outDirPath + "class\\aaa.class";
String classPath = Paths.get(_outDirPath, "class", "aaa.class").toString();

//js 转为 class
// js 转为 class
byte[] bytes = (byte[]) compiled[(j + 1)];
File file = new File(classPath);
file.getParentFile().mkdirs(); //创建文件夹
Expand All @@ -166,16 +180,15 @@ static void toClassFile(String script) throws Exception {
e.printStackTrace();
}

String jarFileName = "code.jar";
//将两个 class 打包为 一个jar
cmdExec("jar cvf demo.jar -C class .");
cmdExec("jar cvf " + jarFileName + " -C class .");

System.out.println(utilsFile.exists());
System.out.println("开始转dex,js代码越多,耗时越长,请耐心等待");

//将 jar 转为 dex
cmdExec("java -jar dx-29.0.3.jar --dex " +
"--output=aaa.dex " +
"demo.jar");
System.out.println();
cmdExec("java -jar " + _dxFileName + " --dex --output=aaa.dex " + jarFileName);

System.out.println();
System.out.println("===================================");
System.out.println("js 转 dex 结束");
Expand All @@ -187,8 +200,6 @@ static void toClassFile(String script) throws Exception {

/**
* 执行cmd命令
*
* @param cmd
*/
public static void cmdExec(String cmd) {

Expand Down

0 comments on commit 29ddcb0

Please sign in to comment.