From 5a52bfff425556b9b61b92ddf933640c780e88d8 Mon Sep 17 00:00:00 2001 From: Robert Wesner Date: Mon, 9 Nov 2026 11:08:31 +0100 Subject: [PATCH] Add support for invokedynamic string concatenation. --- .../net/lenni0451/authhook/UrlRedirector.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/Agent/src/main/java/net/lenni0451/authhook/UrlRedirector.java b/Agent/src/main/java/net/lenni0451/authhook/UrlRedirector.java index c9674e0..4f6db2e 100644 --- a/Agent/src/main/java/net/lenni0451/authhook/UrlRedirector.java +++ b/Agent/src/main/java/net/lenni0451/authhook/UrlRedirector.java @@ -21,6 +21,7 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.tree.MethodNode; @@ -59,21 +60,33 @@ public byte[] transform(final ClassLoader loader, final String className, final boolean modified = false; for (MethodNode method : node.methods) { for (AbstractInsnNode insn : method.instructions) { + String str = null; if (insn instanceof LdcInsnNode && ((LdcInsnNode) insn).cst instanceof String) { - final LdcInsnNode ldc = (LdcInsnNode) insn; - String str = (String) ldc.cst; - for (String url : URLS) { - if (str.startsWith(url)) { - str = str.substring(url.length()); - str = this.targetAddress + "/" + this.secretKey + "/" + Base64.getUrlEncoder().encodeToString(url.getBytes(StandardCharsets.UTF_8)) + str; - ldc.cst = str; - - modified = true; - System.out.println("Redirected '" + url + "' in class '" + node.name + "' method '" + method.name + "'"); - break; - } + str = (String) ((LdcInsnNode) insn).cst; + } else if (insn instanceof InvokeDynamicInsnNode) { + final InvokeDynamicInsnNode indy = (InvokeDynamicInsnNode) insn; + + if (indy.bsm.getOwner().equals("java/lang/invoke/StringConcatFactory") + && indy.bsm.getName().equals("makeConcatWithConstants") + && indy.bsmArgs.length > 0 + && indy.bsmArgs[0] instanceof String) { + str = (String) indy.bsmArgs[0]; } } + + if (str == null) continue; + + final String redirected = this.redirectUrl(str); + if (redirected == null) continue; + + if (insn instanceof LdcInsnNode) { + ((LdcInsnNode) insn).cst = redirected; + } else { + ((InvokeDynamicInsnNode) insn).bsmArgs[0] = redirected; + } + + modified = true; + System.out.println("Redirected URL in class '" + node.name + "' method '" + method.name + "'"); } } return modified ? this.write(node) : null; @@ -95,4 +108,15 @@ private byte[] write(final ClassNode node) { return writer.toByteArray(); } + private String redirectUrl(final String str) { + for (String url : URLS) { + if (str.startsWith(url)) { + return this.targetAddress + "/" + this.secretKey + "/" + + Base64.getUrlEncoder().encodeToString(url.getBytes(StandardCharsets.UTF_8)) + + str.substring(url.length()); + } + } + return null; + } + }