From 44bd70a6aa4d756b78c485a60cef21e73e6cb10b Mon Sep 17 00:00:00 2001 From: sirjonasxx <36828922+sirjonasxx@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:18:30 +0100 Subject: [PATCH] new & improved wasmcodepatcher --- .../main/java/gearth/services/Constants.java | 7 + .../services/unity_tools/WasmCodePatcher.java | 216 ++--------------- .../unity_tools/WasmCodePatcherOld.java | 225 ++++++++++++++++++ .../codepatcher/IncomingPacketPatcher.java | 60 +++++ .../codepatcher/OutgoingPacketPatcher.java | 53 +++++ .../codepatcher/ReturnBytePatcher.java | 48 ++++ .../codepatcher/SetKeyPatcher.java | 60 +++++ 7 files changed, 470 insertions(+), 199 deletions(-) create mode 100644 G-Earth/src/main/java/gearth/services/Constants.java create mode 100644 G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcherOld.java create mode 100644 G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/IncomingPacketPatcher.java create mode 100644 G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/OutgoingPacketPatcher.java create mode 100644 G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/ReturnBytePatcher.java create mode 100644 G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/SetKeyPatcher.java diff --git a/G-Earth/src/main/java/gearth/services/Constants.java b/G-Earth/src/main/java/gearth/services/Constants.java new file mode 100644 index 0000000..6370c65 --- /dev/null +++ b/G-Earth/src/main/java/gearth/services/Constants.java @@ -0,0 +1,7 @@ +package gearth.services; + +public class Constants { + + public static volatile boolean UNITY_PACKETS = false; + +} diff --git a/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcher.java b/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcher.java index 4977c10..af947ca 100644 --- a/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcher.java +++ b/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcher.java @@ -1,27 +1,27 @@ 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.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.code.Locals; 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 wasm.misc.CodeCompare; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class WasmCodePatcher { @@ -32,194 +32,12 @@ public class WasmCodePatcher { } 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 module = new Module(file, Arrays.asList( + new SetKeyPatcher(), + new ReturnBytePatcher(), + new OutgoingPacketPatcher(), + new IncomingPacketPatcher() + )); 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 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 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 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 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 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 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); - } - } diff --git a/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcherOld.java b/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcherOld.java new file mode 100644 index 0000000..aaef51b --- /dev/null +++ b/G-Earth/src/main/java/gearth/services/unity_tools/WasmCodePatcherOld.java @@ -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 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 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 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 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 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 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); +// } +// +//} diff --git a/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/IncomingPacketPatcher.java b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/IncomingPacketPatcher.java new file mode 100644 index 0000000..48e269b --- /dev/null +++ b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/IncomingPacketPatcher.java @@ -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 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; + }; + } +} diff --git a/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/OutgoingPacketPatcher.java b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/OutgoingPacketPatcher.java new file mode 100644 index 0000000..86921e3 --- /dev/null +++ b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/OutgoingPacketPatcher.java @@ -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 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; + }; + } +} diff --git a/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/ReturnBytePatcher.java b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/ReturnBytePatcher.java new file mode 100644 index 0000000..4d90c5c --- /dev/null +++ b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/ReturnBytePatcher.java @@ -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 expr = code.getExpression().getInstructions(); + if (expr.get(expr.size() - 1).getInstrType() != InstrType.I32_XOR) return false; + return true; + }; + } +} diff --git a/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/SetKeyPatcher.java b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/SetKeyPatcher.java new file mode 100644 index 0000000..f952105 --- /dev/null +++ b/G-Earth/src/main/java/gearth/services/unity_tools/codepatcher/SetKeyPatcher.java @@ -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 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; + }; + } +}