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:
commit
16a9a2d2f6
@ -186,4 +186,4 @@ typedef struct _MetApi
|
||||
|
||||
extern MetApi* met_api;
|
||||
|
||||
#endif
|
||||
#endif
|
@ -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,42 +70,94 @@ 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
|
||||
for (index = 0;
|
||||
index < table_ipv4->dwNumEntries;
|
||||
index++)
|
||||
index < table_ipv4->dwNumEntries;
|
||||
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.type = TLV_TYPE_SUBNET;
|
||||
route[0].header.length = sizeof(DWORD);
|
||||
route[0].buffer = (PUCHAR)&table_ipv4->table[index].dwForwardDest;
|
||||
route[1].header.type = TLV_TYPE_NETMASK;
|
||||
route[0].buffer = (PUCHAR)&table_ipv4->table[index].dwForwardDest;
|
||||
route[1].header.type = TLV_TYPE_NETMASK;
|
||||
route[1].header.length = sizeof(DWORD);
|
||||
route[1].buffer = (PUCHAR)&table_ipv4->table[index].dwForwardMask;
|
||||
route[2].header.type = TLV_TYPE_GATEWAY;
|
||||
route[1].buffer = (PUCHAR)&table_ipv4->table[index].dwForwardMask;
|
||||
route[2].header.type = TLV_TYPE_GATEWAY;
|
||||
route[2].header.length = sizeof(DWORD);
|
||||
route[2].buffer = (PUCHAR)&table_ipv4->table[index].dwForwardNextHop;
|
||||
route[2].buffer = (PUCHAR)&table_ipv4->table[index].dwForwardNextHop;
|
||||
|
||||
// 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;
|
||||
_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].buffer = (PUCHAR)int_name;
|
||||
|
||||
metric_bigendian = htonl(table_ipv4->table[index].dwForwardMetric1);
|
||||
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);
|
||||
}
|
||||
|
||||
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_ipv4->table[index].dwForwardMetric1);
|
||||
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;
|
||||
@ -66,7 +165,6 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet)
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user