From aa319bf52f34f587b31155524d98940000f5fdb8 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 6 Nov 2024 09:05:49 -0500 Subject: [PATCH 1/6] Set the working directory when executing commands --- .../meterpreter/stdapi/stdapi_sys_process_execute.java | 2 +- 1 file changed, 1 insertion(+), 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 016f51210..5e9810cb8 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 @@ -147,7 +147,7 @@ protected Process execute(String cmd, ArrayList args) throws IOException } protected Process execute(String cmdstr) throws IOException { - Process proc = Runtime.getRuntime().exec(cmdstr); + Process proc = Runtime.getRuntime().exec(cmdstr, null, Loader.getCWD()); return proc; } } From bda3a299eb4a07b6b495b0e8584e00b46555d6d2 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 6 Nov 2024 10:48:38 -0500 Subject: [PATCH 2/6] Add a FsUtils class to test for symbolic links --- .../meterpreter/stdapi/FsUtils.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/FsUtils.java diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/FsUtils.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/FsUtils.java new file mode 100644 index 000000000..53efd1693 --- /dev/null +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/FsUtils.java @@ -0,0 +1,55 @@ +package com.metasploit.meterpreter.stdapi; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; + +public class FsUtils { + public static boolean isSymlink(File file) throws IOException { + String osName = System.getProperty("os.name"); + if (osName != null && osName.toLowerCase().contains("windows") && isWindowsSymlink(file)) { + return true; + } + + File canon; + if (file.getParent() == null) { + canon = file; + } else { + File canonDir = file.getParentFile().getCanonicalFile(); + canon = new File(canonDir, file.getName()); + } + + return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); + } + + private static boolean isWindowsSymlink(File file) { + // this uses reflection to access the java.nio.file classes necessary that are available on Java 7+ + try { + // first check using isSymbolicLink + Class filesClass = Class.forName("java.nio.file.Files"); + Class pathClass = Class.forName("java.nio.file.Path"); + + Method isSymbolicLinkMethod = filesClass.getMethod("isSymbolicLink", pathClass); + Method toPathMethod = File.class.getMethod("toPath"); + + Object path = toPathMethod.invoke(file); + if ((Boolean)isSymbolicLinkMethod.invoke(null, path)) { + return true; + } + + // next check if the target is a junction because isSymbolicLink doesn't handle that + Class linkOptionClass = Class.forName("java.nio.file.LinkOption"); + Object linkOptionArray = java.lang.reflect.Array.newInstance(linkOptionClass, 0); + Method toRealPath = pathClass.getMethod("toRealPath", linkOptionArray.getClass()); + Object realPath = toRealPath.invoke(path, linkOptionArray); + + // toRealPath resolves junctions so the result will be different + Method equalsMethod = pathClass.getMethod("equals", Object.class); + if (!(Boolean)equalsMethod.invoke(path, realPath)) { + return true; + } + } catch (ReflectiveOperationException e) { + } + return false; + } +} From 04d65be885ac46e379619067749648cdf0842802 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 6 Nov 2024 11:34:00 -0500 Subject: [PATCH 3/6] Add missing detections for Java 7 and 8 --- .../java/com/metasploit/meterpreter/CommandManager.java | 6 ++++++ .../java/com/metasploit/meterpreter/ExtensionLoader.java | 2 ++ 2 files changed, 8 insertions(+) diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java index cf496f724..297db81e8 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java @@ -40,6 +40,12 @@ protected CommandManager() throws Exception { Class.forName("java.util.ServiceLoader"); apiVersion = ExtensionLoader.V1_6; + Class.forName("java.util.Objects"); + apiVersion = ExtensionLoader.V1_7; + + Class.forName("java.util.Optional"); + apiVersion = ExtensionLoader.V1_8; + Class.forName("java.util.Optional").getMethod("stream"); apiVersion = ExtensionLoader.V1_9; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/ExtensionLoader.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/ExtensionLoader.java index 9233b3d40..2b6a57c90 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/ExtensionLoader.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/ExtensionLoader.java @@ -13,6 +13,8 @@ public interface ExtensionLoader { public static final int V1_4 = 14; public static final int V1_5 = 15; public static final int V1_6 = 16; + public static final int V1_7 = 17; + public static final int V1_8 = 18; public static final int V1_9 = 19; public static final int V1_15 = 25; From 894226a0f2a0276f8282fae1efc4340c27e29d39 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 6 Nov 2024 16:01:48 -0500 Subject: [PATCH 4/6] Fix pom.xml checks for version compatibility This edit uses javascript to exclude versioned files requirinig Java 7+. --- .../java14/pom.xml | 2 +- .../java15/pom.xml | 2 +- .../java16/pom.xml | 19 +++++++++++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/java/version-compatibility-check/java14/pom.xml b/java/version-compatibility-check/java14/pom.xml index d6dfe3569..148a661ed 100644 --- a/java/version-compatibility-check/java14/pom.xml +++ b/java/version-compatibility-check/java14/pom.xml @@ -27,7 +27,7 @@ - + diff --git a/java/version-compatibility-check/java15/pom.xml b/java/version-compatibility-check/java15/pom.xml index 22fd0c8cf..7ec3991e3 100644 --- a/java/version-compatibility-check/java15/pom.xml +++ b/java/version-compatibility-check/java15/pom.xml @@ -27,7 +27,7 @@ - + diff --git a/java/version-compatibility-check/java16/pom.xml b/java/version-compatibility-check/java16/pom.xml index d7eac3564..2d1b84bac 100644 --- a/java/version-compatibility-check/java16/pom.xml +++ b/java/version-compatibility-check/java16/pom.xml @@ -28,10 +28,21 @@ - - - - + + + + + + + if (!(new RegExp('_V[0-9]_[0-9]+\.java')).test(filename)) { + self.setSelected(true); + } else if ((new RegExp('_V1_[0-6]\.java')).test(filename)) { + self.setSelected(true); + } else { + self.setSelected(false); + } + + From 64631d276b164706cb232f05eaf1a2be7ad731e8 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 6 Nov 2024 16:14:13 -0500 Subject: [PATCH 5/6] Fix handinig symlinks and junctions on Windows --- .../metasploit/meterpreter/stdapi/Loader.java | 2 +- .../stdapi/stdapi_fs_delete_dir.java | 19 ++++++------------- .../stdapi/stdapi_fs_delete_dir_V1_7.java | 13 +++++++++++++ .../meterpreter/stdapi/stdapi_fs_stat.java | 8 ++++++-- 4 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/Loader.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/Loader.java index 44480c06c..734892d40 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/Loader.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/Loader.java @@ -42,7 +42,7 @@ public static void setCWD(File newCWD) { public void load(CommandManager mgr) throws Exception { mgr.registerCommand(CommandId.CORE_CHANNEL_OPEN, stdapi_channel_open.class, V1_2, V1_15); mgr.registerCommand(CommandId.STDAPI_FS_CHDIR, stdapi_fs_chdir.class); - mgr.registerCommand(CommandId.STDAPI_FS_DELETE_DIR, stdapi_fs_delete_dir.class); + mgr.registerCommand(CommandId.STDAPI_FS_DELETE_DIR, stdapi_fs_delete_dir.class, V1_2, V1_7); mgr.registerCommand(CommandId.STDAPI_FS_DELETE_FILE, stdapi_fs_delete_file.class); mgr.registerCommand(CommandId.STDAPI_FS_FILE_EXPAND_PATH, stdapi_fs_file_expand_path.class, V1_2, V1_5); // %COMSPEC% only mgr.registerCommand(CommandId.STDAPI_FS_FILE_MOVE, stdapi_fs_file_move.class); diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java index 4dd2eed72..4e236b3d9 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java @@ -12,8 +12,8 @@ public class stdapi_fs_delete_dir implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { String path = request.getStringValue(TLVType.TLV_TYPE_DIRECTORY_PATH); File file = Loader.expand(path); - if (isSymlink(file)) { - if (!file.delete()) { + if (FsUtils.isSymlink(file)) { + if (!deleteSymlink(file)) { throw new IOException("Cannot delete symbolic link " + file.getCanonicalPath()); } } else if (file.isDirectory()) { @@ -26,22 +26,15 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons return ERROR_SUCCESS; } - private static boolean isSymlink(File file) throws IOException { - File canon; - if (file.getParent() == null) { - canon = file; - } else { - File canonDir = file.getParentFile().getCanonicalFile(); - canon = new File(canonDir, file.getName()); - } - return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); + protected boolean deleteSymlink(File file) throws IOException { + return file.delete(); } private boolean rmtree(File file) throws IOException { boolean ret = true; for (File subFile : file.listFiles()) { - if (isSymlink(subFile)) { - ret = ret && subFile.delete(); + if (FsUtils.isSymlink(subFile)) { + ret = ret && deleteSymlink(subFile); } else if (subFile.isDirectory()) { ret = ret && rmtree(subFile); } else { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java new file mode 100644 index 000000000..a52dea3a3 --- /dev/null +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java @@ -0,0 +1,13 @@ +package com.metasploit.meterpreter.stdapi; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class stdapi_fs_delete_dir_V1_7 extends stdapi_fs_delete_dir { + @Override + protected boolean deleteSymlink(File file) throws IOException { + Files.delete(file.toPath()); + return true; + } +} diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java index c20271043..5d56a56cd 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java @@ -24,10 +24,10 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons } } File file = new File(path); - if (!file.exists()) { + if (!exists(file)) { file = Loader.expand(path); } - if (!file.exists()) { + if (!exists(file)) { throw new IOException("File/directory does not exist: " + path); } response.add(TLVType.TLV_TYPE_STAT_BUF, stat(file)); @@ -76,6 +76,10 @@ protected boolean canExecute(File file) { return false; } + private boolean exists(File file) throws IOException { + return file.exists() || FsUtils.isSymlink(file); + } + /** * Convert an integer to little endian. */ From af89b273e68e2988e5ad7773dbae1a6b95cf0061 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 6 Nov 2024 17:25:32 -0500 Subject: [PATCH 6/6] Handle deleting symlinks differently on Windows --- .../meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java index a52dea3a3..24c5c0a55 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir_V1_7.java @@ -7,7 +7,11 @@ public class stdapi_fs_delete_dir_V1_7 extends stdapi_fs_delete_dir { @Override protected boolean deleteSymlink(File file) throws IOException { - Files.delete(file.toPath()); - return true; + String osName = System.getProperty("os.name"); + if (osName != null && osName.toLowerCase().contains("windows")) { + Files.delete(file.toPath()); + return true; + } + return file.delete(); } }