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
parent
99aa78a371
commit
70017511f5
|
@ -1830,7 +1830,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
files = { }
|
||||
parm = [
|
||||
26, # Search for ALL files
|
||||
512, # Maximum search count
|
||||
20, # Maximum search count
|
||||
6, # Resume and Close on End of Search
|
||||
260, # Level of interest
|
||||
0, # Storage type is zero
|
||||
|
@ -1838,57 +1838,67 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
|
||||
begin
|
||||
resp = trans2(CONST::TRANS2_FIND_FIRST2, parm, '')
|
||||
search_next = 0
|
||||
begin
|
||||
pcnt = resp['Payload'].v['ParamCount']
|
||||
dcnt = resp['Payload'].v['DataCount']
|
||||
poff = resp['Payload'].v['ParamOffset']
|
||||
doff = resp['Payload'].v['DataOffset']
|
||||
|
||||
pcnt = resp['Payload'].v['ParamCount']
|
||||
dcnt = resp['Payload'].v['DataCount']
|
||||
poff = resp['Payload'].v['ParamOffset']
|
||||
doff = resp['Payload'].v['DataOffset']
|
||||
# Get the raw packet bytes
|
||||
resp_rpkt = resp.to_s
|
||||
|
||||
# Get the raw packet bytes
|
||||
resp_rpkt = resp.to_s
|
||||
# Remove the NetBIOS header
|
||||
resp_rpkt.slice!(0, 4)
|
||||
|
||||
# Remove the NetBIOS header
|
||||
resp_rpkt.slice!(0, 4)
|
||||
resp_parm = resp_rpkt[poff, pcnt]
|
||||
resp_data = resp_rpkt[doff, dcnt]
|
||||
|
||||
resp_parm = resp_rpkt[poff, pcnt]
|
||||
resp_data = resp_rpkt[doff, dcnt]
|
||||
|
||||
# search id, search count, end of search, error offset, last name offset
|
||||
sid, scnt, eos, eoff, loff = resp_parm.unpack('v5')
|
||||
|
||||
didx = 0
|
||||
while (didx < resp_data.length)
|
||||
info_buff = resp_data[didx, 70]
|
||||
break if info_buff.length != 70
|
||||
info = info_buff.unpack(
|
||||
'V'+ # Next Entry Offset
|
||||
'V'+ # File Index
|
||||
'VV'+ # Time Create
|
||||
'VV'+ # Time Last Access
|
||||
'VV'+ # Time Last Write
|
||||
'VV'+ # Time Change
|
||||
'VV'+ # End of File
|
||||
'VV'+ # Allocation Size
|
||||
'V'+ # File Attributes
|
||||
'V'+ # File Name Length
|
||||
'V'+ # Extended Attr List Length
|
||||
'C'+ # Short File Name Length
|
||||
'C' # Reserved
|
||||
)
|
||||
name = resp_data[didx + 70 + 24, info[15]].sub!(/\x00+$/, '')
|
||||
files[name] =
|
||||
{
|
||||
'type' => ((info[14] & 0x10)==0x10) ? 'D' : 'F',
|
||||
'attr' => info[14],
|
||||
'info' => info
|
||||
}
|
||||
|
||||
break if info[0] == 0
|
||||
didx += info[0]
|
||||
end
|
||||
|
||||
last_search_id = sid
|
||||
if search_next == 0
|
||||
# search id, search count, end of search, error offset, last name offset
|
||||
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
|
||||
while (didx < resp_data.length)
|
||||
info_buff = resp_data[didx, 70]
|
||||
break if info_buff.length != 70
|
||||
info = info_buff.unpack(
|
||||
'V'+ # Next Entry Offset
|
||||
'V'+ # File Index
|
||||
'VV'+ # Time Create
|
||||
'VV'+ # Time Last Access
|
||||
'VV'+ # Time Last Write
|
||||
'VV'+ # Time Change
|
||||
'VV'+ # End of File
|
||||
'VV'+ # Allocation Size
|
||||
'V'+ # File Attributes
|
||||
'V'+ # File Name Length
|
||||
'V'+ # Extended Attr List Length
|
||||
'C'+ # Short File Name Length
|
||||
'C' # Reserved
|
||||
)
|
||||
name = resp_data[didx + 70 + 24, info[15]].sub!(/\x00+$/, '')
|
||||
files[name] =
|
||||
{
|
||||
'type' => (info[14] & 0x10) ? 'D' : 'F',
|
||||
'attr' => info[14],
|
||||
'info' => info
|
||||
}
|
||||
|
||||
break if info[0] == 0
|
||||
didx += info[0]
|
||||
end
|
||||
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
|
||||
raise $!
|
||||
end
|
||||
|
@ -1896,21 +1906,19 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
return files
|
||||
end
|
||||
|
||||
# TODO: Finish this method... requires search_id, resume_key, and filename from first
|
||||
=begin
|
||||
def find_next(path, sid = last_search_id)
|
||||
# Supplements find_first if file/dir count exceeds max search count
|
||||
def find_next(sid, resume_key, last_filename)
|
||||
|
||||
parm = [
|
||||
sid, # Search ID
|
||||
512, # Maximum search count
|
||||
20, # Maximum search count (Size of 20 keeps response to 1 packet)
|
||||
260, # Level of interest
|
||||
0, # Resume key from previous
|
||||
1, # Close search if end of search
|
||||
].pack('vvvVv') + path + "\x00"
|
||||
|
||||
return files
|
||||
resume_key, # Resume key from previous (Last name offset)
|
||||
6, # Close search if end of search
|
||||
].pack('vvvVv') + last_filename + "\x00" # Last filename returned from find_first or find_next
|
||||
resp = trans2(CONST::TRANS2_FIND_NEXT2, parm, '')
|
||||
return resp # Returns the FIND_NEXT2 response packet for parsing by the find_first function
|
||||
end
|
||||
=end
|
||||
|
||||
# Creates a new directory on the mounted tree
|
||||
def create_directory(name)
|
||||
|
|
Loading…
Reference in New Issue