都是传入了一个函数来解密的格式

思路:用frida去hook最后的结果,然后用dexlib2来patch
目前写了一个小demo,尝试对一个地方进行patch
踩雷:

修改成

应该是长度对不齐,就会失败,对齐之后会发现确实去掉了这个地方

利用frida打一个表,然后尝试批量化
凡是在frida里面被hook调用到的都会被patch回去

最后改成遍历所有类就ok了,重写了回溯,成功
最终版本
package org.example;
import com.google.common.collect.Lists;
import org.jf.dexlib2.DexFileFactory;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.DexFile;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.builder.MutableMethodImplementation;
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c;
import org.jf.dexlib2.immutable.reference.ImmutableStringReference;
import org.jf.dexlib2.builder.instruction.BuilderInstruction10x;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.immutable.ImmutableClassDef;
import org.jf.dexlib2.immutable.ImmutableMethod;
import org.jf.dexlib2.writer.io.FileDataStore;
import org.jf.dexlib2.writer.pool.DexPool;
import org.jf.dexlib2.builder.BuilderInstruction;
import org.jf.dexlib2.immutable.ImmutableMethodImplementation;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\cpq\\IdeaProjects\\untitled\\src\\main\\resources\\classes03.dex");
DexFile dexFile = DexFileFactory.loadDexFile(file, Opcodes.getDefault());
DexPool dexPool = new DexPool(Opcodes.getDefault());
for (ClassDef classDef : dexFile.getClasses()) {
if (classDef.getType().equals("Lio/liankong/riskdetector/core/VO0O0OOOOOOO0;")) {
System.out.println("Processing target class: " + classDef.getType());
ClassDef modifiedClass = ReplaceStr(classDef);
dexPool.internClass(modifiedClass);
} else {
dexPool.internClass(classDef);
}
}
File outFile = new File("classes03_patched.dex");
System.out.println("Writing to " + outFile.getAbsolutePath());
dexPool.writeTo(new FileDataStore(outFile));
System.out.println("Done.");
}
private static ClassDef ReplaceStr(ClassDef classDef) {
boolean isClassModified = false;
List<Method> newMethods = new ArrayList<>();
for (Method method : classDef.getMethods()) {
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl != null && method.getName().equals("<clinit>")) {
MutableMethodImplementation mutableImpl = new MutableMethodImplementation(methodImpl);
List<BuilderInstruction> instructions = new ArrayList<>(mutableImpl.getInstructions());
boolean isMethodModified = false;
for (int i = 0; i < instructions.size(); i++) {
Instruction instruction = instructions.get(i);
if (instruction instanceof ReferenceInstruction) {
ReferenceInstruction refInst = (ReferenceInstruction) instruction;
if (refInst.getReference() instanceof org.jf.dexlib2.iface.reference.MethodReference) {
org.jf.dexlib2.iface.reference.MethodReference methodRef = (org.jf.dexlib2.iface.reference.MethodReference) refInst
.getReference();
if (methodRef.getDefiningClass().equals("Lio/liankong/riskdetector/OO0O0000O000;") &&
methodRef.getName().equals("IIIIIIIILIII")) {
System.out.println("Found target call at index " + i);
if (i >= 2) {
Instruction prev1 = instructions.get(i - 1);
Instruction prev2 = instructions.get(i - 2);
if (prev1.getOpcode().name.startsWith("const-string") &&
prev2.getOpcode().name.startsWith("const-string")) {
String str1 = ((StringReference) ((ReferenceInstruction) prev1).getReference())
.getString();
String str2 = ((StringReference) ((ReferenceInstruction) prev2).getReference())
.getString();
if (str2.contains("ggFH+206pVWHeByNO0rnJtdlR40APuch1xYmkHAu3TnsX1DGAGyuaYM=") &&
str1.contains("qj59oF0XnBQ=")) {
System.out.println(" --> Patching...");
int targetReg = ((OneRegisterInstruction) prev2).getRegisterA();
BuilderInstruction newConstStr = new BuilderInstruction21c(
Opcode.CONST_STRING,
targetReg,
new ImmutableStringReference("\u98ce\u9669App\u68c0\u6d4b"));
BuilderInstruction nop = new BuilderInstruction10x(Opcode.NOP);
instructions.set(i, newConstStr);
instructions.set(i+1,newConstStr);
isMethodModified = true;
isClassModified = true;
}
}
}
}
}
}
}
if (isMethodModified) {
MethodImplementation newImplementation = new ImmutableMethodImplementation(
mutableImpl.getRegisterCount(),
instructions,
mutableImpl.getTryBlocks(),
mutableImpl.getDebugItems());
newMethods.add(new ImmutableMethod(
method.getDefiningClass(),
method.getName(),
method.getParameters(),
method.getReturnType(),
method.getAccessFlags(),
method.getAnnotations(),
method.getHiddenApiRestrictions(),
newImplementation
));
} else {
newMethods.add(method);
}
} else {
newMethods.add(method);
}
}
if (isClassModified) {
return new ImmutableClassDef(
classDef.getType(),
classDef.getAccessFlags(),
classDef.getSuperclass(),
classDef.getInterfaces(),
classDef.getSourceFile(),
classDef.getAnnotations(),
classDef.getFields(),
newMethods);
} else {
return classDef;
}
}
}
package org.example;
import com.google.common.collect.Lists;
import org.jf.dexlib2.DexFileFactory;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.DexFile;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.builder.MutableMethodImplementation;
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c;
import org.jf.dexlib2.immutable.reference.ImmutableStringReference;
import org.jf.dexlib2.builder.instruction.BuilderInstruction10x;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.immutable.ImmutableClassDef;
import org.jf.dexlib2.immutable.ImmutableMethod;
import org.jf.dexlib2.writer.io.FileDataStore;
import org.jf.dexlib2.writer.pool.DexPool;
import org.jf.dexlib2.builder.BuilderInstruction;
import org.jf.dexlib2.immutable.ImmutableMethodImplementation;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\cpq\\IdeaProjects\\untitled\\src\\main\\resources\\classes03.dex");
DexFile dexFile = DexFileFactory.loadDexFile(file, Opcodes.getDefault());
DexPool dexPool = new DexPool(Opcodes.getDefault());
for (ClassDef classDef : dexFile.getClasses()) {
if (classDef.getType().equals("Lio/liankong/riskdetector/core/VO0O0OOOOOOO0;")) {
System.out.println("Processing target class: " + classDef.getType());
ClassDef modifiedClass = ReplaceStr(classDef);
dexPool.internClass(modifiedClass);
} else {
dexPool.internClass(classDef);
}
}
File outFile = new File("classes03_patched.dex");
System.out.println("Writing to " + outFile.getAbsolutePath());
dexPool.writeTo(new FileDataStore(outFile));
System.out.println("Done.");
}
private static ClassDef ReplaceStr(ClassDef classDef) {
boolean isClassModified = false;
List<Method> newMethods = new ArrayList<>();
for (Method method : classDef.getMethods()) {
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl != null && method.getName().equals("<clinit>")) {
MutableMethodImplementation mutableImpl = new MutableMethodImplementation(methodImpl);
List<BuilderInstruction> instructions = new ArrayList<>(mutableImpl.getInstructions());
boolean isMethodModified = false;
for (int i = 0; i < instructions.size(); i++) {
Instruction instruction = instructions.get(i);
if (instruction instanceof ReferenceInstruction) {
ReferenceInstruction refInst = (ReferenceInstruction) instruction;
if (refInst.getReference() instanceof org.jf.dexlib2.iface.reference.MethodReference) {
org.jf.dexlib2.iface.reference.MethodReference methodRef = (org.jf.dexlib2.iface.reference.MethodReference) refInst
.getReference();
if (methodRef.getDefiningClass().equals("Lio/liankong/riskdetector/OO0O0000O000;") &&
methodRef.getName().equals("IIIIIIIILIII")) {
System.out.println("Found target call at index " + i);
if (i >= 2) {
Instruction prev1 = instructions.get(i - 1);
Instruction prev2 = instructions.get(i - 2);
if (prev1.getOpcode().name.startsWith("const-string") &&
prev2.getOpcode().name.startsWith("const-string")) {
String str1 = ((StringReference) ((ReferenceInstruction) prev1).getReference())
.getString();
String str2 = ((StringReference) ((ReferenceInstruction) prev2).getReference())
.getString();
if (str2.contains("ggFH+206pVWHeByNO0rnJtdlR40APuch1xYmkHAu3TnsX1DGAGyuaYM=") &&
str1.contains("qj59oF0XnBQ=")) {
System.out.println(" --> Patching...");
int targetReg = ((OneRegisterInstruction) prev2).getRegisterA();
BuilderInstruction newConstStr = new BuilderInstruction21c(
Opcode.CONST_STRING,
targetReg,
new ImmutableStringReference("\u98ce\u9669App\u68c0\u6d4b"));
BuilderInstruction nop = new BuilderInstruction10x(Opcode.NOP);
instructions.set(i, newConstStr);
instructions.set(i+1,newConstStr);
isMethodModified = true;
isClassModified = true;
}
}
}
}
}
}
}
if (isMethodModified) {
MethodImplementation newImplementation = new ImmutableMethodImplementation(
mutableImpl.getRegisterCount(),
instructions,
mutableImpl.getTryBlocks(),
mutableImpl.getDebugItems());
newMethods.add(new ImmutableMethod(
method.getDefiningClass(),
method.getName(),
method.getParameters(),
method.getReturnType(),
method.getAccessFlags(),
method.getAnnotations(),
method.getHiddenApiRestrictions(),
newImplementation
));
} else {
newMethods.add(method);
}
} else {
newMethods.add(method);
}
}
if (isClassModified) {
return new ImmutableClassDef(
classDef.getType(),
classDef.getAccessFlags(),
classDef.getSuperclass(),
classDef.getInterfaces(),
classDef.getSourceFile(),
classDef.getAnnotations(),
classDef.getFields(),
newMethods);
} else {
return classDef;
}
}
}
Java.perform(function () {
var OO0O0000O000 = Java.use("io.liankong.riskdetector.OO0O0000O000");
OO0O0000O000["IIIIIIIILIII"].implementation = function (str, str2) {
let result = this["IIIIIIIILIII"](str, str2);
str = str.replace(/\n/g, '');
str2 = str2.replace(/\n/g, '');
console.log(`${str2},${str}:${result}`);
return result;
};
});
Java.perform(function () {
var OO0O0000O000 = Java.use("io.liankong.riskdetector.OO0O0000O000");
OO0O0000O000["IIIIIIIILIII"].implementation = function (str, str2) {
let result = this["IIIIIIIILIII"](str, str2);
str = str.replace(/\n/g, '');
str2 = str2.replace(/\n/g, '');
console.log(`${str2},${str}:${result}`);
return result;
};
});
package org.example;
import org.jf.dexlib2.DexFileFactory;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.DexFile;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.builder.MutableMethodImplementation;
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c;
import org.jf.dexlib2.builder.instruction.BuilderInstruction10x;
import org.jf.dexlib2.immutable.reference.ImmutableStringReference;
import org.jf.dexlib2.immutable.ImmutableClassDef;
import org.jf.dexlib2.immutable.ImmutableMethod;
import org.jf.dexlib2.immutable.ImmutableMethodImplementation;
import org.jf.dexlib2.writer.io.FileDataStore;
import org.jf.dexlib2.writer.pool.DexPool;
import org.jf.dexlib2.builder.BuilderInstruction;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class Main {
static class PatchConfig {
String targetStr1;
String targetStr2;
String newStr;
public PatchConfig(String t1, String t2, String n) {
this.targetStr1 = t1;
this.targetStr2 = t2;
this.newStr = n;
}
}
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\cpq\\IdeaProjects\\untitled\\src\\main\\resources\\classes03.dex");
String configPath = "C:\\Users\\cpq\\IdeaProjects\\untitled\\src\\main\\resources\\tmp.txt";
File outFile = new File("classes03_patched.dex");
List<PatchConfig> patchConfigs = new ArrayList<>();
List<String> lines = Files.readAllLines(Paths.get(configPath), StandardCharsets.UTF_8);
for (String line : lines) {
if (line.trim().isEmpty() || line.startsWith("#"))
continue;
String[] parts = line.split(":", 2);
if (parts.length == 2) {
String encryptedPart = parts[0];
String newStr = parts[1];
String[] encParams = encryptedPart.split(",");
if (encParams.length >= 2) {
String t1 = encParams[0].trim();
String t2 = encParams[1].trim();
if (patchConfigs.stream().noneMatch(pc -> pc.targetStr1.equals(t1) && pc.targetStr2.equals(t2))) {
patchConfigs.add(new PatchConfig(t1, t2, newStr));
}
} else {
System.err.println("Skipping invalid line (comma missing): " + line);
}
} else {
System.err.println("Skipping invalid line (colon missing): " + line);
}
}
System.out.println("Loaded " + patchConfigs.size() + " replacement rules.");
DexFile dexFile = DexFileFactory.loadDexFile(file, Opcodes.getDefault());
DexPool dexPool = new DexPool(Opcodes.getDefault());
for (ClassDef classDef : dexFile.getClasses()) {
if (classDef.getType().contains("io/liankong/riskdetector")) {
System.out.println("Processing target class: " + classDef.getType());
ClassDef currentClass = classDef;
for (PatchConfig config : patchConfigs) {
currentClass = ReplaceStr(
currentClass,
"Lio/liankong/riskdetector/OO0O0000O000;",
"IIIIIIIILIII",
config.targetStr1,
config.targetStr2,
config.newStr
);
}
dexPool.internClass(currentClass);
} else {
dexPool.internClass(classDef);
}
}
System.out.println("Writing to " + outFile.getAbsolutePath());
dexPool.writeTo(new FileDataStore(outFile));
System.out.println("Done.");
}
private static ClassDef ReplaceStr(ClassDef classDef, String ClassName, String MethodName, String TargetStr1,
String TargetStr2, String NewStr) {
boolean isClassModified = false;
List<Method> newMethods = new ArrayList<>();
for (Method method : classDef.getMethods()) {
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl != null) {
MutableMethodImplementation mutableImpl = new MutableMethodImplementation(methodImpl);
List<BuilderInstruction> instructions = new ArrayList<>(mutableImpl.getInstructions());
boolean isMethodModified = false;
for (int i = 0; i < instructions.size(); i++) {
Instruction instruction = instructions.get(i);
if (instruction instanceof ReferenceInstruction) {
ReferenceInstruction refInst = (ReferenceInstruction) instruction;
if (refInst.getReference() instanceof org.jf.dexlib2.iface.reference.MethodReference) {
org.jf.dexlib2.iface.reference.MethodReference methodRef = (org.jf.dexlib2.iface.reference.MethodReference) refInst
.getReference();
if (methodRef.getDefiningClass().equals(ClassName) &&
methodRef.getName().equals(MethodName)) {
String foundContent = null;
String foundKey = null;
int foundCount = 0;
for (int k = i - 1; k >= 0; k--) {
Instruction prev = instructions.get(k);
if (prev.getOpcode().name.startsWith("const-string")) {
String val = ((StringReference) ((ReferenceInstruction) prev).getReference()).getString();
if (foundCount == 0) {
foundContent = val;
foundCount++;
} else if (foundCount == 1) {
foundKey = val;
foundCount++;
break;
}
}
if (i - k > 30) break;
}
if (foundCount == 2 &&
foundKey.contains(TargetStr2) &&
foundContent.contains(TargetStr1)) {
System.out.println("Patching found in: " + method.getName());
int targetReg = 0;
boolean hasMoveResult = false;
if (i + 1 < instructions.size()) {
Instruction nextInst = instructions.get(i + 1);
if (nextInst.getOpcode().name.startsWith("move-result")) {
targetReg = ((OneRegisterInstruction) nextInst).getRegisterA();
hasMoveResult = true;
}
}
if (hasMoveResult) {
BuilderInstruction newConstStr = new BuilderInstruction21c(
Opcode.CONST_STRING,
targetReg,
new ImmutableStringReference(NewStr));
BuilderInstruction nop = new BuilderInstruction10x(Opcode.NOP);
instructions.set(i, newConstStr);
instructions.set(i + 1, newConstStr);
isMethodModified = true;
isClassModified = true;
} else {
System.err.println("Warning: No move-result after invoke, skipping patch.");
}
}
}
}
}
}
if (isMethodModified) {
MethodImplementation newImplementation = new ImmutableMethodImplementation(
mutableImpl.getRegisterCount(),
instructions,
mutableImpl.getTryBlocks(),
mutableImpl.getDebugItems());
newMethods.add(new ImmutableMethod(
method.getDefiningClass(),
method.getName(),
method.getParameters(),
method.getReturnType(),
method.getAccessFlags(),
method.getAnnotations(),
method.getHiddenApiRestrictions(),
newImplementation
));
} else {
newMethods.add(method);
}
} else {
newMethods.add(method);
}
}
if (isClassModified) {
return new ImmutableClassDef(
classDef.getType(),
classDef.getAccessFlags(),
classDef.getSuperclass(),
classDef.getInterfaces(),
classDef.getSourceFile(),
classDef.getAnnotations(),
classDef.getFields(),
newMethods);
} else {
return classDef;
}
}
}
package org.example;
import org.jf.dexlib2.DexFileFactory;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.DexFile;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2025-12-3 17:34
被BediveRe_编辑
,原因: