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 = { }
|
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,57 +1838,67 @@ 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']
|
||||||
|
dcnt = resp['Payload'].v['DataCount']
|
||||||
|
poff = resp['Payload'].v['ParamOffset']
|
||||||
|
doff = resp['Payload'].v['DataOffset']
|
||||||
|
|
||||||
pcnt = resp['Payload'].v['ParamCount']
|
# Get the raw packet bytes
|
||||||
dcnt = resp['Payload'].v['DataCount']
|
resp_rpkt = resp.to_s
|
||||||
poff = resp['Payload'].v['ParamOffset']
|
|
||||||
doff = resp['Payload'].v['DataOffset']
|
|
||||||
|
|
||||||
# Get the raw packet bytes
|
# Remove the NetBIOS header
|
||||||
resp_rpkt = resp.to_s
|
resp_rpkt.slice!(0, 4)
|
||||||
|
|
||||||
# Remove the NetBIOS header
|
resp_parm = resp_rpkt[poff, pcnt]
|
||||||
resp_rpkt.slice!(0, 4)
|
resp_data = resp_rpkt[doff, dcnt]
|
||||||
|
|
||||||
resp_parm = resp_rpkt[poff, pcnt]
|
if search_next == 0
|
||||||
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')
|
||||||
# search id, search count, end of search, error offset, last name offset
|
else
|
||||||
sid, scnt, eos, eoff, loff = resp_parm.unpack('v5')
|
# FINX_NEXT doesn't return a SID
|
||||||
|
scnt, eos, eoff, loff = resp_parm.unpack('v4')
|
||||||
didx = 0
|
end
|
||||||
while (didx < resp_data.length)
|
didx = 0
|
||||||
info_buff = resp_data[didx, 70]
|
while (didx < resp_data.length)
|
||||||
break if info_buff.length != 70
|
info_buff = resp_data[didx, 70]
|
||||||
info = info_buff.unpack(
|
break if info_buff.length != 70
|
||||||
'V'+ # Next Entry Offset
|
info = info_buff.unpack(
|
||||||
'V'+ # File Index
|
'V'+ # Next Entry Offset
|
||||||
'VV'+ # Time Create
|
'V'+ # File Index
|
||||||
'VV'+ # Time Last Access
|
'VV'+ # Time Create
|
||||||
'VV'+ # Time Last Write
|
'VV'+ # Time Last Access
|
||||||
'VV'+ # Time Change
|
'VV'+ # Time Last Write
|
||||||
'VV'+ # End of File
|
'VV'+ # Time Change
|
||||||
'VV'+ # Allocation Size
|
'VV'+ # End of File
|
||||||
'V'+ # File Attributes
|
'VV'+ # Allocation Size
|
||||||
'V'+ # File Name Length
|
'V'+ # File Attributes
|
||||||
'V'+ # Extended Attr List Length
|
'V'+ # File Name Length
|
||||||
'C'+ # Short File Name Length
|
'V'+ # Extended Attr List Length
|
||||||
'C' # Reserved
|
'C'+ # Short File Name Length
|
||||||
)
|
'C' # Reserved
|
||||||
name = resp_data[didx + 70 + 24, info[15]].sub!(/\x00+$/, '')
|
)
|
||||||
files[name] =
|
name = resp_data[didx + 70 + 24, info[15]].sub!(/\x00+$/, '')
|
||||||
{
|
files[name] =
|
||||||
'type' => ((info[14] & 0x10)==0x10) ? 'D' : 'F',
|
{
|
||||||
'attr' => info[14],
|
'type' => (info[14] & 0x10) ? 'D' : 'F',
|
||||||
'info' => info
|
'attr' => info[14],
|
||||||
}
|
'info' => info
|
||||||
|
}
|
||||||
break if info[0] == 0
|
|
||||||
didx += info[0]
|
|
||||||
end
|
|
||||||
|
|
||||||
last_search_id = sid
|
|
||||||
|
|
||||||
|
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
|
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)
|
||||||
|
|
Loading…
Reference in New Issue