经过了差不多一天的努力,看了又看,写了又写.终于把计算机端口监控的程序搞定了.这个过程还算可以不算太复杂。不,应该说是不太令我头痛。
首先,关键代码我已经有了,剩下的就是添加一些枝枝蔓蔓的东西,这个过程当然要理解关键代码。在这个过程当中,也重新温故了动态链接库的动态调用和htonl,htons,inet_addr,inet_ntoa,这几个函数的应用。这东西久了不用还真是会忘记,挺容易混淆的。
其次,学习WINDOWS隐含的API函数,这个函数是AllocateAndGetUdpExTableFromStack和他的另外一个兄弟AllocateAndGetTcpExTableFromStack,这两个函数我在MSDN里面怎么找都找不到。还在QQ群上问了下别人,结果没人理我,或者有人也叫我自己去查MSDN。当然了,这也有可能是因为我的MSDN是典型安装而不是完全安装的原因所致。这两个函数可以直接得到系统中UDP和TCP连接的信息,通过结构体MIB_TCPEXTABLE和MIB_UDPEXTABLE。
说起MSDN就想起了我刚刚学习VC++那会,哪个时候第一次看到VC++/MFC的代码时,感觉就一个字“晕”。第一印象就是这个。甚至当时连VC++到哪里下载都还要问别人,呵呵。好象也没人理我,后来我是自己到迅雷上去找,结果被我给找到了。当时真有一种激动的感觉啊... ...
言归正传,下面是这个程序的源代码。程序当中可能还有一些不尽如人意的地方,很希望有人能够帮我指正。这是一个“凤凰涅盘”的过程。
#include <windows.h>
#include <stdio.h>
#include <Iprtrmib.h>
#include <Tlhelp32.h>
#pragma comment(lib,"Ws2_32.lib")
#define FLAG_SHOW_NUMBERS 0
#define LOCALADDRESS inet_addr("192.168.1.100")
#define HOSTNAMELEN 50
//#define ANY_SIZE 100;
typedef struct{
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwProcessId;
}MIB_UDPEXROW,*PMIB_UDPEXROW;
typedef struct{
DWORD dwNumEntries;
MIB_UDPEXROW table[ANY_SIZE];
}MIB_UDPEXTABLE,*PMIB_UDPEXTABLE;
typedef struct{
DWORD dwState;
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwRemoteAddr;
DWORD dwRemotePort;
DWORD dwProcessId;
}MIB_TCPEXROW,*PMIB_TCPEXROW;
typedef struct{
DWORD dwNumEntries;
MIB_TCPEXROW table[100];
}MIB_TCPEXTABLE,*PMIB_TCPEXTABLE;
typedef DWORD (WINAPI *pAllocateAndGetTcpExTableFromStackFun)(PMIB_TCPEXTABLE *pTcpTable,
BOOL bOrder,
HANDLE heap,
DWORD zero,
DWORD flags
);
pAllocateAndGetTcpExTableFromStackFun pAllocateAndGetTcpExTableFromStack = NULL;
typedef DWORD (WINAPI *pAllocateAndGetUdpExTableFromStackFun)(PMIB_UDPEXTABLE *pTcpTable,
BOOL bOrder,
HANDLE heap,
DWORD zero,
DWORD flags
);
pAllocateAndGetUdpExTableFromStackFun pAllocateAndGetUdpExTableFromStack = NULL;
typedef HANDLE (WINAPI *pCreateToolhelp32SnapshotFun)(DWORD dwFlags,
DWORD th32ProcessID
);
pCreateToolhelp32SnapshotFun pCreateToolhelp32Snapshot;
typedef BOOL (WINAPI *pProcess32FirstFun)(HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
pProcess32FirstFun pProcess32First;
typedef BOOL (WINAPI *pProcess32NextFun)(HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
pProcess32NextFun pProcess32Next;
BOOL ExApisArePresent()
{
pAllocateAndGetTcpExTableFromStack = (pAllocateAndGetTcpExTableFromStackFun) GetProcAddress(LoadLibrary("iphlpapi.dll"),
"AllocateAndGetTcpExTableFromStack");
if(!pAllocateAndGetTcpExTableFromStack)
{
return FALSE;
}
pAllocateAndGetUdpExTableFromStack = (pAllocateAndGetUdpExTableFromStackFun) GetProcAddress(LoadLibrary("iphlpapi.dll"),
"AllocateAndGetUdpExTableFromStack");
if(!pAllocateAndGetTcpExTableFromStack)
{
return FALSE;
}
pCreateToolhelp32Snapshot = (pCreateToolhelp32SnapshotFun) GetProcAddress(GetModuleHandle("kernel32.dll"),
"CreateToolhelp32Snapshot");
if(!pCreateToolhelp32Snapshot)
{
return FALSE;
}
pProcess32First = (pProcess32FirstFun) GetProcAddress(GetModuleHandle("kernel32.dll"),"Process32First");
if(!pProcess32First)
{
return FALSE;
}
pProcess32Next = (pProcess32NextFun) GetProcAddress(GetModuleHandle("kernel32.dll"),"Process32Next");
if(!pProcess32Next)
{
return FALSE;
}
return TRUE;
}
PCHAR GetIpHostName(BOOL local,UINT ipaddr,PCHAR name,int namelen)
{
struct hostent *phostent;
UINT nipaddr;
nipaddr = htonl(ipaddr);
if (FLAG_SHOW_NUMBERS)
{
sprintf(name,"%d.%d.%d.%d",(nipaddr>>24)&0xFF,(nipaddr>>16)&0xFF,
(nipaddr>>8)&0xFF,(nipaddr)&0xFF);
return name;
}
if(!ipaddr)
{
if(!local)
{
sprintf(name,"%d.%d.%d.%d",(nipaddr>>24)&0xFF,(nipaddr>>16)&0xFF,
(nipaddr>>8)&0xFF,(nipaddr)&0xFF);
}
else
{
gethostname(name,namelen);
}
}
else if(ipaddr == LOCALADDRESS)
{
if(local)
{
gethostname(name,namelen);
}
else
{
strcpy(name,"localhost");
}
}
else if(phostent = gethostbyaddr((char*)&ipaddr,sizeof(nipaddr),PF_INET))
{
strcpy(name,phostent->h_name);
}
else
{
sprintf(name,"%d.%d.%d.%d",(nipaddr>>24)&0xFF,(nipaddr>>16)&0xFF,
(nipaddr>>8)&0xFF,(nipaddr)&0xFF);
}
return name;
}
PCHAR ProcessPidToName(HANDLE hProcessSnap,DWORD ProcessId,PCHAR ProcessName)
{
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(processEntry);
strcpy(ProcessName,"???");
if (!pProcess32First(hProcessSnap,&processEntry))
{
return ProcessName;
}
do
{
if(processEntry.th32ProcessID == ProcessId)
{
strcpy(ProcessName,processEntry.szExeFile);
return ProcessName;
}
}while(pProcess32Next(hProcessSnap,&processEntry));
return ProcessName;
}
static char TcpState[][32] =
{
TEXT("???"),
TEXT("CLOSED"),
TEXT("LISTENING"),
TEXT("SYN_SENT"),
TEXT("SYN_RCVD"),
TEXT("ESTABLISHED"),
TEXT("FIN_WAIT1"),
TEXT("FIN_WAIT2"),
TEXT("CLOSE_WAIT"),
TEXT("CLOSING"),
TEXT("LAST_ACK"),
TEXT("TIME_WAIT"),
TEXT("DELETE_TCB")
};
int main(int argc,char *argv[])
{
// PCHAR name;
PCHAR processName;
processName = new char[50];
char* localaddr;
localaddr = new char[HOSTNAMELEN+10];
char* localname;
localname = new char[HOSTNAMELEN];
char remoteaddr[256];
char remotename[256];
if (GetVersion() >= 0x80000000)
{
printf("%s requres Windows NT/2K/XP./n/n",argv[0]);
return -1;
}
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return -1;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup( );
return -1;
}
BOOL exPresent = ExApisArePresent();
PMIB_TCPEXTABLE tcpExTable;
PMIB_UDPEXTABLE udpExTable;
BOOL error;
if (exPresent)
{
error = pAllocateAndGetTcpExTableFromStack(&tcpExTable,TRUE,GetProcessHeap(),2,2);
if (error)
{
printf("Failed to snapshot TCP endpoints./n");
//PrintError(error);
return -1;
}
error = pAllocateAndGetUdpExTableFromStack(&udpExTable,TRUE,GetProcessHeap(),2,2);
if (error)
{
printf("Failed to snapshot UDP endpoints./n");
//PrintError(error);
return -1;
}
HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnapshot == INVALID_HANDLE_VALUE )
{
printf("Failed to take process snapshot.Process names will not be shown./n/n");
}
for (DWORD i=0;i < udpExTable->dwNumEntries;i++)
{
sprintf(localaddr,"%s:%d",GetIpHostName(TRUE,udpExTable->table[i].dwLocalAddr,
localname,HOSTNAMELEN),htons((WORD)udpExTable->table[i].dwLocalPort));
printf("%-5s%s:%d/n","[UDP]",ProcessPidToName(hProcessSnapshot,udpExTable->table[i].dwProcessId,
processName),udpExTable->table[i].dwProcessId);
printf("Local: %s/n Remote: %s/n",localaddr,"*.*.*.*:*");
}
for ( i=0;i < tcpExTable->dwNumEntries;i++)
{
sprintf(localaddr,"%s:%d",GetIpHostName(TRUE,tcpExTable->table[i].dwLocalAddr,
localname,HOSTNAMELEN),htons((WORD)tcpExTable->table[i].dwLocalPort));
sprintf(remoteaddr,"%s:%d",GetIpHostName(FALSE,tcpExTable->table[i].dwRemoteAddr,
remotename,HOSTNAMELEN),tcpExTable->table[i].dwRemoteAddr?
htonl((DWORD)tcpExTable->table[i].dwRemotePort):0);
printf("%-5s %s:%d/n state: %-15s/n","[TCP]",ProcessPidToName(hProcessSnapshot,
tcpExTable->table[i].dwProcessId,processName),tcpExTable->table[i].dwProcessId,
TcpState[tcpExTable->table[i].dwState]);
printf(" LOCAL: %s/n Remote: %s/n",localaddr,remoteaddr);
}
}
return 0;
}