協議分析之搭建Ubuntu16.04下的Qt開發環境

1.完成虛擬機Ubuntu的搭建
2.完成函數庫的安裝(libpcap/libnet/libnids/libglib2.0)
3.完成Qt的安裝
4.完成開發環境的測試(包括Qt運行的配置)

1.虛擬機的搭建

1.安裝設置Ubuntu16.04的虛擬機:
在這裏插入圖片描述
2.安裝Ubuntu系統:
在這裏插入圖片描述
3.安裝VM Tools:

  • 安裝完以後記得重啓一下,否則還是不能實現虛擬機和物理機之間的複製粘貼。
    在這裏插入圖片描述
    4.更新源:
sudo gedit /etc/apt/sources.list

在這裏插入圖片描述
然後替換成清華的、阿里雲的都可以,具體的更新內容網上找。

更新源:

sudo apt-get update

在這裏插入圖片描述
5.後面需要用vim文本編輯器修改配置文件,所以還要安裝vim:

sudo apt-get install vim

在這裏插入圖片描述

  • 需要提醒一下,我以前安裝vim的時候都是失敗的,需要安裝vim-gtk版的才能成功。如果你安裝不了vim的話,可以嘗試一下vim-gtk。
    sudo apt-get install vim-gtk

2.函數庫的安裝(libpcap/libnet/libnids/libglib2.0)

2.1 libpcap

2.1.1 libpcap簡介

Libpcap是Packet Capture Libray的英文縮寫,即數據包捕獲函數庫。該庫提供的C函數接口用於捕捉經過指定網絡接口的數據包,該接口應該是被設爲混雜模式。這個在原始套接字中有提到。
著名的軟件TCPDUMP就是在Libpcap的基礎上開發而成的。Libpcap提供的接口函數實現和封裝了與數據包截獲有關的過程。
Libpcap提供了用戶級別的網絡數據包捕獲接口,並充分考慮到應用程序的可移植性。Libpcap可以在絕大多數Linux平臺上運行。在Windows平臺上,也有一款與其功能類似的開發庫:Wincap。
它的應用範圍非常廣泛,典型應用包括玩羅協議分析器,網絡流量發生器,網絡入侵檢測系統,網絡掃描器和其他安全工具。

它的工作在上層應用程序與網絡接口之間。 主要功能:

  • 數據包捕獲:捕獲流經網卡的原始數據包
  • 自定義數據包發送:構造任何格式的原始數據包
  • 流量採集與統計:採集網絡中的流量信息
  • 規則過濾:提供自帶規則過濾功能,按需要選擇過濾規則
2.1.2 安裝過程
sudo apt install libpcap-dev

在這裏插入圖片描述

2.2 libnet

2.2.1 libnet簡介

libnet是一個小型的接口函數庫,主要用C語言寫成,提供了低層網絡數據包的構造、處理和發送功能。

常用的接口函數和功能:

