1
mirror of https://github.com/rapid7/metasploit-payloads synced 2024-11-20 14:39:22 +01:00

Land #614, Display IPv6 Routes on Windows

Feature to display IPv6 Routes on Windows
This commit is contained in:
Spencer McIntyre 2023-02-28 10:24:20 -05:00
commit 16a9a2d2f6
No known key found for this signature in database
GPG Key ID: 58101BA0D0D9C987
2 changed files with 118 additions and 20 deletions

View File

@ -1,20 +1,67 @@
#include "precomp.h"
#include "common.h"
#include "common_metapi.h"
#include <netioapi.h>
typedef NETIO_STATUS(NETIOAPI_API_* GETIPFORWARDTABLE2)(ADDRESS_FAMILY Family, PMIB_IPFORWARD_TABLE2* Table);
typedef struct v6netmask
{
unsigned int mask[4];
} v6netmask;
DWORD add_remove_route(Packet *request, BOOLEAN add);
static unsigned int bit32mask(unsigned bits){
unsigned int netmask;
if (bits == 32)
netmask = 0xffffffff;
else{
netmask = ((0xffffffff << (32 - (bits % 32))) & 0xffffffff);
}
return netmask;
}
static void bit128mask(unsigned int bits, v6netmask* netmask){
unsigned int part = bit32mask(bits);
if (bits >= 96) {
netmask->mask[0] = 0xffffffff;
netmask->mask[1] = 0xffffffff;
netmask->mask[2] = 0xffffffff;
netmask->mask[3] = htonl(part);
}
else if (bits >= 64) {
netmask->mask[0] = 0xffffffff;
netmask->mask[1] = 0xffffffff;
netmask->mask[2] = htonl(part);
netmask->mask[3] = 0x0;
}
else if (bits >= 32) {
netmask->mask[0] = 0xffffffff;
netmask->mask[1] = htonl(part);
netmask->mask[2] = 0x0;
netmask->mask[3] = 0x0;
}
else {
netmask->mask[0] = htonl(part);
netmask->mask[1] = 0x0;
netmask->mask[2] = 0x0;
netmask->mask[3] = 0x0;
}
return;
}
/*
* Returns zero or more routes to the requestor from the active routing table
*/
DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
{
Packet *response = met_api->packet.create_response(packet);
DWORD result = ERROR_SUCCESS;
DWORD dwResult = ERROR_SUCCESS;
DWORD index;
DWORD metric_bigendian;
PMIB_IPFORWARDTABLE table_ipv4 = NULL;
PMIB_IPFORWARDTABLE table_ipv6 = NULL;
PMIB_IPFORWARD_TABLE2 table_ipv6 = NULL;
DWORD tableSize = sizeof(MIB_IPFORWARDROW) * 96;
char int_name[20];
@ -23,15 +70,14 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
// Allocate storage for the routing table
if (!(table_ipv4 = (PMIB_IPFORWARDTABLE)malloc(tableSize)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Get the routing table
if (GetIpForwardTable(table_ipv4, &tableSize, TRUE) != NO_ERROR)
{
result = GetLastError();
break;
BREAK_ON_ERROR("[NET] request_net_config_get_routes: GetIpForwardTable failed");
}
// Enumerate it
@ -40,7 +86,7 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
index++)
{
Tlv route[5];
memset(int_name, 0, 20);
memset(int_name, 0, sizeof(int_name));
route[0].header.type = TLV_TYPE_SUBNET;
route[0].header.length = sizeof(DWORD);
@ -55,7 +101,7 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
// we just get the interface index, not the name, because names can be __long__
_itoa(table_ipv4->table[index].dwForwardIfIndex, int_name, 10);
route[3].header.type = TLV_TYPE_STRING;
route[3].header.length = (DWORD)strlen(int_name)+1;
route[3].header.length = (DWORD)strlen(int_name) + 1;
route[3].buffer = (PUCHAR)int_name;
metric_bigendian = htonl(table_ipv4->table[index].dwForwardMetric1);
@ -67,6 +113,58 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
route, 5);
}
v6netmask v6_mask;
MIB_IPINTERFACE_ROW iface = { .Family = AF_INET6 };
GETIPFORWARDTABLE2 pGetIpForwardTable2 = (GETIPFORWARDTABLE2)GetProcAddress(GetModuleHandle(TEXT("Iphlpapi.dll")), "GetIpForwardTable2");
// GetIpForwardTable2 is only available on Windows Vista and later.
if (!pGetIpForwardTable2) {
break;
}
if (pGetIpForwardTable2(AF_INET6, &table_ipv6) != NO_ERROR) {
BREAK_ON_ERROR("[NET] request_net_config_get_routes: GetIpForwardTable2 failed");
}
// Enumerate it
for (index = 0;
index < table_ipv6->NumEntries;
index++)
{
Tlv route[5];
memset(int_name, 0, sizeof(int_name));
iface.InterfaceIndex = table_ipv6->Table[index].InterfaceIndex;
if (GetIpInterfaceEntry(&iface) != NO_ERROR)
{
CONTINUE_ON_ERROR("[NET] request_net_config_get_routes: GetIpInterfaceEntry failed");
}
route[0].header.type = TLV_TYPE_SUBNET;
route[0].header.length = sizeof(DWORD)*4;
route[0].buffer = (PUCHAR)&table_ipv6->Table[index].DestinationPrefix.Prefix.Ipv6.sin6_addr;
bit128mask(table_ipv6->Table[index].DestinationPrefix.PrefixLength, &v6_mask);
route[1].header.type = TLV_TYPE_NETMASK;
route[1].header.length = sizeof(DWORD)*4;
route[1].buffer = (PUCHAR)v6_mask.mask;
route[2].header.type = TLV_TYPE_GATEWAY;
route[2].header.length = sizeof(DWORD)*4;
route[2].buffer = (PUCHAR)&table_ipv6->Table[index].NextHop.Ipv6.sin6_addr;
// we just get the interface index, not the name, because names can be __long__
_itoa(table_ipv6->Table[index].InterfaceIndex, int_name, 10);
route[3].header.type = TLV_TYPE_STRING;
route[3].header.length = (DWORD)strlen(int_name)+1;
route[3].buffer = (PUCHAR)int_name;
metric_bigendian = htonl(table_ipv6->Table[index].Metric + iface.Metric);
route[4].header.type = TLV_TYPE_ROUTE_METRIC;
route[4].header.length = sizeof(DWORD);
route[4].buffer = (PUCHAR)&metric_bigendian;
met_api->packet.add_tlv_group(response, TLV_TYPE_NETWORK_ROUTE,
route, 5);
}
} while (0);
if(table_ipv4)
@ -74,7 +172,7 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
if(table_ipv6)
free(table_ipv6);
met_api->packet.transmit_response(result, remote, response);
met_api->packet.transmit_response(dwResult, remote, response);
return ERROR_SUCCESS;
}