Skip to content

Commit 7f588d3

Browse files
committed
Working IPv4 & IPv6 DNS resolution for single and multiple hosts
1 parent 6858efc commit 7f588d3

File tree

2 files changed

+116
-71
lines changed

2 files changed

+116
-71
lines changed

c/meterpreter/source/extensions/stdapi/server/net/resolve.c

Lines changed: 115 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,95 +5,138 @@
55
#include <winsock2.h>
66
#include <ws2tcpip.h>
77

8-
DWORD resolve_host(LPCSTR hostname, u_short ai_family, struct in_addr *result, struct in6_addr *result6)
8+
/// <summary>
9+
/// Resolve a hostname. Don't forget to call `freeaddrinfo` on the `address_info` parameter once done with it.
10+
/// </summary>
11+
/// <param name="hostname">Long pointer to a string</param>
12+
/// <param name="ai_family">The family to get the IP address for (IPv6 / IPv4)</param>
13+
/// <param name="address_info">The resulting addrinfo structure</param>
14+
/// <returns>0 on success, a Windows error code on error</returns>
15+
DWORD resolve_host(const LPCSTR hostname, UINT ai_family, struct addrinfo **address_info)
916
{
10-
struct addrinfo hints, *list;
11-
struct in_addr addr;
12-
struct in6_addr addr6;
13-
struct sockaddr_in *sockaddr_ipv4;
14-
struct sockaddr_in6 *sockaddr_ipv6;
15-
int iResult;
17+
if (hostname == NULL)
18+
{
19+
dprintf("Hostname not set");
20+
return ERROR_INVALID_PARAMETER;
21+
}
22+
23+
if (address_info == NULL)
24+
{
25+
dprintf("Null pointer provided as output to resolve_host");
26+
return ERROR_INVALID_PARAMETER;
27+
}
1628

1729
WSADATA wsaData;
18-
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
19-
if (iResult != NO_ERROR)
30+
DWORD iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
31+
if (iResult != ERROR_SUCCESS)
2032
{
2133
dprintf("Could not initialise Winsock: %x.", iResult);
2234
return iResult;
2335
}
2436

25-
memset(&hints, 0, sizeof(hints));
37+
struct addrinfo hints = { 0 };
2638
hints.ai_socktype = SOCK_DGRAM;
2739
hints.ai_protocol = IPPROTO_UDP;
2840
hints.ai_family = ai_family;
2941

3042
dprintf("Attempting to resolve '%s'", hostname);
3143

32-
iResult = getaddrinfo(hostname, NULL, &hints, &list);
33-
34-
if (iResult != NO_ERROR)
44+
iResult = getaddrinfo(hostname, NULL, &hints, address_info);
45+
if (iResult != ERROR_SUCCESS)
3546
{
36-
dprintf("Unable to resolve host Error: %x.", iResult);
47+
dprintf("Unable to resolve host '%s' Error: %x.", hostname, iResult);
3748
dprintf("Error msg: %s", gai_strerror(iResult));
49+
return iResult;
3850
}
39-
else
51+
dprintf("Resolved host '%s' successfully", hostname);
52+
53+
dprintf("Performing Win Socket cleanup");
54+
iResult = WSACleanup();
55+
if (iResult != ERROR_SUCCESS)
4056
{
41-
switch (list->ai_family) {
57+
dprintf("WSACleanup failed with return code %x", iResult);
58+
return iResult;
59+
}
60+
dprintf("WSACleanup completed successfully");
61+
62+
return ERROR_SUCCESS;
63+
}
64+
65+
/// <summary>
66+
/// Add in all resolved IP addresses for a specific hostname to a TLV group.
67+
/// </summary>
68+
/// <param name="group">The group to insert resolved host IP addresses into.</param>
69+
/// <param name="host">The hostname or a list of hostnames to add to the group.</param>
70+
/// <returns>0 on success.</returns>
71+
DWORD add_all_host_ips_to_group(Packet* group, struct addrinfo* host)
72+
{
73+
if (group == NULL)
74+
{
75+
dprintf("Null pointer provided as group");
76+
return ERROR_INVALID_PARAMETER;
77+
}
78+
79+
for (struct addrinfo* current = host; current != NULL; current = current->ai_next)
80+
{
81+
switch (current->ai_family)
82+
{
4283
case AF_INET:
43-
sockaddr_ipv4 = (struct sockaddr_in *) list->ai_addr;
44-
addr = sockaddr_ipv4->sin_addr;
45-
memcpy((void*)result, &addr, sizeof(result));
84+
dprintf("Adding IP v4 Family to Group TLV");
85+
met_api->packet.add_tlv_uint(group, TLV_TYPE_ADDR_TYPE, (UINT)current->ai_family);
86+
dprintf("Adding IP v4 Address to Group TLV");
87+
struct in_addr ipv4_addr = ((struct sockaddr_in*)(current->ai_addr))->sin_addr;
88+
met_api->packet.add_tlv_raw(group, TLV_TYPE_IP, &ipv4_addr, sizeof(struct in_addr));
89+
break;
4690
case AF_INET6:
47-
sockaddr_ipv6 = (struct sockaddr_in6 *) list->ai_addr;
48-
addr6 = sockaddr_ipv6->sin6_addr;
49-
memcpy((void*)result6, &addr6, sizeof(struct in6_addr));
50-
default:
91+
dprintf("Adding IP v6 Family to Group TLV");
92+
met_api->packet.add_tlv_uint(group, TLV_TYPE_ADDR_TYPE, (UINT)current->ai_family);
93+
dprintf("Adding IP v6 Address to Group TLV");
94+
struct in6_addr ipv6_addr = ((struct sockaddr_in6*)(current->ai_addr))->sin6_addr;
95+
met_api->packet.add_tlv_raw(group, TLV_TYPE_IP, &ipv6_addr, sizeof(struct in6_addr));
5196
break;
97+
default:
98+
dprintf("Unknown family, skipping entry.");
99+
continue;
52100
}
53101
}
54-
55-
freeaddrinfo(list);
56-
WSACleanup();
57-
58-
return iResult;
102+
return ERROR_SUCCESS;
59103
}
60104

61105
DWORD request_resolve_host(Remote *remote, Packet *packet)
62106
{
63107
Packet *response = met_api->packet.create_response(packet);
64-
LPCSTR hostname = NULL;
65-
struct in_addr addr;
66-
struct in6_addr addr6;
67-
u_short ai_family = AF_INET;
68-
int iResult;
108+
LPCSTR hostname = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_HOST_NAME);
109+
UINT ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE);
110+
DWORD iResult = ERROR_SUCCESS;
69111

