基於socket原始套接字的網路嗅探器

2021-07-08 10:24:45 字數 3685 閱讀 3319

// netsniffer.cpp : 定義控制台應用程式的入口點。

///*

簡單說明一下什麼是網路嗅探器,網路嗅探器是乙個抓取所有經過網絡卡資料的軟體,在一般使用電腦時,網絡卡

只接受到傳送至本機的資料,那是因為這是網絡卡是非混雜模式的,擋乙個目的位址非本機位址的資料報經過網

卡時,網絡卡在資料鏈路層(mac位址)檢測到是非本機資料,則直接丟棄,當設定為混雜模式時,所有經過網絡卡

的資料報均可被讀取出來。

*/#include "stdafx.h"

#include #include #include #include "datastruct.h"

#include "procdata.h"

#pragma comment(lib, "ws2_32.lib")

#define buf 256

#define recvbuf 1500

int _tmain(int argc, _tchar* argv)

socket sock = invalid_socket;

// 理論上在socket 第三個引數設定為制定協議型別(如0x0800或0x0806或多個等等),則可以獲取

// 資料鏈路層的資料,即包括了乙太網幀的首部在資料部分,但window 封閉了這一層,所以獲取

// 資料只能去到ip層。若想獲取乙太網幀可以使用winpcap 開發庫,linux下是libpcap。(注意:

// linux下可用socket套接字獲取資料鏈路層)

if ((sock = socket(af_inet, sock_raw, /*htons(0x0800)*/ipproto_ip)) == invalid_socket)

// hostent 結構體包含了所有能抓取到的網絡卡對應的位址

struct sockaddr_in addr;

char hostname[buf] = ;

int namelen = gethostname(hostname, buf);

struct hostent *phost = gethostbyname(hostname);

if (phost != null)

printf("please chose a device for sniffer:");

int index;

reenter:

scanf("%d", &index);

if (index < 0 || index >= i)

goto reenter;

paddr = *(phost->h_addr_list + index);

memcpy(&(addr.sin_addr), paddr, phost->h_length);

} else

if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == socket_error)

// 設定網絡卡為混雜模式

unsigned long flag = 1;

if (ioctlsocket(sock, sio_rcvall, &flag) != 0)

char recvbuf[recvbuf];

size_t size = 0;

pip_header pip;

int count = 0;

while (1)

continue;

} count++;

//printf("[%0.4d]\t", count);

pip = (pip_header)recvbuf;

switch (pip->proto)

; memset(recvbuf, 0, sizeof(recvbuf));

} return 0;

}

datastruct.h

#ifndef _datastruct_h_

#define _datastruct_h_

typedef struct mac_header

mac_header, *pmac_header;

#pragma pack(push, 1)

typedef struct ip_header

ip_header, *pip_header;

typedef struct udp_header

udp_header, *pudp_header;

typedef struct tcp_header

tcp_header, *ptcp_header;

typedef struct iph_pack

iph_pack;

#pragma pack(pop)

#endif

procdata.h

#ifndef _procdata_h

#define _procdata_h

#define _winsock_deprecated_no_warnings

#define _crt_secure_no_warnings

#include "datastruct.h"

#include #include #include #include #include struct iph_pack procipheader(char *ipdata);

// udp,tcp,icmp 和 http,ftp... 均是被封裝在ip資料報中

void procu***ack(char *ipdata);

void proctcppack(char *ipdata);

void procicmppack(char *ipdata);

void procigmppack(char *ipdata);

#endif

procdata.cpp

#include "procdata.h"

// 處理ip首部

struct iph_pack procipheader(char *ipdata)

void procu***ack(char *ipdata)

printf("%-6s\t", buf);

addr1.s_addr = hpack.souraddr;

addr2.s_addr = hpack.destaddr;

printf("%-15s:%5d -> ",

inet_ntoa(addr1), ntohs(uh->sourport)

);printf("%-15s:%5d\n", inet_ntoa(addr2), ntohs(uh->destport));

}void proctcppack(char *ipdata)

printf("%-6s\t", buf);

addr1.s_addr = hpack.souraddr;

addr2.s_addr = hpack.destaddr;

printf("%-15s:%5d -> ",

inet_ntoa(addr1), ntohs(th->sourport)

);printf("%-15s:%5d\n", inet_ntoa(addr2), ntohs(th->destport));

}void procicmppack(char *ipdata)

原始套接字

資料出處 實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需...

原始套接字

參考1 原始套接字能幹什麼?參考2 原始套接字抓包實踐 參考3 各層頭結構 通過原始套接字,我們可以抓取所有傳送到本機的ip包 包括ip頭和tcp udp icmp包頭 也可以抓取所有本機收到的幀 包括資料鏈路層協議頭 普通的套接字無法處理icmp igmp等網路報文,而sock raw可以。利用原...

原始套接字

利用原始套接字實現乙個tcp syn flooding 程式 要求 客戶端不斷向攻擊端傳送syn連線請求 客戶端在傳送資料時,通過源位址隨機位址的方式隱藏自己的 位址 檢驗 在shell下通過 netstat tn 檢查syn recv連線數檢驗自己的程式是否成功 好像有點問題。不能偽造mac位址。...