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-b9f4589650da
unstable
HD Moore 2006-04-26 16:59:44 +00:00
parent d0b3483d41
commit 42bc7496cf
6 changed files with 227 additions and 48 deletions

View File

@ -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

View File

@ -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')

View File

@ -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 = '')

View File

@ -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)

View File

@ -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)

View File

@ -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