All sorts of fun changes to smb/dcerpc, the basics are:
1) Clean up SMB constants, add new ones, define which ones are supported by dialect 2) DCERPC over SMB uses a 'OpenPipe' class, not an 'OpenFile' 3) A new DCERPC option called 'smb_pipeio' allows the user to switch between Read/Write and TransactNamedPipe() git-svn-id: file:///home/svn/incoming/trunk@3622 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
d0b3483d41
commit
42bc7496cf
|
@ -15,7 +15,7 @@ require 'rex/proto/smb/exceptions'
|
|||
def initialize(handle, socket, useroptions = Hash.new)
|
||||
self.handle = handle
|
||||
self.socket = socket
|
||||
self.options = { 'smb_user' => '', 'smb_pass' => '' } # put default options here...
|
||||
self.options = { 'smb_user' => '', 'smb_pass' => '', 'smb_pipeio' => 'rw' } # put default options here...
|
||||
self.options.merge!(useroptions)
|
||||
|
||||
# we must have a valid handle, regardless of everything else
|
||||
|
@ -45,7 +45,7 @@ require 'rex/proto/smb/exceptions'
|
|||
raise "ack, #{self.handle.protocol} requires socket type tcp, not #{self.socket.type?}!"
|
||||
end
|
||||
when 'ncacn_np'
|
||||
if self.socket.class == Rex::Proto::SMB::SimpleClient::OpenFile
|
||||
if self.socket.class == Rex::Proto::SMB::SimpleClient::OpenPipe
|
||||
self.ispipe = 1
|
||||
elsif self.socket.type? == 'tcp'
|
||||
self.smb_connect()
|
||||
|
@ -87,17 +87,20 @@ require 'rex/proto/smb/exceptions'
|
|||
|
||||
def smb_connect()
|
||||
require 'rex/proto/smb/simpleclient'
|
||||
if self.socket.peerport == 445
|
||||
smb = Rex::Proto::SMB::SimpleClient.new(self.socket, true)
|
||||
elsif self.socket.peerport == 139
|
||||
|
||||
if self.socket.peerport == 139
|
||||
smb = Rex::Proto::SMB::SimpleClient.new(self.socket)
|
||||
else
|
||||
raise "ACK, how did we get a peerport other than 139 or 445? #{self.socket.peerport}"
|
||||
smb = Rex::Proto::SMB::SimpleClient.new(self.socket, true)
|
||||
end
|
||||
|
||||
smb.client.evasion_level = 0
|
||||
smb.login('*SMBSERVER', self.options['smb_user'], self.options['smb_pass'])
|
||||
smb.connect('IPC$')
|
||||
|
||||
f = smb.create_pipe(self.handle.options[0])
|
||||
f.mode = self.options['smb_pipeio']
|
||||
|
||||
self.socket = f
|
||||
self.smb = smb
|
||||
end
|
||||
|
@ -105,7 +108,7 @@ require 'rex/proto/smb/exceptions'
|
|||
def read()
|
||||
raw_response = ''
|
||||
|
||||
if self.socket.class == Rex::Proto::SMB::SimpleClient::OpenFile
|
||||
if self.socket.class == Rex::Proto::SMB::SimpleClient::OpenPipe
|
||||
begin
|
||||
if self.options['segment_read']
|
||||
while(true)
|
||||
|
@ -144,12 +147,13 @@ require 'rex/proto/smb/exceptions'
|
|||
end
|
||||
|
||||
def write(data)
|
||||
if self.options['segment_write']
|
||||
|
||||
if (! self.options['segment_write'] or (self.handle.protocol == 'ncacn_np' and self.options['smb_pipeio'] != 'rw'))
|
||||
self.socket.write(data)
|
||||
else
|
||||
while (data.length > 0)
|
||||
len = self.socket.write( data.slice!(0, (rand(20)+5)) )
|
||||
end
|
||||
else
|
||||
self.socket.write(data)
|
||||
end
|
||||
|
||||
data.length
|
||||
|
|
|
@ -259,7 +259,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
smb.login('*SMBSERVER', user, pass)
|
||||
smb.connect('IPC$')
|
||||
f = smb.create_pipe('\BROWSER')
|
||||
assert_instance_of(Rex::Proto::SMB::SimpleClient::OpenFile, f, 'pipe')
|
||||
assert_instance_of(Rex::Proto::SMB::SimpleClient::OpenPipe, f, 'pipe')
|
||||
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0'], 'ncacn_np', $_REX_TEST_SMB_HOST, ['\BROWSER'])
|
||||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
|
|
|
@ -131,7 +131,7 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
when CONST::SMB_COM_TREE_DISCONNECT
|
||||
res = smb_parse_tree_disconnect(pkt, data)
|
||||
|
||||
when CONST::SMB_COM_CREATE_ANDX
|
||||
when CONST::SMB_COM_NT_CREATE_ANDX
|
||||
res = smb_parse_create(pkt, data)
|
||||
|
||||
when CONST::SMB_COM_TRANSACTION, CONST::SMB_COM_TRANSACTION2
|
||||
|
@ -262,7 +262,7 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
raise XCEPT::InvalidWordCount
|
||||
end
|
||||
|
||||
# Process incoming SMB_COM_CREATE_ANDX packets
|
||||
# Process incoming SMB_COM_NT_CREATE_ANDX packets
|
||||
def smb_parse_create(pkt, data)
|
||||
|
||||
# Windows says 42, but Samba says 34, same structure :-/
|
||||
|
@ -805,7 +805,7 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
pkt = CONST::SMB_CREATE_PKT.make_struct
|
||||
self.smb_defaults(pkt['Payload']['SMB'])
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x18
|
||||
pkt['Payload']['SMB'].v['Flags2'] = 0x2001
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 24
|
||||
|
@ -822,7 +822,7 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
|
||||
self.smb_send(pkt.to_s)
|
||||
|
||||
ack = self.smb_recv_parse(CONST::SMB_COM_CREATE_ANDX)
|
||||
ack = self.smb_recv_parse(CONST::SMB_COM_NT_CREATE_ANDX)
|
||||
|
||||
# Save off the FileID
|
||||
if (ack['Payload'].v['FileID'] > 0)
|
||||
|
@ -1116,7 +1116,6 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
return ack
|
||||
end
|
||||
|
||||
|
||||
# Perform a transaction2 request using the specified subcommand, parameters, and data
|
||||
def trans2 (subcommand, param = '', body = '', setup_count = 0, setup_data = '')
|
||||
|
||||
|
|
|
@ -7,26 +7,78 @@ require 'rex/text'
|
|||
require 'rex/struct2'
|
||||
|
||||
# SMB Commands
|
||||
SMB_COM_CREATE_DIR = 0x00
|
||||
SMB_COM_DELETE_DIR = 0x01
|
||||
SMB_COM_CREATE_DIRECTORY = 0x00
|
||||
SMB_COM_DELETE_DIRECTORY = 0x01
|
||||
SMB_COM_OPEN = 0x02
|
||||
SMB_COM_CREATE = 0x03
|
||||
SMB_COM_CLOSE = 0x04
|
||||
SMB_COM_FLUSH = 0x05
|
||||
SMB_COM_DELETE = 0x06
|
||||
SMB_COM_RENAME = 0x07
|
||||
SMB_COM_CHECK_DIR = 0x10
|
||||
SMB_COM_QUERY_INFORMATION = 0x08
|
||||
SMB_COM_SET_INFORMATION = 0x09
|
||||
SMB_COM_READ = 0x0a
|
||||
SMB_COM_WRITE = 0x0b
|
||||
SMB_COM_LOCK_BYTE_RANGE = 0x0c
|
||||
SMB_COM_UNLOCK_BYTE_RANGE = 0x0d
|
||||
SMB_COM_CREATE_TEMPORARY = 0x0e
|
||||
SMB_COM_CREATE_NEW = 0x0f
|
||||
SMB_COM_CHECK_DIRECTORY = 0x10
|
||||
SMB_COM_PROCESS_EXIT = 0x11
|
||||
SMB_COM_SEEK = 0x12
|
||||
SMB_COM_LOCK_AND_READ = 0x13
|
||||
SMB_COM_WRITE_AND_UNLOCK = 0x14
|
||||
SMB_COM_READ_RAW = 0x1a
|
||||
SMB_COM_READ_MPX = 0x1b
|
||||
SMB_COM_READ_MPX_SECONDARY = 0x1c
|
||||
SMB_COM_WRITE_RAW = 0x1d
|
||||
SMB_COM_WRITE_MPX = 0x1e
|
||||
SMB_COM_WRITE_MPX_SECONDARY = 0x1f
|
||||
SMB_COM_WRITE_COMPLETE = 0x20
|
||||
SMB_COM_QUERY_SERVER = 0x21
|
||||
SMB_COM_SET_INFORMATION2 = 0x22
|
||||
SMB_COM_QUERY_INFORMATION2 = 0x23
|
||||
SMB_COM_LOCKING_ANDX = 0x24
|
||||
SMB_COM_TRANSACTION = 0x25
|
||||
SMB_COM_TRANSACTION2 = 0x32
|
||||
SMB_COM_TRANSACTION_SECONDARY = 0x26
|
||||
SMB_COM_IOCTL = 0x27
|
||||
SMB_COM_IOCTL_SECONDARY = 0x28
|
||||
SMB_COM_COPY = 0x29
|
||||
SMB_COM_MOVE = 0x2a
|
||||
SMB_COM_ECHO = 0x2b
|
||||
SMB_COM_WRITE_AND_CLOSE = 0x2c
|
||||
SMB_COM_OPEN_ANDX = 0x2d
|
||||
SMB_COM_READ_ANDX = 0x2e
|
||||
SMB_COM_WRITE_ANDX = 0x2f
|
||||
SMB_COM_NEW_FILE_SIZE = 0x30
|
||||
SMB_COM_CLOSE_AND_TREE_DISC = 0x31
|
||||
SMB_COM_TRANSACTION2 = 0x32
|
||||
SMB_COM_TRANSACTION2_SECONDARY = 0x33
|
||||
SMB_COM_FIND_CLOSE2 = 0x34
|
||||
SMB_COM_FIND_NOTIFY_CLOSE = 0x35
|
||||
SMB_COM_TREE_CONNECT = 0x70
|
||||
SMB_COM_TREE_DISCONNECT = 0x71
|
||||
SMB_COM_NEGOTIATE = 0x72
|
||||
SMB_COM_SESSION_SETUP_ANDX = 0x73
|
||||
SMB_COM_LOGOFF = 0x74
|
||||
SMB_COM_LOGOFF_ANDX = 0x74
|
||||
SMB_COM_TREE_CONNECT_ANDX = 0x75
|
||||
SMB_COM_QUERY_INFORMATION_DISK = 0x80
|
||||
SMB_COM_SEARCH = 0x81
|
||||
SMB_COM_FIND = 0x82
|
||||
SMB_COM_FIND_UNIQUE = 0x83
|
||||
SMB_COM_FIND_CLOSE = 0x84
|
||||
SMB_COM_NT_TRANSACT = 0xa0
|
||||
SMB_COM_CREATE_ANDX = 0xa2
|
||||
SMB_COM_NT_TRANSACT_SECONDARY = 0xa1
|
||||
SMB_COM_NT_CREATE_ANDX = 0xa2
|
||||
SMB_COM_NT_CANCEL = 0xa4
|
||||
SMB_COM_NT_RENAME = 0xa5
|
||||
SMB_COM_OPEN_PRINT_FILE = 0xc0
|
||||
SMB_COM_WRITE_PRINT_FILE = 0xc1
|
||||
SMB_COM_CLOSE_PRINT_FILE = 0xc2
|
||||
SMB_COM_GET_PRINT_QUEUE = 0xc3
|
||||
SMB_COM_READ_BULK = 0xd8
|
||||
SMB_COM_WRITE_BULK = 0xd9
|
||||
SMB_COM_NO_ANDX_COMMAND = 0xff
|
||||
|
||||
# SMB_COM_NT_TRANSACT Subcommands
|
||||
NT_TRANSACT_CREATE = 1 # File open/create
|
||||
|
@ -49,12 +101,14 @@ OPEN_SHARE_DENY_WRITE = 0x20
|
|||
OPEN_SHARE_DENY_READEXEC = 0x30
|
||||
OPEN_SHARE_DENY_NONE = 0x40
|
||||
|
||||
|
||||
# File Access
|
||||
OPEN_ACCESS_READ = 0x00
|
||||
OPEN_ACCESS_WRITE = 0x01
|
||||
OPEN_ACCESS_READWRITE = 0x02
|
||||
OPEN_ACCESS_EXEC = 0x03
|
||||
|
||||
|
||||
# Create Disposition
|
||||
CREATE_ACCESS_SUPERSEDE = 0x00 # Replace any previously existing file
|
||||
CREATE_ACCESS_EXIST = 0x01 # Open existing file and fail if it does not exist
|
||||
|
@ -72,6 +126,84 @@ NETBIOS_REDIR = 'CACACACACACACACACACACACACACACAAA'
|
|||
# SMB Error Codes
|
||||
SMB_ERROR_BUFFER_OVERFLOW = 0x80000005
|
||||
|
||||
# SMB Dialect Compatibility
|
||||
DIALECT = {}
|
||||
|
||||
DIALECT['PC NETWORK PROGRAM 1.0'] = [
|
||||
SMB_COM_CHECK_DIRECTORY,
|
||||
SMB_COM_CLOSE,
|
||||
SMB_COM_CLOSE_PRINT_FILE,
|
||||
SMB_COM_CREATE,
|
||||
SMB_COM_CREATE_DIRECTORY,
|
||||
SMB_COM_CREATE_NEW,
|
||||
SMB_COM_CREATE_TEMPORARY,
|
||||
SMB_COM_DELETE,
|
||||
SMB_COM_DELETE_DIRECTORY,
|
||||
SMB_COM_FLUSH,
|
||||
SMB_COM_GET_PRINT_QUEUE,
|
||||
SMB_COM_LOCK_BYTE_RANGE,
|
||||
SMB_COM_NEGOTIATE,
|
||||
SMB_COM_OPEN,
|
||||
SMB_COM_OPEN_PRINT_FILE,
|
||||
SMB_COM_PROCESS_EXIT,
|
||||
SMB_COM_QUERY_INFORMATION,
|
||||
SMB_COM_QUERY_INFORMATION_DISK,
|
||||
SMB_COM_READ,
|
||||
SMB_COM_RENAME,
|
||||
SMB_COM_SEARCH,
|
||||
SMB_COM_SEEK,
|
||||
SMB_COM_SET_INFORMATION,
|
||||
SMB_COM_TREE_CONNECT,
|
||||
SMB_COM_TREE_DISCONNECT,
|
||||
SMB_COM_UNLOCK_BYTE_RANGE,
|
||||
SMB_COM_WRITE,
|
||||
SMB_COM_WRITE_PRINT_FILE
|
||||
]
|
||||
|
||||
DIALECT['LANMAN 1.0'] = DIALECT['PC NETWORK PROGRAM 1.0'] + [
|
||||
SMB_COM_COPY,
|
||||
SMB_COM_ECHO,
|
||||
SMB_COM_FIND,
|
||||
SMB_COM_FIND_CLOSE,
|
||||
SMB_COM_FIND_UNIQUE,
|
||||
SMB_COM_IOCTL,
|
||||
SMB_COM_IOCTL_SECONDARY,
|
||||
SMB_COM_LOCK_AND_READ,
|
||||
SMB_COM_LOCKING_ANDX,
|
||||
SMB_COM_MOVE,
|
||||
SMB_COM_OPEN_ANDX,
|
||||
SMB_COM_QUERY_INFORMATION2,
|
||||
SMB_COM_READ_ANDX,
|
||||
SMB_COM_READ_MPX,
|
||||
SMB_COM_READ_RAW,
|
||||
SMB_COM_SESSION_SETUP_ANDX,
|
||||
SMB_COM_SET_INFORMATION2,
|
||||
SMB_COM_TRANSACTION,
|
||||
SMB_COM_TRANSACTION_SECONDARY,
|
||||
SMB_COM_TREE_CONNECT_ANDX,
|
||||
SMB_COM_WRITE_AND_CLOSE,
|
||||
SMB_COM_WRITE_AND_UNLOCK,
|
||||
SMB_COM_WRITE_ANDX,
|
||||
SMB_COM_WRITE_COMPLETE,
|
||||
SMB_COM_WRITE_MPX,
|
||||
SMB_COM_WRITE_MPX_SECONDARY,
|
||||
SMB_COM_WRITE_RAW
|
||||
]
|
||||
|
||||
DIALECT['LM1.2X002'] = DIALECT['LANMAN 1.0'] + [
|
||||
SMB_COM_FIND_CLOSE2,
|
||||
SMB_COM_LOGOFF_ANDX,
|
||||
SMB_COM_TRANSACTION2,
|
||||
SMB_COM_TRANSACTION2_SECONDARY
|
||||
]
|
||||
|
||||
DIALECT['NTLM 0.12'] = DIALECT['LM1.2X002'] + [
|
||||
SMB_COM_NT_CANCEL,
|
||||
SMB_COM_NT_CREATE_ANDX,
|
||||
SMB_COM_NT_RENAME,
|
||||
SMB_COM_NT_TRANSACT,
|
||||
SMB_COM_NT_TRANSACT_SECONDARY
|
||||
]
|
||||
|
||||
# Create a NetBIOS session packet template
|
||||
def self.make_nbs (template)
|
||||
|
|
|
@ -45,7 +45,7 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
end
|
||||
|
||||
# Read data from the file
|
||||
def read (length = nil, offset = 0)
|
||||
def read(length = nil, offset = 0)
|
||||
if (length == nil)
|
||||
data = ''
|
||||
fptr = offset
|
||||
|
@ -105,6 +105,50 @@ EVADE = Rex::Proto::SMB::Evasions
|
|||
end
|
||||
end
|
||||
|
||||
class OpenPipe < OpenFile
|
||||
|
||||
# Valid modes are: 'trans' and 'rw'
|
||||
attr_accessor :mode
|
||||
|
||||
def initalize(*args)
|
||||
super(*args)
|
||||
mode = 'rw'
|
||||
@buff = ''
|
||||
end
|
||||
|
||||
def read_buffer(length, offset=0)
|
||||
@buff.slice!(0, length)
|
||||
end
|
||||
|
||||
def read(length = nil, offset = 0)
|
||||
case self.mode
|
||||
when 'trans'
|
||||
read_buffer(length, offset)
|
||||
when 'rw'
|
||||
super(length, offset)
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
end
|
||||
|
||||
def write(data, offset = 0)
|
||||
case self.mode
|
||||
|
||||
when 'trans'
|
||||
write_trans(data, offset)
|
||||
when 'rw'
|
||||
super(data, offset)
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
end
|
||||
|
||||
def write_trans(data, offset=0)
|
||||
ack = self.client.trans_named_pipe(self.file_id, data)
|
||||
@buff << ack['Payload'].v['Payload']
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Public accessors
|
||||
attr_accessor :last_error
|
||||
|
@ -168,7 +212,7 @@ attr_accessor :socket, :client, :direct, :shares, :last_share
|
|||
disposition = UTILS.create_mode_to_disposition(perm)
|
||||
ok = self.client.create(path, disposition)
|
||||
file_id = ok['Payload'].v['FileID']
|
||||
fh = OpenFile.new(self.client, path, self.client.last_tree_id, file_id)
|
||||
fh = OpenPipe.new(self.client, path, self.client.last_tree_id, file_id)
|
||||
end
|
||||
|
||||
def trans_pipe(fid, data)
|
||||
|
|
|
@ -125,7 +125,7 @@ class Exploits::Windows::Smb::MS04_011_LSASS < Msf::Exploit::Remote
|
|||
Rex::Text.rand_text(528) +
|
||||
NDR.long(rand(0xFFFFFF))
|
||||
|
||||
print_status('sending exploit ...')
|
||||
print_status('Calling the vulnerable function...')
|
||||
begin
|
||||
response = dcerpc_call(9, stub)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
|
||||
|
|
Loading…
Reference in New Issue