1.內存管理函數
單數據包內存初始化:
int libnet_init_packet(u_short packet_size, u_char **buf);
單數據包內存釋放:
void libnet_destroy_packet(u_char **buf);
多數據包內存初始化:
int libnet_init_packet_arena(struct libnet_arena **arena,
u_short packet_num, u_short packet_size);
訪問多數據包內存中的下一個數據包:
u_char *libnet_next_packet_from_arena(struct libnet_arena **arena,
u_short packet_size);
多數據包內存釋放:
void libnet_destroy_packet_arena(struct libnet_arena **arena);
2.地址解析函數
解析主機名:
u_char *libnet_host_lookup(u_long ip, u_short use_name);
解析主機名(可重入函數):
void libnet_host_lookup_r(u_long ip, u_short use_name, u_char *buf);
域名解析:
u_long libnet_name_resolve(u_char *ip, u_short use_name);
獲取接口設備IP地址:
u_long libnet_get_ipaddr(struct libnet_link_int *l,
const u_char *device, const u_char *ebuf);
獲取接口設備硬件地址:
struct ether_addr *libnet_get_hwaddr(struct libnet_link_int *l,
const u_char *device,
const u_char *ebuf);
3.數據包構造函數
ARP協議數據包:
int libnet_build_arp(u_short hrdw, u_short prot, u_short h_len,
u_short p_len, u_short op, u_char *s_ha,
u_char *s_pa, u_char *t_ha, u_char *t_pa,
const u_char *payload, int payload_len,
u_char *packet_buf);
DNS協議數據包:
int libnet_build_dns(u_short id, u_short flags, u_short num_q,
u_short num_answ_rr, u_short num_auth_rr,
u_short num_add_rr, const u_char * payload,
int payload_len, u_char *packet_buf);
以太網協議數據包:
int libnet_build_ethernet(u_char *daddr, u_char *saddr, u_short id,
const u_char *payload, int payload_len,
u_char *packet_buf);
ICMP協議數據包(ICMP_ECHO / ICMP_ECHOREPLY):
int libnet_build_icmp_echo(u_char type, u_char code, u_short id,
u_short seq, const u_char *payload,
int payload_len, u_char *packet_buf);
ICMP協議數據包(ICMP_MASKREQ / ICMP_MASKREPLY):
int libnet_build_icmp_mask(u_char type, u_char code, u_short id,
u_short seq, u_long mask,
const u_char *payload, int payload_len,
u_char *packet_buf);
ICMP協議數據包(ICMP_UNREACH):
int libnet_build_icmp_unreach(u_char type, u_char code,
u_short orig_len, u_char orig_tos,
u_short orig_id, u_short orig_frag,
u_char orig_ttl, u_char orig_prot,
u_long orig_saddr, u_long orig_daddr,
const u_char *payload, int payload_len,
u_char *packet_buf);
ICMP協議數據包(ICMP_TIMEXCEED):
int libnet_build_icmp_timeexceed(u_char type, u_char code,
u_short orig_len, u_char orig_tos,
u_short orig_id, u_short orig_frag,
u_char orig_ttl, u_char orig_prot,
u_long orig_saddr, u_long orig_daddr,
const u_char *payload, int payload_len,
u_char *packet_buf);
ICMP協議數據包(ICMP_REDIRECT):
int libnet_build_icmp_redirect(u_char type, u_char code, u_long gateway,
u_short orig_len, u_char orig_tos,
u_short orig_id, u_short orig_frag,
u_char orig_ttl, u_char orig_prot,
u_long orig_saddr, u_long orig_daddr,
const u_char *payload, int payload_len,
u_char *packet_buf);
ICMP協議數據包(ICMP_TSTAMP / ICMP_TSTAMPREPLY):
int libnet_build_icmp_timestamp(u_char type, u_char code, u_short id,
u_short seq, n_time otime, n_time rtime,
n_time ttime, const u_char *payload,
int payload_len, u_char *packet_buf);
IGMP協議數據包:
int libnet_build_igmp(u_char type, u_char code, u_long ip,
const u_char *payload, int payload_len,
u_char *packet_buf);
IP協議數據包:
int libnet_build_ip(u_short len, u_char tos, u_short ip_id, u_short frag,
u_char ttl, u_char protocol, u_long saddr,
u_long daddr, const u_char *payload, int payload_len,
u_char *packet_buf);
OSPF路由協議數據包:
int libnet_build_ospf(u_short len, u_char type, u_long router_id,
u_long area_id, u_short auth_type,
const char *payload, int payload_s, u_char *buf);
OSPF路由協議數據包(Hello):
int libnet_build_ospf_hello(u_long netmask, u_short interval,
u_char options, u_char priority,
u_int dead_interval, u_long des_router,
u_long backup, u_long neighbor,
const char *payload, int payload_s,
u_char *buf);
OSPF路由協議數據包(DataBase Description (DBD)):
int libnet_build_ospf_dbd(u_short len, u_char options, u_char type,
u_int sequence_num, const char *payload,
int payload_s, u_char *buf);
OSPF路由協議數據包(Link State Request (LSR)):
int libnet_build_ospf_lsr(u_int type, u_int ls_id, u_long adv_router,
const char *payload, int payload_s,
u_char *buf);
OSPF路由協議數據包(Link State Update (LSU)):
int libnet_build_ospf_lsu(u_int num, const char *payload,
int payload_s, u_char *buf);
OSPF路由協議數據包(Link State Acknowledgement (LSA)):
int libnet_build_ospf_lsa(u_short age, u_char options, u_char type,
u_int ls_id, u_long adv_router,
u_int sequence_num, u_short len,
const char *payload, int payload_s,
u_char *buf);
OSPF路由協議數據包(OSPF Link Sate NetworkLink State Router):
int libnet_build_ospf_lsa_net(u_long netmask, u_int router_id,
const char *payload, int payload_s,
u_char *buf);
OSPF路由協議數據包(Link State Router):
int libnet_build_ospf_lsa_rtr(u_short flags, u_short num, u_int id,
u_int data, u_char type, u_char tos,
u_short metric, const char *payload,
int payload_s, u_char *buf);
OSPF路由協議數據包(Link State Summary):
int libnet_build_ospf_lsa_sum(u_long netmask, u_int metric, u_int tos,
const char *payload, int payload_s,
u_char *buf);
OSPF路由協議數據包(Link State AS External):
int libnet_build_ospf_lsa_as(u_long netmask, u_int metric,
u_long fwd_addr, u_int tag,
const char *payload, int payload_s,
u_char *buf);
RIP路由協議數據包:
int libnet_build_rip(u_char cmd, u_char ver, u_short domain,
u_short addr_fam, u_short route_tag, u_long ip,
u_long mask, u_long next_hop, u_long metric,
const u_char *payload, int payload_len,
u_char *packet_buf);
TCP協議數據包:
int libnet_build_tcp(u_short th_sport, u_short th_dport, u_long th_seq,
u_long th_ack, u_char th_flags, u_short th_win,
u_short th_urg, const u_char *payload,
int payload_len, u_char *packet_buf);
UDP協議數據包:
int libnet_build_udp(u_short sport, u_short dport, const u_char *payload,
int payload_len, u_char *packet_buf);
IP協議數據包選項:
int libnet_insert_ipo(struct ipoption *opt, u_char opt_len,
u_char *packet_buf);
TCP協議數據包選項:
int libnet_insert_tcpo(struct tcpoption *opt, u_char opt_len,
u_char *packet_buf);
4.數據包發送函數
打開raw socket:
int libnet_open_raw_sock(int protocol);
關閉raw socket:
int libnet_close_raw_sock(int socket);
選擇接口設備:
int libnet_select_device(struct sockaddr_in *sin,
u_char **device, u_char *ebuf);
打開鏈路層接口設備:
struct libnet_link_int *libnet_open_link_interface(char *device,
char *ebuf);
關閉鏈路層接口設備:
int libnet_close_link_interface(struct libnet_link_int *l);
發送IP數據包:
int libnet_write_ip(int socket, u_char *packet, int packet_size);
發送鏈路層數據包:
int libnet_write_link_layer(struct libnet_link_int *l,
const u_char *device, u_char *packet,
int packet_size);
檢驗和計算:
int libnet_do_checksum(u_char *packet, int protocol, int packet_size);
5.相關的支持函數
隨機數種子生成器:
int libnet_seed_prand();
獲取隨機數:
u_long libnet_get_prand(int modulus);
16進制數據輸出:
void libnet_hex_dump(u_char * buf, int len, int swap, FILE *stream);
端口列表鏈初始化:
int libnet_plist_chain_new(struct libnet_plist_chain **plist,
char *token_list);
獲取端口列表鏈的下一項(端口範圍):
int libnet_plist_chain_next_pair(struct libnet_plist_chain *plist,
u_short *bport, u_short *eport);
端口列表鏈輸出顯示:
int libnet_plist_chain_dump(struct libnet_plist_chain *plist);
獲取端口列表鏈:
u_char *libnet_plist_chain_dump_string(struct libnet_plist_chain *plist);
端口列表鏈內存釋放:
void libnet_plist_chain_free(struct libnet_plist_chain *plist);

2.2.2 安裝過程
sudo apt install libpnet-dev

在這裏插入圖片描述

2.3 libnids

2.3.1 libnids簡介

Libnids 是一個用於網絡入侵檢測開發的專業編程接口,它使用了Libpcap所以它具有捕獲數據包的功能。同時,Libnids提供了TCP數據流重組功能,所以對於分析基於TCP協議的各種協議Libnids都能勝任。Libnids還提供了對IP分片進行重組的功能,以及端口掃描檢測和異常數據包檢測功能。

一、基本常量

1.報警類型

enum

{

NIDS_WARN_IP =1, //IP數據包異常

NIDS_WARN_TCP,//TCP數據包異常

NIDS_WARN_UDP,//UDP數據包異常

NIDS_WARN_SCAN//表示有掃描攻擊發生

}

enum

{

NIDS_WARN_UNDEFINED=0, //表示未定義

NIDS_WARN_IP_OVERSIZED.//表示IP數據包超長

NIDS_WARN_IP_INVLIST,//表示無效的碎片隊列

NIDS_WARN_IP_OVERLAP,//表示發生重疊

NIDS_WARN_IP_HDR,//表示無效IP首部,IP數據包發生異常

NIDS_WARN_IP_SRR,//表示源路由IP數據包

NIDS_WARN_TCP_TOOMUCH,//表示tcp數據個數太多,因爲在libnids中在同一時刻捕獲的tcp個數最大值爲tcp連接參數的哈希表長度3/4

NIDS_WARN_TCP_HDR,//表示無效TCP首部,TCP數據包發生異常

NIDS_WARN_TCP_BIGAQUEUE,//表示TCP接收的隊列數據過多

NIDS_WARN_TCP_BADFLAGS//表示錯誤標記

}

2.Libnids狀態

在對TCP數據流進行重組時,必須考慮到TCP的連接狀態,在Libnids中爲了方便開發而定義了6種Libnids狀態(描述的是連接的邏輯狀態)

#define NIDS_JUST_EST 1//表示tcp連接建立

#define NIDS_DATA 2 //表示接受數據的狀態

#define NIDS_CLOSE 3 //表示tcp連接正常關閉

#define NIDS_RESET 4 //表示tcp連接被重置關閉

#define NIDS_TIMED_OUT 5 //表示由於超時tcp連接被關閉

#define NIDS_EXITING 6 //表示libnids正在退出

真正的TCP連接狀態有11種

enum

{

TCP_ESTABLISHED=1, //表示ESTABLISH狀態,TCP連接建立,開始傳輸數據

TCP_SYN_SENT,//表示syn_sent狀態,主動打開

TCP_SYN_RECV,//表示syn_recv狀態,接收SYN

TCP_FIN_WAIT1,//表示FIN_WAIT_1狀態

TCP_FIN_WAIT2,//表示FIN_WAIT2狀態

TCP_TIME_WAIT//表示TIME_WAIT狀態

TCP_ClOSE,//表示Closed狀態

TCP_CLOSE_WAIT,//表示CLose_WAIT狀態

TCP_LAST_ACK,//表示LAST_ACK狀態

TCP_LISTEN,//表示LISTEN狀態

TCP_CLOSING//表示CLOSING 狀態

}

3.校驗和,與此相關的常量定義如下:

#define NIDS_DO_CHKSUM 0 //表示告訴Libnids要計算校驗和

#define NIDS_DONT_CHKSUM 1//表示告訴LIbnids不需要計算校驗和

二、數據結構

1.tuple4:
此數據結構是Libnids中最基本的一種數據結構

struct tuple4

{

u_short source;//源端口

u_short dest;//目標端口

u_int saddr; //源IP

u_int daddr;//目的IP

};//用於描述一個地址端口對,它表示發送方IP和端口以及接收方IP和端口

2.half_stream:
此數據結構用來描述在tcp連接中一端的所有信息,可以使客戶端也可以是服務端。

struct half_stream

{

char state;//表示套接字的狀態,也就是tcp連接狀態

char collect;//表示是否存儲數據到data中,如果大於0就存儲,否則忽略

char collect_urg;//是否存儲緊急數據到urgdata中,如果大於0就存儲,否則忽略

char *data;//存儲正常接收的數據

int offset;//存儲在data中數據的第一個字節的偏移量

int count;//表示從tcp連接開始已經存儲到data中的數據的字節數

int count_new;//表示有多少新數據寸到data 中

int bufsize;//

int rmem_alloc;

int urg_count;

u_int acked;

u_int seq;

u_int ack_seq;

u_int first_data_seg;

u_char urgdata;//用來存儲緊急數據

u_char count_new_urg;//表示是否有新的緊急數據到達

u_char urg_seen;

u_int urg_ptr;

u_short window;

u_char ts_on;

u_int curr_ts;

struct skbuff *list;

struct skbuff *listtail;

}

3.tcp_stream:
描述的是一個TCP連接的所有信息

struct tcp_stream

{

struct tuple4 addr;//是一個tuple4類型的成員,它表示一個tcp連接的四個重要信息

char nids_state;//表示邏輯連接狀態

struct lurker_node *listeners;

struct half_stream client;

struct half_stream server;

struct tcp_stream *next_node;

struct tcp_stream *prev_node;

int hash_index;

struct tcp_stream *next_time;

struct tcp_stream *prev_time;

int read;

struct tcp_stream *next_free;

};//描述了一個TCP連接的完整信息

4.nids_prm:
描述libnids的一些全局參數信息

struct nids_prm

{

int n_tcp_streams;//表示哈西表大小,此哈西表用來存放tcp_stream數據結構,

int n_hosts;//表示存放ip碎片信息的哈西表的大小

char *device;

char *filename;//用來存儲網絡數據捕獲文件.如果設置了文件,與此同時就應該設置成員device爲null,默認值爲NULL

int
sk_buff_size;//表示數據結構sk_buff的大小.數據結構sk_buff是linux內核中一個重要的數據結構,是用來進行數據包隊列操作的

int
dev_addon;//表示在數據結構sk_buff中用於網絡接口上信息的字節數,如果是-1(默認值),那麼libnids會根據不同的網絡接口進行修正

void (*syslog)();//函數指針,默認值爲nids_syslog()函數.在syslog中可以檢測入侵攻擊,如:網絡掃描攻擊

函數定義類型爲nids_syslog(int type,int errnum,struct ip_header * iph,void
*data)

int syslog_level;//表示日誌等級,默認值爲LOG_ALERT.

int scan_num_hosts;//表示存儲端口掃描信息的哈西表的大小

int scan_delay;//表示在掃描檢測中,兩端口掃描的間隔時間

int scan_num_ports;//表示相同源地址必須掃描的tcp端口數目

void (*no_mem)(char *);//當libnids發生內存溢出時被調用

int
(*ip_filter)();//函數指針,此函數可以用來分析ip數據包,當有ip數據包到達時,此函數被調用.默認值爲nids_ip_filter,該函數的定義如下:

static int nids_ip_filter(struct ip * x,int len)

char *pcap_filter;//表示過濾規則

int promisc;//表示網卡模式,非0爲混雜模式,否則爲非混雜模式,默認值爲1

int one_loop_less;//表示捕獲數據返回的時間,以豪秒計算.默認值爲1024

int pcap_timeout;

};

在Libnids中用nids_prm數據結構定義了一個全局變量nids_params,其定義和初始值如下:

struct nids_prm nids_params={

1040,//n_tcp_streams

256,//n_hosts

NULL,//device

NULL,//filename

168,//sk_buff_size

-1,//dev_addon

nids_syslog,//syslog()

LOG_ALERT,//syslog_level

256,//scan_num_hosts

3000,//scan_delay

10,//scan_num_prots

nids_no_mem,//no_mem()

nids_ip_filter,//ip_filter

NULL,//pcap_filter

1,//promisc

0,//one_loop_less

1024//pcap_timeout

}在使用Libnids開發程序時,可以首先對nids_params全局變量的值進行修改,這樣對整個Libnids就全部有效

5.nids_chksum_ctl:
描述的是計算校驗和

struct nids_chksum_ctl

{

u_int netaddr;

u_int mask;

u_int
action;//表示動作,如果是NIDS_DO_CHKSUM,表示要計算校驗和;如果是NIDS_DONT_CHKSUM表示不計算校驗和

u_int reserved;

}

三、Libnids函數

1.基本函數

(1)int nids_init(void);//對libnids進行初始化

(2)void nids_run(void);//運行Libnids,進入循環捕獲數據包狀態.

(3)int nids_getfd(void);//獲得文件描述號

(4)int nids_dispatch(int cnt)//功能是調用Libpcap中的捕獲數據包函數pcap_dispatch().

(5)int nids_next(void)//調用Libpcap中的捕獲數據包函數pcap_next()

(6)void nids_register_chksum_ctl(struct nids_chksum_ctl *ptr,int
nr)//決定是否計算校驗和,它是根據數據結構nids_chksum_ctl中的action進行決定的

2.IP碎片函數

(1)void
nids_register_ip_frag(void(*))//此函數的功能是註冊一個能夠檢測所有IP數據包的回調函數,包括IP碎片

eg:nids_register_ip_frag(ip_frag_function);

這樣就定義了一個回調函數ip_frag_function的定義類型如下:

void ip_frag_function(struct ip *a_packet,int len)

(2)void nids_register_ip(void(*))//此函數定義一個回調函數,此回調函數可以接受正常的IP數據包,eg:

nids_register_ip(ip_function);

此回調函數的定義類型如下:

void ip_function(struct ip * a_packet)

3.TCP數據流重組函數

(1)void nids_register_tcp(void(*))

回調函數的功能是註冊一個TCP連接的回調函數,回調函數的類型定義如下:

void tcp_callback(struct tcp_stream *ns,void **param);

其中參數ns表示一個tcp連接的所有信息,它的類型是tcp_stream數據結構;參數param表示要傳遞的連接參數信息,可以指向一個TCP連接的私有數據

(2)void nids_killtcp(struct tcp_stream * a_tcp)//此函數功能是終止TCP連接

(3)void nids_discard(struct tcp_stream *a_tcp,int
num)//丟棄num字節TCP數據,用於存儲更多的數據

4.UDP註冊函數

(1)void nids_register_udp(void(*));

此函數的功能註冊一個分析UDP協議的回調函數,回調函數的類型定義如下:

void udp_callback(struct tuple4 *addr,char *buf,int len,struct ip *
iph);

其中參數addr表示的是端口的信息,參數buf表示UDP協議負載數據內容,參數len
表示UDP負載數據的長度;參數iph表示一個IP數據包,包括IP首部,UDP首部以及UDP負載內容

四、利用Libnids開發的流程

用函數nids_init()進行初始化。

然後註冊相應的回調函數。不同的回調函數實現不同的功能

最後利用函數nids_run()進入循環捕獲數據包的狀態。

2.3.2 安裝過程
sudo apt install libnids-dev

