Skip to content

Commit e0df664

Browse files
committed
Land rapid7#3653 : NETAPI x64 fixes
2 parents 5fac151 + 8302e82 commit e0df664

File tree

1 file changed

+29
-18
lines changed

1 file changed

+29
-18
lines changed

lib/msf/core/post/windows/netapi.rb

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ def net_server_enum(server_type=SV_TYPE_ALL, domain=nil)
5050

5151
case result['return']
5252
when 0
53-
hosts = read_server_structs(result['bufptr'], result['totalentries'], domain, server_type)
53+
# Railgun assumes PDWORDS are pointers and returns 8 bytes for x64 architectures.
54+
# Therefore we need to truncate the result value to an actual
55+
# DWORD for entriesread or totalentries.
56+
hosts = read_server_structs(result['bufptr'], (result['entriesread'] % 4294967296), domain, server_type)
5457
when ERROR_NO_BROWSER_SERVERS_FOUND
5558
print_error("ERROR_NO_BROWSER_SERVERS_FOUND")
5659
return nil
@@ -65,26 +68,28 @@ def net_server_enum(server_type=SV_TYPE_ALL, domain=nil)
6568
end
6669

6770
def read_server_structs(start_ptr, count, domain, server_type)
68-
base = 0
69-
struct_size = 8
7071
hosts = []
72+
return hosts if count <= 0
7173

72-
if count == 0
73-
return hosts
74-
end
74+
ptr_size = client.railgun.util.pointer_size
75+
ptr = (ptr_size == 8) ? 'Q<' : 'V'
76+
77+
base = 0
78+
# Struct -> Ptr, Ptr
79+
struct_size = ptr_size * 2
7580

7681
mem = client.railgun.memread(start_ptr, struct_size*count)
7782

7883
count.times do
7984
x = {}
80-
x[:version]= mem[(base + 0),4].unpack("V*")[0]
81-
nameptr = mem[(base + 4),4].unpack("V*")[0]
85+
x[:version]= mem[(base + 0),ptr_size].unpack(ptr).first
86+
nameptr = mem[(base + ptr_size),ptr_size].unpack(ptr).first
8287
x[:name] = UnicodeByteStringToAscii(client.railgun.memread(nameptr, 255))
8388
hosts << x
8489
base += struct_size
8590
end
8691

87-
return hosts
92+
hosts
8893
end
8994

9095
def net_session_enum(hostname, username)
@@ -105,7 +110,7 @@ def net_session_enum(hostname, username)
105110
case result['return']
106111
when 0
107112
vprint_error("#{hostname} Session identified")
108-
sessions = read_session_structs(result['bufptr'], result['totalentries'], hostname)
113+
sessions = read_session_structs(result['bufptr'], (result['entriesread'] % 4294967296), hostname)
109114
when ERROR_ACCESS_DENIED
110115
vprint_error("#{hostname} Access denied...")
111116
return nil
@@ -130,25 +135,31 @@ def net_session_enum(hostname, username)
130135
end
131136

132137
def read_session_structs(start_ptr, count, hostname)
133-
base = 0
134-
struct_size = 16
135138
sessions = []
139+
return sessions if count <= 0
140+
141+
ptr_size = client.railgun.util.pointer_size
142+
ptr = (ptr_size == 8) ? 'Q<' : 'V'
143+
144+
base = 0
145+
# Struct -> Ptr, Ptr, Dword Dword
146+
struct_size = (ptr_size * 2) + 8
136147
mem = client.railgun.memread(start_ptr, struct_size*count)
137-
148+
138149
count.times do
139150
sess = {}
140-
cnameptr = mem[(base + 0),4].unpack("V*")[0]
141-
usernameptr = mem[(base + 4),4].unpack("V*")[0]
142-
sess[:usetime] = mem[(base + 8),4].unpack("V*")[0]
143-
sess[:idletime] = mem[(base + 12),4].unpack("V*")[0]
151+
cnameptr = mem[(base + 0),ptr_size].unpack(ptr).first
152+
usernameptr = mem[(base + ptr_size),ptr_size].unpack(ptr).first
153+
sess[:usetime] = mem[(base + (ptr_size * 2)),4].unpack('V').first
154+
sess[:idletime] = mem[(base + (ptr_size * 2) + 4),4].unpack('V').first
144155
sess[:cname] = UnicodeByteStringToAscii(client.railgun.memread(cnameptr,255))
145156
sess[:username] = UnicodeByteStringToAscii(client.railgun.memread(usernameptr,255))
146157
sess[:hostname] = hostname
147158
sessions << sess
148159
base = base + struct_size
149160
end
150161

151-
return sessions
162+
sessions
152163
end
153164

154165
end # NetAPI

0 commit comments

Comments
 (0)