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{
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
back to its own VBScript.
back to its Windows Scripting Host.
},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ],
@ -39,10 +39,12 @@ class MetasploitModule < Msf::Post
file?("#{get_program_file_path}\\7-Zip\\7z.exe")
end
def vbs(dest, src)
vbs_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.vbs"))
vbs_file << "WindowsZip \"#{src}\",\"#{dest}\""
vbs_file
def wsh_script(dst, src)
script_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.js"))
src.gsub!("\\", "\\\\\\")
dst.gsub!("\\", "\\\\\\")
script_file << "zip(\"#{src}\",\"#{dst}\");"
script_file
end
def find_pid_by_user(username)
@ -62,7 +64,7 @@ class MetasploitModule < Msf::Post
pid = find_pid_by_user(current_user)
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
print_status("Stealing token from PID #{pid} for #{current_user}")
@ -77,21 +79,21 @@ class MetasploitModule < Msf::Post
@token_stolen = true
end
def upload_exec_vbs_zip
def upload_exec_wsh_script_zip
if is_system?
unless session
print_error('Unable to decompress with VBS technique without Meterpreter')
print_error('Unable to compress with WSH technique without Meterpreter')
return
end
steal_token
end
script = vbs(datastore['DESTINATION'], datastore['SOURCE'])
tmp_path = "#{get_env('TEMP')}\\zip.vbs"
print_status("VBS file uploaded to #{tmp_path}")
script = wsh_script(datastore['DESTINATION'], datastore['SOURCE'])
tmp_path = "#{get_env('TEMP')}\\zip.js"
print_status("script file uploaded to #{tmp_path}")
write_file(tmp_path, script)
cmd_exec("wscript.exe #{tmp_path}")
cmd_exec("cscript.exe #{tmp_path}")
end
def do_7zip
@ -110,8 +112,8 @@ class MetasploitModule < Msf::Post
print_status("Compressing #{datastore['DESTINATION']} via 7zip")
do_7zip
else
print_status("Compressing #{datastore['DESTINATION']} via VBS")
upload_exec_vbs_zip
print_status("Compressing #{datastore['DESTINATION']} via WSH")
upload_exec_wsh_script_zip
end
end