java调用js文件的两种方法(支持V8引擎)

2025-12-18 18:07:28

前言

对java逆向感兴趣的盆友可以关注我以前的文章,有图片验证码识别、AES、SHA256等各种加密的java实现,不定时更新常用算法和加密,欢迎一起交流讨论!

在日常逆向中,一些前端的加密代码用java复现出来比较难,所以经常需要调用js文件来实现加密操作,接下来将介绍两种常用调用js的思路,第一种适用于普通js文件,第二种则适用于比较新的V8引擎。在实现的过程中,也会展示可能遇到的问题以及解决办法,废话不多话,正文开始!

方法一

本方法用的是jdk自带的ScriptEngine来实现,大概流程是:加载引擎->绑定环境->预编译js文件->调用文件内方法,具体实现代码:

import javax.script.*;

import java.io.InputStreamReader;

//因为js文件读取一次就行,因此用静态代码块来读取

private static ScriptEngine engine;

static {

try {

ScriptEngineManager manager = new ScriptEngineManager();

engine = manager.getEngineByName("javascript");

Bindings engineScope = engine.getBindings(ScriptContext.ENGINE_SCOPE);

engineScope.put("window", engineScope);

engineScope.put("navigator", engineScope);

InputStreamReader jsencryptFileReader = new InputStreamReader(EncJs.class.getClassLoader().getResourceAsStream("enc.js"));

engine.eval(jsencryptFileReader);

jsencryptFileReader.close();

} catch (Exception e) {

e.printStackTrace();

}

}

读取完js后,就可以使用js引擎来直接用invokeFunction方法来调用文件内函数,代码如下

public static String enc(String data, String key) {

Invocable invoke = (Invocable) engine;

try {

String result = (String) invoke.invokeFunction("Enc", data, key);

return result.toUpperCase();

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

在上边代码invoke.invokeFunction("Enc", data, key)中,Enc为js文件内的函数名,data和key是需要方法需要传递的参数,如果方法只有一个参数,则传入一个,如果是多个参数,则按顺序排列在后边即可。

上边代码在执行普通js时比较方便使用,但是如果是比较新的开发版本,有些语法会不支持,像lambda表达式等,如下图:

此处再介绍一种方法,使用的是V8引擎,可以支持最新语法

方法二

使用到的maven依赖,以下依赖根据自己环境任选其一即可。

com.eclipsesource.j2v8

j2v8_linux_x86_64

3.1.6

com.eclipsesource.j2v8

j2v8_macosx_x86_64

4.6.0

com.eclipsesource.j2v8

j2v8_win32_x86_64

4.6.0

这个的实现流程和上边稍微有些不同,也是:预读取js文件>加载引擎->编译js文件->调用文件内方法,具体实现代码如下:

import com.eclipsesource.v8.V8;

import org.apache.commons.io.IOUtils;

import java.io.IOException;

import java.nio.charset.StandardCharsets;

public class V8JSUtils {

private static String fileStr;

static {

try {

fileStr = IOUtils.toString(V8JSUtils.class.getClassLoader().getResourceAsStream("enc.js"), StandardCharsets.UTF_8);

} catch (IOException e) {

e.printStackTrace();

}

}

public static String dec(String data, String key) {

V8 runtime = V8.createV8Runtime();

try {

runtime.executeVoidScript(fileStr);

return (String) runtime.executeJSFunction("Dec", data, key);

} catch (Exception e) {

e.printStackTrace();

} finally {

runtime.release();

}

return null;

}

}

代码写完了,调用一下结果还是遇到了错误

这个错误的大概意思就是:严格模式外不能使用let,const之类的es6的命令,也就是说版本太低了,怎么办,更新版本?no no no,找到JS文件出错的代码位置,在方法前加上一句:'use strict';

注意!引号不能省略,必须全部复制,如图

现在再运行就正常了。