Changeset 5466

Show
Ignore:
Timestamp:
04/04/08 15:54:39 (4 months ago)
Author:
hdm
Message:

Properly handle SMB::pipe_(read|write)_(min|max)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • framework3/trunk/lib/msf/core/exploit/dcerpc.rb

    r5378 r5466  
    8181                        end                              
    8282                end 
    83  
    84                 if datastore['SMBUser'] 
    85                         opts['smb_user'] = datastore['SMBUser'] 
    86                 end 
    87                  
    88                 if datastore['SMBPass'] 
    89                         opts['smb_pass'] = datastore['SMBPass'] 
    90                 end 
    91  
    92                 if datastore['DCERPC::smb_pipeio'] 
    93                         opts['smb_pipeio'] = datastore['DCERPC::smb_pipeio'] 
    94                 end 
    95                  
    96                 if self.respond_to?('simple') and self.simple 
    97                         opts['smb_client'] = self.simple 
    98                 end 
    9983                 
    10084                opts['connect_timeout'] = (datastore['ConnectTimeout'] || 10).to_i 
    10185                 
    10286                opts['read_timeout']    = (datastore['DCERPC::ReadTimeout'] || 10).to_i 
     87         
     88         
     89                # Configure the SMB evasion options 
    10390                 
     91                if (datastore['SMBUser']) 
     92                        opts['smb_user'] = datastore['SMBUser'] 
     93                end 
    10494                 
     95                if (datastore['SMBPass']) 
     96                        opts['smb_pass'] = datastore['SMBPass'] 
     97                end 
     98 
     99                if (datastore['DCERPC::smb_pipeio']) 
     100                        opts['smb_pipeio'] = datastore['DCERPC::smb_pipeio'] 
     101                end 
     102                 
     103                if (datastore['SMB::pipe_write_min_size']) 
     104                        opts['pipe_write_min_size'] = datastore['SMB::pipe_write_min_size'] 
     105                end 
     106 
     107                if (datastore['SMB::pipe_write_max_size']) 
     108                        opts['pipe_write_max_size'] = datastore['SMB::pipe_write_max_size'] 
     109                end 
     110 
     111                if (datastore['SMB::pipe_read_min_size']) 
     112                        opts['pipe_read_min_size'] = datastore['SMB::pipe_read_min_size'] 
     113                end 
     114 
     115                if (datastore['SMB::pipe_read_max_size']) 
     116                        opts['pipe_read_max_size'] = datastore['SMB::pipe_read_max_size'] 
     117                end 
     118 
     119                if (self.respond_to?('simple') and self.simple) 
     120                        opts['smb_client'] = self.simple 
     121                end 
     122                 
     123                # Create the DCERPC client       
    105124                self.dcerpc = Rex::Proto::DCERPC::Client.new(h, self.sock, opts) 
    106125 
  • framework3/trunk/lib/rex/proto/dcerpc/client.rb

    r5378 r5466  
    132132 
    133133        def read() 
     134         
     135                max_read = self.options['pipe_read_max_size'] || nil 
     136                min_read = self.options['pipe_read_min_size'] || max_read 
     137                 
    134138                raw_response = '' 
    135                          
    136                 if self.socket.class == Rex::Proto::SMB::SimpleClient::OpenPipe 
     139                 
     140                # Are we reading from a remote pipe over SMB?    
     141                if (self.socket.class == Rex::Proto::SMB::SimpleClient::OpenPipe) 
    137142                        begin 
    138                                 if self.options['segment_read'] 
     143                                if(max_read) 
    139144                                        while(true) 
    140                                                 data = self.socket.read((rand(20)+5), rand(1024)+1) 
    141                                                 last if ! data.length 
     145                                                # Random read offsets will not work on Windows NT 4.0 (thanks Dave!) 
     146                                                data = self.socket.read( (rand(max_read-min_read)+min_read), rand(1024)+1) 
     147                                                last if not data.length 
    142148                                                raw_response += data 
    143149                                        end 
     
    152158                                end 
    153159                        end 
    154                 else # must be a regular socket 
    155                         if self.socket.type? == 'tcp' 
    156                                 if self.options['segment_read'] 
     160                # This must be a regular TCP or UDP socket 
     161                else  
     162                        if (self.socket.type? == 'tcp') 
     163                                if (max_read) 
    157164                                        while (true) 
    158                                                 data = self.socket.get_once(rand(5)+5, self.options['read_timeout']) 
    159                                                 break if data == nil 
    160                                                 break if ! data.length 
     165                                                data = self.socket.get_once((rand(max_read-min_read)+min_read), self.options['read_timeout']) 
     166                                                break if not data 
     167                                                break if not data.length 
    161168                                                raw_response << data 
    162169                                        end 
    163170                                else  
     171                                        # Just read the entire response in one go 
    164172                                        raw_response = self.socket.get_once(-1, self.options['read_timeout']) 
    165173                                end 
    166174                        else 
     175                                # No segmented read support for non-TCP sockets 
    167176                                raw_response = self.socket.read(0xFFFFFFFF / 2 - 1)  # read max data 
    168177                        end 
     
    172181        end 
    173182 
     183        # Write data to the underlying socket, limiting the sizes of the writes based on 
     184        # the pipe_write_min / pipe_write_max options. 
    174185        def write(data) 
    175186         
    176                 if (! self.options['segment_write'] or (self.handle.protocol == 'ncacn_np')) 
     187                max_write = self.options['pipe_write_max_size'] || data.length 
     188                min_write = self.options['pipe_write_min_size'] || max_write 
     189                idx = 0 
     190 
     191                if (self.socket.class == Rex::Proto::SMB::SimpleClient::OpenPipe) 
     192                        while(idx < data.length) 
     193                                bsize = (rand(max_write-min_write)+min_write).to_i 
     194                                len = self.socket.write(data[idx, bsize], rand(1024)+1) 
     195                                idx += bsize 
     196                        end 
     197                else 
    177198                        self.socket.write(data) 
    178                 else 
    179                         while (data.length > 0) 
    180                                 len = self.socket.write( data.slice!(0, (rand(20)+5)) ) 
    181                         end 
    182199                end 
    183200