網路掃描技術網路分析技術
這兩本書異常的難懂。前一本還好有windows API介面說明
後一本直接講一個WINPCAP好像是一個框架,專門用來抓取資料包分析,不能阻塞通訊。
《一》TCP/IP協議程式設計
- Socket地址=(IP地址:埠號)
伺服器要想讓客戶端訪問自身,必須同時將二者公之於眾,缺一不可;否則客戶端將不知道該到哪臺主機或者某臺主機的埠訪問服務,即:
連線=(Socket地址1,Socket地址2)=(IP地址1:埠地址1,IP地址2:埠地址2)
1
2. 手工掃描
想掃描192.168.1.1~192.168.1.254這段IP中哪些主機是開的,則可以通過如下一個批處理來完成,系統會按順序依次不停地ping每一臺主機。
for /1 %%a in ( 1 1 254 ) do ( ping 192.168.1.%%a)
1
要檢測對方主機80埠是否提供WWW服務,只需要在命令列中輸入:
Talnet <對方IP地址> 80
如果失敗,會提示無法連線遠端主機
如果成功,則對方主機進入到等待客戶端輸入命令的狀態,這個時候可以隨便輸入一些字元,並連續回車,五六個回車後,對方就會返回如下內容:
HTTP/1.1 400 Bad Request
Server:Microsoft-IIS/5.1
Date:Sun, 19 Jun 2011 14:43:50 GMT
Connect-Type: test/html
Connect-Length: 87
測試21埠是否提供FTP服務,在命令列輸入:
Telnet <對方IP地址> 21
如果連線失敗,提示Telnet無法連線到遠端主機
如果連線成功,對方會顯示以下內容:
220-Micrsoft FTP Service
220 歡迎訪問LRM伺服器
3.埠和套接字
一個二元組(IP地址,埠地址)組成一個套接字,
一個五元組(本地IP,本地埠,使用協議,遠端IP,遠端埠)組成了一個通訊過程。
一個IPv4的基本資料結構主要有in_addr和socketaddr_in兩個,前者表示32位的地址,後者是通用的套介面地址結構,它們的結構如下:
struct in_addr
{
in_addr_t s_addr;
};
struct sockaddr_in
{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
1
2
3
4
5
6
7
8
9
10
11
12
地址表示順序
不同的系統在記憶體儲存多位元組資料的方式有所不同,而網路傳輸中,資料儲存順序不一定和系統儲存順序一樣,因此為保證系統正確性和可移植性,需要利用系統的轉換函式進行轉換。
以IPv4的地址為例,一個IP地址的四個位元組”192.168.1.100“,在PC架構的計算機中,資料的表示是低位優先,由前至後是100、1、168、192;而在網路Socket協議所表示的網路傳輸中,則是高位優先,由前至後是192.168.1.100,這需要在處理時通過函式轉化。
4.Windows Socket結構
sockaddr結構
在Socket的函式中,有幾個函式使用了socketaddr結構,該結構用於儲存一個IP地址,其結構如下:
struct sockaddr
{
unsigned short sa_family;
char sa_data[14];
};
1
2
3
4
5
結構成員如下:
sa_family:協議族,一般是AF_INET。
sa_data:資料,14是其最大長度。
sockaddr結構通常只是為了在各作業系統中保持相容使用,平時很少有人直接使用該結構格式,而是使用一個一直相容的sockaddr_in結構,其結構如下:
struct sockaddr_in
{
short sin_family;
unsigned short sin_port;
struct in_addr;
char sin_zero[8];
};
1
2
3
4
5
6
7
該結構表示一個TCP/IP通訊中,某個主機IP地址和埠的完整表示,其結構成員如下:
sin_family:協議族,一般是AF_INET。
sin_port:埠地址。需要注意的是該埠在記憶體中儲存格式是低位優先,因此在複製的時候,應該呼叫htons函式做一下轉換。
sin_addr:一個儲存IP的結構。
sin_zero:為了和sockaddr結構保持同樣的長度二補足8個位元組,一般情況下,使用者應該全部填成0.
其中真正儲存IP結構的sin_addr變數有事一個結構,該結構如下:
struct in_addr
{
union
{
sturct{
unsigned char s_b1,s_b2,s_b3,s_b4;
}S_un_b;
struct{
unsigned short s_w1,s_w2;
}S_un_w;
}S_un;
}
1
2
3
4
5
6
7
8
9
10
11
12
hostent結構
hostent結構的定義為:
struct hostent {
cahr FAR* h_name;
char FAR * FAR *h_aliases;
short h_addrtype;
short h_length;
cahr FAR * FAR *h_addr_list;
};
1
2
3
4
5
6
7
hostent結構用於儲存給定主機的資訊,例如主機名、IP地址等屬性。
結構成員如下:
h_name:主機名
h_aliases:主機的別名
h_addrtype:地址的型別
h_length:每個地址的長度,以位元組為單位
servent結構
struct servent{
char FAR* s_name;
char FAR *FAR s_aliases;
short s_port;
char FAR * s_proto’
};
1
2
3
4
5
6
servent結構用於儲存或返回給指定伺服器的名稱和伺服器數。
成員函式如下:
s_name:服務名
s_aliases:服務的別名
s_port:服務的埠。埠號以網路順序儲存
s_proto:協議的名稱
- Windows socket轉換類函式
htons函式
u_short htond(
u_short hostshort
);
1
2
3
htons函式將計算機儲存的USHORT格式轉換為網路儲存的USHORT格式。該函式名可以理解為:Host TO Net usigned Short。
返回值:返回一個網路順序的USHORT格式整數。
引數:hostshort,一個16位的以計算機儲存格式的USHORT整數。
ntohs函式
u_short ntohs(
u_short netshort
);
1
2
3
ntohs函式將網路儲存的USHORT格式轉換為計算機儲存的USHORT格式。該函式名可以理解為:Net TO Host unsigned Short。
返回值:返回一個網路順序的USHORT格式整數
引數:netshort,一個16位的以網路儲存格式的USHORT整數。
htonl函式
u_long htonl(
u_long hostlong
);
1
2
3
htonl函式將計算機儲存的ULONG格式轉換為網路儲存USHORT格式。該函式名可以理解為:Host TO Net unsigned Long。
返回值:返回一個網路順序的ULONG格式函式。
引數:hostlong,一個32位的以計算機儲存格式發的ULONG整數
ntohl函式
u_long ntoh1(
u_long netlong
);
1
2
3
ntohl函式將網路儲存的ULONG格式轉換為計算機儲存的ULING格式。該函式名可以理解為:Net TO Host unsigned Long
返回值:返回一個32位的以網路格式的ULONG整數
引數:netlong,一個32位的以網路儲存格式的ULONG整數。
inet_ntoa函式
char FAR * inet_ntoa(
struct in_addr in
);
1
2
3
inet_ntoa函式將由in_addr結構所表示的網路地址,轉換成由字串表示的IP地址,在本書中的掃描器,有大量的ip字串和ULONG之間的互換操作,由於該函式還要使用一個in_addr結構,所以比較麻煩,並且出錯時,不能正確指出出錯位置,因此本書中大部分的轉換採用的是自編的一個函式,詳細內容見“2.2.5節IP格式的互換”。
返回值:如果沒有錯誤,則返回一個字串型的IPv4地址串(形如“a.b.c.d”),否則返回NULL。
引數:in_addr,是一個in_addr型別的主機地址結構。該結構在本節前面內容中已詳細說明了。
inrt_addr
unsigned long innt_addr(
const char FAR *cp
};
1
2
3
inet_addr函式將字串組成的IP地址串轉換成一個ULNG的整數,該整數可用於in_sddr結構中,是按網路格式儲存的。在本書中的掃描器,有大量的IP字串和ULONG之間的互換操作,由於該函式還要使用一個in_addr結構,所以比較麻煩,並且出錯時,不能正確指出出錯位置。因此本書中大部分的轉換採用的是自編的一個函式,詳細內容見“2.2.5節IP格式的互換”。
返回值:如果沒有錯誤,則返回一個ULONG型整數,否則返回INADDR_NONE,此時例如IP字元好慘的某一項值大於255或為負值
引數:cp,字串指標,指向一個IP字串
gethostbyname函式
struct hostent FAR * gethostbyname(
const char FAR *name
);
1
2
3
gethostbyname函式根據主機名讀取主機資訊(主要是IP地址)。
返回值:如果呼叫成功,則返回一個指向hostent結構的指標,hostent結構的定義參見前面小節;否則返回NULL,可以通過呼叫WSAGetLastError獲得對錯誤資訊的進一步描述
引數:name:指向一個以NULL結尾的,表示主機名的字串。
gethostbyaddr函式
struct HOSTENT FAR * gethostbyaddr(
const char FAR *addr,
int len,
int type
);
1
2
3
4
5
gethostbyaddr函式通過網路地址讀取主機資訊。
返回值:如果呼叫成功,則返回一個指向hostent結構的指標;否則返回NULL。可以通過呼叫WSAGetLastError獲得對錯誤資訊的進一步描述。
引數:
addr:指向一個網路位元組順序的IP地址
len:地址的長度
type:協議型別,通常是AF_INET。
gethostname函式
int gethostname(
char FAR *name,
int namelen
);
1
2
3
4
gethostname函式讀取本地主機的主機名
返回值:如果呼叫成功,則返回
,否則返回SOCKET_ERROR,可以通過呼叫WSAGetLastError獲得對錯誤資訊的進一步描述。
引數:
name:指向一個一NULL結尾的,表示主機名的字串
namelen:name的長度,以位元組為單位
getservbyname函式
struct servent FAR *getservbyname(
int char FAR *name,
const char FAR *proto
);
1
2
3
4
getservbyname函式根據服務名和協議讀取服務資訊
返回值:如果呼叫成功,則返回servent結構,該結構的定義參見前面第七小節。
引數:
name:指向一個以NULL結尾的,表示服務名的字串
proto:指向一個以NULL結尾的協議字串,如果是NULL,則返回第一個服務
getservbyport函式
struct servent FAR *getservbyport(
int port,
const char FAR *proto
);
1
2
3
4
getservbyport函式根據埠和協議讀取服務資訊
返回值:如果呼叫成功,則返回servent結構,該結構的定義參見前面結構說明;否則返回NULL。
可以通過呼叫WSAGetLastError獲得對錯誤資訊的進一步描述,參見前面第七小節。
引數:
port:要查詢的埠值
proto:指向一個以NULL結尾的協議字串,如果是NULL,則返回第一個服務。
- Windows Socket通訊類函式
需要說明的是,這些函式至少時1.1版本,如果要是使用這些函式,需要在檔案前面包含標頭檔案,已經靜態連結庫
#include <Winsock2.h>
#program comment(lib,“Ws2_32.lib”)
1
2
WSAStartup函式
int WSASartup(
WORD wVersionRequested,
LPWSADATA IpWSAData
);
1
2
3
4
WSAStartup函式首先查詢當前作業系統是否支援所要求的版本號,完成對Windows Socket的初始化工作。要使用Socket2通訊,必須首先使用該函式,因此該函式應在邏輯上,處於Socket2所有函式的第一位
返回值:函式如果呼叫成功,則返回0;否則返回錯誤碼
此時由於Socket機制還沒有完全建立,所以還不能通過WSAGetLastError函式獲得錯誤的詳細資訊。只有該函式返回成功了,之後的操作才能使用WSAGetLastError函式。
引數:
wVersionRequrested:一個WORD型別的變數可以看成兩個由BYTE拼成,其中高位位元組表示要使用功能的最低副版本號(修訂版本號),低位位元組表示的是要使用功能的最低主版本號
IpWSAData:指向一個WSADATA結構的指標,該指標列出了當前Windows Sockets的各項實現細節。
WSACleanup函式
intWSACleanup (void)
1
WSACleanup函式完成與socket庫繫結的解除,並釋放socket庫所佔用的系統資源。
該函式應該作為某次socket操作的左後一個函式,否則之後任何socket操作都會導致出錯。
返回值:如果呼叫正確,返回0;佛足額會返回SOCKET_ERROR。可以通過WSAGetLastError函式讀取對錯誤資訊的進一步描述。
socket函式
SOCKET socket(
int af,
int type,
int protocol
);
1
2
3
4
5
socket函式建立一個sockert套接字,該函式相對簡單,但卻非常重要,因為這個函式是後面各種操作的基礎,還有一點必須提出的是,該協議中type欄位將直接決定後面所建立的的連線是面向連線的,還是面向非連線的,這將直接影響後續所有該ssocket的操作:
返回值:如果建立成功,則返回一個socket套接字;否則返回INVALID_SOCKET。可以通過WSAGetLastError函式獲得詳細錯誤資訊。
引數:
af:網路通訊協議族,一般情況下用AF_INET,表示IPv4協議
type:指定協議的採用連線型別,在Windows Docket1.1中只支援以下幾種:SOCK_STREAM, SOCK_DGRAM, SOCK_RAW,Winsows Socket 2 及以後,還支援多種型別,可以通過WSAEnumProtocils函式讀取
protocol:指定要用的協議。如果第二個引數type不是SOCK_RAW ,則此函式一般是0,表示採用預設協議。如果type是SOCK_RAW ,則此函式就可以指定相應的協議,比如IPPROTO_IP表示採用IP協議,IPPROTO_ICMP表示採用ICMP協議。
closesocket函式
int closesocket(
SOCKET s
);
1
2
3
closesocket關閉之前開啟的socket套接字,在進行關閉之前,一般要通過shutdown函式,通知對方自己要關閉套接字。
返回值:如果關閉成功,則返回0;否則返回SOCKET_ERROR。如果想知道詳細錯誤,可以呼叫WSAGetLasetError函式獲得進一步解釋
引數:
s:之前開啟的套接字
setsocketopt函式
int setsocketopt(
SOCKET s,
int level,
const optname,
const char FAR *optval,
int optlen
);
1
2
3
4
5
6
7
setsocketopt函式設定一個socket的引數選項。通常情況下,預設的選項就夠用,但掃描器本身的特點是,幾乎每一個程式都需要修改器預設的選項,所以該函式也是socket中的一個重要的函式,在呼叫順序上,如果setsocketopt函式在bind函式之前,則設定的項會在會直到bind函式時才有效。即使setsocketopt功能成功,bind函式也會因為setsocketopt函式過早呼叫而失敗。
與setsocketopt作用相反的一個函式是getsockopt,getsockopt函式的功能是讀取一個socket的引數選項,由於其函式引數項數和各項的意義與setsockopt一樣,所以此處不再重複。
返回值:如果呼叫成功,則返回0;否則返回SOCKET_ERROR。可以通過呼叫WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數:
s:由socket函式建立的socket套接字
level:設定選項所定義的級別,當前支援的級別主要有SOL_SOCKET,IPPROTO_TCP和IPPROTO_IP,分別對應於應用層、傳輸層、網路層的設定
optname:要設定的選項,這些選項引數一次只能設定一個,所以要同時設定兩個或兩個以上引數時,需多次重複呼叫setsockopt函式,並在每次呼叫時設定一個引數,如果連續重複設定同一個引數,則以最後一次的設定為有效設定。
optval:一個指向選項值的指標,集體的值由optname決定
aptlen:一個指向選項值長度的指標。
select函式
int select(
int nfds,
fd_set FAR *readfds,
fd_set FAR *writefds,
fd_set FAR *exceptfds,
const struct timeval FAR *timeout
);
1
2
3
4
5
6
7
socket函式的作用是監視阻塞狀態下埠的狀態,如當前是否有資料到達,從而進入讀埠的狀態,需要說明的是select函式在windows下和在linux下使用方法有一定差別,select函式最重要的作用是通過readfds引數判斷當前socket是否有資料到達,如果到達則轉入讀狀態,否則繼續空轉或處理其他事務。本書較少採用這一功能來判斷是否要資料到達,而是採用阻塞讀取,直至超時後退出阻塞的方式,考慮到本書只有少數地方是用到此函式,所以在此只是稍作介紹。
返回值:如果呼叫成功,則返回所監視的埠處於”準備”狀態的socket控制代碼個數,並且將這些控制代碼儲存在一個fd_set結構中,如果超時,則返回0,否則返回SOCKET_ERROR,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
bind函式
int bind(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
1
2
3
4
5
bind函式可以將一個本地地址昱socket套接字進行繫結。一旦繫結成功,則此後該socket操作將與該地址有關。該函式既可用於面向物件的TVP通訊,也可以用於面向非連線的UDP通訊中。
返回值:如果呼叫成功,則返回0,否則返回SOCKET_ERROR,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:由socket函式建立的socket套接字
name:分配給該socket套接字的一個地址SOCKADDR結構
namelen:SOCKADDR結構的長度
listen函式
int listen(
SOCKET S,
int backlog
);
1
2
3
4
listen函式使用socket狀態監聽狀態,並等待其他socket的連線。該函式僅用於面向連線的TCP通訊中,UDP通訊是不需要listen函式的
返回值:如果呼叫成功,則返回0,否則返回SOCKET_ERROR,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:指向一個由socket的函式建立的socket套接字
backlog:能連線的最大客戶端數。如果設定成SOMAXCONN,則服務提供者儘可能地建立最大的值
accept函式
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
1
2
3
4
5
函式允許和接收一個遠端的連線,該函式僅用於面向連線的TCP通訊中,並且只用於伺服器端,用於接收客戶端通過connect函式發來的連線申請;面向非連線的UDP通訊是不需要處理此函式的
呼叫成功後,該函式將會處於阻塞狀態,直到有遠端的連線,才會返回,從外表上看程式很像是死掉了,因此除非程式本身沒有要求,否則一般建議將此函式放入執行緒中使用,以避免整個函式像“僵死”一樣。
該函式看似簡單,其實比較複雜,也是多執行緒處理效果的關鍵,首先呼叫此函式之前程式已成功地呼叫了listen函式,然後再呼叫該函式時,如果呼叫成功,則返回一個新的socket,所以如果後面服務端的處理很簡單,可以在當前執行緒中用這個新建立的,進行處理,俗稱“短連線”;如果處理很複雜,並且仍在當前執行緒中處理,則會影響到accept函式對其他執行緒通過connect進行連線,此時就需要再建立一個執行緒,有新建的執行緒,並使用返回的一個socket專門處理此次連線後的各項操作,俗稱“長連線”。
返回值:如果呼叫成功,則返回接收遠端通過connect連線後,新建立的一個socket,否則返回INVALID_SOCKET,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
需要說明的是,新建立的語言有的具有相同的屬性,因此不必再初始化。
引數:
s:指向一個有socket函式建立的socket套接字
addr:連線一個socketaddr結構的指標,改制真中儲存著遠端socket的一些資訊。如果該值置成NULL,則表示使用者對誰建立的連線並不感興趣,而只處理內容,其中的socketaddr結構詳見前面內容。
addrlen:sockadddr結構的長度,呼叫之後,函式會返回實際需要的長度,如果該值置成NULL,則表示使用者對誰建立的連線並不感興趣,而只處理內容。
connect函式
int connect(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
1
2
3
4
5
connect函式與客戶端的身份與遠端主機建立連線。在掃描器的應用中,connect是一種簡單而有效的連線方式,連線成功,則可以認為對方的埠是開啟的,該函式僅用於面向連線的TCP通訊中,並且只用於伺服器端,用來接收客戶端通過connect函式發來的連線請求,面向非連線的UDP通常是不需要處理引數的。
返回值:如果呼叫成功,則返回0,否則返回INVALID_SOCKET,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:指向一個有socket函式建立的socket套接字
name:指向一個sockaddr的結構指標,該結構中儲存了要連線的遠端主機的IP地址和埠地址,其中一個sockaddr結構詳見前面內容
addrlen:sockadddr結構的長度,呼叫之後,函式會返回實際需要的長度,如果該值置成NULL,則表示使用者對誰建立的連線並不感興趣,而只處理內容。
send函式
int send(
SOCKET s,
const cahr FAR *buf,
int len,
int flags
);
1
2
3
4
5
6
7
send函式傳送資料到已建立連線的socket上,該函式即可以用於伺服器,也可以用於客戶端,但雙方都必須是採用TCP連線
返回值:如果呼叫成功,則返回0,否則返回INVALID_SOCKET,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:指向一個有socket函式建立的socket套接字
buff:指向一個傳送緩衝區的指標
len:buff緩衝區的長度,以位元組為單位
flags:傳送的方法,一般置0
recv函式
int recv(
SOCKET s,
char FAR *buf,
int len,.
int flags
);
1
2
3
4
5
6
recv函式用於接收從已建立連線的socket上的資料,該函式即可以用於伺服器,也可以用於客戶端,但雙方都必須是採用TCP連線.
返回值:如果呼叫成功,則返回0,否則返回INVALID_SOCKET,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
shutdown函式
int shutdown(
SOCKET s,
int how
);
1
2
3
4
shutdown函式禁止當前的傳送或接收。對該函式關注的不多,所以可以看到很多程式在關閉的時候在收發完成後,直接就呼叫函數了,這樣做有的時候會使對方仍處於連線中,而己方已斷開。
返回值:如果呼叫成功,則返回0,否則返回INVALID_SOCKET,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:要停止傳送或接受的socket
how:要關閉的型別,其中how的取值可以是:SD_RECEIVE,SD_SEND,SD_BOTH
sendto函式
int sendto(
SOCKET s,
const char FAR *buf,
int len,
int flags,
xonst struct sockaddr FAR *to,
int tolen
);
1
2
3
4
5
6
7
8
sendto函式傳送資料報道遠端的主機指定的埠上。該函式只能用於面向非連線的通訊中。
返回值:如果呼叫成功,則返回0,否則返回INVALID_SOCKET,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:指向一個有socket函式建立的socket套接字
buff:指向一個傳送緩衝區的指標
len:buff緩衝區的長度,以位元組為單位
flags:傳送的方法,一般置0
to:要傳送的目標主機IP和埠,該指標指向一個sockaddr結構,該結構詳見前面內容。
recvfrom函式
int recvfrom(
SOCKET s,
char FAR *buf,
int len,
int flags,
struct sockaddr FAR *from,
int FAR *fromlen
);
1
2
3
4
5
6
7
8
recvfrom函式接收遠端發過來的資料報。該函式只能用於面向連線的通訊中。
返回值:如果呼叫成功,則返回實際接收的位元組數;否則返回SOCKET_ERROR,可以通過WSAGetLastError函式獲得對錯誤資訊的進一步解釋。
引數如下:
s:指向一個有socket函式建立的socket套接字
buff:指向一個傳送緩衝區的指標
len:buff緩衝區的長度,以位元組為單位
flags:傳送的方法,一般置0
from:向本身傳送資料包的源主機IP和埠,該指標指向一個socketaddr結構,該結構的詳細說明在前面結構說明中。
fromlen:sockaddr結構的長度。
7.原始套接字
上述函式介紹中提到一個原始套接字(Raw Socket),如果不使用原始套接字,則無論是傳送和接收,系統都會自動處理IP包頭,TCP/UDP包頭的資料,這時使用者最需要關心傳送和接收的資料本身即可,這種自動處理雖然方便,但也是系統失去了靈活性。而當使用原始套接字時,如果傳送資料系統會將要傳送的資料包的前面若干位元組資料IP頭、TCP/UDP頭;如果接收資料,系統會將接收到的資料包前面加上資料IP頭、TCP/UDP頭。
在所有掃描例項中,絕大多數都是掃描器主動發起探測,但也有少部分掃描器是坐等接收資訊,然後對被動接收的資料進行分析,從而得出結論,而這些應用在後面會廣泛使用,故在這些專門列出。
該功能只能用於Windows 2000/XP以及以後的版本中,在Windows 95/98/Me/NT中無法使用,如果確實要使用,只能使用鉤子(hook)技術,直接從網絡卡驅動程式中進行擷取。
- 原始套接字的傳送
原始套接字的傳送很簡單,但實際編寫卻很麻煩,這主要是因為需自己填寫IP頭和TCP頭的資料內容,並分別計算IP頭和TCP頭的校驗和。由於不再使用Socket提供的IP和TCP頭,所以需要通過setsocketopt函式告訴系統使用自己定義的IP和TCP頭,並且雖然所填的是面向連線的TCP頭,仍然要使用UDP所專用得sendto函式,而不是使用send函式。
原始套接字的接收
原始套接字的接收相對複雜,步驟較多,但通常情況下,只要按圖所示的步驟操作即可,每一個步驟只有一兩行語句,不像“原始套接字的傳送”中的填充IP頭和TCP頭那樣需要很多行,其中的WSAIoctl函式的SIO_CVALL引數表示接收經過本機網絡卡的所有資料包。
二、網路分析技術
.
Winpcap提供了一個強大的程式設計介面,它很容易地在各個作業系統之間進行移植,也很方便程式設計師進行開發。
什麼樣的程式需要使用Winpcap
很多不同的工具軟體使用Winpcap於網路分析,故障排除,網路安全監控等方面。Winpcap特別適用於下面這幾個經典領域:
1、網路及協議分析
2、網路監控
3、通訊日誌記錄
4、traffic generators
5、使用者級別的橋路和路由
6、網路入侵檢測系統(NIDS)
7、網路掃描
8、安全工具
Winpcap有些方面不能做。它不依靠主機的諸如TCP/IP協議去收發資料包。這意味著它不能阻塞,不能處理同一臺主機中各程式之間的通訊資料。它只能“嗅探”到物理線路上的資料包。因此它不適用於traffic shapers,QoS排程,以及個人防火牆。
Winpcap內部結構
Winpcap是一個Win32平臺下用於抓包和分析的系統。包括一個核心級別的packet filter,一個底層的DLL(packet.dll)和一個高階的獨立於系統的DLL(Wpcap.dll) [1]