Enumerating TCP ports and mapping them to PID (for XP)

Hello,

I've written an example for Windows XP that enumerates all open TCP and UDP ports and map them to the owning application. It uses a couple of undocumented functions like NETSTAT.EXE does.

Unfortunately, I don't have a time to write an article about this technique for Godeguru so if anybody want to write it, please feel free to use my example.

// portsenumxp.cpp (Windows XP)
//
// This example will show how you can enumerate
// all open TCP and UDP ports and map them to
// the owning application. It uses undocumented
// functions from iphlpapi.dll which were found
// by reversing netstat.exe.
//
//
// (c) 2002 Ashot Oganesyan K (ashot@protect-me.com)
// (c) 2002 SmartLine, Inc. (http://www.protect-me.com)

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <Iphlpapi.h>

typedef struct _MIB_TCPROW_EX
{
DWORD dwState; // MIB_TCP_STATE_*
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwRemoteAddr;
DWORD dwRemotePort;
DWORD dwProcessId;
} MIB_TCPROW_EX, *PMIB_TCPROW_EX;

typedef struct _MIB_TCPTABLE_EX
{
DWORD dwNumEntries;
MIB_TCPROW_EX table[ANY_SIZE];
} MIB_TCPTABLE_EX, *PMIB_TCPTABLE_EX;

typedef struct _MIB_UDPROW_EX
{
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwProcessId;
} MIB_UDPROW_EX, *PMIB_UDPROW_EX;

typedef struct _MIB_UDPTABLE_EX
{
DWORD dwNumEntries;
MIB_UDPROW_EX table[ANY_SIZE];
} MIB_UDPTABLE_EX, *PMIB_UDPTABLE_EX;

/*
DWORD
WINAPI
AllocateAndGetTcpExTableFromStack(
OUT PMIB_TCPTABLE_EX *pTcpTableEx,
IN BOOL bOrder,
IN HANDLE hAllocHeap,
IN DWORD dwAllocFlags,
IN DWORD dwProtocolVersion; // 2 - TCP, 23 - TCPv6 (size of *pTcpTableEx must be 56!)
);
*/
typedef DWORD (WINAPI *PROCALLOCATEANDGETTCPEXTABLEFROMSTACK)(PMIB_TCPTABLE_EX*,BOOL,HANDLE,DWORD,DWORD);
PROCALLOCATEANDGETTCPEXTABLEFROMSTACK lpfnAllocateAndGetTcpExTableFromStack = NULL;

/*
DWORD
WINAPI
AllocateAndGetUdpExTableFromStack(
OUT PMIB_UDPTABLE_EX *pUdpTable,
IN BOOL bOrder,
IN HANDLE hAllocHeap,
IN DWORD dwAllocFlags,
IN DWORD dwProtocolVersion; // 2 - UDP, 23 - UDPv6 (size of *pUdpTable must be 28!)
);
*/
typedef DWORD (WINAPI *PROCALLOCATEANDGETUDPEXTABLEFROMSTACK)(PMIB_UDPTABLE_EX*,BOOL,HANDLE,DWORD,DWORD);
PROCALLOCATEANDGETUDPEXTABLEFROMSTACK lpfnAllocateAndGetUdpExTableFromStack = NULL;

BOOL LoadExIpHelperProcedures(void)
{
HMODULE hModule;

hModule = LoadLibrary(_T("iphlpapi.dll"));
if (hModule == NULL)
return FALSE;

// XP and later
lpfnAllocateAndGetTcpExTableFromStack = (PROCALLOCATEANDGETTCPEXTABLEFROMSTACK)GetProcAddress(hModule,"AllocateAndGetTcpExTableFromStack");
if (lpfnAllocateAndGetTcpExTableFromStack == NULL)
return FALSE;

// XP and later
lpfnAllocateAndGetUdpExTableFromStack = (PROCALLOCATEANDGETUDPEXTABLEFROMSTACK)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");
if (lpfnAllocateAndGetUdpExTableFromStack == NULL)
return FALSE;

return TRUE;
}

void main(void)
{
DWORD dwLastError,
dwSize;
PMIB_TCPTABLE_EX lpBuffer = NULL;
PMIB_UDPTABLE_EX lpBuffer1 = NULL;

if (!LoadExIpHelperProcedures())
return;

dwLastError = lpfnAllocateAndGetTcpExTableFromStack(&lpBuffer,TRUE,GetProcessHeap(),0,2);
if (dwLastError == NO_ERROR)
{
printf(_T("Local IP\tLocal Port\tRemote Ip\tRemote Port\tPID\n\n"));

for (dwSize = 0; dwSize < lpBuffer->dwNumEntries; dwSize++)
{
// Local IP Address
printf(_T("%d.%d.%d.%d\t"),LOBYTE(LOWORD(lpBuffer->table[dwSize].dwLocalAddr)),HIBYTE(LOWORD(lpBuffer->table[dwSize].dwLocalAddr)),LOBYTE(HIWORD(lpBuffer->table[dwSize].dwLocalAddr)),HIBYTE(HIWORD(lpBuffer->table[dwSize].dwLocalAddr)));

// Local Port
printf(_T("%d\t"),((lpBuffer->table[dwSize].dwLocalPort & 0xFF00) >> 8) + ((lpBuffer->table[dwSize].dwLocalPort & 0x00FF) << 8));

// Remote IP Address
printf(_T("%d.%d.%d.%d\t"),LOBYTE(LOWORD(lpBuffer->table[dwSize].dwRemoteAddr)),HIBYTE(LOWORD(lpBuffer->table[dwSize].dwRemoteAddr)),LOBYTE(HIWORD(lpBuffer->table[dwSize].dwRemoteAddr)),HIBYTE(HIWORD(lpBuffer->table[dwSize].dwRemoteAddr)));

// Remote Port
if (lpBuffer->table[dwSize].dwRemoteAddr)
printf(_T("%d\t"),((lpBuffer->table[dwSize].dwRemotePort & 0xFF00) >> 8) + ((lpBuffer->table[dwSize].dwRemotePort & 0x00FF) << 8));
else
printf(_T("0\t"));

// PID
printf(_T("%lu\n"),lpBuffer->table[dwSize].dwProcessId);
}
}

dwLastError = lpfnAllocateAndGetUdpExTableFromStack(&lpBuffer1,TRUE,GetProcessHeap(),0,2);
if (dwLastError == NO_ERROR)
{
printf(_T("Local IP\tLocal Port\tPID\n\n"));

for (dwSize = 0; dwSize < lpBuffer1->dwNumEntries; dwSize++)
{
// Local IP Address
printf(_T("%d.%d.%d.%d\t"),LOBYTE(LOWORD(lpBuffer1->table[dwSize].dwLocalAddr)),HIBYTE(LOWORD(lpBuffer1->table[dwSize].dwLocalAddr)),LOBYTE(HIWORD(lpBuffer1->table[dwSize].dwLocalAddr)),HIBYTE(HIWORD(lpBuffer1->table[dwSize].dwLocalAddr)));

// Local Port
printf(_T("%d\t"),((lpBuffer1->table[dwSize].dwLocalPort & 0xFF00) >> 8) + ((lpBuffer1->table[dwSize].dwLocalPort & 0x00FF) << 8));

// PID
printf(_T("%lu\n"),lpBuffer1->table[dwSize].dwProcessId);
}
}


if (lpBuffer)
HeapFree(GetProcessHeap(),0,lpBuffer);

if (lpBuffer1)
HeapFree(GetProcessHeap(),0,lpBuffer1);
}
[6022 byte] By [ashotog] at [2007-11-17 14:26:34]