From 26eddbb7a33e7f2b6bd4c71e0ce434fd0733d230 Mon Sep 17 00:00:00 2001 From: Ashley Donaldson Date: Tue, 15 Oct 2024 21:21:58 +1100 Subject: [PATCH 1/2] Handle Windows oddity in java's process launch library --- .../stdapi/stdapi_sys_process_execute.java | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java index 7707c7db2..9c0ff6d91 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java @@ -65,10 +65,65 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons return ERROR_SUCCESS; } + // On Windows, Java quote-escapes _some_ arguments (like those with spaces), but doesn't deal correctly with some + // edge cases; e.g. empty strings, strings that already have quotes. + protected String escapeArg(String arg) { + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + if (arg == "") { + return "\"\""; + } else { + StringBuilder sb = new StringBuilder(); + int numBackslashes = 0; + boolean needsQuoting = false; + for (int i = 0; i < arg.length(); i++) { + char c = arg.charAt(i); + switch (c) { + case '"': { + for (int nb = 0; nb < numBackslashes; nb++) { + sb.append('\\'); + } + numBackslashes = 0; + sb.append('\\'); + break; + } + case '\\': { + numBackslashes++; + break; + } + case ' ': + case '\t': + case (char)11: + { + needsQuoting = true; + numBackslashes = 0; + break; + } + default: { + numBackslashes = 0; + break; + } + } + sb.append(c); + } + if (needsQuoting) { + for (int nb = 0; nb < numBackslashes; nb++) { + sb.append('\\'); + } + return "\"" + sb.toString() + "\""; + } + return sb.toString(); + } + } else { + return arg; + } + } + protected Process execute(String cmd, ArrayList args) throws IOException { ArrayList cmdAndArgs = new ArrayList(); cmdAndArgs.add(cmd); - cmdAndArgs.addAll(args); + for (String arg : args) { + cmdAndArgs.add(escapeArg(arg)); + } ProcessBuilder builder = new ProcessBuilder(cmdAndArgs); builder.directory(Loader.getCWD()); return builder.start(); From 26d0aa3e8d7d80ce141360921f15e417a2004090 Mon Sep 17 00:00:00 2001 From: Ashley Donaldson Date: Tue, 15 Oct 2024 22:11:02 +1100 Subject: [PATCH 2/2] Changes from code review --- .../meterpreter/stdapi/stdapi_sys_process_execute.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java index 9c0ff6d91..4bec2f964 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java @@ -68,8 +68,12 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons // On Windows, Java quote-escapes _some_ arguments (like those with spaces), but doesn't deal correctly with some // edge cases; e.g. empty strings, strings that already have quotes. protected String escapeArg(String arg) { - if (System.getProperty("os.name").toLowerCase().contains("windows")) { - if (arg == "") { + if (arg == null) { + return null; + } + String osName = System.getProperty("os.name"); + if (osName != null && osName.toLowerCase().contains("windows")) { + if (arg.equals("")) { return "\"\""; } else { StringBuilder sb = new StringBuilder();