f221984d89
Seemingly Npcap returns a read-only string and `niclist.exe` tries to modify (tokenize) it using `strtrok()`. That results in the crash: #161 Probably related to https://github.com/the-tcpdump-group/libpcap/pull/949. Here is my try at fixing this. For successful modification I propose to use a stack-allocated copy instead of the original (const) version string. Now [packetWin7/Dll/Packet32.cpp#L159](https://github.com/nmap/npcap/blob/a41bc6a/packetWin7/Dll/Packet32.cpp#L159) seems to initialize `const char PacketLibraryVersion[]` from the define `WINPCAP_VER_STRING`, which seems to be of arbitrary length: ``` __declspec(dllexport) const char PacketLibraryVersion[] = WINPCAP_VER_STRING; ``` Let's search for the longest string present in their repo: ``` $ git log -u version.h | awk 'BEGIN { FPAT="(([^ \t]+)?(\"[^\"]+\")?)+" } /^.*define.+WINPCAP_VER_STRING.+[0-9]/ { gsub(/"/, "", $NF); print $NF }' | sort -Vu | while read; do printf "%4s %s\n" ${#REPLY} "${REPLY}"; done | sort -n 4 0.01 4 0.03 4 0.04 4 0.05 4 0.06 4 0.07 4 0.08 4 0.09 4 0.10 4 0.11 4 0.78 4 0.80 4 0.81 4 0.82 4 0.83 4 0.84 4 0.85 4 0.86 4 0.90 4 0.91 4 0.92 4 0.93 4 0.94 4 0.95 4 0.96 4 0.97 4 0.98 4 1.00 4 1.10 4 1.20 4 1.30 4 1.31 4 1.40 4 1.50 4 1.55 4 1.60 4 1.70 4 1.71 4 1.72 4 1.73 4 1.74 4 1.75 4 1.76 4 1.77 4 1.78 5 0.991 5 0.992 5 0.993 5 0.994 5 0.995 5 0.996 5 0.997 6 0.9981 6 0.9982 6 0.9983 6 0.9984 6 0.9985 6 0.9986 6 0.9987 6 0.9988 6 0.9989 6 0.9990 6 0.9991 6 0.9992 6 0.9993 6 0.9994 6 0.9995 6 0.9996 6 0.9997 7 0.08 r8 7 0.08 r9 7 0.09 r2 7 0.09 r3 7 0.09 r4 7 0.09 r5 7 0.09 r6 7 0.09 r7 7 0.09 r8 7 0.09 r9 7 0.10 r2 7 0.10 r3 7 0.10 r4 7 0.10 r5 7 0.10 r6 7 0.10 r7 7 0.10 r8 7 0.10 r9 7 0.78 r2 7 0.78 r3 7 0.78 r4 7 0.78 r5 7 0.99-r1 7 0.99-r2 7 0.99-r3 7 0.99-r4 7 0.99-r5 7 0.99-r6 7 0.99-r7 7 0.99-r8 7 0.99-r9 8 0.08 r10 8 0.09 r10 8 0.09 r11 8 0.09 r12 8 0.09 r13 8 0.10 r10 8 0.10 r11 8 0.10 r12 8 0.10 r13 8 0.10 r14 8 0.10 r15 8 0.10 r16 8 0.10 r17 8 0.10 r18 10 4.1.0.2980 10 4.1.0.3001 ``` So it's 10 characters. (Sorry for the long Bash one-liner) Also I visited the older code from WinPcap, and it seems it used a 64-byte long string: [packetNtx/Dll/Packet32.c#L105](https://github.com/wireshark/winpcap/blob/267327e/packetNtx/Dll/Packet32.c#L105) ``` char PacketLibraryVersion[64]; ``` So I assumed it's safe to allocate the same on stack.
200 lines
5.3 KiB
C
200 lines
5.3 KiB
C
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// misc/niclist.c
|
|
// by Don Becker <x-odus@iname.com>
|
|
// $Id$
|
|
//
|
|
// This program is for win32 only. It lists the network interface cards
|
|
// that you can use in the "ethdev" field of the ne2k line in your bochsrc.
|
|
//
|
|
// For this program and for win32 ethernet, the winpcap library is required.
|
|
// Download it from http://www.winpcap.org/
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef WIN32
|
|
#error Niclist will only work on WIN32 platforms.
|
|
#endif
|
|
|
|
#ifndef CDECL
|
|
#if defined(_MSC_VER)
|
|
#define CDECL __cdecl
|
|
#else
|
|
#define CDECL
|
|
#endif
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#ifdef __CYGWIN__
|
|
#include <wchar.h>
|
|
#else
|
|
#include <conio.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
|
|
#if defined(_MSC_VER)
|
|
#define getch _getch
|
|
#endif
|
|
|
|
#define MAX_ADAPTERS 10
|
|
#define NIC_BUFFER_SIZE 2048
|
|
|
|
// declare our NT/9X structures to hold the adapter name and descriptions
|
|
typedef struct {
|
|
LPWSTR wstrName;
|
|
LPSTR strDesc;
|
|
} NIC_INFO_NT;
|
|
|
|
typedef struct {
|
|
LPSTR strName;
|
|
LPSTR strDesc;
|
|
} NIC_INFO_9X;
|
|
|
|
// declare an array of structures to hold our adapter information
|
|
NIC_INFO_NT niNT[MAX_ADAPTERS];
|
|
NIC_INFO_9X ni9X[MAX_ADAPTERS];
|
|
|
|
typedef BOOLEAN (CDECL *PGetAdapterNames)(PTSTR, PULONG);
|
|
typedef PCHAR (CDECL *PGetVersion)();
|
|
|
|
PGetAdapterNames PacketGetAdapterNames = NULL;
|
|
PGetVersion PacketGetVersion = NULL;
|
|
|
|
void myexit(int code)
|
|
{
|
|
#ifndef __CYGWIN__
|
|
printf ("\nPress any key to continue\n");
|
|
getch();
|
|
#endif
|
|
exit(code);
|
|
}
|
|
|
|
int CDECL main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
HINSTANCE hPacket;
|
|
char AdapterInfo[NIC_BUFFER_SIZE] = { '\0','\0' };
|
|
ULONG AdapterLength = NIC_BUFFER_SIZE;
|
|
LPWSTR wstrName;
|
|
LPSTR strName, strDesc;
|
|
int nAdapterCount;
|
|
char dllVersion[64] = { '\0' };
|
|
PCHAR testString;
|
|
int nDLLMajorVersion, nDLLMinorVersion;
|
|
|
|
// Attemp to load the WinpCap packet library
|
|
hPacket = LoadLibrary("PACKET.DLL");
|
|
if (hPacket)
|
|
{
|
|
// Now look up the address
|
|
PacketGetAdapterNames = (PGetAdapterNames)GetProcAddress(hPacket, "PacketGetAdapterNames");
|
|
PacketGetVersion = (PGetVersion)GetProcAddress(hPacket, "PacketGetVersion");
|
|
} else {
|
|
printf("Could not load WinPCap driver!\n");
|
|
printf ("You can download them for free from\n");
|
|
printf ("http://www.winpcap.org/\n");
|
|
myexit(1);
|
|
}
|
|
|
|
// Get DLL Version and Tokenize
|
|
strcpy(dllVersion, PacketGetVersion());
|
|
nDLLMajorVersion = -1;
|
|
nDLLMinorVersion = -1;
|
|
for (testString = strtok(dllVersion, ",. ");
|
|
testString != NULL; testString = strtok(NULL, ",. "))
|
|
{
|
|
// If Single Character, Convert
|
|
if (strlen( testString ) == 1)
|
|
{
|
|
// Check Major First
|
|
if (nDLLMajorVersion == -1)
|
|
{
|
|
nDLLMajorVersion = atoi(testString);
|
|
}
|
|
else if ( nDLLMinorVersion == -1 )
|
|
{
|
|
nDLLMinorVersion = atoi(testString);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get out blob of adapter info
|
|
PacketGetAdapterNames(AdapterInfo, &AdapterLength);
|
|
|
|
if (nDLLMajorVersion < 3 || (nDLLMajorVersion == 3 && nDLLMinorVersion < 1))
|
|
{
|
|
// DLL returns UNICODE
|
|
wstrName=(LPWSTR)AdapterInfo;
|
|
|
|
// Obtain Names
|
|
nAdapterCount = 0;
|
|
while ((*wstrName))
|
|
{
|
|
// store pointer to name
|
|
niNT[nAdapterCount].wstrName=wstrName;
|
|
wstrName += lstrlenW(wstrName) +1;
|
|
nAdapterCount++;
|
|
}
|
|
|
|
strDesc = (LPSTR)++wstrName;
|
|
|
|
// Obtain descriptions ....
|
|
for (i=0;i<nAdapterCount;i++)
|
|
{
|
|
// store pointer to description
|
|
niNT[i].strDesc=strDesc;
|
|
strDesc += lstrlen(strDesc) +1;
|
|
|
|
// ... and display adapter info
|
|
printf("\n%d: %s\n",i+1,niNT[i].strDesc);
|
|
wprintf(L" Device: %s",niNT[i].wstrName);
|
|
}
|
|
|
|
if (i) {
|
|
printf("\n\nExample config for bochsrc:\n");
|
|
wprintf(L"ne2k: ioaddr=0x300, irq=3, mac=b0:c4:20:00:00:00, ethmod=win32, ethdev=%s",niNT[0].wstrName);
|
|
printf("\n");
|
|
}
|
|
|
|
} else {
|
|
// DLL returns ANSI
|
|
strName=(LPSTR)AdapterInfo;
|
|
|
|
// Obtain Names
|
|
nAdapterCount = 0;
|
|
while ((*strName))
|
|
{
|
|
// store pointer to name
|
|
ni9X[nAdapterCount].strName=strName;
|
|
strName += lstrlen(strName) +1;
|
|
nAdapterCount++;
|
|
}
|
|
|
|
strDesc = (LPSTR)++strName;
|
|
|
|
// Obtain descriptions ....
|
|
for (i=0;i<nAdapterCount;i++)
|
|
{
|
|
// store pointer to description
|
|
ni9X[i].strDesc=strDesc;
|
|
strDesc += lstrlen(strDesc) +1;
|
|
|
|
// ... and display adapter info
|
|
printf("\n%d: %s\n",i+1,ni9X[i].strDesc);
|
|
printf(" Device: %s",ni9X[i].strName);
|
|
}
|
|
|
|
if (i) {
|
|
printf("\n\nExample config for bochsrc:\n");
|
|
printf("ne2k: ioaddr=0x300, irq=3, mac=b0:c4:20:00:00:00, ethmod=win32, ethdev=%s",ni9X[0].strName);
|
|
printf("\n");
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
myexit (0);
|
|
return 0; /* shut up stupid compilers */
|
|
}
|