Skip to content

Commit 3110c7b

Browse files
author
Matthew Hall
committed
Adds smb_cmd_trans_find_first2_full to respond to "Find File Full Directory Info" FIND_FIRST2 requests,
as seen when using "type \\ip\share\file".
1 parent 3c10b04 commit 3110c7b

File tree

1 file changed

+113
-4
lines changed

1 file changed

+113
-4
lines changed

lib/rex/proto/smb/server.rb

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ def alias
5757
# Debugging
5858
#
5959
def dprint(msg)
60-
$stdout.puts "#{msg}"
61-
#dlog("#{msg}", 'rex', LEV_3)
60+
#$stdout.puts "#{msg}"
61+
dlog("#{msg}", 'rex', LEV_3)
6262
end
6363

6464
#
@@ -413,6 +413,8 @@ def smb_cmd_trans(c, buff)
413413
smb_cmd_trans_find_first2_file(c, buff)
414414
when '0401' # Find File Both Directory Info # 260
415415
smb_cmd_trans_find_first2(c, buff)
416+
when '0201' # Find File Full Directory Info # 258
417+
smb_cmd_trans_find_first2_full(c, buff)
416418
else
417419
smb_cmd_trans_find_first2(c, buff)
418420
end
@@ -795,12 +797,14 @@ def smb_cmd_trans_query_path_info_standard(c, buff)
795797
pkt = CONST::SMB_TRANS2_PKT.make_struct
796798
pkt.from_s(buff)
797799

800+
payload = pkt['Payload'].v['SetupData'].gsub(/\x00/, '').gsub(/.*\\/, '').chomp.strip
798801
ar = Rex::Text.to_hex(buff, '').to_s
799802
fid = ar[146..147] + ar[144..145]
800803
dprint("[smb_cmd_trans_query_path_info_standard] fid is : #{fid.hex}, file_id is : " + self.file_id.to_s)
804+
dprint("[smb_cmd_trans_query_path_info_standard] Payload length: #{payload.length.to_s}")
801805

802-
# If FileID matches, send the file
803-
if ( fid.hex.eql?(self.file_id.to_i) )
806+
# If FileID matches or matches file, send file response
807+
if ( fid.hex.eql?(self.file_id.to_i) or payload.length.eql?(@file_name.length) )
804808
attrib2 = "\x00" # IsFile
805809
dprint("[smb_cmd_trans_query_path_info_standard] Sending file response")
806810
else
@@ -1208,6 +1212,111 @@ def smb_cmd_trans_find_first2_file(c, buff)
12081212
c.put(pkt.to_s)
12091213
end
12101214

