|
| 1 | +# -*- coding: binary -*- |
| 2 | +module Msf |
| 3 | +class Post |
| 4 | +module Windows |
| 5 | + |
| 6 | +module NetAPI |
| 7 | + |
| 8 | + MAX_PREFERRED_LENGTH = -1 |
| 9 | + SV_TYPE_ALL = 0xFFFFFFFF |
| 10 | + SV_TYPE_DOMAIN_ENUM = 0x80000000 |
| 11 | + SV_TYPE_DOMAIN_BAKCTRL = 10 |
| 12 | + SV_TYPE_DOMAIN_CTRL = 4 |
| 13 | + |
| 14 | + def UnicodeByteStringToAscii(str) |
| 15 | + length = (str.index "\0\0\0") + 1 |
| 16 | + Rex::Text.to_ascii(str[0..length]) |
| 17 | + end |
| 18 | + |
| 19 | + def netapi_buffer_free(ptr) |
| 20 | + # Free the buffer |
| 21 | + ret = client.railgun.netapi32.NetApiBufferFree(ptr) |
| 22 | + vprint_error("Unable to free buffer, Error Code: #{ret['return']}") unless ret['return'] == 0 |
| 23 | + end |
| 24 | + |
| 25 | + def net_server_enum(server_type=SV_TYPE_ALL, domain=nil) |
| 26 | + result = client.railgun.netapi32.NetServerEnum( |
| 27 | + nil, # servername |
| 28 | + 100, # level (100/101) |
| 29 | + 4, # bufptr |
| 30 | + MAX_PREFERRED_LENGTH, # prefmaxlen |
| 31 | + 4, # entries read |
| 32 | + 4, # total entries |
| 33 | + server_type, # server_type |
| 34 | + domain, # domain |
| 35 | + nil # resume handle |
| 36 | + ) |
| 37 | + |
| 38 | + case result['return'] |
| 39 | + when 5 |
| 40 | + vprint_error("Access Denied when trying to enum hosts.") |
| 41 | + return nil |
| 42 | + when 6118 |
| 43 | + vprint_error("No Browser servers found.") |
| 44 | + return nil |
| 45 | + when 50 |
| 46 | + vprint_error("Request not supported.") |
| 47 | + return nil |
| 48 | + when 2184 |
| 49 | + vprint_error("Service not installed.") |
| 50 | + return nil |
| 51 | + when 0 |
| 52 | + vprint_status("Success.") |
| 53 | + when 87 |
| 54 | + vprint_error ("Invalid parameter.") |
| 55 | + return nil |
| 56 | + else |
| 57 | + if result['return'] != 234 |
| 58 | + vprint_status("Unaccounted for error code: #{result['return']}") |
| 59 | + return nil |
| 60 | + end |
| 61 | + end |
| 62 | + |
| 63 | + hosts = read_server_structs(result['bufptr'], result['totalentries']) |
| 64 | + |
| 65 | + netapi_buffer_free(result['bufptr']) |
| 66 | + |
| 67 | + return hosts |
| 68 | + end |
| 69 | + |
| 70 | + def read_server_structs(start_ptr, count) |
| 71 | + base = 0 |
| 72 | + struct_size = 8 |
| 73 | + hosts = [] |
| 74 | + mem = client.railgun.memread(start_ptr, struct_size*count) |
| 75 | + |
| 76 | + 0.upto(count-1) do |i| |
| 77 | + x = {} |
| 78 | + x[:version]= mem[(base + 0),4].unpack("V*")[0] |
| 79 | + nameptr = mem[(base + 4),4].unpack("V*")[0] |
| 80 | + x[:name] = UnicodeByteStringToAscii(client.railgun.memread(nameptr, 255)) |
| 81 | + hosts << x |
| 82 | + base += struct_size |
| 83 | + end |
| 84 | + |
| 85 | + return hosts |
| 86 | + end |
| 87 | + |
| 88 | + def getSessions(hostname, username) |
| 89 | + result = client.railgun.netapi32.NetSessionEnum( |
| 90 | + hostname, |
| 91 | + nil, |
| 92 | + username, |
| 93 | + 10, |
| 94 | + 4, |
| 95 | + MAX_PREFERRED_LENGTH, |
| 96 | + 4, |
| 97 | + 4, |
| 98 | + nil |
| 99 | + ) |
| 100 | + |
| 101 | + case result['return'] |
| 102 | + when 5 |
| 103 | + vprint_error("#{hostname} Access denied...") |
| 104 | + return nil |
| 105 | + when 53 |
| 106 | + vprint_error("Host not found or did not respond: #{hostname}") |
| 107 | + return nil |
| 108 | + when 123 |
| 109 | + vprint_error("Invalid host: #{hostname}") |
| 110 | + return nil |
| 111 | + when 0 |
| 112 | + vprint_status("#{hostname} Session identified") |
| 113 | + when 2221 #username not found |
| 114 | + return nil |
| 115 | + else |
| 116 | + if result['return'] != 234 |
| 117 | + vprint_error("Unaccounted for error code: #{result['return']}") |
| 118 | + return nil |
| 119 | + end |
| 120 | + end |
| 121 | + |
| 122 | + sessions = read_session_structs(result['bufptr'], result['totalentries'], hostname) |
| 123 | + |
| 124 | + netapi_buffer_free(result['bufptr']) |
| 125 | + |
| 126 | + return sessions |
| 127 | + end |
| 128 | + |
| 129 | + def read_session_structs(start_ptr, count, hostname) |
| 130 | + base = 0 |
| 131 | + struct_size = 16 |
| 132 | + sessions = [] |
| 133 | + mem = client.railgun.memread(start_ptr, struct_size*count) |
| 134 | + |
| 135 | + 0.upto(count-1) do |i| |
| 136 | + sess = {} |
| 137 | + cnameptr = mem[(base + 0),4].unpack("V*")[0] |
| 138 | + usernameptr = mem[(base + 4),4].unpack("V*")[0] |
| 139 | + sess[:usetime] = mem[(base + 8),4].unpack("V*")[0] |
| 140 | + sess[:idletime] = mem[(base + 12),4].unpack("V*")[0] |
| 141 | + sess[:cname] = UnicodeByteStringToAscii(client.railgun.memread(cnameptr,255)) |
| 142 | + sess[:username] = UnicodeByteStringToAscii(client.railgun.memread(usernameptr,255)) |
| 143 | + sess[:hostname] = hostname |
| 144 | + sessions << sess |
| 145 | + base = base + struct_size |
| 146 | + end |
| 147 | + |
| 148 | + return sessions |
| 149 | + end |
| 150 | + |
| 151 | +end # NetAPI |
| 152 | +end # Windows |
| 153 | +end # Post |
| 154 | +end # Msf |
0 commit comments