Skip to content

Commit 27089ad

Browse files
committed
cleanup
1 parent d4e46b8 commit 27089ad

1 file changed

Lines changed: 28 additions & 26 deletions

File tree

deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixStringTransformer.java

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
import uwu.narumi.deobfuscator.api.helper.AsmHelper;
2222
import uwu.narumi.deobfuscator.api.transformer.Transformer;
2323

24-
import java.util.ArrayList;
25-
import java.util.HashMap;
26-
import java.util.List;
27-
import java.util.Map;
24+
import java.util.*;
2825
import java.util.concurrent.atomic.AtomicBoolean;
2926

3027
/**
@@ -78,7 +75,7 @@ protected void transform() throws Exception {
7875

7976
SandBox sandBox = new SandBox(context());
8077
encryptedClassWrapper.forEach((classWrapper, tmpClassWrapper) -> {
81-
AtomicBoolean isDecryptedFully = new AtomicBoolean(true);
78+
AtomicBoolean shouldCleanArray = new AtomicBoolean(true);
8279

8380
try {
8481
InstanceClass clazz = sandBox.getHelper().loadClass("tmp." + classWrapper.canonicalName());
@@ -102,11 +99,12 @@ protected void transform() throws Exception {
10299
matchContext.removeAll();
103100
markChange();
104101
} catch (Exception e) {
105-
isDecryptedFully.set(false);
102+
shouldCleanArray.set(false);
106103
}
107104
});
108105
}
109106

107+
// TODO: Access directly array without getter
110108
SimpleArrayValue arrayValue = (SimpleArrayValue) sandBox.getInvocationUtil().invokeReference(
111109
clazz.getMethod("getArr", "()[Ljava/lang/String;")
112110
);
@@ -155,7 +153,7 @@ else if (insn instanceof VarInsnNode varInsnNode &&
155153

156154
context().removeCompiledClass(tmpClassWrapper);
157155

158-
if (isDecryptedFully.get())
156+
if (shouldCleanArray.get())
159157
cleanUpFunction(classWrapper);
160158
});
161159
}
@@ -167,27 +165,19 @@ private void cleanUpFunction(ClassWrapper classWrapper) {
167165
MatchContext match = matches.get(matches.size() - 1);
168166

169167
JumpInsnNode jumpInsnNode = match.captures().get("label").insn().asJump();
170-
AbstractInsnNode currentInsn = jumpInsnNode.label;
171168

172-
List<AbstractInsnNode> removedInsns = new ArrayList<>();
173-
LabelNode firstLabel = null;
169+
Arrays.stream(clinitMethod.instructions.toArray()).filter(insn -> insn instanceof LabelNode).map(insn -> (LabelNode) insn).findFirst().ifPresent(firstLabel -> {
170+
AbstractInsnNode currentInsn = jumpInsnNode.label;
174171

175-
for (AbstractInsnNode insn : clinitMethod.instructions.toArray()) {
176-
if (insn instanceof LabelNode labelNode) {
177-
firstLabel = labelNode;
178-
break;
172+
List<AbstractInsnNode> removedInsns = new ArrayList<>();
173+
while (currentInsn != firstLabel) {
174+
currentInsn = currentInsn.getPrevious();
175+
removedInsns.add(currentInsn);
179176
}
180-
}
181-
182-
if (firstLabel == null)
183-
return;
184177

185-
while (currentInsn != firstLabel) {
186-
currentInsn = currentInsn.getPrevious();
187-
removedInsns.add(currentInsn);
188-
}
178+
removedInsns.forEach(insn -> clinitMethod.instructions.remove(insn));
179+
});
189180

190-
removedInsns.forEach(insn -> clinitMethod.instructions.remove(insn));
191181
classWrapper.methods().removeIf(methodNode -> methodNode.desc.equals("(II)Ljava/lang/String;"));
192182
}
193183

@@ -205,6 +195,7 @@ private byte[] cloneClassWithClinit(ClassWrapper classWrapper, MethodNode clinit
205195
classNode.methods.add(clinit);
206196

207197
// create a tmp array for getting data
198+
// TODO: Can we find a way to access direcly variable without getter?
208199
classNode.fields.add(new FieldNode(ACC_PUBLIC | ACC_STATIC, "arr", "[Ljava/lang/String;", null, null));
209200

210201
MethodNode getMethodNode = new MethodNode(ACC_PUBLIC | ACC_STATIC, "getArr", "()[Ljava/lang/String;", null, new String[0]);
@@ -229,7 +220,7 @@ private byte[] cloneClassWithClinit(ClassWrapper classWrapper, MethodNode clinit
229220
}
230221
}
231222

232-
classWrapper.findMethod(methodNode -> methodNode.desc.equals("(II)Ljava/lang/String;")).ifPresent(method -> {
223+
classWrapper.findMethod(this::isDecryptMethod).ifPresent(method -> {
233224
if (!classNode.methods.contains(method))
234225
classNode.methods.add(method);
235226
});
@@ -238,6 +229,15 @@ private byte[] cloneClassWithClinit(ClassWrapper classWrapper, MethodNode clinit
238229
return cw.toByteArray();
239230
}
240231

232+
private boolean isDecryptMethod(MethodNode methodNode) {
233+
if (!methodNode.desc.equals("(II)Ljava/lang/String;"))
234+
return false;
235+
236+
if ((methodNode.access & (ACC_PRIVATE | ACC_STATIC)) == 0)
237+
return false;
238+
239+
return Arrays.stream(methodNode.instructions.toArray()).anyMatch(abstractInsnNode -> abstractInsnNode.getOpcode() == TABLESWITCH);
240+
}
241241

242242
private byte[] modifyByteCode(ClassWrapper classWrapper, byte[] classByte) {
243243
ClassReader cr = new ClassReader(classByte);
@@ -273,9 +273,11 @@ private byte[] modifyByteCode(ClassWrapper classWrapper, byte[] classByte) {
273273
if (insn instanceof LabelNode)
274274
break;
275275

276-
if (insn.getOpcode() == Opcodes.INVOKESTATIC)
276+
if (insn.getOpcode() == Opcodes.INVOKESTATIC) {
277277
clinitMethod.instructions.remove(insn);
278-
else if (insn instanceof VarInsnNode varInsnNode &&
278+
} else if (insn instanceof TypeInsnNode typeInsnNode && typeInsnNode.getOpcode() == Opcodes.ANEWARRAY && !typeInsnNode.desc.equals("java/lang/String")) {
279+
typeInsnNode.desc = "java/lang/String";
280+
} else if (insn instanceof VarInsnNode varInsnNode &&
279281
insn.getPrevious() instanceof TypeInsnNode typeInsnNode && typeInsnNode.getOpcode() == Opcodes.ANEWARRAY && typeInsnNode.desc.equals("java/lang/String") &&
280282
insn.getPrevious().getPrevious() != null && insn.getPrevious().getPrevious().isInteger()
281283
) {

0 commit comments

Comments
 (0)