From 98726de8be4f33034020ee3c8224090940056905 Mon Sep 17 00:00:00 2001 From: Nishant Desai Date: Fri, 10 Feb 2023 16:37:50 +0000 Subject: [PATCH 1/3] Display-ipv6-routes --- c/meterpreter/source/common/common_metapi.h | 7 +- .../stdapi/server/net/config/route.c | 106 ++++++++++++++++-- .../source/extensions/stdapi/server/precomp.h | 1 + 3 files changed, 106 insertions(+), 8 deletions(-) diff --git a/c/meterpreter/source/common/common_metapi.h b/c/meterpreter/source/common/common_metapi.h index 138a8187..a0f3d26e 100644 --- a/c/meterpreter/source/common/common_metapi.h +++ b/c/meterpreter/source/common/common_metapi.h @@ -159,6 +159,11 @@ typedef struct _ListApi VOID(*destroy)(PLIST pList); } ListApi; +typedef struct v6netmask +{ + unsigned mask[4]; +} v6netmask; + #ifdef DEBUGTRACE typedef struct _LoggingApi { @@ -186,4 +191,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..25d76287 100644 --- a/c/meterpreter/source/extensions/stdapi/server/net/config/route.c +++ b/c/meterpreter/source/extensions/stdapi/server/net/config/route.c @@ -3,6 +3,45 @@ DWORD add_remove_route(Packet *request, BOOLEAN add); +int bit32mask(unsigned bits){ + unsigned netmask; + if (bits == 32) + netmask = 0xffffffff; + else{ + netmask = ((0xffffffff << (32 - (bits % 32))) & 0xffffffff); + } + return netmask; +} + +void bit128mask(unsigned bits, v6netmask* netmask){ + unsigned part; + 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 */ @@ -14,20 +53,21 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet) DWORD metric_bigendian; PMIB_IPFORWARDTABLE table_ipv4 = NULL; - PMIB_IPFORWARDTABLE table_ipv6 = NULL; + PMIB_IPFORWARD_TABLE2 val = NULL; + PMIB_IPFORWARD_TABLE2 *table_ipv6 = &val; DWORD tableSize = sizeof(MIB_IPFORWARDROW) * 96; char int_name[20]; do { - // Allocate storage for the routing table +// Allocate storage for the routing table if (!(table_ipv4 = (PMIB_IPFORWARDTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } - // Get the routing table +// Get the routing table if (GetIpForwardTable(table_ipv4, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); @@ -60,19 +100,71 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet) metric_bigendian = htonl(table_ipv4->table[index].dwForwardMetric1); route[4].header.type = TLV_TYPE_ROUTE_METRIC; - route[4].header.length = sizeof(DWORD); + 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); } + if (GetIpForwardTable2(AF_INET6, table_ipv6) == NO_ERROR) + { + // Enumerate it + for (index = 0; + index < val->NumEntries; + index++) + { + Tlv route[5]; + memset(int_name, 0, 20); + v6netmask* v6_mask = malloc(sizeof(v6netmask)); + PMIB_IPINTERFACE_ROW iface = malloc(sizeof(MIB_IPINTERFACE_ROW)); + iface->Family = AF_INET6; + iface->InterfaceIndex = val->Table[index].InterfaceIndex; + if (GetIpInterfaceEntry(iface) != NO_ERROR) + { + result = GetLastError(); + break; + } + + route[0].header.type = TLV_TYPE_SUBNET; + route[0].header.length = sizeof(DWORD)*4; + route[0].buffer = (PUCHAR)&val->Table[index].DestinationPrefix.Prefix.Ipv6.sin6_addr; + bit128mask(val->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)&val->Table[index].NextHop.Ipv6.sin6_addr; + + // we just get the interface index, not the name, because names can be __long__ + _itoa(val->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(val->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); + free(v6_mask); + free(iface); + } + } + else + { + result = GetLastError(); + break; + } } while (0); if(table_ipv4) free(table_ipv4); - if(table_ipv6) - free(table_ipv6); + if(val) + free(val); met_api->packet.transmit_response(result, remote, response); @@ -153,4 +245,4 @@ DWORD add_remove_route(Packet *packet, BOOLEAN add) return CreateIpForwardEntry(&route); else return DeleteIpForwardEntry(&route); -} +} \ No newline at end of file diff --git a/c/meterpreter/source/extensions/stdapi/server/precomp.h b/c/meterpreter/source/extensions/stdapi/server/precomp.h index 95f76b88..b6f636cf 100644 --- a/c/meterpreter/source/extensions/stdapi/server/precomp.h +++ b/c/meterpreter/source/extensions/stdapi/server/precomp.h @@ -6,6 +6,7 @@ #define _WIN32_WINNT _WIN32_WINNT_WIN2K #include "../stdapi.h" #include +#include #include #include "resource/resource.h" From bf7e5cb7c65e032cd66c2e5a0acbe61bac4c60e4 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Mon, 27 Feb 2023 13:20:46 -0500 Subject: [PATCH 2/3] Fix compiler and other errors --- c/meterpreter/source/common/common_metapi.h | 5 - .../stdapi/server/net/config/route.c | 172 +++++++++--------- .../source/extensions/stdapi/server/precomp.h | 1 - 3 files changed, 85 insertions(+), 93 deletions(-) diff --git a/c/meterpreter/source/common/common_metapi.h b/c/meterpreter/source/common/common_metapi.h index a0f3d26e..d617215a 100644 --- a/c/meterpreter/source/common/common_metapi.h +++ b/c/meterpreter/source/common/common_metapi.h @@ -159,11 +159,6 @@ typedef struct _ListApi VOID(*destroy)(PLIST pList); } ListApi; -typedef struct v6netmask -{ - unsigned mask[4]; -} v6netmask; - #ifdef DEBUGTRACE typedef struct _LoggingApi { 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 25d76287..6b64e3fb 100644 --- a/c/meterpreter/source/extensions/stdapi/server/net/config/route.c +++ b/c/meterpreter/source/extensions/stdapi/server/net/config/route.c @@ -1,10 +1,17 @@ #include "precomp.h" +#include "common.h" #include "common_metapi.h" +#include + +typedef struct v6netmask +{ + unsigned int mask[4]; +} v6netmask; DWORD add_remove_route(Packet *request, BOOLEAN add); -int bit32mask(unsigned bits){ - unsigned netmask; +static unsigned int bit32mask(unsigned bits){ + unsigned int netmask; if (bits == 32) netmask = 0xffffffff; else{ @@ -13,28 +20,27 @@ int bit32mask(unsigned bits){ return netmask; } -void bit128mask(unsigned bits, v6netmask* netmask){ - unsigned part; - part = bit32mask(bits); - if (bits >= 96){ +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){ + 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){ + else if (bits >= 32) { netmask->mask[0] = 0xffffffff; netmask->mask[1] = htonl(part); netmask->mask[2] = 0x0; netmask->mask[3] = 0x0; } - else{ + else { netmask->mask[0] = htonl(part); netmask->mask[1] = 0x0; netmask->mask[2] = 0x0; @@ -48,125 +54,117 @@ void bit128mask(unsigned bits, v6netmask* netmask){ 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_IPFORWARD_TABLE2 val = NULL; - PMIB_IPFORWARD_TABLE2 *table_ipv6 = &val; + PMIB_IPFORWARD_TABLE2 table_ipv6 = NULL; DWORD tableSize = sizeof(MIB_IPFORWARDROW) * 96; char int_name[20]; do { -// Allocate storage for the routing table + // 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 + // 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); + } + + if (GetIpForwardTable2(AF_INET6, &table_ipv6) != NO_ERROR) { + BREAK_ON_ERROR("[NET] request_net_config_get_routes: GetIpForwardTable2 failed"); + } + + v6netmask v6_mask; + MIB_IPINTERFACE_ROW iface = { .Family = AF_INET6 }; + // 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].header.length = sizeof(DWORD); route[4].buffer = (PUCHAR)&metric_bigendian; met_api->packet.add_tlv_group(response, TLV_TYPE_NETWORK_ROUTE, route, 5); } - - if (GetIpForwardTable2(AF_INET6, table_ipv6) == NO_ERROR) - { - // Enumerate it - for (index = 0; - index < val->NumEntries; - index++) - { - Tlv route[5]; - memset(int_name, 0, 20); - v6netmask* v6_mask = malloc(sizeof(v6netmask)); - PMIB_IPINTERFACE_ROW iface = malloc(sizeof(MIB_IPINTERFACE_ROW)); - iface->Family = AF_INET6; - iface->InterfaceIndex = val->Table[index].InterfaceIndex; - if (GetIpInterfaceEntry(iface) != NO_ERROR) - { - result = GetLastError(); - break; - } - - route[0].header.type = TLV_TYPE_SUBNET; - route[0].header.length = sizeof(DWORD)*4; - route[0].buffer = (PUCHAR)&val->Table[index].DestinationPrefix.Prefix.Ipv6.sin6_addr; - bit128mask(val->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)&val->Table[index].NextHop.Ipv6.sin6_addr; - - // we just get the interface index, not the name, because names can be __long__ - _itoa(val->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(val->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); - free(v6_mask); - free(iface); - } - } - else - { - result = GetLastError(); - break; - } } while (0); if(table_ipv4) free(table_ipv4); - if(val) - free(val); + 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; } @@ -245,4 +243,4 @@ DWORD add_remove_route(Packet *packet, BOOLEAN add) return CreateIpForwardEntry(&route); else return DeleteIpForwardEntry(&route); -} \ No newline at end of file +} diff --git a/c/meterpreter/source/extensions/stdapi/server/precomp.h b/c/meterpreter/source/extensions/stdapi/server/precomp.h index b6f636cf..95f76b88 100644 --- a/c/meterpreter/source/extensions/stdapi/server/precomp.h +++ b/c/meterpreter/source/extensions/stdapi/server/precomp.h @@ -6,7 +6,6 @@ #define _WIN32_WINNT _WIN32_WINNT_WIN2K #include "../stdapi.h" #include -#include #include #include "resource/resource.h" From f402d7cb9ed59ece46b0b944a884bd1f103a2136 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Mon, 27 Feb 2023 15:19:50 -0500 Subject: [PATCH 3/3] Fix Windows XP compatibility GetIpForwardTable2 is not available on Windows versions prior to Vista. Use GetProcAddress to call it when it's available while avoiding crashing on XP. --- .../extensions/stdapi/server/net/config/route.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) 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 6b64e3fb..dd52c94d 100644 --- a/c/meterpreter/source/extensions/stdapi/server/net/config/route.c +++ b/c/meterpreter/source/extensions/stdapi/server/net/config/route.c @@ -3,6 +3,8 @@ #include "common_metapi.h" #include +typedef NETIO_STATUS(NETIOAPI_API_* GETIPFORWARDTABLE2)(ADDRESS_FAMILY Family, PMIB_IPFORWARD_TABLE2* Table); + typedef struct v6netmask { unsigned int mask[4]; @@ -111,12 +113,18 @@ DWORD request_net_config_get_routes(Remote *remote, Packet *packet) route, 5); } - if (GetIpForwardTable2(AF_INET6, &table_ipv6) != NO_ERROR) { + 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"); } - v6netmask v6_mask; - MIB_IPINTERFACE_ROW iface = { .Family = AF_INET6 }; // Enumerate it for (index = 0; index < table_ipv6->NumEntries;