diff --git a/c/meterpreter/source/common/common_metapi.h b/c/meterpreter/source/common/common_metapi.h index 138a8187..d617215a 100644 --- a/c/meterpreter/source/common/common_metapi.h +++ b/c/meterpreter/source/common/common_metapi.h @@ -186,4 +186,4 @@ typedef struct _MetApi extern MetApi* met_api; -#endif +#endif \ No newline at end of file diff --git a/c/meterpreter/source/extensions/stdapi/server/net/config/route.c b/c/meterpreter/source/extensions/stdapi/server/net/config/route.c index 377e0f1b..dd52c94d 100644 --- a/c/meterpreter/source/extensions/stdapi/server/net/config/route.c +++ b/c/meterpreter/source/extensions/stdapi/server/net/config/route.c @@ -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; }