From 27fa95c0671fb1b9977190d2bf93bdbd6b841858 Mon Sep 17 00:00:00 2001 From: sjanusz-r7 Date: Wed, 15 Nov 2023 17:36:27 +0000 Subject: [PATCH] Working IPv4 & IPv6 DNS resolution for single and multiple hosts --- .../extensions/stdapi/server/net/resolve.c | 179 +++++++++++------- .../source/extensions/stdapi/stdapi.h | 1 + 2 files changed, 110 insertions(+), 70 deletions(-) diff --git a/c/meterpreter/source/extensions/stdapi/server/net/resolve.c b/c/meterpreter/source/extensions/stdapi/server/net/resolve.c index b8a7aeaf6..17ea4f9c4 100644 --- a/c/meterpreter/source/extensions/stdapi/server/net/resolve.c +++ b/c/meterpreter/source/extensions/stdapi/server/net/resolve.c @@ -5,95 +5,133 @@ #include #include -DWORD resolve_host(LPCSTR hostname, u_short ai_family, struct in_addr *result, struct in6_addr *result6) +/// +/// Resolve a hostname. Don't forget to call `freeaddrinfo` on the `out` parameter once done with it. +/// +/// Long pointer to a string +/// The family to get the IP address for (IPv6 / IPv4) +/// The resulting addrinfo structure +/// 0 on success, a Windows error code on error +DWORD resolve_host(const LPCSTR hostname, u_short ai_family, struct addrinfo **out) { - struct addrinfo hints, *list; - struct in_addr addr; - struct in6_addr addr6; - struct sockaddr_in *sockaddr_ipv4; - struct sockaddr_in6 *sockaddr_ipv6; - int iResult; + if (hostname == NULL) + { + dprintf("Hostname not set"); + return ERROR_INVALID_PARAMETER; + } + + if (out == NULL) + { + dprintf("Null pointer provided as output to resolve_host"); + return ERROR_INVALID_PARAMETER; + } WSADATA wsaData; - iResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if (iResult != NO_ERROR) + DWORD iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != ERROR_SUCCESS) { dprintf("Could not initialise Winsock: %x.", iResult); return iResult; } - memset(&hints, 0, sizeof(hints)); + struct addrinfo hints = { 0 }; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_family = ai_family; dprintf("Attempting to resolve '%s'", hostname); - iResult = getaddrinfo(hostname, NULL, &hints, &list); - - if (iResult != NO_ERROR) + iResult = getaddrinfo(hostname, NULL, &hints, out); + if (iResult != ERROR_SUCCESS) { - dprintf("Unable to resolve host Error: %x.", iResult); + dprintf("Unable to resolve host '%s' Error: %x.", hostname, iResult); dprintf("Error msg: %s", gai_strerror(iResult)); + return iResult; + } + dprintf("Resolved host '%s' successfully", hostname); + + dprintf("Performing Win Socket cleanup"); + iResult = WSACleanup(); + if (iResult != ERROR_SUCCESS) + { + dprintf("WSACleanup failed with return code %x", iResult); + return iResult; } - else + dprintf("WSACleanup completed successfully"); + + return ERROR_SUCCESS; +} + +/// +/// Add in all resolved IP addresses for a specific hostname to a TLV group. +/// +/// The group to insert resolved host IP addresses into. +/// The hostname to resolve +/// 0 on success. +DWORD add_all_host_ips_to_group(Packet** group, struct addrinfo* host) +{ + for (struct addrinfo* current = host; current != NULL; current = current->ai_next) { - switch (list->ai_family) { + switch (current->ai_family) + { case AF_INET: - sockaddr_ipv4 = (struct sockaddr_in *) list->ai_addr; - addr = sockaddr_ipv4->sin_addr; - memcpy((void*)result, &addr, sizeof(result)); + dprintf("Adding IP v4 Family to Group TLV"); + met_api->packet.add_tlv_uint(*group, TLV_TYPE_ADDR_TYPE, (UINT)current->ai_family); + dprintf("Adding IP v4 Address to Group TLV"); + struct in_addr ipv4_addr = ((struct sockaddr_in*)(current->ai_addr))->sin_addr; + met_api->packet.add_tlv_raw(*group, TLV_TYPE_IP, &ipv4_addr, sizeof(struct in_addr)); + break; case AF_INET6: - sockaddr_ipv6 = (struct sockaddr_in6 *) list->ai_addr; - addr6 = sockaddr_ipv6->sin6_addr; - memcpy((void*)result6, &addr6, sizeof(struct in6_addr)); - default: + dprintf("Adding IP v6 Family to Group TLV"); + met_api->packet.add_tlv_uint(*group, TLV_TYPE_ADDR_TYPE, (UINT)current->ai_family); + dprintf("Adding IP v6 Address to Group TLV"); + struct in6_addr ipv6_addr = ((struct sockaddr_in6*)(current->ai_addr))->sin6_addr; + met_api->packet.add_tlv_raw(*group, TLV_TYPE_IP, &ipv6_addr, sizeof(struct in6_addr)); break; + default: + dprintf("Unknown family, skipping entry."); + continue; } } - - freeaddrinfo(list); - WSACleanup(); - - return iResult; + return ERROR_SUCCESS; } DWORD request_resolve_host(Remote *remote, Packet *packet) { Packet *response = met_api->packet.create_response(packet); - LPCSTR hostname = NULL; - struct in_addr addr; - struct in6_addr addr6; - u_short ai_family = AF_INET; - int iResult; + LPCSTR hostname = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_HOST_NAME); + u_short ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE); + DWORD iResult = ERROR_SUCCESS; - hostname = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_HOST_NAME); + struct addrinfo* result = NULL; + iResult = resolve_host(hostname, ai_family, &result); + if (iResult != ERROR_SUCCESS || result == NULL) + { + dprintf("Could not resolve_host for '%s': %x", hostname, iResult); + goto done; + } - if (!hostname) + dprintf("Creating group for resolve host entry"); + Packet* resolved_hosts = met_api->packet.create_group(); + if (resolved_hosts == NULL) { - iResult = ERROR_INVALID_PARAMETER; - dprintf("Hostname not set"); + dprintf("Could not create TLV Group"); + goto done; } - else + + DWORD adding_host_ips = add_all_host_ips_to_group(&resolved_hosts, result); + if (adding_host_ips != ERROR_SUCCESS) { - ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE); - iResult = resolve_host(hostname, ai_family, &addr, &addr6); - if (iResult == NO_ERROR) - { - if (ai_family == AF_INET) - { - met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr)); - } else { - met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6)); - } - met_api->packet.add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family); - } - else - { - dprintf("Unable to resolve_host %s error: %x", hostname, iResult); - } + dprintf("Error adding resolved host IP addresses to group. Something went really wrong."); } + dprintf("Adding IP TLVs to Group TLV in response packet"); + met_api->packet.add_group(response, TLV_TYPE_RESOLVE_HOST_ENTRY, resolved_hosts); + dprintf("Freeing addrinfo"); + freeaddrinfo(result); + +done: + dprintf("Sending return packet for resolve_host"); met_api->packet.transmit_response(iResult, remote, response); return ERROR_SUCCESS; } @@ -103,33 +141,34 @@ DWORD request_resolve_hosts(Remote *remote, Packet *packet) Packet *response = met_api->packet.create_response(packet); Tlv hostname = {0}; int index = 0; - int iResult; + int iResult = 0; u_short ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE); while( met_api->packet.enum_tlv( packet, index++, TLV_TYPE_HOST_NAME, &hostname ) == ERROR_SUCCESS ) { - struct in_addr addr = {0}; - struct in6_addr addr6 = {0}; + struct addrinfo* addr = NULL; + + iResult = resolve_host((LPCSTR)hostname.buffer, ai_family, &addr); - iResult = resolve_host((LPCSTR)hostname.buffer, ai_family, &addr, &addr6); + Packet* resolved_host_group = met_api->packet.create_group(); - if (iResult == NO_ERROR) + if (iResult != ERROR_SUCCESS || addr == NULL) { - if (ai_family == AF_INET) - { - met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr)); - } else { - met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6)); - } + dprintf("Unable to resolve_host %s error: %x", hostname.buffer, iResult); + goto done; } - else + + DWORD adding_host_ips = add_all_host_ips_to_group(&resolved_host_group, addr); + if (adding_host_ips != ERROR_SUCCESS) { - dprintf("Unable to resolve_host %s error: %x", hostname.buffer, iResult); - met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, NULL, 0); + dprintf("Error adding resolved host IP addresses to group. Something went really wrong."); + goto done; } - met_api->packet.add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family); + + met_api->packet.add_group(response, TLV_TYPE_RESOLVE_HOST_ENTRY, resolved_host_group); } - met_api->packet.transmit_response(NO_ERROR, remote, response); +done: + met_api->packet.transmit_response(iResult, remote, response); return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/stdapi/stdapi.h b/c/meterpreter/source/extensions/stdapi/stdapi.h index 7ee5303a3..1c868691c 100755 --- a/c/meterpreter/source/extensions/stdapi/stdapi.h +++ b/c/meterpreter/source/extensions/stdapi/stdapi.h @@ -171,6 +171,7 @@ #define TLV_TYPE_LOCAL_HOST_RAW MAKE_CUSTOM_TLV( TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_STDAPI, 1507 ) #define TLV_TYPE_SHUTDOWN_HOW MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 1530 ) +#define TLV_TYPE_RESOLVE_HOST_ENTRY MAKE_CUSTOM_TLV( TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_STDAPI, 1550 ) // Ui #define TLV_TYPE_IDLE_TIME MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 3000 )