mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2024-11-27 02:40:51 +01:00
new & improved wasmcodepatcher
This commit is contained in:
parent
37adbdb600
commit
44bd70a6aa
7
G-Earth/src/main/java/gearth/services/Constants.java
Normal file
7
G-Earth/src/main/java/gearth/services/Constants.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package gearth.services;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static volatile boolean UNITY_PACKETS = false;
|
||||||
|
|
||||||
|
}
|
@ -1,27 +1,27 @@
|
|||||||
package gearth.services.unity_tools;
|
package gearth.services.unity_tools;
|
||||||
|
|
||||||
|
import com.sun.org.apache.xpath.internal.operations.Mod;
|
||||||
|
import gearth.services.unity_tools.codepatcher.IncomingPacketPatcher;
|
||||||
|
import gearth.services.unity_tools.codepatcher.OutgoingPacketPatcher;
|
||||||
|
import gearth.services.unity_tools.codepatcher.ReturnBytePatcher;
|
||||||
|
import gearth.services.unity_tools.codepatcher.SetKeyPatcher;
|
||||||
import wasm.disassembly.InvalidOpCodeException;
|
import wasm.disassembly.InvalidOpCodeException;
|
||||||
import wasm.disassembly.instructions.Expression;
|
|
||||||
import wasm.disassembly.instructions.Instr;
|
import wasm.disassembly.instructions.Instr;
|
||||||
import wasm.disassembly.instructions.InstrType;
|
import wasm.disassembly.instructions.InstrType;
|
||||||
import wasm.disassembly.instructions.control.CallInstr;
|
|
||||||
import wasm.disassembly.instructions.variable.LocalVariableInstr;
|
|
||||||
import wasm.disassembly.modules.Module;
|
import wasm.disassembly.modules.Module;
|
||||||
import wasm.disassembly.modules.indices.FuncIdx;
|
|
||||||
import wasm.disassembly.modules.indices.LocalIdx;
|
|
||||||
import wasm.disassembly.modules.indices.TypeIdx;
|
|
||||||
import wasm.disassembly.modules.sections.code.Func;
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
import wasm.disassembly.modules.sections.export.Export;
|
import wasm.disassembly.modules.sections.code.Locals;
|
||||||
import wasm.disassembly.modules.sections.export.ExportDesc;
|
|
||||||
import wasm.disassembly.modules.sections.imprt.Import;
|
import wasm.disassembly.modules.sections.imprt.Import;
|
||||||
import wasm.disassembly.modules.sections.imprt.ImportDesc;
|
import wasm.disassembly.modules.sections.imprt.ImportDesc;
|
||||||
import wasm.disassembly.types.FuncType;
|
import wasm.disassembly.types.FuncType;
|
||||||
import wasm.disassembly.types.ResultType;
|
import wasm.disassembly.types.ResultType;
|
||||||
import wasm.disassembly.types.ValType;
|
import wasm.disassembly.types.ValType;
|
||||||
import wasm.misc.Function;
|
import wasm.misc.CodeCompare;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class WasmCodePatcher {
|
public class WasmCodePatcher {
|
||||||
|
|
||||||
@ -32,194 +32,12 @@ public class WasmCodePatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void patch() throws IOException, InvalidOpCodeException {
|
public void patch() throws IOException, InvalidOpCodeException {
|
||||||
Module module = new Module(file);
|
Module module = new Module(file, Arrays.asList(
|
||||||
|
new SetKeyPatcher(),
|
||||||
FuncIdx returnByteId = findReturnByteFunc(module);
|
new ReturnBytePatcher(),
|
||||||
FuncIdx setkey = findSetKeyFunc(module);
|
new OutgoingPacketPatcher(),
|
||||||
FuncIdx outgoingIdx = findOutFunc(module);
|
new IncomingPacketPatcher()
|
||||||
FuncIdx incomingIdx = findInFunc(module);
|
));
|
||||||
|
|
||||||
hook(module, setkey, "g_chacha_setkey");
|
|
||||||
copyEmptyHook(module, returnByteId, "_gearth_returnbyte_copy", "g_chacha_returnbyte");
|
|
||||||
copyEmptyHook(module, outgoingIdx, "_gearth_outgoing_copy", "g_outgoing_packet");
|
|
||||||
copyEmptyHook(module, incomingIdx, "_gearth_incoming_copy", "g_incoming_packet");
|
|
||||||
|
|
||||||
module.assembleToFile(file);
|
module.assembleToFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private FuncIdx findOutFunc(Module module) {
|
|
||||||
TypeIdx expectedTypeIdx = module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
|
||||||
new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
|
||||||
new ResultType(Collections.emptyList())
|
|
||||||
));
|
|
||||||
|
|
||||||
outerloop:
|
|
||||||
for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
|
||||||
FuncIdx currentIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
|
||||||
|
|
||||||
Func func = module.getCodeSection().getByIdx(currentIdx);
|
|
||||||
if (func.getLocalss().size() != 0) continue;
|
|
||||||
if (!module.getFunctionSection().getByIdx(currentIdx).equals(expectedTypeIdx)) continue;
|
|
||||||
|
|
||||||
List<Instr> expression = func.getExpression().getInstructions();
|
|
||||||
|
|
||||||
if (expression.size() != 6) continue;
|
|
||||||
|
|
||||||
if (expression.get(0).getInstrType() != InstrType.LOCAL_GET) continue;
|
|
||||||
if (expression.get(1).getInstrType() != InstrType.LOCAL_GET) continue;
|
|
||||||
if (expression.get(2).getInstrType() != InstrType.LOCAL_GET) continue;
|
|
||||||
if (expression.get(3).getInstrType() != InstrType.I32_LOAD) continue;
|
|
||||||
if (expression.get(4).getInstrType() != InstrType.I32_CONST) continue;
|
|
||||||
if (expression.get(5).getInstrType() != InstrType.CALL) continue;
|
|
||||||
|
|
||||||
return currentIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private FuncIdx findSetKeyFunc(Module module) {
|
|
||||||
FuncType expectedType = new FuncType(
|
|
||||||
new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
|
||||||
new ResultType(Collections.emptyList())
|
|
||||||
);
|
|
||||||
|
|
||||||
List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
|
||||||
InstrType.I32_EQZ, InstrType.IF, InstrType.BLOCK, InstrType.LOCAL_GET, InstrType.I32_CONST,
|
|
||||||
InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.I32_CONST, InstrType.I32_CONST, InstrType.I32_CONST,
|
|
||||||
InstrType.CALL);
|
|
||||||
|
|
||||||
outerloop:
|
|
||||||
for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
|
||||||
FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
|
||||||
|
|
||||||
Function function = new Function(module, funcIdx);
|
|
||||||
if (!function.getFuncType().equals(expectedType)) continue;
|
|
||||||
if (!(function.getLocalsFloored().size() == 1 && function.getLocalsFloored().get(0) == ValType.I32)) continue;
|
|
||||||
if (function.getCode().getInstructions().size() != expectedExpr.size()) continue;
|
|
||||||
|
|
||||||
for (int j = 0; j < function.getCode().getInstructions().size(); j++) {
|
|
||||||
Instr instr = function.getCode().getInstructions().get(j);
|
|
||||||
if (instr.getInstrType() != expectedExpr.get(j)) continue outerloop;
|
|
||||||
}
|
|
||||||
|
|
||||||
return funcIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private FuncIdx findReturnByteFunc(Module module) {
|
|
||||||
FuncType expectedType = new FuncType(
|
|
||||||
new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
|
||||||
new ResultType(Collections.singletonList(ValType.I32))
|
|
||||||
);
|
|
||||||
|
|
||||||
outerloop:
|
|
||||||
for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
|
||||||
FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
|
||||||
|
|
||||||
Function function = new Function(module, funcIdx);
|
|
||||||
if (!function.getFuncType().equals(expectedType)) continue;
|
|
||||||
if (function.getLocalsFloored().size() != 0) continue;
|
|
||||||
if (function.getCode().getInstructions().size() != 30) continue;
|
|
||||||
|
|
||||||
List<Instr> expr = function.getCode().getInstructions();
|
|
||||||
if (expr.get(expr.size() - 1).getInstrType() != InstrType.I32_XOR) continue;
|
|
||||||
|
|
||||||
return funcIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private FuncIdx findInFunc(Module module) {
|
|
||||||
FuncType expectedType = new FuncType(
|
|
||||||
new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
|
||||||
new ResultType(Collections.emptyList())
|
|
||||||
);
|
|
||||||
|
|
||||||
List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
|
||||||
InstrType.I32_EQZ, InstrType.IF, InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.LOCAL_TEE,
|
|
||||||
InstrType.IF);
|
|
||||||
|
|
||||||
outerloop:
|
|
||||||
for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
|
||||||
FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
|
||||||
|
|
||||||
Function function = new Function(module, funcIdx);
|
|
||||||
if (!function.getFuncType().equals(expectedType)) continue;
|
|
||||||
if (!(function.getLocalsFloored().size() == 1 && function.getLocalsFloored().get(0) == ValType.I32)) continue;
|
|
||||||
if (function.getCode().getInstructions().size() != expectedExpr.size()) continue;
|
|
||||||
|
|
||||||
for (int j = 0; j < function.getCode().getInstructions().size(); j++) {
|
|
||||||
Instr instr = function.getCode().getInstructions().get(j);
|
|
||||||
if (instr.getInstrType() != expectedExpr.get(j)) continue outerloop;
|
|
||||||
}
|
|
||||||
|
|
||||||
return funcIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyEmptyHook(Module module, FuncIdx orgFuncIdx, String exportName, String hookname) throws InvalidOpCodeException, IOException {
|
|
||||||
// copies the method, empties the first one
|
|
||||||
// export the copy
|
|
||||||
// hooks to the emptied one
|
|
||||||
|
|
||||||
Func func = module.getCodeSection().getByIdx(orgFuncIdx);
|
|
||||||
FuncType funcType = module.getTypeSection().getByFuncIdx(orgFuncIdx);
|
|
||||||
|
|
||||||
// copy the function
|
|
||||||
Function copy = new Function(funcType, func.getLocalss(), func.getExpression());
|
|
||||||
FuncIdx copyIdx = copy.addToModule(module);
|
|
||||||
|
|
||||||
module.getExportSection().getExports().add(new Export(exportName, new ExportDesc(copyIdx)));
|
|
||||||
|
|
||||||
|
|
||||||
// clear & hook original function, let it return whatever JS returns
|
|
||||||
Import imp = new Import(
|
|
||||||
"env",
|
|
||||||
hookname,
|
|
||||||
new ImportDesc(module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
|
||||||
funcType.getParameterType(),
|
|
||||||
funcType.getResultType()
|
|
||||||
)))
|
|
||||||
);
|
|
||||||
FuncIdx hookIdx = module.getImportSection().importFunction(imp);
|
|
||||||
|
|
||||||
CallInstr call = new CallInstr(hookIdx);
|
|
||||||
List<Instr> newInstrs = new ArrayList<>();
|
|
||||||
for (int i = 0; i < funcType.getParameterType().typeList().size(); i++) {
|
|
||||||
newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(i)));
|
|
||||||
}
|
|
||||||
newInstrs.add(call);
|
|
||||||
func.setExpression(new Expression(newInstrs));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hook(Module module, FuncIdx funcIdx, String jsFunctionName) throws InvalidOpCodeException, IOException {
|
|
||||||
FuncType funcType = module.getTypeSection().getByFuncIdx(funcIdx);
|
|
||||||
|
|
||||||
Import imp = new Import(
|
|
||||||
"env",
|
|
||||||
jsFunctionName,
|
|
||||||
new ImportDesc(module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
|
||||||
funcType.getParameterType(),
|
|
||||||
new ResultType(Collections.emptyList())
|
|
||||||
)))
|
|
||||||
);
|
|
||||||
FuncIdx hookIdx = module.getImportSection().importFunction(imp);
|
|
||||||
|
|
||||||
CallInstr call = new CallInstr(hookIdx);
|
|
||||||
|
|
||||||
Func root = module.getCodeSection().getByIdx(funcIdx);
|
|
||||||
List<Instr> newInstrs = new ArrayList<>();
|
|
||||||
for (int i = 0; i < funcType.getParameterType().typeList().size(); i++) {
|
|
||||||
newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(i)));
|
|
||||||
}
|
|
||||||
newInstrs.add(call);
|
|
||||||
newInstrs.addAll(root.getExpression().getInstructions());
|
|
||||||
root.getExpression().setInstructions(newInstrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,225 @@
|
|||||||
|
//package gearth.services.unity_tools;
|
||||||
|
//
|
||||||
|
//import wasm.disassembly.InvalidOpCodeException;
|
||||||
|
//import wasm.disassembly.instructions.Expression;
|
||||||
|
//import wasm.disassembly.instructions.Instr;
|
||||||
|
//import wasm.disassembly.instructions.InstrType;
|
||||||
|
//import wasm.disassembly.instructions.control.CallInstr;
|
||||||
|
//import wasm.disassembly.instructions.variable.LocalVariableInstr;
|
||||||
|
//import wasm.disassembly.modules.Module;
|
||||||
|
//import wasm.disassembly.modules.indices.FuncIdx;
|
||||||
|
//import wasm.disassembly.modules.indices.LocalIdx;
|
||||||
|
//import wasm.disassembly.modules.indices.TypeIdx;
|
||||||
|
//import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
//import wasm.disassembly.modules.sections.export.Export;
|
||||||
|
//import wasm.disassembly.modules.sections.export.ExportDesc;
|
||||||
|
//import wasm.disassembly.modules.sections.imprt.Import;
|
||||||
|
//import wasm.disassembly.modules.sections.imprt.ImportDesc;
|
||||||
|
//import wasm.disassembly.types.FuncType;
|
||||||
|
//import wasm.disassembly.types.ResultType;
|
||||||
|
//import wasm.disassembly.types.ValType;
|
||||||
|
//import wasm.misc.Function;
|
||||||
|
//
|
||||||
|
//import java.io.*;
|
||||||
|
//import java.util.*;
|
||||||
|
//
|
||||||
|
//public class WasmCodePatcherOld {
|
||||||
|
//
|
||||||
|
// private String file;
|
||||||
|
//
|
||||||
|
// public WasmCodePatcherOld(String file) {
|
||||||
|
// this.file = file;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void patch() throws IOException, InvalidOpCodeException {
|
||||||
|
// Module module = new Module(file);
|
||||||
|
//
|
||||||
|
// FuncIdx returnByteId = findReturnByteFunc(module);
|
||||||
|
// FuncIdx setkey = findSetKeyFunc(module);
|
||||||
|
// FuncIdx outgoingIdx = findOutFunc(module);
|
||||||
|
// FuncIdx incomingIdx = findInFunc(module);
|
||||||
|
//
|
||||||
|
// hook(module, setkey, "g_chacha_setkey");
|
||||||
|
// copyEmptyHook(module, returnByteId, "_gearth_returnbyte_copy", "g_chacha_returnbyte");
|
||||||
|
// copyEmptyHook(module, outgoingIdx, "_gearth_outgoing_copy", "g_outgoing_packet");
|
||||||
|
// copyEmptyHook(module, incomingIdx, "_gearth_incoming_copy", "g_incoming_packet");
|
||||||
|
//
|
||||||
|
// module.assembleToFile(file);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// private FuncIdx findOutFunc(Module module) {
|
||||||
|
// TypeIdx expectedTypeIdx = module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// ));
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx currentIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Func func = module.getCodeSection().getByIdx(currentIdx);
|
||||||
|
// if (func.getLocalss().size() != 0) continue;
|
||||||
|
// if (!module.getFunctionSection().getByIdx(currentIdx).equals(expectedTypeIdx)) continue;
|
||||||
|
//
|
||||||
|
// List<Instr> expression = func.getExpression().getInstructions();
|
||||||
|
//
|
||||||
|
// if (expression.size() != 6) continue;
|
||||||
|
//
|
||||||
|
// if (expression.get(0).getInstrType() != InstrType.LOCAL_GET) continue;
|
||||||
|
// if (expression.get(1).getInstrType() != InstrType.LOCAL_GET) continue;
|
||||||
|
// if (expression.get(2).getInstrType() != InstrType.LOCAL_GET) continue;
|
||||||
|
// if (expression.get(3).getInstrType() != InstrType.I32_LOAD) continue;
|
||||||
|
// if (expression.get(4).getInstrType() != InstrType.I32_CONST) continue;
|
||||||
|
// if (expression.get(5).getInstrType() != InstrType.CALL) continue;
|
||||||
|
//
|
||||||
|
// return currentIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// private FuncIdx findSetKeyFunc(Module module) {
|
||||||
|
// FuncType expectedType = new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
// InstrType.I32_EQZ, InstrType.IF, InstrType.BLOCK, InstrType.LOCAL_GET, InstrType.I32_CONST,
|
||||||
|
// InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.I32_CONST, InstrType.I32_CONST, InstrType.I32_CONST,
|
||||||
|
// InstrType.CALL);
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Function function = new Function(module, funcIdx);
|
||||||
|
// if (!function.getFuncType().equals(expectedType)) continue;
|
||||||
|
// if (!(function.getLocalsFloored().size() == 1 && function.getLocalsFloored().get(0) == ValType.I32)) continue;
|
||||||
|
// if (function.getCode().getInstructions().size() != expectedExpr.size()) continue;
|
||||||
|
//
|
||||||
|
// for (int j = 0; j < function.getCode().getInstructions().size(); j++) {
|
||||||
|
// Instr instr = function.getCode().getInstructions().get(j);
|
||||||
|
// if (instr.getInstrType() != expectedExpr.get(j)) continue outerloop;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return funcIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// private FuncIdx findReturnByteFunc(Module module) {
|
||||||
|
// FuncType expectedType = new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.singletonList(ValType.I32))
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Function function = new Function(module, funcIdx);
|
||||||
|
// if (!function.getFuncType().equals(expectedType)) continue;
|
||||||
|
// if (function.getLocalsFloored().size() != 0) continue;
|
||||||
|
// if (function.getCode().getInstructions().size() != 30) continue;
|
||||||
|
//
|
||||||
|
// List<Instr> expr = function.getCode().getInstructions();
|
||||||
|
// if (expr.get(expr.size() - 1).getInstrType() != InstrType.I32_XOR) continue;
|
||||||
|
//
|
||||||
|
// return funcIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// private FuncIdx findInFunc(Module module) {
|
||||||
|
// FuncType expectedType = new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
// InstrType.I32_EQZ, InstrType.IF, InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.LOCAL_TEE,
|
||||||
|
// InstrType.IF);
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Function function = new Function(module, funcIdx);
|
||||||
|
// if (!function.getFuncType().equals(expectedType)) continue;
|
||||||
|
// if (!(function.getLocalsFloored().size() == 1 && function.getLocalsFloored().get(0) == ValType.I32)) continue;
|
||||||
|
// if (function.getCode().getInstructions().size() != expectedExpr.size()) continue;
|
||||||
|
//
|
||||||
|
// for (int j = 0; j < function.getCode().getInstructions().size(); j++) {
|
||||||
|
// Instr instr = function.getCode().getInstructions().get(j);
|
||||||
|
// if (instr.getInstrType() != expectedExpr.get(j)) continue outerloop;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return funcIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void copyEmptyHook(Module module, FuncIdx orgFuncIdx, String exportName, String hookname) throws InvalidOpCodeException, IOException {
|
||||||
|
// // copies the method, empties the first one
|
||||||
|
// // export the copy
|
||||||
|
// // hooks to the emptied one
|
||||||
|
//
|
||||||
|
// Func func = module.getCodeSection().getByIdx(orgFuncIdx);
|
||||||
|
// FuncType funcType = module.getTypeSection().getByFuncIdx(orgFuncIdx);
|
||||||
|
//
|
||||||
|
// // copy the function
|
||||||
|
// Function copy = new Function(funcType, func.getLocalss(), func.getExpression());
|
||||||
|
// FuncIdx copyIdx = copy.addToModule(module);
|
||||||
|
//
|
||||||
|
// module.getExportSection().getExports().add(new Export(exportName, new ExportDesc(copyIdx)));
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // clear & hook original function, let it return whatever JS returns
|
||||||
|
// Import imp = new Import(
|
||||||
|
// "env",
|
||||||
|
// hookname,
|
||||||
|
// new ImportDesc(module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
||||||
|
// funcType.getParameterType(),
|
||||||
|
// funcType.getResultType()
|
||||||
|
// )))
|
||||||
|
// );
|
||||||
|
// FuncIdx hookIdx = module.getImportSection().importFunction(imp);
|
||||||
|
//
|
||||||
|
// CallInstr call = new CallInstr(hookIdx);
|
||||||
|
// List<Instr> newInstrs = new ArrayList<>();
|
||||||
|
// for (int i = 0; i < funcType.getParameterType().typeList().size(); i++) {
|
||||||
|
// newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(i)));
|
||||||
|
// }
|
||||||
|
// newInstrs.add(call);
|
||||||
|
// func.setExpression(new Expression(newInstrs));
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void hook(Module module, FuncIdx funcIdx, String jsFunctionName) throws InvalidOpCodeException, IOException {
|
||||||
|
// FuncType funcType = module.getTypeSection().getByFuncIdx(funcIdx);
|
||||||
|
//
|
||||||
|
// Import imp = new Import(
|
||||||
|
// "env",
|
||||||
|
// jsFunctionName,
|
||||||
|
// new ImportDesc(module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
||||||
|
// funcType.getParameterType(),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// )))
|
||||||
|
// );
|
||||||
|
// FuncIdx hookIdx = module.getImportSection().importFunction(imp);
|
||||||
|
//
|
||||||
|
// CallInstr call = new CallInstr(hookIdx);
|
||||||
|
//
|
||||||
|
// Func root = module.getCodeSection().getByIdx(funcIdx);
|
||||||
|
// List<Instr> newInstrs = new ArrayList<>();
|
||||||
|
// for (int i = 0; i < funcType.getParameterType().typeList().size(); i++) {
|
||||||
|
// newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(i)));
|
||||||
|
// }
|
||||||
|
// newInstrs.add(call);
|
||||||
|
// newInstrs.addAll(root.getExpression().getInstructions());
|
||||||
|
// root.getExpression().setInstructions(newInstrs);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
@ -0,0 +1,60 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.modules.sections.code.Locals;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IncomingPacketPatcher implements StreamReplacement {
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.emptyList())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOKCOPYEXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_incoming_packet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return "_gearth_incoming_copy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (!(code.getLocalss().equals(Collections.singletonList(new Locals(1, ValType.I32)))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
InstrType.I32_EQZ, InstrType.IF, InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.LOCAL_TEE,
|
||||||
|
InstrType.IF);
|
||||||
|
|
||||||
|
if (code.getExpression().getInstructions().size() != expectedExpr.size()) return false;
|
||||||
|
|
||||||
|
for (int j = 0; j < code.getExpression().getInstructions().size(); j++) {
|
||||||
|
Instr instr = code.getExpression().getInstructions().get(j);
|
||||||
|
if (instr.getInstrType() != expectedExpr.get(j)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OutgoingPacketPatcher implements StreamReplacement {
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOKCOPYEXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_outgoing_packet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return "_gearth_outgoing_copy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (code.getLocalss().size() != 0) return false;
|
||||||
|
List<Instr> expression = code.getExpression().getInstructions();
|
||||||
|
if (expression.get(0).getInstrType() != InstrType.LOCAL_GET) return false;
|
||||||
|
if (expression.get(1).getInstrType() != InstrType.LOCAL_GET) return false;
|
||||||
|
if (expression.get(2).getInstrType() != InstrType.LOCAL_GET) return false;
|
||||||
|
if (expression.get(3).getInstrType() != InstrType.I32_LOAD) return false;
|
||||||
|
if (expression.get(4).getInstrType() != InstrType.I32_CONST) return false;
|
||||||
|
if (expression.get(5).getInstrType() != InstrType.CALL) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReturnBytePatcher implements StreamReplacement {
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.singletonList(ValType.I32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOKCOPYEXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_chacha_returnbyte";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return "_gearth_returnbyte_copy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (code.getLocalss().size() != 0) return false;
|
||||||
|
if (code.getExpression().getInstructions().size() != 30) return false;
|
||||||
|
List<Instr> expr = code.getExpression().getInstructions();
|
||||||
|
if (expr.get(expr.size() - 1).getInstrType() != InstrType.I32_XOR) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.modules.sections.code.Locals;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SetKeyPatcher implements StreamReplacement {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_chacha_setkey";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (!(code.getLocalss().equals(Collections.singletonList(new Locals(1, ValType.I32)))))
|
||||||
|
return false;
|
||||||
|
List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
InstrType.I32_EQZ, InstrType.IF, InstrType.BLOCK, InstrType.LOCAL_GET, InstrType.I32_CONST,
|
||||||
|
InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.I32_CONST, InstrType.I32_CONST, InstrType.I32_CONST,
|
||||||
|
InstrType.CALL);
|
||||||
|
|
||||||
|
if (code.getExpression().getInstructions().size() != expectedExpr.size()) return false;
|
||||||
|
|
||||||
|
for (int j = 0; j < code.getExpression().getInstructions().size(); j++) {
|
||||||
|
Instr instr = code.getExpression().getInstructions().get(j);
|
||||||
|
if (instr.getInstrType() != expectedExpr.get(j)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user