70-
hostname = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_HOST_NAME);
112+
struct addrinfo* result;
113+
iResult = resolve_host(hostname, ai_family, &result);
114+
if (iResult != ERROR_SUCCESS || result == NULL)
115+
{
116+
dprintf("Could not resolve_host for '%s': %x", hostname, iResult);
117+
goto done;
118+
}
71119

72-
if (!hostname)
120+
dprintf("Creating group for resolve host entry");
121+
Packet* resolved_hosts = met_api->packet.create_group();
122+
if (resolved_hosts == NULL)
73123
{
74-
iResult = ERROR_INVALID_PARAMETER;
75-
dprintf("Hostname not set");
124+
dprintf("Could not create TLV Group");
125+
goto done;
76126
}
77-
else
127+
128+
if (add_all_host_ips_to_group(resolved_hosts, result) != ERROR_SUCCESS)
78129
{
79-
ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE);
80-
iResult = resolve_host(hostname, ai_family, &addr, &addr6);
81-
if (iResult == NO_ERROR)
82-
{
83-
if (ai_family == AF_INET)
84-
{
85-
met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr));
86-
} else {
87-
met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6));
88-
}
89-
met_api->packet.add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family);
90-
}
91-
else
92-
{
93-
dprintf("Unable to resolve_host %s error: %x", hostname, iResult);
94-
}
130+
dprintf("Error adding resolved host IP addresses to group");
95131
}
96132

133+
dprintf("Adding IP TLVs to Group TLV in response packet");
134+
met_api->packet.add_group(response, TLV_TYPE_RESOLVE_HOST_ENTRY, resolved_hosts);
135+
dprintf("Freeing addrinfo");
136+
freeaddrinfo(result);
137+
138+
done:
139+
dprintf("Sending return packet for resolve_host");
97140
met_api->packet.transmit_response(iResult, remote, response);
98141
return ERROR_SUCCESS;
99142
}
@@ -103,33 +146,34 @@ DWORD request_resolve_hosts(Remote *remote, Packet *packet)
103146
Packet *response = met_api->packet.create_response(packet);
104147
Tlv hostname = {0};
105148
int index = 0;
106-
int iResult;
107-
u_short ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE);
149+
int iResult = 0;
150+
UINT ai_family = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE);
108151

109152
while( met_api->packet.enum_tlv( packet, index++, TLV_TYPE_HOST_NAME, &hostname ) == ERROR_SUCCESS )
110153
{
111-
struct in_addr addr = {0};
112-
struct in6_addr addr6 = {0};
154+
struct addrinfo* addr = NULL;
155+
156+
iResult = resolve_host((LPCSTR)hostname.buffer, ai_family, &addr);
113157

114-
iResult = resolve_host((LPCSTR)hostname.buffer, ai_family, &addr, &addr6);
158+
Packet* resolved_host_group = met_api->packet.create_group();
115159

116-
if (iResult == NO_ERROR)
160+
if (iResult != ERROR_SUCCESS || addr == NULL)
117161
{
118-
if (ai_family == AF_INET)
119-
{
120-
met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr));
121-
} else {
122-
met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6));
123-
}
162+
dprintf("Unable to resolve_host %s error: %x", hostname.buffer, iResult);
163+
goto done;
124164
}
125-
else
165+
166+
if (add_all_host_ips_to_group(resolved_host_group, addr) != ERROR_SUCCESS)
126167
{
127-
dprintf("Unable to resolve_host %s error: %x", hostname.buffer, iResult);
128-
met_api->packet.add_tlv_raw(response, TLV_TYPE_IP, NULL, 0);
168+
dprintf("Error adding resolved host IP addresses to group");
169+
goto done;
129170
}
130-
met_api->packet.add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family);
171+
172+
met_api->packet.add_group(response, TLV_TYPE_RESOLVE_HOST_ENTRY, resolved_host_group);
173+
if (addr != NULL) { dprintf("Freeing Address Info for hostname: %s", hostname.buffer); freeaddrinfo(addr); }
131174
}
132175

133-
met_api->packet.transmit_response(NO_ERROR, remote, response);
176+
done:
177+
met_api->packet.transmit_response(iResult, remote, response);
134178
return ERROR_SUCCESS;
135179
}

c/meterpreter/source/extensions/stdapi/stdapi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
#define TLV_TYPE_LOCAL_HOST_RAW MAKE_CUSTOM_TLV( TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_STDAPI, 1507 )
172172

173173
#define TLV_TYPE_SHUTDOWN_HOW MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 1530 )
174+
#define TLV_TYPE_RESOLVE_HOST_ENTRY MAKE_CUSTOM_TLV( TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_STDAPI, 1550 )
174175

175176
// Ui
176177
#define TLV_TYPE_IDLE_TIME MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 3000 )

0 commit comments

Comments
 (0)