From 95da1f36ecdfe2e3d5fec1bb4fbf13fa114851c7 Mon Sep 17 00:00:00 2001 From: Nayera Date: Tue, 10 Feb 2026 00:31:49 +0200 Subject: [PATCH 1/3] Fix mkdir post API to behave consistently across session types --- lib/msf/core/post/file.rb | 34 +++++++++++++++++++++++++++++++++- test/modules/post/test/file.rb | 7 +++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/post/file.rb b/lib/msf/core/post/file.rb index 193d02b6a423c..42a9fafbc9903 100644 --- a/lib/msf/core/post/file.rb +++ b/lib/msf/core/post/file.rb @@ -117,13 +117,45 @@ def dir(directory) alias ls dir + def meterpreter_parent_directory(path) + separator = session.fs.file.separator + normalized_path = path.tr('\\', '/') + parent_path = ::File.dirname(normalized_path) + + return nil if parent_path == '.' + + if parent_path.match?(/^[a-zA-Z]:$/) + return "#{parent_path}#{separator}" + end + + parent_path.tr('/', separator) + end + + def meterpreter_mkdir_p(path) + return nil if directory?(path) + + begin + return session.fs.dir.mkdir(path) + rescue StandardError + parent_path = meterpreter_parent_directory(path) + + if parent_path && parent_path != path && !directory?(parent_path) + meterpreter_mkdir_p(parent_path) + end + + return session.fs.dir.mkdir(path) unless directory?(path) + end + + nil + end + # create and mark directory for cleanup def mkdir(path) result = nil vprint_status("Creating directory #{path}") if session.type == 'meterpreter' # behave like mkdir -p and don't throw an error if the directory exists - result = session.fs.dir.mkdir(path) unless directory?(path) + result = meterpreter_mkdir_p(path) elsif session.type == 'powershell' result = cmd_exec("New-Item \"#{path}\" -itemtype directory") elsif session.platform == 'windows' diff --git a/test/modules/post/test/file.rb b/test/modules/post/test/file.rb index db6cf38b96590..b0ec7a02791b6 100644 --- a/test/modules/post/test/file.rb +++ b/test/modules/post/test/file.rb @@ -67,6 +67,13 @@ def test_dir ret end + it 'should create intermediary directories' do + nested_path = [datastore['BaseDirectoryName'], 'parent', 'child'].join(fs_sep) + mkdir(nested_path) + + directory?(nested_path) + end + it 'should list the directory we just made' do dents = dir(datastore['BaseDirectoryName']) dents.include?('file') && dents.include?('directory') From 0226459008936043060384141a6c43a437091c2a Mon Sep 17 00:00:00 2001 From: Nayera <115358236+Nayeraneru@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:57:20 +0200 Subject: [PATCH 2/3] Refactor mkdir creation method in file.rb --- lib/msf/core/post/file.rb | 48 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/lib/msf/core/post/file.rb b/lib/msf/core/post/file.rb index 42a9fafbc9903..3cf06faadd796 100644 --- a/lib/msf/core/post/file.rb +++ b/lib/msf/core/post/file.rb @@ -117,38 +117,36 @@ def dir(directory) alias ls dir - def meterpreter_parent_directory(path) - separator = session.fs.file.separator - normalized_path = path.tr('\\', '/') - parent_path = ::File.dirname(normalized_path) - - return nil if parent_path == '.' - - if parent_path.match?(/^[a-zA-Z]:$/) - return "#{parent_path}#{separator}" - end - - parent_path.tr('/', separator) +def meterpreter_mkdir_p(path) + return nil if directory?(path) + + separator = session.fs.file.separator + normalized = path.tr('\\/', separator) + directories = normalized.split(separator) + current_path = '' + + if normalized.match?(/\A[a-zA-Z]:#{Regexp.escape(separator)}?/) + current_path = "#{directories.shift}#{separator}" + elsif normalized.start_with?(separator) + current_path = separator end - def meterpreter_mkdir_p(path) - return nil if directory?(path) - - begin - return session.fs.dir.mkdir(path) - rescue StandardError - parent_path = meterpreter_parent_directory(path) + directories.each do |dir| + next if dir.empty? - if parent_path && parent_path != path && !directory?(parent_path) - meterpreter_mkdir_p(parent_path) + current_path = + if current_path.end_with?(separator) || current_path.empty? + "#{current_path}#{dir}" + else + "#{current_path}#{separator}#{dir}" end - return session.fs.dir.mkdir(path) unless directory?(path) - end - - nil + session.fs.dir.mkdir(current_path) unless directory?(current_path) end + nil +end + # create and mark directory for cleanup def mkdir(path) result = nil From 526464c14d261eecc1e93146e7675e17146c2410 Mon Sep 17 00:00:00 2001 From: Nayera <115358236+Nayeraneru@users.noreply.github.com> Date: Thu, 19 Feb 2026 08:55:52 +0200 Subject: [PATCH 3/3] Removed changes , Migrate them in meterpreter side --- lib/msf/core/post/file.rb | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/lib/msf/core/post/file.rb b/lib/msf/core/post/file.rb index 3cf06faadd796..193d02b6a423c 100644 --- a/lib/msf/core/post/file.rb +++ b/lib/msf/core/post/file.rb @@ -117,43 +117,13 @@ def dir(directory) alias ls dir -def meterpreter_mkdir_p(path) - return nil if directory?(path) - - separator = session.fs.file.separator - normalized = path.tr('\\/', separator) - directories = normalized.split(separator) - current_path = '' - - if normalized.match?(/\A[a-zA-Z]:#{Regexp.escape(separator)}?/) - current_path = "#{directories.shift}#{separator}" - elsif normalized.start_with?(separator) - current_path = separator - end - - directories.each do |dir| - next if dir.empty? - - current_path = - if current_path.end_with?(separator) || current_path.empty? - "#{current_path}#{dir}" - else - "#{current_path}#{separator}#{dir}" - end - - session.fs.dir.mkdir(current_path) unless directory?(current_path) - end - - nil -end - # create and mark directory for cleanup def mkdir(path) result = nil vprint_status("Creating directory #{path}") if session.type == 'meterpreter' # behave like mkdir -p and don't throw an error if the directory exists - result = meterpreter_mkdir_p(path) + result = session.fs.dir.mkdir(path) unless directory?(path) elsif session.type == 'powershell' result = cmd_exec("New-Item \"#{path}\" -itemtype directory") elsif session.platform == 'windows'