Module: Msf::Exploit::Remote::SMB::Server::Share::Command::NtCreateAndx

Included in:
Msf::Exploit::Remote::SMB::Server::Share
Defined in:
lib/msf/core/exploit/smb/server/share/command/nt_create_andx.rb

Instance Method Summary collapse

Instance Method Details

#send_nt_create_andx_res(c, opts = {}) ⇒ Integer

Builds and sends an SMB_COM_NT_CREATE_ANDX response.

Parameters:

  • c (Socket)

    The client to answer.

  • opts (Hash{Symbol => <Integer>}) (defaults to: {})

    Response custom values.

Options Hash (opts):

  • :file_id (Integer)

    A FID representing the file or directory created or opened.

  • :attributes (Integer)

    The attributes that the server assigned to the file or directory.

  • :end_of_file_low (Integer)

    The end of file offset value (4 bytes)

  • :is_directory (Integer)

    Indicates if the FID represents a directory.

  • :alloc_low (Integer)

    The number of bytes allocated to the file by the server.

Returns:

  • (Integer)

    The number of bytes returned to the client as response.


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/msf/core/exploit/smb/server/share/command/nt_create_andx.rb', line 79

def send_nt_create_andx_res(c, opts = {})
  file_id = opts[:file_id] || 0
  attributes = opts[:attributes] || 0
  end_of_file_low = opts[:end_of_file_low] || 0
  is_directory = opts[:is_directory] || 0
  alloc_low = opts[:alloc_low] || 0

  pkt = CONST::SMB_CREATE_ANDX_RES_PKT.make_struct
  smb_set_defaults(c, pkt)
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
  pkt['Payload']['SMB'].v['Flags1'] = FLAGS
  pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
  pkt['Payload']['SMB'].v['WordCount'] = CONST::SMB_NT_CREATE_ANDX_RES_WORD_COUNT
  pkt['Payload'].v['AndX'] = CONST::SMB_COM_NO_ANDX_COMMAND
  pkt['Payload'].v['OpLock'] = CONST::LEVEL_II_OPLOCK # Grant Oplock on File
  pkt['Payload'].v['FileID'] = file_id
  pkt['Payload'].v['Action'] = CONST::FILE_OPEN # The file existed and was opened
  pkt['Payload'].v['CreateTimeLow'] = lo
  pkt['Payload'].v['CreateTimeHigh'] = hi
  pkt['Payload'].v['AccessTimeLow'] = lo
  pkt['Payload'].v['AccessTimeHigh'] = hi
  pkt['Payload'].v['WriteTimeLow'] = lo
  pkt['Payload'].v['WriteTimeHigh'] = hi
  pkt['Payload'].v['ChangeTimeLow'] = lo
  pkt['Payload'].v['ChangeTimeHigh'] = hi
  pkt['Payload'].v['Attributes'] = attributes
  pkt['Payload'].v['AllocLow'] = alloc_low
  pkt['Payload'].v['AllocHigh'] = 0
  pkt['Payload'].v['EOFLow'] = end_of_file_low
  pkt['Payload'].v['EOFHigh'] = 0
  pkt['Payload'].v['FileType'] = CONST::SMB_RESOURCE_FILE_TYPE_DISK
  pkt['Payload'].v['IPCState'] = 0x7 # Number maxim of instance a named pipe can have
  pkt['Payload'].v['IsDirectory'] = is_directory
  pkt['Payload'].v['MaxAccess'] = CREATE_MAX_ACCESS
  c.put(pkt.to_s)
end

#smb_cmd_nt_create_andx(c, buff) ⇒ Integer

Handles an SMB_COM_NT_CREATE_ANDX command, used by the client to create and open a new file.

Parameters:

  • c (Socket)

    The client sending the request.

  • buff (String)

    The data including the client request.

Returns:

  • (Integer)

    The number of bytes returned to the client as response.


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/msf/core/exploit/smb/server/share/command/nt_create_andx.rb', line 15

def smb_cmd_nt_create_andx(c, buff)
  smb = @state[c]
  pkt = CONST::SMB_CREATE_PKT.make_struct
  pkt.from_s(buff)

  payload = pkt['Payload'].v['Payload'].downcase

  if pkt['Payload']['SMB'].v['Flags2'] & CONST::FLAGS2_UNICODE_STRINGS == CONST::FLAGS2_UNICODE_STRINGS
    # If path length is odd first character is alignment
    if payload.length.odd?
      payload = payload[1..-1]
    end
    payload = Rex::Text.to_ascii(payload)
  end

  payload.gsub!(/[\x00]*/, '') # delete nulls

  if payload.nil? || payload.empty?
    payload = file_name
  end

  contents = get_file_contents(client: c)

  if payload.ends_with?(file_name.downcase)
    vprint_status("SMB Share - #{smb[:ip]} SMB_COM_NT_CREATE_ANDX request for #{unc}... ")
    fid = smb[:file_id].to_i
    attribs = CONST::SMB_EXT_FILE_ATTR_NORMAL
    eof = contents.length
    is_dir = 0
  elsif folder_name && payload.ends_with?(folder_name.downcase)
    fid = smb[:dir_id].to_i
    attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
    eof = 0
    is_dir = 1
  elsif payload == "\\"
    fid = smb[:dir_id].to_i
    attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
    eof = 0
    is_dir = 1
  else
    # Otherwise send not found
    vprint_status("SMB Share - #{smb[:ip]} SMB_COM_NT_CREATE_ANDX for #{payload}, not found")
    return smb_error(CONST::SMB_COM_NT_CREATE_ANDX, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)
  end

  send_nt_create_andx_res(c, {
    file_id: fid,
    attributes: attribs,
    end_of_file_low: eof,
    is_directory: is_dir,
    alloc_low: 0x100000
  })
end