Files
metasploit-gs/lib/msf/core/post/windows/netapi.rb
T
Jon Cave b1a7e77fa9 Correct domain controller server type constants
The should be specified in hex as BAKCTRL is 16, not 10. CTRL should
be 8. See documentation for NetServerEnum.
2015-04-05 11:12:18 +01:00

169 lines
4.6 KiB
Ruby

# -*- coding: binary -*-
module Msf
class Post
module Windows
module NetAPI
MAX_PREFERRED_LENGTH = -1
SV_TYPE_ALL = 0xFFFFFFFF
SV_TYPE_DOMAIN_ENUM = 0x80000000
SV_TYPE_DOMAIN_BAKCTRL = 0x00000010
SV_TYPE_DOMAIN_CTRL = 0x00000008
ERROR_ACCESS_DENIED = 5
ERROR_NOT_ENOUGH_MEMORY = 8
ERROR_INVALID_PARAMETER = 87
ERROR_INVALID_LEVEL = 124
ERROR_MORE_DATA = 234
ERROR_NO_BROWSER_SERVERS_FOUND = 6118
NERR_ClientNameNotFound = 2312
NERR_InvalidComputer = 2351
NERR_UserNotFound = 2221
def UnicodeByteStringToAscii(str)
length = (str.index "\0\0\0") + 1
Rex::Text.to_ascii(str[0..length])
end
def netapi_buffer_free(ptr)
# Free the buffer
ret = client.railgun.netapi32.NetApiBufferFree(ptr)
vprint_error("Unable to free buffer, Error Code: #{ret['return']}") unless ret['return'] == 0
end
def net_server_enum(server_type=SV_TYPE_ALL, domain=nil)
hosts = []
result = client.railgun.netapi32.NetServerEnum(
nil, # servername
100, # level (100/101)
4, # bufptr
MAX_PREFERRED_LENGTH, # prefmaxlen
4, # entries read
4, # total entries
server_type, # server_type
domain, # domain
nil # resume handle
)
case result['return']
when 0
# Railgun assumes PDWORDS are pointers and returns 8 bytes for x64 architectures.
# Therefore we need to truncate the result value to an actual
# DWORD for entriesread or totalentries.
hosts = read_server_structs(result['bufptr'], (result['entriesread'] % 4294967296), domain, server_type)
when ERROR_NO_BROWSER_SERVERS_FOUND
print_error("ERROR_NO_BROWSER_SERVERS_FOUND")
return nil
when ERROR_MORE_DATA
vprint_error("ERROR_MORE_DATA")
return nil
end
netapi_buffer_free(result['bufptr'])
return hosts
end
def read_server_structs(start_ptr, count, domain, server_type)
hosts = []
return hosts if count <= 0
ptr_size = client.railgun.util.pointer_size
ptr = (ptr_size == 8) ? 'Q<' : 'V'
base = 0
# Struct -> Ptr, Ptr
struct_size = ptr_size * 2
mem = client.railgun.memread(start_ptr, struct_size*count)
count.times do
x = {}
x[:version]= mem[(base + 0),ptr_size].unpack(ptr).first
nameptr = mem[(base + ptr_size),ptr_size].unpack(ptr).first
x[:name] = UnicodeByteStringToAscii(client.railgun.memread(nameptr, 255))
hosts << x
base += struct_size
end
hosts
end
def net_session_enum(hostname, username)
sessions = []
result = client.railgun.netapi32.NetSessionEnum(
hostname, # servername
nil, # UncClientName
username, # username
10, # level
4, # bufptr
MAX_PREFERRED_LENGTH, # prefmaxlen
4, # entriesread
4, # totalentries
nil # resume_handle
)
case result['return']
when 0
vprint_error("#{hostname} Session identified")
sessions = read_session_structs(result['bufptr'], (result['entriesread'] % 4294967296), hostname)
when ERROR_ACCESS_DENIED
vprint_error("#{hostname} Access denied...")
return nil
when 53
vprint_error("Host not found or did not respond: #{hostname}")
return nil
when 123
vprint_error("Invalid host: #{hostname}")
return nil
when NERR_UserNotFound
return nil
when ERROR_MORE_DATA
vprint_error("#{hostname} ERROR_MORE_DATA")
else
vprint_error("Unaccounted for error code: #{result['return']}")
return nil
end
netapi_buffer_free(result['bufptr'])
return sessions
end
def read_session_structs(start_ptr, count, hostname)
sessions = []
return sessions if count <= 0
ptr_size = client.railgun.util.pointer_size
ptr = (ptr_size == 8) ? 'Q<' : 'V'
base = 0
# Struct -> Ptr, Ptr, Dword Dword
struct_size = (ptr_size * 2) + 8
mem = client.railgun.memread(start_ptr, struct_size*count)
count.times do
sess = {}
cnameptr = mem[(base + 0),ptr_size].unpack(ptr).first
usernameptr = mem[(base + ptr_size),ptr_size].unpack(ptr).first
sess[:usetime] = mem[(base + (ptr_size * 2)),4].unpack('V').first
sess[:idletime] = mem[(base + (ptr_size * 2) + 4),4].unpack('V').first
sess[:cname] = UnicodeByteStringToAscii(client.railgun.memread(cnameptr,255))
sess[:username] = UnicodeByteStringToAscii(client.railgun.memread(usernameptr,255))
sess[:hostname] = hostname
sessions << sess
base = base + struct_size
end
sessions
end
end # NetAPI
end # Windows
end # Post
end # Msf