// Based on example code from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365947(v=vs.85).aspx // and http://www.nynaeve.net/Code/GetInterfaceMetric.cpp. #include #include #include #include #include #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "Ole32.lib") #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) /* Note: could also use malloc() and free() */ // // Suspected prototype of NsiGetParameter, via reverse engineering. // typedef DWORD (__stdcall *NsiGetParameterProc)( DWORD Argument1, CONST UCHAR* Argument2, DWORD Argument3, PNET_LUID Argument4, DWORD Argument5, DWORD Argument6, PUCHAR Argument7, DWORD Argument8, DWORD Argument9 ); /* 0:000> db NPI_MS_IPV4_MODULEID l14 751b3364 18 00 00 00 01 00 00 00-00 4a 00 eb 1a 9b d4 11 751b3374 91 23 00 50 04 77 59 BC */ const unsigned char NPI_MS_IPV4_MODULEID[0x18] = { 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x00, 0xEB, 0x1A, 0x9B, 0xD4, 0x11, 0x91, 0x23, 0x00, 0x50, 0x04, 0x77, 0x59, 0xBC }; VOID PrintHex(PBYTE Data, ULONG dwBytes) { for (ULONG i = 0; i < dwBytes; i += 16) { printf("%.8x: ", i); for (ULONG j = 0; j < 16; j++) { if (i + j < dwBytes) { printf("%.2x ", Data[i + j]); } else { printf("?? "); } } for (ULONG j = 0; j < 16; j++) { if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) { printf("%c", Data[i + j]); } else { printf("."); } } printf("\n"); } } int main() { HMODULE hNsi = LoadLibraryW(L"Nsi.dll"); NsiGetParameterProc _NsiGetParameter = (NsiGetParameterProc)GetProcAddress(hNsi, "NsiGetParameter"); // Declare and initialize variables PIP_INTERFACE_INFO pInfo = NULL; ULONG ulOutBufLen = 0; DWORD dwRetVal = 0; int iReturn = 1; int i; // Make an initial call to GetInterfaceInfo to get // the necessary size in the ulOutBufLen variable dwRetVal = GetInterfaceInfo(NULL, &ulOutBufLen); if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) { pInfo = (IP_INTERFACE_INFO *)MALLOC(ulOutBufLen); if (pInfo == NULL) { printf ("Unable to allocate memory needed to call GetInterfaceInfo\n"); return 1; } } // Make a second call to GetInterfaceInfo to get // the actual data we need dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen); if (dwRetVal == NO_ERROR) { printf("Number of Adapters: %ld\n\n", pInfo->NumAdapters); for (i = 0; i < pInfo->NumAdapters; i++) { printf("Adapter Index[%d]: %ld\n", i, pInfo->Adapter[i].Index); NET_LUID Luid; NETIO_STATUS st = ConvertInterfaceIndexToLuid(pInfo->Adapter[i].Index, &Luid); if (st == NO_ERROR) { BYTE OutputBuffer[0xB8] = { /* zero padding */ }; DWORD nsi_st = _NsiGetParameter(1, NPI_MS_IPV4_MODULEID, 7, &Luid, sizeof(Luid), 0, OutputBuffer, sizeof(OutputBuffer), 0); if (nsi_st == NO_ERROR) { PrintHex(OutputBuffer, sizeof(OutputBuffer)); } } } iReturn = 0; } else if (dwRetVal == ERROR_NO_DATA) { printf ("There are no network adapters with IPv4 enabled on the local system\n"); iReturn = 0; } else { printf("GetInterfaceInfo failed with error: %d\n", dwRetVal); iReturn = 1; } FREE(pInfo); return (iReturn); }