mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Deobfuscate received server error messages
This commit is contained in:
parent
5056b248a9
commit
778485b4a9
4 changed files with 115 additions and 22 deletions
|
@ -12,6 +12,7 @@ import io.xpipe.beacon.exchange.MessageExchanges;
|
|||
import io.xpipe.beacon.exchange.data.ClientErrorMessage;
|
||||
import io.xpipe.beacon.exchange.data.ServerErrorMessage;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
import io.xpipe.core.util.Deobfuscator;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
@ -276,8 +277,8 @@ public class BeaconClient implements AutoCloseable {
|
|||
}
|
||||
|
||||
try {
|
||||
var reader = JacksonMapper.newMapper().readerFor(ClientErrorMessage.class);
|
||||
return Optional.of(reader.readValue(content));
|
||||
var message = JacksonMapper.getDefault().treeToValue(content, ClientErrorMessage.class);
|
||||
return Optional.of(message);
|
||||
} catch (IOException ex) {
|
||||
throw new ConnectorException("Couldn't parse client error message", ex);
|
||||
}
|
||||
|
@ -290,8 +291,9 @@ public class BeaconClient implements AutoCloseable {
|
|||
}
|
||||
|
||||
try {
|
||||
var reader = JacksonMapper.newMapper().readerFor(ServerErrorMessage.class);
|
||||
return Optional.of(reader.readValue(content));
|
||||
var message = JacksonMapper.getDefault().treeToValue(content, ServerErrorMessage.class);
|
||||
Deobfuscator.deobfuscate(message.getError());
|
||||
return Optional.of(message);
|
||||
} catch (IOException ex) {
|
||||
throw new ConnectorException("Couldn't parse server error message", ex);
|
||||
}
|
||||
|
|
94
core/src/main/java/io/xpipe/core/util/Deobfuscator.java
Normal file
94
core/src/main/java/io/xpipe/core/util/Deobfuscator.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
import io.xpipe.core.charsetter.NewLine;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Deobfuscator {
|
||||
|
||||
public static void deobfuscate(Throwable throwable) {
|
||||
if (!System.getenv().containsKey("XPIPE_MAPPING")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String deobf = deobfuscateToString(throwable);
|
||||
if (deobf == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// "at package.class.method(source.java:123)"
|
||||
Pattern tracePattern = Pattern.compile("\\s*at\\s+([\\w.$_]+)\\.([\\w$_]+)\\((.*):(\\d+)\\)(\\n|\\r\\n)");
|
||||
Matcher traceMatcher = tracePattern.matcher(deobf);
|
||||
List<StackTraceElement> stackTrace = new ArrayList<>();
|
||||
while (traceMatcher.find()) {
|
||||
String className = traceMatcher.group(1);
|
||||
String methodName = traceMatcher.group(2);
|
||||
String sourceFile = traceMatcher.group(3);
|
||||
int lineNum = Integer.parseInt(traceMatcher.group(4));
|
||||
stackTrace.add(new StackTraceElement(className, methodName, sourceFile, lineNum));
|
||||
}
|
||||
|
||||
throwable.setStackTrace(stackTrace.toArray(StackTraceElement[]::new));
|
||||
|
||||
// Also deobfuscate any other exceptions
|
||||
if (throwable.getCause() != null && throwable.getCause() != throwable) {
|
||||
deobfuscate(throwable.getCause());
|
||||
}
|
||||
for (Throwable suppressed : throwable.getSuppressed()) {
|
||||
if (suppressed != throwable) deobfuscate(suppressed);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
System.err.println("Deobfuscation failed");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String deobfuscateToString(Throwable t) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
t.printStackTrace(pw);
|
||||
String stackTrace = sw.toString();
|
||||
stackTrace = stackTrace.replaceAll("at .+/(.+)", "at $1");
|
||||
|
||||
if (!System.getenv().containsKey("XPIPE_MAPPING")) {
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
try {
|
||||
var file = Files.createTempFile("xpipe_stracktrace", null);
|
||||
Files.writeString(file, stackTrace);
|
||||
var proc = new ProcessBuilder(
|
||||
"retrace." + (OsType.getLocal().equals(OsType.WINDOWS) ? "bat" : "sh"),
|
||||
System.getenv("XPIPE_MAPPING"),
|
||||
file.toString())
|
||||
.redirectErrorStream(true);
|
||||
var active = proc.start();
|
||||
var out = new String(active.getInputStream().readAllBytes()).replaceAll("\\r\\n", NewLine.LF.getNewLineString());
|
||||
var code = active.waitFor();
|
||||
if (code == 0) {
|
||||
return out;
|
||||
} else {
|
||||
System.err.println("Deobfuscation failed: " + out);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.err.println("Deobfuscation failed");
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
public static void printStackTrace(Throwable t) {
|
||||
var s = deobfuscateToString(t);
|
||||
System.err.println(s);
|
||||
}
|
||||
}
|
13
core/src/main/java/io/xpipe/core/util/ModuleHelper.java
Normal file
13
core/src/main/java/io/xpipe/core/util/ModuleHelper.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
public class ModuleHelper {
|
||||
|
||||
public static boolean isImage() {
|
||||
return ModuleHelper.class
|
||||
.getProtectionDomain()
|
||||
.getCodeSource()
|
||||
.getLocation()
|
||||
.getProtocol()
|
||||
.equals("jrt");
|
||||
}
|
||||
}
|
|
@ -6,8 +6,6 @@ import io.xpipe.core.process.CommandProcessControl;
|
|||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.process.ShellProcessControl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class XPipeInstallation {
|
||||
|
||||
public static String getInstallationBasePathForCLI(ShellProcessControl p, String cliExecutable) throws Exception {
|
||||
|
@ -32,7 +30,7 @@ public class XPipeInstallation {
|
|||
public static boolean containsCompatibleDefaultInstallation(ShellProcessControl p, String version) throws Exception {
|
||||
var defaultBase = getDefaultInstallationBasePath(p);
|
||||
var executable = getInstallationExecutable(p, defaultBase);
|
||||
if (executable.isEmpty()) {
|
||||
if (!p.executeBooleanSimpleCommand(p.getShellType().createFileExistsCommand(executable))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -44,14 +42,7 @@ public class XPipeInstallation {
|
|||
public static String getInstallationExecutable(ShellProcessControl p, String installation) throws Exception {
|
||||
var executable = getDaemonExecutablePath(p.getOsType());
|
||||
var file = FileNames.join(installation, executable);
|
||||
try (CommandProcessControl c =
|
||||
p.command(p.getShellType().createFileExistsCommand(file)).start()) {
|
||||
if (!c.startAndCheckExit()) {
|
||||
throw new IOException("File not found: " + file);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public static String getDataBasePath(ShellProcessControl p) throws Exception {
|
||||
|
@ -83,13 +74,6 @@ public class XPipeInstallation {
|
|||
path = "/opt/xpipe";
|
||||
}
|
||||
|
||||
try (CommandProcessControl c =
|
||||
p.command(p.getShellType().createFileExistsCommand(path)).start()) {
|
||||
if (!c.discardAndCheckExit()) {
|
||||
throw new IOException("Installation not found in " + path);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue