Chủ đề: Kiến thức cơ bản về Winpcap
-
30-07-2012, 09:02 AM #1Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Kiến thức cơ bản về Winpcap
Tut viết từ năm ngoái, nên có nhiều sai xót, văn vẻ lủng củng, mọi người thông cảm và giúp mình bổ sung.
Giới thiệu Winpcap
WinPcap là gì ?
WinPcap là thư viện mã nguồn mở được sử dụng để bắt các gói dữ liệu và phân tích mạng cho nền tảng Win32.
• Thu thập những gói dữ liuệ thô, 1 là ngay trên chính máy đang chạy truyền dữ liệu đi và 1 là sự trao đổi bởi những máy khác trên môi trường chia sẻ.
• Lọc gói dữ liệu theo những luật của người dùng khi chúng được truyền tới ứng dụng.
• Tuyền những gói dữ liệu thô tới mạng.
• Thu thập thông tin thống kê lưu lượng mạng.
Những khả năng này co được thông qua trình điều khiển thiết bị đã được cài đặt bên trong phần Network của nhân Win32 cùng với 2 DLL.
Những loại chương trình sử dụng WinPcap
Giao diện lập trình WinPcap được sử dụng bởi nhiều tiện ích mạng như phân tích, xử lý sự cố, bảo mật , theo dõi. Cụ thể :
• Trình phân tích mạng và giao thức.
• Giám sát mạng.
• Theo dõi băng thông.
• Traffic generator.
• user-level bridges and routers.
• Hệ thống phát hiện xâm nhập mạng NIDS
• Network scanner.
• Công cụ bảo mật.
Cài đặt và sử dụng WinPcap
Tạo ứng dụng sử dụng thư viện wpcap.dll trong VC++
Include pcap.h.
Include thư mục chứa các thành phần cần Inlcude thêm :
Inlcude thư mục chứa các thư viện cần thêm :
Nếu chương trình sử dụng những hàm Win32 trong Winpcap , thì include WPCAP trong khai báo tiền xử lý :
Nếu chương trình sử dụng khả năng remote capture của Winpcap, thì include HAVE_REMOTE trong khai báo tiền xử lý tương tự như ảnh trên. Không include trực tiếp remote-ext.h.
Liên kết tới file wpcap.lib trong \lib nếu ứng dụng dành tro x86 hoặc \lib\x64 nếu ứng dụng dành cho x64 ; và file ws2_32.lib.
View more random threads:
- Inject Code Cave
- Hướng dẫn viết một chương trình Sniffer
- Tutorial - Tạo một chương trình MFC đơn giản trong VC++ 2008 bằng hình ảnh
- Cài đặt Blocking Queue với C++11
- Tìm hiểu về thư viện liên kết động trên Win32 API
- Hiểu COM là gì?
- Tìm hiểu về âm thanh và âm nhạc trong lập trình C ( Win32API)
- Công Ty Sửa Vi Tính Tận Nơi quận mười Chất Lượng
- Hướng dẫn khắc phục lỗi không tìm thấy MSVCR80D.dll
- hồn trương ba, da hàng thịt
-
30-07-2012, 09:07 AM #2Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Liệt kê các device
Thường thì việc đầu tiền của các ứng dụng sử dụng Winpcap là liệt kê các network adapter. Cả libpcap và Winpcap đều cung cấp hàm pcap_findalldevs_ex cho mục đích này , nó trả lại 1 danh sách liên kết của cấu trúc pcap_if .
Ví dụ :
File Stdafx.h :
Mã:#pragma once #include "targetver.h" #include <stdio.h>#include <tchar.h>#include <pcap.h>#include <WinSock2.h>
Mã:// TestWinpcap.cpp : Defines the entry point for the console application.// #include "stdafx.h" #define IPTOSBUFFERS 12 WCHAR * Address2String(SOCKADDR * Sockaddr){ WCHAR wcAddr[256]; DWORD dwSize = sizeof(wcAddr); if (WSAAddressToString(Sockaddr,sizeof(SOCKADDR_STORAGE /*Sử dụng cho cả IPv6 và IPv4*/),NULL,wcAddr,&dwSize) == 0) { return wcAddr; } return L"";} int _tmain(int argc, _TCHAR* argv[]){ WSADATA wsaData; // Khởi động Winsock2 if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) { printf("WSAStartup(0 loi, ma %d",WSAGetLastError()); return -1; } pcap_if_t *LinkedListDevices; // danh sách liên kết của cấu trúc // pcap_addr_t chứa thông tin network adapters char ErrorBuffer[PCAP_ERRBUF_SIZE + 1]; // Buffer nhận nguyên nhân lỗi // Tìm các network adapters if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL , &LinkedListDevices , ErrorBuffer) != 0 ) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_findalldevs_ex() loi, ma %d",ErrorBuffer); goto Exit; } pcap_if_t *Temp; int index = 0; pcap_addr_t *Addr; for (Temp = LinkedListDevices ; Temp != NULL ; Temp = Temp->next) { // in tên và mô tả của network adapters printf("%i Name : %s Description : %s ",++index,Temp->name,Temp->description); // có phải địa chỉ loopback hay không ? printf("\tLoopback : %s ",Temp->flags & PCAP_IF_LOOPBACK ? "Yes" : "No"); for (Addr = Temp->addresses ; Addr != NULL ; Addr = Addr->next) { if (Addr->addr) { printf("\tAddress: %S ",Address2String(Addr->addr)); } if (Addr->broadaddr) { printf("\tbroadaddr :%S ",Address2String(Addr->broadaddr)); } if (Addr->dstaddr) { printf("\tdstaddr : %S ",Address2String(Addr->dstaddr)); } if (Addr->netmask) { printf("\tnetmask : %S ",Address2String(Addr->netmask)); } } } Exit: // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết pcap_freealldevs(LinkedListDevices); system("pause"); return 0;}
Mở 1 adapter và capture packet
Để mở 1 capture device ta sử dụng hàm pcap_open().
Hàm pcap_open() có 1 vài tham số đáng chú ý :
• snaplen : Chỉ định phần packet được capture. Trên 1 vài OS ( như xBSD và Win32 ) , trình điều khiển packet có thể được cấu hình để capture chỉ phần đầu của packet, điều này làm giảm lượng dữ liệu capture được. Do đó , để tăng hiệu quả , chúng ta sử dụng giá trị 65536, giá trị này lớn hơn cả giá trị lớn nhất của MTU. Theo cách này , chúng ta đảm bảo rằng ứng dụng luôn capture được toàn bộ packet.
• flags : Cờ quan trọng nhất là cờ chỉ định adapter sẽ trong chế độ không phân biệt ( promiscuous mode ). Thường thì adapter chỉ capture các packet đi tới nó, các packet trao đổi qua lại giữa các host sẽ bị bỏ qua. Vì vậy, khi adapter trong chế độ không phân biệt, nó sẽ capture mọi packet cho dù packet đó đi tới nó hoặc không. Điều này có nghĩa , trên môi trường được chia sẻ, ( như non-switched Ethernet) , Winpcap có thể capture các packet của các host khác. Chế độ không phân biệt là mặc định cho hầu hết các ứng dụng capture, nên chúng ta sử dụng chế độ này trong ví dụ.
• to_ms : Thời gian timeout của hàm đọc( ms ). Hàm đọc trên 1 adapter ( ví dụ , hàm pcap_dispatch() hoặc pcap_next_ex()) sẽ luôn return sau khoảng thời gian timeout , ngay cả khi không capture được packet nào. Tham số to_ms cũng khai báo khoảng thời gian giữa các báo cáo thống kê nếu adapter trong chế độ thống kê ( statistical mode ). to_ms = 0 nghĩa là không có thời gian timeout, hàm đọc sẽ không return nếu không capture được packet nào. to_ms = -1 nghĩa là hàm đọc sẽ return ngay lập tức.
Một khi adapter đã được mở , để capture sử dụng hàm pcap_dispatch() hoặc pcap_loop(). Hai hàm này khá giống nhau, hàm pcap_dispatch() return ( mặc dù không đảm bảo ) khi thời gian timeout hết hạn, trong khi hàm pcap_loop() không return cho tới khi capture được cnt ( tham số số lượng ) packet.
Cả 2 hàm đều có 1 tham số CALLBACK , packet_handle , trỏ tới 1 hàm sẽ nhận các packet. Hàm này được kích hoạt bởi libpcap khi có 1 packet đến từ mạng và nhận 1 trạng thái chung ( generic status ) ( tương ứng với tham số user của hàm pcap_loop() hoặc pcap_dispatch() ) , 1 header với 1 vài thông tin trên packet như timestamp , độ dài và dữ liệu thực sự của packet bao gồm tất cả các header giao thức.
Chú ý rằng frame CRC thường không xuất hiện, vì nó bị xóa bởi network adapter sau sự xác nhận frame. Cũng chú ý rằng, hầu hết các adapter bỏ packet với CRC sai, do đó Winpcap thường không thể capture đc chúng.
Ví dụ sau , triết xuất timestamp và độ dài của mỗi packet để in lên màn hình.
Có 1 nhược điểm khi sử dụng hàm pcap_loop() , là hàm handler được gọi bởi pạket capture driver, nên ta không thể điều khiển trực tiếp chúng. Có 1 cách tiếp cận khác là sử dụng hàm pcap_next_ex() , sẽ có ở chương sau.
Ví dụ :
File Stdafx.h :
Mã:#pragma once #include "targetver.h" #include <stdio.h>#include <tchar.h>#include <pcap.h>#include <WinSock2.h>
Mã:File TestWinpcap.cpp :// TestWinpcap.cpp : Defines the entry point for the console application.// #include "stdafx.h"int index = 0;WCHAR * Address2String(SOCKADDR * Sockaddr){ WCHAR wcAddr[256]; DWORD dwSize = sizeof(wcAddr); if (WSAAddressToString(Sockaddr,sizeof(SOCKADDR_STORAGE /*Sử dụng cho cả IPv6 và IPv4*/),NULL,wcAddr,&dwSize) == 0) { return wcAddr; } return L"";} void PrintAdapters(pcap_if_t * LinkedListDevices){ pcap_if_t *Temp; index = 0; pcap_addr_t *Addr; for (Temp = LinkedListDevices ; Temp != NULL ; Temp = Temp->next) { // in tên và mô tả của network adapters printf("%i Name : %s Description : %s ",++index,Temp->name,Temp->description); // có phải địa chỉ loopback hay không ? printf("\tLoopback : %s ",Temp->flags & PCAP_IF_LOOPBACK ? "Yes" : "No"); for (Addr = Temp->addresses ; Addr != NULL ; Addr = Addr->next) { if (Addr->addr) { printf("\tAddress: %S ",Address2String(Addr->addr)); } if (Addr->broadaddr) { printf("\tbroadaddr :%S ",Address2String(Addr->broadaddr)); } if (Addr->dstaddr) { printf("\tdstaddr : %S ",Address2String(Addr->dstaddr)); } if (Addr->netmask) { printf("\tnetmask : %S ",Address2String(Addr->netmask)); } } }} void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data){ struct tm ltime; char timestr[16]; time_t local_tv_sec; /* * unused variables */ (VOID)(param); (VOID)(pkt_data); /* convert the timestamp to readable format */ local_tv_sec = header->ts.tv_sec; localtime_s(<ime, &local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); printf("%s,%.6d len:%d ", timestr, header->ts.tv_usec, header->len); } int _tmain(int argc, _TCHAR* argv[]){ WSADATA wsaData; // Khởi động Winsock2 if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) { printf("WSAStartup(0 loi, ma %d",WSAGetLastError()); return -1; } pcap_if_t *LinkedListDevices; // danh sách liên kết của cấu trúc // pcap_addr_t chứa thông tin network adapters char ErrorBuffer[PCAP_ERRBUF_SIZE + 1]; // Buffer nhận nguyên nhân lỗi // Tìm các network adapters if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL , &LinkedListDevices , ErrorBuffer) != 0 ) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_findalldevs_ex() loi, ma %s",ErrorBuffer); goto Exit; } // Gọi hàm hiển thị các adapter PrintAdapters(LinkedListDevices); // Chọn adapter để capture printf("Chon adapter tu 1 - %i",index); int SelectedIndex; scanf_s("%d",&SelectedIndex); if (SelectedIndex < 1 || SelectedIndex > index) { printf("So hieu adapter da chon khong co "); goto Exit; } pcap_if_t * Temp; // Chuyển con trỏ trỏ tới adapter đã chọn for (Temp = LinkedListDevices , index = 0 ; index < SelectedIndex -1 ; index ++ , Temp = Temp->next); // gọi pcap_open() để mở adapter // Tham số 1 : Tên adapter kiểu char*. // Tham số 2 : Độ dài packet có thể capture , chọn 65536 để đảm bảo capture đc toàn bộ packet. // Tham sô 3 : Cờ áp đặt chế độ cho adapter để capture. // PCAP_OPENFLAG_PROMISCUOUS : Chế độ không phân biệt , sẽ capture mọi packet // mà adadpter trao đổi giữa network hoặc host khác. // Tham số 4 : Thời gian đọc timeout. // Tham số 5 : Buffer nhận lỗi nếu có. pcap_t *Handle = pcap_open(Temp->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,ErrorBuffer); if (Handle == NULL) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_open() loi , ma %s ",ErrorBuffer); goto Exit; } printf("Dang capture tren adapter : %s ",Temp->description); // Bắt đầu capture packet trên adapter đã chọn. // Tham số 1 là handle trả lại từ hàm pcap_open(). // Tham số 2 là số lượng packet cần capture, sau khi capture đc lượng // packet này, hàm sẽ return // Tham số 3 là con trỏ tới hàm CALLBACK nhận packet đến. // pcap_loop(Handle, 5, packet_handler, NULL); Exit: // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết pcap_freealldevs(LinkedListDevices); system("pause"); return 0;}
-
30-07-2012, 09:13 AM #3Silver member
- Ngày tham gia
- Sep 2015
- Đang ở
- Hà Nội
- Bài viết
- 0
Capture packet không sử dụng hàm CALLBACK
Ở chương trước, cơ chế capture packet dựa trên hàm pcap_loop() có thể là lựa chọn tốt cho vài trường hợp. Nhưng điều khiển 1 hàm CALLBACK sẽ khiến chương trình phức tạp hơn và đôi khi không thực tế , đặc biệt trong trường hợp ứng dụng multithread hoặc C++ class.
Trong trường hợp này, pcap_next_ex() nhận packet 1 cách trực tiếp - sử dụng pcap_next_ex() có lợi thế là nó sẽ nhận packet chỉ khi ta muốn.
Tham số của hàm cũng tương tự như hàm CALLBACK, nó nhận 1 tham số là miêu tả của adapter và 2 con trỏ được khởi tạo và return ( 1 là trỏ tới cấu trúc pcap_pkthdr , 1 là trỏ tới buffer nhận data của packet ).
Tại sao không sử dụng pcap_next() ? Vì hàm này có 1 vài nhược điểm. Đầu tiền là nó không hiệu quả, nó ẩn phương pháp CALLBACK, nhưng vẫn dựa trên hàm pcap_dispatch(). Thứ 2 là nó không thể phát hiện EOF, vậy nếu nó ko hữu dụng khi capture các packet từ 1 file.
Lưu ý, hàm pcap_next_ex() trả lại các giá trị khác nhau khi thành công, hay khi hết timeout , hay khi lỗi và khi có điều kiện EOF.
Ví dụ :
File Stdafx.h :
Mã:#pragma once #include "targetver.h" #include <stdio.h>#include <tchar.h>#include <pcap.h>#include <WinSock2.h>
Mã:// TestWinpcap.cpp : Defines the entry point for the console application.// #include "stdafx.h"int index = 0;WCHAR * Address2String(SOCKADDR * Sockaddr){ WCHAR wcAddr[256]; DWORD dwSize = sizeof(wcAddr); if (WSAAddressToString(Sockaddr,sizeof(SOCKADDR_STORAGE /*Sử dụng cho cả IPv6 và IPv4*/),NULL,wcAddr,&dwSize) == 0) { return wcAddr; } return L"";} void PrintAdapters(pcap_if_t * LinkedListDevices){ pcap_if_t *Temp; index = 0; pcap_addr_t *Addr; for (Temp = LinkedListDevices ; Temp != NULL ; Temp = Temp->next) { // in tên và mô tả của network adapters printf("%i Name : %s Description : %s ",++index,Temp->name,Temp->description); // có phải địa chỉ loopback hay không ? printf("\tLoopback : %s ",Temp->flags & PCAP_IF_LOOPBACK ? "Yes" : "No"); for (Addr = Temp->addresses ; Addr != NULL ; Addr = Addr->next) { if (Addr->addr) { printf("\tAddress: %S ",Address2String(Addr->addr)); } if (Addr->broadaddr) { printf("\tbroadaddr :%S ",Address2String(Addr->broadaddr)); } if (Addr->dstaddr) { printf("\tdstaddr : %S ",Address2String(Addr->dstaddr)); } if (Addr->netmask) { printf("\tnetmask : %S ",Address2String(Addr->netmask)); } } }} int _tmain(int argc, _TCHAR* argv[]){ WSADATA wsaData; // Khởi động Winsock2 if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) { printf("WSAStartup(0 loi, ma %d",WSAGetLastError()); return -1; } pcap_if_t *LinkedListDevices; // danh sách liên kết của cấu trúc // pcap_addr_t chứa thông tin network adapters char ErrorBuffer[PCAP_ERRBUF_SIZE + 1]; // Buffer nhận nguyên nhân lỗi // Tìm các network adapters if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL , &LinkedListDevices , ErrorBuffer) != 0 ) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_findalldevs_ex() loi, ma %s",ErrorBuffer); goto Exit; } // Gọi hàm hiển thị các adapter PrintAdapters(LinkedListDevices); // Chọn adapter để capture printf("Chon adapter tu 1 - %i",index); int SelectedIndex; scanf_s("%d",&SelectedIndex); if (SelectedIndex < 1 || SelectedIndex > index) { printf("So hieu adapter da chon khong co "); goto Exit; } pcap_if_t * Temp; // Chuyển con trỏ trỏ tới adapter đã chọn for (Temp = LinkedListDevices , index = 0 ; index < SelectedIndex -1 ; index ++ , Temp = Temp->next); // gọi pcap_open() để mở adapter // Tham số 1 : Tên adapter kiểu char*. // Tham số 2 : Độ dài packet có thể capture , chọn 65536 để đảm bảo capture đc toàn bộ packet. // Tham sô 3 : Cờ áp đặt chế độ cho adapter để capture. // PCAP_OPENFLAG_PROMISCUOUS : Chế độ không phân biệt , sẽ capture mọi packet // mà adadpter trao đổi giữa network hoặc host khác. // Tham số 4 : Thời gian đọc timeout. // Tham số 5 : Buffer nhận lỗi nếu có. pcap_t *Handle = pcap_open(Temp->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,ErrorBuffer); if (Handle == NULL) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_open() loi , ma %s ",ErrorBuffer); goto Exit; } printf("Dang capture tren adapter : %s ",Temp->description); int iRt; pcap_pkthdr * pPacketHeader; const u_char *ucPacketData; time_t local_tv_sec;W tm ltime; char timestr[16]; while (iRt = pcap_next_ex(Handle,&pPacketHeader,&ucPacketData) >= 0) { if(iRt == 0) continue; // Hết thời gian timeout // Convert timestamp sang string local_tv_sec = pPacketHeader->ts.tv_sec; localtime_s(<ime, &local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); printf("%s,%.6d len:%d ", timestr, pPacketHeader->ts.tv_usec, pPacketHeader->len); // Nếu lỗi if (iRt == -1) printf("pcap_next_ex() loi, %s ",pcap_geterr(Handle)); } Exit: // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết pcap_freealldevs(LinkedListDevices); system("pause"); return 0;}
Lọc traffic
Một tính năng mạnh mẽ mà Winpcap ( libpcap cũng vậy ) cung cấp là bộ lọc traffic.
Các hàm được sử dụng để filter traffic là pcap_compile() và pcap_setfilter().
Ví dụ :
File Stdafx.h :
Mã:// stdafx.h : include file for standard system include files,// or project specific include files that are used frequently, but// are changed infrequently// #pragma once #include "targetver.h" #include <stdio.h>#include <tchar.h>#include <pcap.h>#include <WinSock2.h> // TODO: reference additional headers your program requires here
Mã:// TestWinpcap.cpp : Defines the entry point for the console application.// #include "stdafx.h" // Toàn cụcint index = 0; /* 4 bytes IP address - cấu trúc mô tả địa chỉ Ipv4 ở dạng 4 bytes */typedef struct ip_address{ u_char byte1; u_char byte2; u_char byte3; u_char byte4;}ip_address; /* IPv4 header */typedef struct ip_header{ u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits) u_char tos; // Type of service u_short tlen; // Total length u_short identification; // Identification u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits) u_char ttl; // Time to live u_char proto; // Protocol u_short crc; // Header checksum ip_address saddr; // Source address ip_address daddr; // Destination address u_int op_pad; // Option + Padding}ip_header; /* UDP header*/typedef struct udp_header{ u_short sport; // Source port u_short dport; // Destination port u_short len; // Datagram length u_short crc; // Checksum}udp_header; WCHAR * Address2String(SOCKADDR * Sockaddr){ WCHAR wcAddr[256]; DWORD dwSize = sizeof(wcAddr); if (WSAAddressToString(Sockaddr,sizeof(SOCKADDR_STORAGE /*Sử dụng cho cả IPv6 và IPv4*/),NULL,wcAddr,&dwSize) == 0) { return wcAddr; } return L"";} void PrintAdapters(pcap_if_t * LinkedListDevices){ pcap_if_t *Temp; index = 0; pcap_addr_t *Addr; for (Temp = LinkedListDevices ; Temp != NULL ; Temp = Temp->next) { // in tên và mô tả của network adapters printf("%i Name : %s Description : %s ",++index,Temp->name,Temp->description); // có phải địa chỉ loopback hay không ? printf("\tLoopback : %s ",Temp->flags & PCAP_IF_LOOPBACK ? "Yes" : "No"); for (Addr = Temp->addresses ; Addr != NULL ; Addr = Addr->next) { if (Addr->addr) { printf("\tAddress: %S ",Address2String(Addr->addr)); } if (Addr->broadaddr) { printf("\tbroadaddr :%S ",Address2String(Addr->broadaddr)); } if (Addr->dstaddr) { printf("\tdstaddr : %S ",Address2String(Addr->dstaddr)); } if (Addr->netmask) { printf("\tnetmask : %S ",Address2String(Addr->netmask)); } } }} void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data){ struct tm ltime; char timestr[16]; ip_header *ih; udp_header *uh; u_int ip_len; u_short sport,dport; time_t local_tv_sec; /* * Unused variable */ (VOID)(param); /* convert the timestamp to readable format */ local_tv_sec = header->ts.tv_sec; localtime_s(<ime, &local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); /* print timestamp and length of the packet */ printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len); /* retireve the position of the ip header */ ih = (ip_header *) (pkt_data + 14); //length of ethernet header /* retireve the position of the udp header */ ip_len = (ih->ver_ihl & 0xf) * 4; uh = (udp_header *) ((u_char*)ih + ip_len); /* convert from network byte order to host byte order */ sport = ntohs( uh->sport ); dport = ntohs( uh->dport ); /* print ip addresses and udp ports */ printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d ", ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4, sport, ih->daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4, dport); } int _tmain(int argc, _TCHAR* argv[]){ WSADATA wsaData; // Khởi động Winsock2 if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) { printf("WSAStartup(0 loi, ma %d",WSAGetLastError()); return -1; } pcap_if_t *LinkedListDevices; // danh sách liên kết của cấu trúc // pcap_addr_t chứa thông tin network adapters char ErrorBuffer[PCAP_ERRBUF_SIZE + 1]; // Buffer nhận nguyên nhân lỗi // Tìm các network adapters if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL , &LinkedListDevices , ErrorBuffer) != 0 ) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_findalldevs_ex() loi, ma %s",ErrorBuffer); goto Exit; } // Gọi hàm hiển thị các adapter PrintAdapters(LinkedListDevices); // Chọn adapter để capture printf("Chon adapter tu 1 - %i : ",index); int SelectedIndex; scanf_s("%d",&SelectedIndex); if (SelectedIndex < 1 || SelectedIndex > index) { printf("So hieu adapter da chon khong co "); goto Exit; } pcap_if_t * Temp; // Chuyển con trỏ trỏ tới adapter đã chọn for (Temp = LinkedListDevices , index = 0 ; index < SelectedIndex -1 ; index ++ , Temp = Temp->next); // gọi pcap_open() để mở adapter // Tham số 1 : Tên adapter kiểu char*. // Tham số 2 : Độ dài packet có thể capture , chọn 65536 để đảm bảo capture đc toàn bộ packet. // Tham sô 3 : Cờ áp đặt chế độ cho adapter để capture. // PCAP_OPENFLAG_PROMISCUOUS : Chế độ không phân biệt , sẽ capture mọi packet // mà adadpter trao đổi giữa network hoặc host khác. // Tham số 4 : Thời gian đọc timeout. // Tham số 5 : Buffer nhận lỗi nếu có. pcap_t *Handle = pcap_open(Temp->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,ErrorBuffer); if (Handle == NULL) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_open() loi , ma %s ",ErrorBuffer); goto Exit; } // Ta kiểm tra Mac layer để chắc chắn rằng là mạng Ethernet có độ dài // Mac header là 14 bytes // IP Header có vị trí ngay sau Mac header. // Để có được UDP header có 1 chút phức tạp, vì Ip header không có độ // dài cố định , nên ta lấy độ dài của Internet header , là 1 trường // trong IP header , để xác định vị trí của UDP header. // if (pcap_datalink(Handle) != DLT_EN10MB) { printf("Chuong trinh chi ho tro capture packet tren mang Ethernet. "); goto Exit; } u_int netmask; if(Temp->addresses->next != NULL) /* Retrieve the mask of the first address of the interface */ netmask=((struct sockaddr_in *)(Temp->addresses->next->netmask))->sin_addr.S_un.S_addr; else /* If the interface is without addresses we suppose to be in a C class network */ netmask=0xffffff; char packet_filter[] = "ip and udp"; // Chỉ capture các packte có giao // thức là UDP và IPv4. struct bpf_program fcode; if (pcap_compile(Handle,&fcode,packet_filter,TRUE,netmask) < 0) { printf("pcap_compile() loi "); goto Exit; } if (pcap_setfilter(Handle,&fcode) < 0) { printf("pcap_setfilter() loi. "); goto Exit; } // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết printf("Dang capture tren adapter : %s ",Temp->description); pcap_freealldevs(LinkedListDevices); // Bắt đầu capture packet trên adapter đã chọn. // Tham số 1 là handle trả lại từ hàm pcap_open(). // Tham số 2 là số lượng packet cần capture, sau khi capture đc lượng // packet này, hàm sẽ return // Tham số 3 là con trỏ tới hàm CALLBACK nhận packet đến. // pcap_loop(Handle,0,packet_handler,NULL); // Phương pháp capture packet không thông qua hàm CALLBACK /*int iRt; pcap_pkthdr * pPacketHeader; const u_char *ucPacketData; time_t local_tv_sec; tm ltime; char timestr[16]; while (iRt = pcap_next_ex(Handle,&pPacketHeader,&ucPacketData) >= 0) { if(iRt == 0) continue; // Hết thời gian timeout // Convert timestamp sang string local_tv_sec = pPacketHeader->ts.tv_sec; localtime_s(<ime, &local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); printf("%s,%.6d len:%d ", timestr, pPacketHeader->ts.tv_usec, pPacketHeader->len); // Nếu lỗi if (iRt == -1) printf("pcap_next_ex() loi, %s ",pcap_geterr(Handle)); }*/ Exit: // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết pcap_freealldevs(LinkedListDevices); system("pause"); return 0;}
Mỗi dòng là 1 packet.
-
30-07-2012, 09:14 AM #4Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Xử lý dump file
Hiện tại , tính năng này đang bị vô hiệu hóa vì gặp phải 1 vài vấn đề với kernel buffer mới.
Ví dụ :
File Stdafx.h :
Mã:// stdafx.h : include file for standard system include files,// or project specific include files that are used frequently, but// are changed infrequently// #pragma once #include "targetver.h" #include <stdio.h>#include <tchar.h>#include <pcap.h>#include <WinSock2.h> // TODO: reference additional headers your program requires here
Mã:// TestWinpcap.cpp : Defines the entry point for the console application.// #include "stdafx.h" // Toàn cụcint index = 0; /* 4 bytes IP address - cấu trúc mô tả địa chỉ Ipv4 ở dạng 4 bytes */typedef struct ip_address{ u_char byte1; u_char byte2; u_char byte3; u_char byte4;}ip_address; /* IPv4 header */typedef struct ip_header{ u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits) u_char tos; // Type of service u_short tlen; // Total length u_short identification; // Identification u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits) u_char ttl; // Time to live u_char proto; // Protocol u_short crc; // Header checksum ip_address saddr; // Source address ip_address daddr; // Destination address u_int op_pad; // Option + Padding}ip_header; /* UDP header*/typedef struct udp_header{ u_short sport; // Source port u_short dport; // Destination port u_short len; // Datagram length u_short crc; // Checksum}udp_header; WCHAR * Address2String(SOCKADDR * Sockaddr){ WCHAR wcAddr[256]; DWORD dwSize = sizeof(wcAddr); if (WSAAddressToString(Sockaddr,sizeof(SOCKADDR_STORAGE /*Sử dụng cho cả IPv6 và IPv4*/),NULL,wcAddr,&dwSize) == 0) { return wcAddr; } return L"";} void PrintAdapters(pcap_if_t * LinkedListDevices){ pcap_if_t *Temp; index = 0; pcap_addr_t *Addr; for (Temp = LinkedListDevices ; Temp != NULL ; Temp = Temp->next) { // in tên và mô tả của network adapters printf("%i Name : %s Description : %s ",++index,Temp->name,Temp->description); // có phải địa chỉ loopback hay không ? printf("\tLoopback : %s ",Temp->flags & PCAP_IF_LOOPBACK ? "Yes" : "No"); for (Addr = Temp->addresses ; Addr != NULL ; Addr = Addr->next) { if (Addr->addr) { printf("\tAddress: %S ",Address2String(Addr->addr)); } if (Addr->broadaddr) { printf("\tbroadaddr :%S ",Address2String(Addr->broadaddr)); } if (Addr->dstaddr) { printf("\tdstaddr : %S ",Address2String(Addr->dstaddr)); } if (Addr->netmask) { printf("\tnetmask : %S ",Address2String(Addr->netmask)); } } }} void packet_handler(u_char *DumpFile, const struct pcap_pkthdr *header, const u_char *pkt_data){/* struct tm ltime; char timestr[16]; ip_header *ih; udp_header *uh; u_int ip_len; u_short sport,dport; time_t local_tv_sec; / * * Unused variable * / (VOID)(param); / * convert the timestamp to readable format * / local_tv_sec = header->ts.tv_sec; localtime_s(<ime, &local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); / * print timestamp and length of the packet * / printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len); / * retireve the position of the ip header * / ih = (ip_header *) (pkt_data + 14); //length of ethernet header / * retireve the position of the udp header * / ip_len = (ih->ver_ihl & 0xf) * 4; uh = (udp_header *) ((u_char*)ih + ip_len); / * convert from network byte order to host byte order * / sport = ntohs( uh->sport ); dport = ntohs( uh->dport ); / * print ip addresses and udp ports * / printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d ", ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4, sport, ih->daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4, dport);*/ // Lưu dữ liệu packet vào dump file // Các tham số của hàm pcap_dump() tương ứng với các tham số của hàm // CALLBACK // pcap_dump(DumpFile,header,pkt_data); } int _tmain(int argc, _TCHAR* argv[]){ WSADATA wsaData; // Khởi động Winsock2 if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) { printf("WSAStartup(0 loi, ma %d",WSAGetLastError()); return -1; } pcap_if_t *LinkedListDevices; // danh sách liên kết của cấu trúc // pcap_addr_t chứa thông tin network adapters char ErrorBuffer[PCAP_ERRBUF_SIZE + 1]; // Buffer nhận nguyên nhân lỗi // Tìm các network adapters if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL , &LinkedListDevices , ErrorBuffer) != 0 ) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_findalldevs_ex() loi, ma %s",ErrorBuffer); goto Exit; } // Gọi hàm hiển thị các adapter PrintAdapters(LinkedListDevices); // Chọn adapter để capture printf("Chon adapter tu 1 - %i : ",index); int SelectedIndex; scanf_s("%d",&SelectedIndex); if (SelectedIndex < 1 || SelectedIndex > index) { printf("So hieu adapter da chon khong co "); goto Exit; } pcap_if_t * Temp; // Chuyển con trỏ trỏ tới adapter đã chọn for (Temp = LinkedListDevices , index = 0 ; index < SelectedIndex -1 ; index ++ , Temp = Temp->next); // gọi pcap_open() để mở adapter // Tham số 1 : Tên adapter kiểu char*. // Tham số 2 : Độ dài packet có thể capture , chọn 65536 để đảm bảo capture đc toàn bộ packet. // Tham sô 3 : Cờ áp đặt chế độ cho adapter để capture. // PCAP_OPENFLAG_PROMISCUOUS : Chế độ không phân biệt , sẽ capture mọi packet // mà adadpter trao đổi giữa network hoặc host khác. // Tham số 4 : Thời gian đọc timeout. // Tham số 5 : Buffer nhận lỗi nếu có. pcap_t *Handle = pcap_open(Temp->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,ErrorBuffer); if (Handle == NULL) { ErrorBuffer[PCAP_ERRBUF_SIZE + 1] = NULL; printf("pcap_open() loi , ma %s ",ErrorBuffer); goto Exit; } // Liên kết dump file với handle của adapter đã mở. pcap_dumper_t *DumpFile = pcap_dump_open(Handle,"DumpFile.txt"); // Ta kiểm tra Mac layer để chắc chắn rằng là mạng Ethernet có độ dài // Mac header là 14 bytes // IP Header có vị trí ngay sau Mac header. // Để có được UDP header có 1 chút phức tạp, vì Ip header không có độ // dài cố định , nên ta lấy độ dài của Internet header , là 1 trường // trong IP header , để xác định vị trí của UDP header. // if (pcap_datalink(Handle) != DLT_EN10MB) { printf("Chuong trinh chi ho tro capture packet tren mang Ethernet. "); goto Exit; } u_int netmask; if(Temp->addresses/*->next*/ != NULL) /* Retrieve the mask of the first address of the interface */ netmask=((struct sockaddr_in *)(Temp->addresses/*->next*/->netmask))->sin_addr.S_un.S_addr; else /* If the interface is without addresses we suppose to be in a C class network */ netmask=0xffffff; char packet_filter[] = "ip and udp"; // Chỉ capture các packte có giao // thức là UDP và IPv4. struct bpf_program fcode; if (pcap_compile(Handle,&fcode,packet_filter,TRUE,netmask) < 0) { printf("pcap_compile() loi "); goto Exit; } if (pcap_setfilter(Handle,&fcode) < 0) { printf("pcap_setfilter() loi. "); goto Exit; } // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết printf("Dang capture tren adapter : %s ",Temp->description); pcap_freealldevs(LinkedListDevices); // Bắt đầu capture packet trên adapter đã chọn. // Tham số 1 là handle trả lại từ hàm pcap_open(). // Tham số 2 là số lượng packet cần capture, sau khi capture đc lượng // packet này, hàm sẽ return // Tham số 3 là con trỏ tới hàm CALLBACK nhận packet đến. // Tham số 4 là handle của dump file đã liên kết với adapter. pcap_loop(Handle,0,packet_handler,(u_char*)DumpFile); // Phương pháp capture packet không thông qua hàm CALLBACK /*int iRt; pcap_pkthdr * pPacketHeader; const u_char *ucPacketData; time_t local_tv_sec; tm ltime; char timestr[16]; while (iRt = pcap_next_ex(Handle,&pPacketHeader,&ucPacketData) >= 0) { if(iRt == 0) continue; // Hết thời gian timeout // Convert timestamp sang string local_tv_sec = pPacketHeader->ts.tv_sec; localtime_s(<ime, &local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); printf("%s,%.6d len:%d ", timestr, pPacketHeader->ts.tv_usec, pPacketHeader->len); // Nếu lỗi if (iRt == -1) printf("pcap_next_ex() loi, %s ",pcap_geterr(Handle)); }*/ Exit: // Ngừng sử dụng Winsock 2 if (WSACleanup() != 0) { printf("WSACleanup(0 loi, ma %d",WSAGetLastError()); return -1; } // Giải phóng bộ nhớ của danh sách liên kết pcap_freealldevs(LinkedListDevices); system("pause"); return 0;}
-
19-08-2012, 07:54 PM #5Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
tks a nhiều lắm, nhưng mà có thể cho em hỏi 1 vấn đề là với Winpcap mình có thể chặn 1 Packet đi ko ?
-
05-09-2012, 11:55 AM #6Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Gửi bởi raymondle
Bạn có thể tham khảo thêm tại :
Mã:http://www.winpcap.org/docs/default.htm
-
05-09-2012, 06:22 PM #7Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
^
Demo một chương trình ghi nhật kí Ymsg đi bác. :x Cái này tiện lắm đấy. [IMG]images/smilies/18.gif[/IMG]
Thông qua phân tích dữ liệu Google từ 86 quốc gia, mới đây, một công ty tại Anh đã công bố bảng xếp hạng kích tấc "cậu nhỏ" của các nước trên thế giới. Kết quả, hầu hết các nước xếp ở nhóm đầu của...
"Chim" của chàng trai Việt thuộc...