diff --git a/php/meterpreter/ext_server_stdapi.php b/php/meterpreter/ext_server_stdapi.php index f6a5d6c6a..1fe3d7c21 100755 --- a/php/meterpreter/ext_server_stdapi.php +++ b/php/meterpreter/ext_server_stdapi.php @@ -63,6 +63,9 @@ define("TLV_TYPE_SHUTDOWN_HOW", TLV_META_TYPE_UINT | 1530); +# Resolve hosts/host +define("TLV_TYPE_RESOLVE_HOST_ENTRY", TLV_META_TYPE_GROUP | 1550); + ## # Sys ## @@ -440,10 +443,10 @@ function add_stat_buf($path) { $st_buf .= pack_p($st['atime']); $st_buf .= pack_p($st['mtime']); $st_buf .= pack_p($st['ctime']); - + $st_buf .= pack("V", $st['blksize']); $st_buf .= pack("V", $st['blocks']); - + return create_tlv(TLV_TYPE_STAT_BUF, $st_buf); } return false; @@ -480,16 +483,21 @@ function resolve_host($hostname, $family) { return NULL; } - $result = array("family" => $family); - $record = $dns[0]; - if ($record["type"] == "A") { - $result["address"] = $record["ip"]; - } - if ($record["type"] == "AAAA") { - $result["address"] = $record["ipv6"]; + $addresses = []; + + foreach ($dns as $record) { + if ($record["type"] == "A") { + $addr = $record["ip"]; + } + if ($record["type"] == "AAAA") { + $addr = $record["ipv6"]; + } + + $binary_address = inet_pton($addr); + array_push($addresses, $binary_address); } - $result["packed_address"] = inet_pton($result["address"]); - return $result; + + return ['family' => $family, 'addresses' => $addresses]; } } @@ -1271,9 +1279,9 @@ function stdapi_registry_set_value($req, &$pkt) { function stdapi_net_resolve_host($req, &$pkt) { my_print("doing stdapi_net_resolve_host"); $hostname_tlv = packet_get_tlv($req, TLV_TYPE_HOST_NAME); - $hostname = $hostname['value']; + $hostname = $hostname_tlv['value']; $family_tlv = packet_get_tlv($req, TLV_TYPE_ADDR_TYPE); - $family = $family['value']; + $family = $family_tlv['value']; if ($family != WIN_AF_INET && $family != WIN_AF_INET6) { my_print('invalid family, must be AF_INET or AF_INET6'); @@ -1282,11 +1290,18 @@ function stdapi_net_resolve_host($req, &$pkt) { $ret = ERROR_FAILURE; $result = resolve_host($hostname, $family); + if ($result != NULL) { $ret = ERROR_SUCCESS; - packet_add_tlv($pkt, create_tlv(TLV_TYPE_IP, $result['packed_address'])); - packet_add_tlv($pkt, create_tlv(TLV_TYPE_ADDR_TYPE, $result['family'])); + $host_tlv = ""; + foreach($result['addresses'] as $ip){ + packet_add_tlv($host_tlv, create_tlv(TLV_TYPE_IP, $ip)); + packet_add_tlv($host_tlv, create_tlv(TLV_TYPE_ADDR_TYPE, $family)); + } + + packet_add_tlv($pkt, create_tlv(TLV_TYPE_RESOLVE_HOST_ENTRY, $host_tlv)); } + return $ret; } } @@ -1311,10 +1326,16 @@ function stdapi_net_resolve_hosts($req, &$pkt) { packet_add_tlv($pkt, create_tlv(TLV_TYPE_IP, '')); packet_add_tlv($pkt, create_tlv(TLV_TYPE_ADDR_TYPE, $family)); } else { - packet_add_tlv($pkt, create_tlv(TLV_TYPE_IP, $result['packed_address'])); - packet_add_tlv($pkt, create_tlv(TLV_TYPE_ADDR_TYPE, $result['family'])); + $host_tlv = ""; + foreach($result['addresses'] as $ip){ + packet_add_tlv($host_tlv, create_tlv(TLV_TYPE_IP, $ip)); + packet_add_tlv($host_tlv, create_tlv(TLV_TYPE_ADDR_TYPE, $family)); + } + + packet_add_tlv($pkt, create_tlv(TLV_TYPE_RESOLVE_HOST_ENTRY, $host_tlv)); } } + return ERROR_SUCCESS; } } diff --git a/python/meterpreter/ext_server_stdapi.py b/python/meterpreter/ext_server_stdapi.py index d7abbcd89..a8b689a0f 100644 --- a/python/meterpreter/ext_server_stdapi.py +++ b/python/meterpreter/ext_server_stdapi.py @@ -581,6 +581,9 @@ class RTMSG(ctypes.Structure): TLV_TYPE_SHUTDOWN_HOW = TLV_META_TYPE_UINT | 1530 +# Resolve hosts/host +TLV_TYPE_RESOLVE_HOST_ENTRY = TLV_META_TYPE_GROUP | 1550 + ## # Railgun ## @@ -1076,8 +1079,12 @@ def netlink_request(req_type, req_data): def resolve_host(hostname, family): address_info = getaddrinfo(hostname, family=family, socktype=socket.SOCK_DGRAM, proto=socket.IPPROTO_UDP) - address = address_info[0]['sockaddr'][0] - return {'family': family, 'address': address, 'packed_address': inet_pton(family, address)} + addresses = [] + for addr in address_info: + binary_address = inet_pton(family, addr['sockaddr'][0]) + addresses.append(binary_address) + + return { 'family': family, 'addresses': addresses } def tlv_pack_local_addrinfo(sock): local_host, local_port = sock.getsockname()[:2] @@ -2641,9 +2648,16 @@ def stdapi_net_resolve_host(request, response): family = socket.AF_INET6 else: raise Exception('invalid family') + result = resolve_host(hostname, family) - response += tlv_pack(TLV_TYPE_IP, result['packed_address']) - response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family']) + + host_tlv = bytes() + for ip in result['addresses']: + host_tlv += tlv_pack(TLV_TYPE_IP, ip) + host_tlv += tlv_pack(TLV_TYPE_ADDR_TYPE, family) + + response += tlv_pack(TLV_TYPE_RESOLVE_HOST_ENTRY, host_tlv) + return ERROR_SUCCESS, response @register_function @@ -2661,8 +2675,13 @@ def stdapi_net_resolve_hosts(request, response): result = resolve_host(hostname, family) except socket.error: result = {'family':family, 'packed_address':''} - response += tlv_pack(TLV_TYPE_IP, result['packed_address']) - response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family']) + + host_tlv = bytes() + for ip in result['addresses']: + host_tlv += tlv_pack(TLV_TYPE_IP, ip) + host_tlv += tlv_pack(TLV_TYPE_ADDR_TYPE, family) + + response += tlv_pack(TLV_TYPE_RESOLVE_HOST_ENTRY, host_tlv) return ERROR_SUCCESS, response @register_function diff --git a/python/meterpreter/tests/test_ext_server_stdapi.py b/python/meterpreter/tests/test_ext_server_stdapi.py index 6989a9cdb..25cf2c421 100644 --- a/python/meterpreter/tests/test_ext_server_stdapi.py +++ b/python/meterpreter/tests/test_ext_server_stdapi.py @@ -320,6 +320,108 @@ def test_stdapi_sys_config_getsid(self): ).get("value") self.assertRegex(sid, "S-1-5-.*") +class ExtStdNetResolveTest(ExtServerStdApiTest): + def test_stdapi_net_resolve_host(self): + MSF_AF_INET = 2 + + request = bytes() + request += self.meterpreter_context["tlv_pack"]( + self.meterpreter_context["TLV_TYPE_COMMAND_ID"], + self.meterpreter_context['cmd_string_to_id']('stdapi_net_resolve_host') + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_REQUEST_ID"], + "18252822037434405542596288798302" + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_HOST_NAME"], + "rapid7.com" + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_ADDR_TYPE"], + MSF_AF_INET + ) + + response = bytes() + _result_code, result_tlvs = self.assertMethodErrorSuccess( + "stdapi_net_resolve_hosts", request, response + ) + + resolve_host_entries = self.meterpreter_context["packet_get_tlv"]( + result_tlvs, self.ext_server_stdapi["TLV_TYPE_RESOLVE_HOST_ENTRY"] + ).get("value") + + resolved_host_ips = self.meterpreter_context["packet_enum_tlvs"]( + resolve_host_entries, self.ext_server_stdapi["TLV_TYPE_IP"] + ) + + resolved_host_families = self.meterpreter_context["packet_enum_tlvs"]( + resolve_host_entries, self.ext_server_stdapi["TLV_TYPE_ADDR_TYPE"] + ) + + for ip in resolved_host_ips: + resolved_ip = socket.inet_ntop(socket.AF_INET, ip['value']) + self.assertTrue(isinstance(socket.inet_aton(resolved_ip), bytes)) + + for family in resolved_host_families: + self.assertEqual(family['value'], MSF_AF_INET) + + def test_stdapi_net_resolve_hosts(self): + MSF_AF_INET = 2 + + request = bytes() + request += self.meterpreter_context["tlv_pack"]( + self.meterpreter_context["TLV_TYPE_COMMAND_ID"], + self.meterpreter_context['cmd_string_to_id']('stdapi_net_resolve_hosts') + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_REQUEST_ID"], + "11047287278261284282680986949856" + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_ADDR_TYPE"], + MSF_AF_INET + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_HOST_NAME"], + "rapid7.com" + ) + + request += self.meterpreter_context["tlv_pack"]( + self.ext_server_stdapi["TLV_TYPE_HOST_NAME"], + "google.com" + ) + + response = bytes() + _result_code, result_tlvs = self.assertMethodErrorSuccess( + "stdapi_net_resolve_hosts", request, response + ) + + resolved_host_entry_list = self.meterpreter_context["packet_enum_tlvs"]( + result_tlvs, self.ext_server_stdapi["TLV_TYPE_RESOLVE_HOST_ENTRY"] + ) + + for resolved_host_entry in resolved_host_entry_list: + resolved_host_ips = self.meterpreter_context["packet_enum_tlvs"]( + resolved_host_entry['value'], self.ext_server_stdapi["TLV_TYPE_IP"] + ) + + resolved_host_families = self.meterpreter_context["packet_enum_tlvs"]( + resolved_host_entry['value'], self.ext_server_stdapi["TLV_TYPE_ADDR_TYPE"] + ) + + for ip in resolved_host_ips: + resolved_ip = socket.inet_ntop(socket.AF_INET, ip['value']) + self.assertTrue(isinstance(socket.inet_aton(resolved_ip), bytes)) + + for family in resolved_host_families: + self.assertEqual(family['value'], MSF_AF_INET) if __name__ == "__main__": unittest.main()