在這裏插入圖片描述

2.4 libglib2.0

2.4.1 glib簡介

glib庫是Linux平臺下最常用的C語言函數庫,它具有很好的可移植性和實用性。
glib是Gtk +庫和Gnome的基礎。glib可以在多個平臺下使用,比如Linux、Unix、Windows等。glib爲許多標準的、常用的C語言結構提供了相應的替代物。

2.4.2 安裝過程
sudo apt install libglib2.0-dev

在這裏插入圖片描述

3.Qt安裝

3.1 Qt簡介

Qt(官方發音 [kju:t],音同 cute)是一個跨平臺C++圖形用戶界面應用程序開發框架。

Qt是用於臺式機,嵌入式和移動設備的跨平臺應用程序開發框架。支持的平臺包括Linux,OS X,Windows,VxWorks,QNX,Android,iOS,BlackBerry,Sailfish OS等。
Qt本身並不是一種編程語言。它是用C ++編寫的框架。預處理程序MOC(元對象編譯器)用於擴展C ++語言,使其具有信號和插槽等功能。在編譯步驟之前,MOC將解析使用Qt擴展C ++編寫的源文件,並從中生成符合標準的C ++源。因此,框架本身和使用它的應用程序/庫可以由任何符合標準的C ++編譯器(如Clang,GCC,ICC,MinGW和MSVC)進行編譯。
Qt帶有自己的名爲Qt Creator的集成開發環境(IDE)。它運行在Linux,OS X和Windows上,並提供智能代碼完成,語法突出顯示,集成的幫助系統,調試器和分析器集成,以及所有主要版本控制系統(例如git,Bazaar)的集成。除了Qt Creator,Windows上的開發人員還可以使用Qt的Visual Studio加載項。其他IDE(如KDevelop的關於KDE)也可以使用。但是,當然根本不強制使用任何IDE。

3.2 安裝過程

sudo apt install qtcreator

在這裏插入圖片描述

sudo apt-get install build-essential
sudo apt-get install cmake qt5-default qtcreator

在這裏插入圖片描述
下好以後桌面上並沒有出現Qt的圖標,於是從啓動器去查找程序。
方法是:點擊桌面,按【Windows】鍵,搜索Qt:
在這裏插入圖片描述
爲了下次方便,我們右鍵,將它鎖定到啓動器:
在這裏插入圖片描述

4.完成開發環境的測試(包括Qt運行的配置)

1.新建項目:
在這裏插入圖片描述
2.這裏用之前寫的HTTP協議抓包程序進行測試:
在這裏插入圖片描述

#include"nids.h"   //Libnids的頭文件,必須包含
#include<ctype.h>
#include<string.h>
#include<nids.h>
#include<stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

char ascii_string[10000];
char *char_to_ascii(char ch)
{
    char *string;
    ascii_string[0] = 0;
    string = ascii_string;
    if (isgraph((ch)))
    {
        *string++ = ch;
    }
    else if (ch == ' ')
    {
        *string++ = ch;
    }
    else if (ch == '\n' || ch == '\r')
    {
        *string++ = ch;
    }
    else
    {
        *string++ = '.';
    }
    *string = 0;
    return ascii_string;
}

