improve zip module windows script fallback

- handle non-English locales
 - wait more reliably, handle network paths where FS info gets stale
 - use absolute paths correctly
This commit is contained in:
Brent Cook 2017-01-07 12:17:24 -06:00
parent 969df408c7
commit cdcf4cce7d
3 changed files with 81 additions and 76 deletions

65
data/post/zip/zip.js Normal file
View File

@ -0,0 +1,65 @@
function create_zip(dst)
{
var header = "\x50\x4b\x05\x06" +
"\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
"\x00\x00\x00\x00\x00\x00\x00\x00\x00";
var outw = new ActiveXObject("ADODB.Stream");
outw.Type = 2;
outw.Open();
outw.WriteText(header);
outw.Position = 0;
var outa = new ActiveXObject("ADODB.Stream");
outa.Type = 2;
outa.Charset = "windows-1252";
outa.Open()
outw.CopyTo(outa);
outa.SaveToFile(dst, 2);
outw.Close();
outa.Close();
}
function basename(path)
{
var a = path.split("\\");
var b = a.slice(-1);
return b[0];
}
function fileeq(a, b)
{
return basename(a).toLowerCase() == basename(b).toLowerCase();
}
function zip(src, dst)
{
var shell = new ActiveXObject('Shell.Application');
var fso = new ActiveXObject('Scripting.FileSystemObject');
src = fso.GetAbsolutePathName(src);
dst = fso.GetAbsolutePathName(dst);
if (!fso.FileExists(dst)) {
create_zip(dst);
}
var zipfile = shell.Namespace(dst);
var files = zipfile.items();
var count = files.Count;
for (var i = 0; i < files.Count; i++) {
if (fileeq(files.Item(i).Name, src)) {
return;
}
}
zipfile.CopyHere(src);
var max_tries = 50;
while (count == zipfile.items().Count) {
WScript.Sleep(100);
if (max_tries-- == 0) {
return;
}
}
}

View File

@ -1,62 +0,0 @@
On Error Resume Next
Function WindowsZip(sFile, sZipFile)
'This script is provided under the Creative Commons license located
'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
'be used for commercial purposes with out the expressed written consent
'of NateRice.com
Set oZipShell = CreateObject("WScript.Shell")
Set oZipFSO = CreateObject("Scripting.FileSystemObject")
If Not oZipFSO.FileExists(sZipFile) Then
NewZip(sZipFile)
End If
Set oZipApp = CreateObject("Shell.Application")
sZipFileCount = oZipApp.NameSpace(sZipFile).items.Count
aFileName = Split(sFile, "\")
sFileName = (aFileName(Ubound(aFileName)))
'listfiles
sDupe = False
For Each sFileNameInZip In oZipApp.NameSpace(sZipFile).items
If LCase(sFileName) = LCase(sFileNameInZip) Then
sDupe = True
Exit For
End If
Next
If Not sDupe Then
oZipApp.NameSpace(sZipFile).Copyhere sFile
'Keep script waiting until Compressing is done
On Error Resume Next
sLoop = 0
Do Until sZipFileCount < oZipApp.NameSpace(sZipFile).Items.Count
Wscript.Sleep(100)
sLoop = sLoop + 1
Loop
On Error GoTo 0
End If
End Function
Sub NewZip(sNewZip)
'This script is provided under the Creative Commons license located
'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
'be used for commercial purposes with out the expressed written consent
'of NateRice.com
Set oNewZipFSO = CreateObject("Scripting.FileSystemObject")
Set oNewZipFile = oNewZipFSO.CreateTextFile(sNewZip)
oNewZipFile.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
oNewZipFile.Close
Set oNewZipFSO = Nothing
Wscript.Sleep(500)
End Sub

View File

@ -16,7 +16,7 @@ class MetasploitModule < Msf::Post
'Description' => %q{ 'Description' => %q{
This module zips a file or a directory. On Linux, it uses the zip command. This module zips a file or a directory. On Linux, it uses the zip command.
On Windows, it will try to use remote target's 7Zip if found. If not, it falls On Windows, it will try to use remote target's 7Zip if found. If not, it falls
back to its own VBScript. back to its Windows Scripting Host.
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ], 'Author' => [ 'sinn3r' ],
@ -39,10 +39,12 @@ class MetasploitModule < Msf::Post
file?("#{get_program_file_path}\\7-Zip\\7z.exe") file?("#{get_program_file_path}\\7-Zip\\7z.exe")
end end
def vbs(dest, src) def wsh_script(dst, src)
vbs_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.vbs")) script_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.js"))
vbs_file << "WindowsZip \"#{src}\",\"#{dest}\"" src.gsub!("\\", "\\\\\\")
vbs_file dst.gsub!("\\", "\\\\\\")
script_file << "zip(\"#{src}\",\"#{dst}\");"
script_file
end end
def find_pid_by_user(username) def find_pid_by_user(username)
@ -62,7 +64,7 @@ class MetasploitModule < Msf::Post
pid = find_pid_by_user(current_user) pid = find_pid_by_user(current_user)
unless pid unless pid
fail_with(Failure::Unknown, "Unable to find a PID for #{current_user} to execute .vbs") fail_with(Failure::Unknown, "Unable to find a PID for #{current_user} to execute WSH")
end end
print_status("Stealing token from PID #{pid} for #{current_user}") print_status("Stealing token from PID #{pid} for #{current_user}")
@ -77,21 +79,21 @@ class MetasploitModule < Msf::Post
@token_stolen = true @token_stolen = true
end end
def upload_exec_vbs_zip def upload_exec_wsh_script_zip
if is_system? if is_system?
unless session unless session
print_error('Unable to decompress with VBS technique without Meterpreter') print_error('Unable to compress with WSH technique without Meterpreter')
return return
end end
steal_token steal_token
end end
script = vbs(datastore['DESTINATION'], datastore['SOURCE']) script = wsh_script(datastore['DESTINATION'], datastore['SOURCE'])
tmp_path = "#{get_env('TEMP')}\\zip.vbs" tmp_path = "#{get_env('TEMP')}\\zip.js"
print_status("VBS file uploaded to #{tmp_path}") print_status("script file uploaded to #{tmp_path}")
write_file(tmp_path, script) write_file(tmp_path, script)
cmd_exec("wscript.exe #{tmp_path}") cmd_exec("cscript.exe #{tmp_path}")
end end
def do_7zip def do_7zip
@ -110,8 +112,8 @@ class MetasploitModule < Msf::Post
print_status("Compressing #{datastore['DESTINATION']} via 7zip") print_status("Compressing #{datastore['DESTINATION']} via 7zip")
do_7zip do_7zip
else else
print_status("Compressing #{datastore['DESTINATION']} via VBS") print_status("Compressing #{datastore['DESTINATION']} via WSH")
upload_exec_vbs_zip upload_exec_wsh_script_zip
end end
end end