Lua virtualsation toolset in Java
Lua virtualsation toolset in Java
To be used to analyse and other things on compiled lua scripts
The file parser works for all luac compiled files from version 5.0 -> 5.3 Here is some simple code to read a compiled file:
...
byte[] data = ...;
LuaDataStream stream = new LuaDataStream(data);
LuaFileReader reader = new LuaFileReader(stream);
LuaFile file = reader.read();
Disassembly gives direct insight into the programs behaviour and operations
...
LuaFunction main = file.getFunction();
Disassembler disasm = new Disassembler(main, System.out);
disasm.disassemble(); // print disassembly to main
// assuming that some function calls get set up in this sample
ClosureInstruction inst = main.getInstructions().get(0);
// get the function referenced by this instruction
LuaFunction refFunction = inst.getProto();
...
The Virtual machine allows for virtualizing and executing compiled bytecode allowing for full static analysis of lua binaries
// prepare a vm
VM vm = new VM();
vm.initialize();
// execute the main function
ExecutionContext result = vm.getHelper().invoke(main, vm.getGlobal());
Value val = results.get(0); // get R0
System.out.println(val.asString()); // print R0
In the vm it is possible to overwrite functions to give control what these do, this includes library functions
// get the vm libraries
Libraries libs = vm.getLibraries();
Library base = libs.getTop(); // get the top library (the base library)
// choose a method (in this case 'print')
// then provide a new method to execute
base.set("print", (ctx) -> {
System.out.println("Custom print call!");
});
// or during/before execution access the global table and overwrite functions directly
Table global = vm.getGlobal();
// first define a new Closure
Closure customClosure = new Closure((ctx) -> {
System.out.println("Intercepted call!");
});
// wrap in ClosureValue
ClosureValue value = new ClosureValue(customClosure);
// set new closure
global.set("customFunction", value);
It is also possible to overwrite the behaviour of specific instructions entirely
vm.getInterpreter().install(Opcodes.MOVE, (Executor<LoadInstruction>) (insn, ctx) -> {
System.out.println("Custom instructions");
});