Implement proto/smb/client find_next for find_files

Squashed commit of the following:

commit b5370b24d48a0b79d13cff465ef1fe53738754d0
Author: Rob Fuller <jd.mubix@gmail.com>
Date:   Sat Jul 21 01:52:31 2012 -0400

    add some documentation for smb client

commit 92438f515ef272337ce02b6deebb35f62a50f0a3
Author: Rob Fuller <jd.mubix@gmail.com>
Date:   Fri Jul 20 03:09:27 2012 -0400

    adds find_next to find_files

[Closes #627]
unstable
Rob Fuller 2012-07-21 00:03:19 -06:00 committed by James Lee
parent 99aa78a371
commit 70017511f5
1 changed files with 65 additions and 57 deletions

View File

@ -1830,7 +1830,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
files = { } files = { }
parm = [ parm = [
26, # Search for ALL files 26, # Search for ALL files
512, # Maximum search count 20, # Maximum search count
6, # Resume and Close on End of Search 6, # Resume and Close on End of Search
260, # Level of interest 260, # Level of interest
0, # Storage type is zero 0, # Storage type is zero
@ -1838,7 +1838,8 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
begin begin
resp = trans2(CONST::TRANS2_FIND_FIRST2, parm, '') resp = trans2(CONST::TRANS2_FIND_FIRST2, parm, '')
search_next = 0
begin
pcnt = resp['Payload'].v['ParamCount'] pcnt = resp['Payload'].v['ParamCount']
dcnt = resp['Payload'].v['DataCount'] dcnt = resp['Payload'].v['DataCount']
poff = resp['Payload'].v['ParamOffset'] poff = resp['Payload'].v['ParamOffset']
@ -1853,9 +1854,13 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
resp_parm = resp_rpkt[poff, pcnt] resp_parm = resp_rpkt[poff, pcnt]
resp_data = resp_rpkt[doff, dcnt] resp_data = resp_rpkt[doff, dcnt]
if search_next == 0
# search id, search count, end of search, error offset, last name offset # search id, search count, end of search, error offset, last name offset
sid, scnt, eos, eoff, loff = resp_parm.unpack('v5') sid, scnt, eos, eoff, loff = resp_parm.unpack('v5')
else
# FINX_NEXT doesn't return a SID
scnt, eos, eoff, loff = resp_parm.unpack('v4')
end
didx = 0 didx = 0
while (didx < resp_data.length) while (didx < resp_data.length)
info_buff = resp_data[didx, 70] info_buff = resp_data[didx, 70]
@ -1878,7 +1883,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
name = resp_data[didx + 70 + 24, info[15]].sub!(/\x00+$/, '') name = resp_data[didx + 70 + 24, info[15]].sub!(/\x00+$/, '')
files[name] = files[name] =
{ {
'type' => ((info[14] & 0x10)==0x10) ? 'D' : 'F', 'type' => (info[14] & 0x10) ? 'D' : 'F',
'attr' => info[14], 'attr' => info[14],
'info' => info 'info' => info
} }
@ -1886,9 +1891,14 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
break if info[0] == 0 break if info[0] == 0
didx += info[0] didx += info[0]
end end
last_search_id = sid last_search_id = sid
last_offset = loff
last_filename = name
if eos != 1 #If we aren't at the end of the search, run find_next
resp = find_next(last_search_id, last_offset, last_filename)
search_next = 1 # Flip bit so response params will parse correctly
end
end until eos == 1
rescue ::Exception rescue ::Exception
raise $! raise $!
end end
@ -1896,21 +1906,19 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
return files return files
end end
# TODO: Finish this method... requires search_id, resume_key, and filename from first # Supplements find_first if file/dir count exceeds max search count
=begin def find_next(sid, resume_key, last_filename)
def find_next(path, sid = last_search_id)
parm = [ parm = [
sid, # Search ID sid, # Search ID
512, # Maximum search count 20, # Maximum search count (Size of 20 keeps response to 1 packet)
260, # Level of interest 260, # Level of interest
0, # Resume key from previous resume_key, # Resume key from previous (Last name offset)
1, # Close search if end of search 6, # Close search if end of search
].pack('vvvVv') + path + "\x00" ].pack('vvvVv') + last_filename + "\x00" # Last filename returned from find_first or find_next
resp = trans2(CONST::TRANS2_FIND_NEXT2, parm, '')
return files return resp # Returns the FIND_NEXT2 response packet for parsing by the find_first function
end end
=end
# Creates a new directory on the mounted tree # Creates a new directory on the mounted tree
def create_directory(name) def create_directory(name)