//下面的函數是對瀏覽器接收的數據進行分析
void parse_client_data(char content[],int number)
{
    char temp[1024];
    char str1[1024];
    char str2[1024];
    char str3[1024];
    int i;
    int k;
    int j;
    char entity_content[1024];
    if (content[0] != 'H' && content[1] != 'T' && content[2] != 'T' && content[3] != 'P')
    {
        printf("實體內容爲(續):\n");
        for (i - 0;i < number;i++)
        {
            printf("%s",char_to_ascii(content[i]));
        }
        printf("\n");
    }
    else
    {
        for (i = 0;i < strlen(content);i++)
        {
            if (content[i] != '\n')
            {
                k++;
                continue;
            }
            for (j = 0;j < k;j++)
                temp[j] = content[j + i - k];
            temp[j] = '\0';
            if (strstr(temp,"HTTP"))
            {
                printf("狀態行爲:");
                printf("%s\n",temp);
                sscanf(temp,"%s %s",str1,str2);
                printf("HTTP協議爲:%s\n",str1);
                printf("狀態代碼爲:%s\n",str2);
            }
            if (strstr(temp,"Date"))
            {
                printf("當前的時間爲(Date):%s\n",temp + strlen("Date:"));
                printf("%s\n",temp);
            }
            if (strstr(temp,"Server"))
            {
                printf("服務器爲(Server):%s\n",temp + strlen("Server:"));
                printf("%s\n",temp);
            }
            if (strstr(temp,"Cache-Control"))
            {
                printf("緩存機制爲:(Cache-Control):%s\n",temp + strlen("Cache-Control"));
                printf("%s\n",temp);
            }
            if (strstr(temp,"Expires"))
            {
               printf("資源期限爲(Expires):%s\n",temp + strlen("Expires:"));
               printf("%s\n",temp);
            }
            if (strstr(temp,"Last-Modified"))
            {
               printf("最後一次修改時間爲(Last-Modified):%s\n",temp + strlen("Last-Modified:"));
               printf("%s\n",temp);
            }
            if (strstr(temp,"ETag"))
            {
               printf("ETag爲(ETag):%s\n",temp + strlen("ETag:"));
               printf("%s\n",temp);
            }
            if (strstr(temp,"Accept-Ranges"))
            {
               printf("Accept-Ranges爲(Accept-Ranges):%s\n",temp + strlen("Accept-Ranges:"));
               printf("%s\n",temp);
            }
            if (strstr(temp,"Content-Length"))
            {
               printf("內容長度爲(Content-Length):%s\n",temp + strlen("Content-Length:"));
               printf("%s\n",temp);
            }
            if (strstr(temp,"Connection"))
            {
               printf("連接狀態(Connection):%s\n",temp + strlen("Connection:"));
               printf("%s\n",temp);
            }
            if (strstr(temp,"Content-Type"))
            {
               printf("內容類型(Content-Type):%s\n",temp + strlen("Content-Type:"));
               printf("%s\n",temp);
            }
            //獲取實體內容
            if ((content[i] == '\n') && (content[i + 1] == '\r'));
            {
                if (i + 3 == strlen(content))
                {
                    printf("無實體內容\n");
                    break;
                }
                for (j = 0;j < number - i - 3;j++)
                    entity_content[j] = content[i + 3 + j];
                entity_content[j] = '\0';
                printf("實體內容爲:\n");
                for (i = 0;i < j;i++)
                {
                    printf("%s",char_to_ascii(entity_content[i]));
                }
                printf("\n");
                break;
            }
            k = 0;
        }
    }
}

