From 1bf758430b5727a17b135fe2bee315be2942d1a3 Mon Sep 17 00:00:00 2001 From: cgranleese-r7 Date: Tue, 17 Oct 2023 14:59:20 +0100 Subject: [PATCH] Adds support for resolving multiple hosts --- python/meterpreter/ext_server_stdapi.py | 50 ++++++++++++++++--- .../tests/test_ext_server_stdapi.py | 18 +++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/python/meterpreter/ext_server_stdapi.py b/python/meterpreter/ext_server_stdapi.py index d7abbcd89..04c1a9830 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 ## @@ -1074,10 +1077,27 @@ def netlink_request(req_type, req_data): sock.close() return responses +# 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] +# addresses = [] +# for addr in address_info: +# addresses.append(addr['sockaddr'][0]) +# +# all_addresses = ", ".join(addresses) +# return {'family': family, 'address': address, 'packed_address': inet_pton(family, address), 'all_addresses': all_addresses } + +# TODO: Let's update this to return an array of hosts 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, 'address': addresses }] +# return [{ 'family': family, 'address': addresses }, { 'family': family, 'address': inet_pton(family, '127.0.0.2') }] + def tlv_pack_local_addrinfo(sock): local_host, local_port = sock.getsockname()[:2] @@ -2633,6 +2653,7 @@ def stdapi_net_config_get_proxy(request, response): @register_function def stdapi_net_resolve_host(request, response): + # TODO: Ticket suggests updating to AF_UNSPEC. not sure if that needs to be here or in Framework's resolve_host method hostname = packet_get_tlv(request, TLV_TYPE_HOST_NAME)['value'] family = packet_get_tlv(request, TLV_TYPE_ADDR_TYPE)['value'] if family == WIN_AF_INET: @@ -2641,9 +2662,20 @@ def stdapi_net_resolve_host(request, response): family = socket.AF_INET6 else: raise Exception('invalid family') + # resolve_host will now return an array of objects, we'll loop over the objects and put it into a group. Each group will contain the IP and addr type. - DONE + # TODO: Assuming I should be calling both familys here and not relying on the family that is pulled out result = resolve_host(hostname, family) - response += tlv_pack(TLV_TYPE_IP, result['packed_address']) - response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family']) + + # TODO: Update this to now use the pattern of using groups of IP/ADDRTYPE - DONE + for resolved_host in result: + host_tlv = bytes() + for ip in resolved_host['address']: + 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 +2693,14 @@ 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']) + for resolved_host in result: + host_tlv = bytes() + for ip in resolved_host['address']: + host_tlv += tlv_pack(TLV_TYPE_IP, ip) + host_tlv += tlv_pack(TLV_TYPE_ADDR_TYPE, family) + + # TLV_TYPE RESOLVE_HOST_ENTRY + 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..31da6ed3c 100644 --- a/python/meterpreter/tests/test_ext_server_stdapi.py +++ b/python/meterpreter/tests/test_ext_server_stdapi.py @@ -320,6 +320,24 @@ def test_stdapi_sys_config_getsid(self): ).get("value") self.assertRegex(sid, "S-1-5-.*") +class ExtStdNetResolveTest(ExtServerStdApiTest): + def stdapi_net_resolve_hosts(self): + # Full request from msfconsole + request = b'\x00\x00\x00\x0c\x00\x02\x00\x01\x00\x00\x04\x00\x00\x00\x00)\x00\x01\x00\x0264769531726942037539492283558475\x00\x00\x00\x00\x13\x00\x01\x05xrapid7.com\x00\x00\x00\x00\x0c\x00\x02\x05\xa4\x00\x00\x00\x02' + response = bytes() + _result_code, result_tlvs = self.assertMethodErrorSuccess( + "stdapi_net_resolve_hosts", request, response + ) + + print(response) + + # TODO: Assert + # user_name = self.meterpreter_context["packet_get_tlv"]( + # result_tlvs, self.ext_server_stdapi["TLV_TYPE_USER_NAME"] + # ).get("value") + # + #self.assert(response, bytes('......')) + if __name__ == "__main__": unittest.main()