/* 簡易 Sniffer - 畢業專題範例 */
#include
#include
#include "..\\..\\Include\\packet32.h"
#include "..\\..\\Include\\ntddndis.h"
#define MAX_ADAPTER 10
void PrintPackets(LPPACKET lpPacket); // 自訂封包解析列印
char AdapterList[MAX_ADAPTER][1024];
int main() {
LPADAPTER lpAdapter = 0;
LPPACKET lpPacket;
int i, Open, AdapterNum = 0;
DWORD dwErrorCode, dwVersion, dwWinMajorVer;
ULONG AdapterLength = 4096;
char buffer[256000];
struct bpf_stat stat;
// 版本資訊
printf("Packet.dll version: %s\n", PacketGetVersion());
printf("Adapters installed:\n");
// 取得作業系統版本區分 Unicode/ANSI
dwVersion = GetVersion();
dwWinMajorVer = (DWORD)(LOBYTE(LOWORD(dwVersion)));
// 列舉網卡
if (!(dwVersion >= 0x80000000 && dwWinMajorVer >= 4)) { // Windows NT 系列
WCHAR AdapterName[8192], *temp, *temp1;
if (!PacketGetAdapterNames(AdapterName, &AdapterLength)) {
printf("Unable to retrieve adapter list!\n"); return -1;
}
temp = temp1 = AdapterName;
while ((*temp != L'\0') || (*(temp-1) != L'\0')) {
if (*temp == L'\0') {
memcpy(AdapterList[AdapterNum], temp1, (temp-temp1)*2);
temp1 = temp + 1;
AdapterNum++;
}
temp++;
}
for (i=0; i AdapterNum) printf("Number must be <= %d\n", AdapterNum);
} while (Open > AdapterNum);
// 開啟介面
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
if (!lpAdapter || lpAdapter->hFile == INVALID_HANDLE_VALUE) {
dwErrorCode = GetLastError();
printf("Open adapter failed, Error: %lx\n", dwErrorCode); return -1;
}
// 設定混雜模式
if (!PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS))
printf("Warning: cannot set promiscuous mode!\n");
// 設定 512KB 核心緩衝
if (!PacketSetBuff(lpAdapter, 512000)) {
printf("Cannot set kernel buffer!\n"); return -1;
}
// 設定 1 秒讀取逾時
if (!PacketSetReadTimeout(lpAdapter, 1000))
printf("Warning: cannot set read timeout!\n");
// 分配封包結構
if ((lpPacket = PacketAllocatePacket()) == NULL) {
printf("Failed to allocate LPPACKET\n"); return -1;
}
PacketInitPacket(lpPacket, buffer, 256000);
// 主擷取迴圈
while (!kbhit()) {
if (!PacketReceivePacket(lpAdapter, lpPacket, TRUE)) {
printf("PacketReceivePacket failed\n"); break;
}
PrintPackets(lpPacket); // 解析並列印
}
// 統計
if (PacketGetStats(lpAdapter, &stat))
printf("\n\n%d packets received.\n%d packets dropped\n", stat.bs_recv, stat.bs_drop);
else
printf("Warning: cannot get stats!\n");
// 清理
PacketFreePacket(lpPacket);
PacketCloseAdapter(lpAdapter);
return 0;
}
| 函數 | 用途 | 關鍵參數 |
|---|---|---|
PacketGetAdapterNames | 列舉網卡名稱 | 緩衝區、長度指標 |
PacketOpenAdapter | 開啟介面 | 介面名稱 |
PacketSetHwFilter | 硬體過濾器 | NDIS_PACKET_TYPE_PROMISCUOUS 等 |
PacketSetBuff | 核心緩衝區大小 | 位元組數 (建議 512KB+) |
PacketSetReadTimeout | 讀取逾時 | 毫秒 (0=無限等待) |
PacketAllocatePacket | 分配封包結構 | 無 |
PacketInitPacket | 綁定使用者緩衝區 | 封包結構、緩衝區、長度 |
PacketReceivePacket | 同步擷取封包 | 介面、封包結構、TRUE |
PacketGetStats | 取得統計 (收到/丟棄) | 介面、bpf_stat 結構 |
PacketFreePacket | 釋放封包結構 | 封包結構 |
PacketCloseAdapter | 關閉介面 | 介面 |
NDIS_PACKET_TYPE_PROMISCUOUS:混雜模式 (全部封包)NDIS_PACKET_TYPE_DIRECTED:導向本機NDIS_PACKET_TYPE_BROADCAST:廣播NDIS_PACKET_TYPE_MULTICAST:多播NDIS_PACKET_TYPE_ALL_MULTICAST:所有多播pcap_loop, pcap_next_ex, pcap_compile/pcap_setfilter (BPF 過濾)。封包擷取涉及網路隱私與資安法規,僅限於自有網路環境、授權滲透測試、教學研究用途。未經授權監聽他人流量可能違法。