//下面的函數是對Web服務器接收到的數據進行分析
void parse_server_data(char content[],int number)
{
    char temp[1024];
    char str1[1024];
    char str2[1024];
    char str3[1024];
    int i;
    int k;
    int j;
    char entity_content[1024];
    for (i = 0; i < strlen(content);i++)
    {
        if (content[i] != '\n')
        {
            k++;
            continue;
        }
        for (j = 0;j < k;j++)
            temp[j] = content[j + i - k];
        temp[j] = '\0';
        if (strstr(temp,"GET"))
        {
             printf("請求行爲:");
             printf("%s\n",temp);
             sscanf(temp,"%s %s %s",str1,str2,str3);
             printf("使用的命令爲:%s\n",str1);
             printf("獲得的資源爲:%s\n",str2);
             printf("HTTP協議類型爲:%s\n",str3);
        }
        if (strstr(temp,"Accept"))
        {
             printf("接收的文件包括(Accept):%s\n",temp + strlen("Accept:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"Referer"))
        {
             printf("偏移地址爲(Referer):%s\n",temp + strlen("Referer:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"Accept-Language"))
        {
             printf("使用的語言爲(Accept-Language):%s\n",temp + strlen("Accept-Language:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"Accept-Encoding"))
        {
             printf("接收的編碼方式爲(Accept-Encoding):%s\n",temp + strlen("Accept-Encoding:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"If-Modified-Since"))
        {
             printf("上次修改時間爲(If-Modified-Since):%s\n",temp + strlen("If-Modified-Since:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"If-None-Match"))
        {
             printf("If-None-Match爲(If-None-Match):%s\n",temp + strlen("If-None-Match:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"User-Agent"))
        {
             printf("用戶的瀏覽器信息爲(User-Agent):%s\n",temp + strlen("User-Agent:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"Host"))
        {
             printf("訪問的主機爲(Host):%s\n",temp + strlen("Host:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"Connection"))
        {
             printf("連接狀態爲(Connection):%s\n",temp + strlen("Connection:"));
             printf("%s\n",temp);
        }
        if (strstr(temp,"Cookie"))
        {
             printf("Cookie爲(Cookie):%s\n",temp + strlen("Cookie:"));
             printf("%s\n",temp);
        }
        //獲取實體內容
        if ((content[i] == '\n') && (content[i + 1] == '\r') && (content[i + 2] == '\n'))
        {
            if (i + 3 == strlen(content))
            {
                printf("無實體內容\n");
                break;
            }
            for (j - 0;j < strlen(content) - i - 3;j++)
                entity_content[j] - content[i + 3 + j];
            entity_content[j] = '\0';
            printf("實體內容爲:\n");
            printf("%s",entity_content);
            printf("\n");
            break;
        }
        k = 0;
    }
}

//下面是回調函數,實現對HTTP協議的分析
void http_protocol_callback(struct tcp_stream *tcp_http_connection,void **param)
            {
                  char address_content[1024];
                  char content[65535];
                  char content_urgent[65535];
                  struct tuple4 ip_and_port = tcp_http_connection->addr;
                  strcpy(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.saddr))));
                  sprintf(address_content + strlen(address_content)," : %i",ip_and_port.source);
                  strcat(address_content,"<----->");
                  strcat(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.daddr))));
                  sprintf(address_content + strlen(address_content)," : %i",ip_and_port.dest);
                  strcat(address_content,"\n");
                  if (tcp_http_connection->nids_state == NIDS_JUST_EST)
                  {
                      if (tcp_http_connection->addr.dest != 80)   //只捕獲HTTP協議數據包
                      {
                          return;
                      }
                      tcp_http_connection->client.collect++;   //瀏覽器接收數據
                      tcp_http_connection->server.collect++;   //Web服務器端接收數據
                      printf("\n\n\n======================================\n");
                      return;
                  }
                  if (tcp_http_connection->nids_state == NIDS_CLOSE)
                  {
                      printf("-----------------------------------\n");
                      printf("%s連接正常關閉...\n",address_content);   //連接正常關閉
                      return;
                  }
                  if (tcp_http_connection->nids_state == NIDS_RESET)
                  {
                      printf("-----------------------------------\n");
                      printf("%s連接被RST關閉...\n",address_content);   //連接被RST關閉
                      return;
                  }
                  if (tcp_http_connection->nids_state == NIDS_DATA)
                  {
                      struct half_stream *hlf;
                      if (tcp_http_connection->client.count_new)   //瀏覽器接收數據
                      {
                          hlf = &tcp_http_connection->client;   //hlf表示瀏覽器接收到的數據
                          strcpy(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.saddr))));
                          sprintf(address_content + strlen(address_content)," : %i",ip_and_port.source);
                          strcat(address_content,"<-----");
                          strcat(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.daddr))));
                          sprintf(address_content + strlen(address_content)," : %i",ip_and_port.dest);
                          strcat(address_content,"\n");
                          printf("\n");
                          printf("%s",address_content);
                          printf("瀏覽器接收數據...\n");
                          printf("\n");
                          memcpy(content,hlf->data,hlf->count_new);
                          content[hlf->count_new] = '\0';
                          parse_client_data(content,hlf->count_new);   //分析瀏覽器接收到的數據
                      }
                      else
                      {
                          hlf = &tcp_http_connection->server;   //hlf表示Web服務器的TCP連接端
                          strcpy(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.saddr))));
                          sprintf(address_content + strlen(address_content)," : %i",ip_and_port.source);
                          strcat(address_content,"----->");
                          strcat(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.daddr))));
                          sprintf(address_content + strlen(address_content)," : %i",ip_and_port.dest);
                          strcat(address_content,"\n");
                          printf("\n");
                          printf("%s",address_content);
                          printf("服務器接收數據...\n");
                          printf("\n");
                          memcpy(content,hlf->data,hlf->count_new);
                          content[hlf->count_new] = '\0';
                          parse_server_data(content,hlf->count_new);   //分析Web服務器接收到的數據
                      }
                  }
                  return;
        }


//主函數
void main()
{
        struct nids_chksum_ctl tmp;   //這5行是關閉數據校驗和
        tmp.netaddr = 0;
        tmp.mask = 0;
        tmp.action = 1;
        nids_register_chksum_ctl(&tmp,1);


    if (!nids_init())   //Libnids初始化
     {
         printf("出現錯誤:%s\n",nids_errbuf);
         exit(1);
     }
     nids_register_tcp(http_protocol_callback);   //註冊回調函數
     nids_run();   //進入循環捕獲數據包狀態
}

  • 開發注意:要在主函數中關閉網卡校驗和,否則抓包程序運行後終端沒有任何反應。
    在這裏插入圖片描述

3.配置Qt運行額外的參數:

LIBS="-lpcap -lnet -lnids -lgthread-2.0"

在這裏插入圖片描述
4.然後運行程序:
在這裏插入圖片描述
在這裏插入圖片描述
5.用虛擬機自帶的瀏覽器去訪問一個使用HTTP協議的URL。
用Google語法搜一下,找一個http的網站:
在這裏插入圖片描述
在這裏插入圖片描述
6.抓包成功:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章