1215+
#
1216+
# Responds to FIND_FIRST2 requests
1217+
# Command: Find File Full Directory Info
1218+
#
1219+
def smb_cmd_trans_find_first2_full(c, buff)
1220+
pkt = CONST::SMB_TRANS_RES_PKT.make_struct
1221+
smb_set_defaults(c, pkt)
1222+
1223+
pkt.from_s(buff)
1224+
1225+
payload = pkt['Payload'].v['SetupData'].gsub(/\x00/, '').gsub(/.*\\/, '\\').chomp.strip
1226+
file = @file_name
1227+
file_name = Rex::Text.to_unicode(@file_name)
1228+
path = Rex::Text.to_unicode(@path_name)
1229+
1230+
dprint("[smb_cmd_trans_find_first2_full] Payload is: #{payload}")
1231+
dprint("[smb_cmd_trans_find_first2_full] Payload length: #{payload.length.to_s}")
1232+
1233+
ar = Rex::Text.to_hex(buff, '').to_s
1234+
dprint("[smb_cmd_trans_find_first2_full] ar is : #{ar}")
1235+
fid = ar[146..147] + ar[144..145]
1236+
dprint("[smb_cmd_trans_find_first2_full] fid is : #{fid.hex}, file_id is : " + self.file_id.to_s)
1237+
if ( fid.hex.eql?(self.file_id.to_i) )
1238+
dprint("File match")
1239+
end
1240+
if ( fid.hex.eql?(self.dir_id.to_i) )
1241+
dprint("Dir match")
1242+
end
1243+
1244+
if path.nil? || path == 0
1245+
dprint("[smb_cmd_trans_find_first2_full] Path is empty")
1246+
path = '\\'
1247+
else
1248+
dprint("[smb_cmd_trans_find_first2_full] Path is: #{path}")
1249+
end
1250+
1251+
begin
1252+
fileext = file.split('.').last
1253+
rescue
1254+
fileext = file
1255+
end
1256+
1257+
begin
1258+
payext = payload.split('.').last
1259+
rescue
1260+
payext = payload
1261+
end
1262+
1263+
pkt = CONST::SMB_TRANS_RES_PKT.make_struct
1264+
smb_set_defaults(c, pkt)
1265+
1266+
if (payext and payext.downcase.eql?(fileext.downcase)) or payload.length.to_s.eql?('4')
1267+
dprint("[smb_cmd_trans_find_first2_full] Sending file response #{file}")
1268+
data = file_name
1269+
length = [@exe.length].pack("V")
1270+
ea = "\x00\x00"
1271+
alloc = "\x00\x00\x10\x00\x00\x00\x00\x00" # Allocation Size = 1048576 || 1Mb
1272+
attrib = "\x80\x00\x00\x00" # File
1273+
search = "\x01\x00"
1274+
else
1275+
dprint("[smb_cmd_trans_find_first2_full] Sending directory response #{path}")
1276+
data = path
1277+
length = "\x00\x00\x00\x00"
1278+
ea = "\x21\x00"
1279+
alloc = "\x00\x00\x00\x00\x00\x00\x00\x00" # 0Mb
1280+
attrib = "\x10\x00\x00\x00" # Dir
1281+
pkt['Payload'].v['SetupCount'] = 0
1282+
search = "\x00\x01"
1283+
end
1284+
1285+
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION2
1286+
pkt['Payload']['SMB'].v['Flags1'] = 0x88
1287+
pkt['Payload']['SMB'].v['Flags2'] = @flags2
1288+
pkt['Payload']['SMB'].v['WordCount'] = 10
1289+
pkt['Payload'].v['ParamCountTotal'] = 10
1290+
pkt['Payload'].v['DataCountTotal'] = 68 + data.length
1291+
pkt['Payload'].v['ParamCount'] = 10
1292+
pkt['Payload'].v['ParamOffset'] = 56
1293+
pkt['Payload'].v['DataCount'] = 68 + data.length
1294+
pkt['Payload'].v['DataOffset'] = 68
1295+
pkt['Payload'].v['Payload'] =
1296+
"\x00" + # Padding
1297+
# FIND_FIRST2 Parameters
1298+
"\xfd\xff" + # Search ID
1299+
search + # Search count
1300+
search + # End Of Search
1301+
ea + # EA Error Offset
1302+
"\x00\x00" + # Last Name Offset
1303+
"\x00\x00" + # Padding
1304+
# QUERY_PATH_INFO Data
1305+
[68 + data.length].pack("V") + # Next Entry Offset
1306+
"\x00\x00\x00\x00" + # File Index
1307+
[@lo, @hi].pack("VV") + # Created
1308+
[@lo, @hi].pack("VV") + # Last Access
1309+
[@lo, @hi].pack("VV") + # Last Write
1310+
[@lo, @hi].pack("VV") + # Change
1311+
length + "\x00\x00\x00\x00" + # End Of File
1312+
alloc +
1313+
attrib +
1314+
[data.length].pack("V") + # File name len
1315+
"\x00\x00\x00\x00" + # EA List Length
1316+
data
1317+
c.put(pkt.to_s)
1318+
end
1319+
12111320
end # End Class
12121321
end # End SMB
12131322
end # End Proto

0 commit comments

Comments
 (0)