歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux教程

Linux C 原始套接字抓包

抓包分析主機上網浏覽了那些網頁,並把浏覽網頁的網址寫入一個文件。

首先我列舉下我在寫抓包程序所犯下的錯誤。供大家學習參考。

創建原始套接字失敗:

分析原因:剛開始的時候運行程序正常,但是同事覃書芹幫我虛擬機添加了一個虛擬網卡的時候就出現錯誤了。原因說出來很簡單,就是設備名稱錯誤,但是當時我怎麼調都調不出來。最後請他們看了下,一下就看出來了。起碼讓我明白創建套接字的時候要與監聽的網卡名稱相對應,不然要監聽eth1,結果在綁定設備名稱的時候綁成了eth0,那就可能出現錯誤,獲得不到效果。

1.         寫文件總是亂碼:

             分析原因:這個問題在我進公司前以前就犯過,那時候是用C++寫,改正過來比較快。現在在全字符環境下,改了半天,最後發現,在寫的時候直接傳了地址,而沒有加上所傳字符串的長度。導致亂碼,加上一個sizeof()以後問題解決。

2.         浏覽部分網頁時程序出現段錯誤:

      在C環境下,出現段錯誤是很常見的,但對於我來說見的很少,所以出現這類問題的時候顯得還不到哪錯了。原因是我在定位域名字段的時候是以“com\r\n”結束為標記的。因為很多域名都是以.com結尾的,所以就忽略了還有以“.cn”或者以“.net”結尾的域名。我當時就奇怪了,為什麼有的網頁可以,但是訪問有些域名的時候,一點擊就出錯。當找不到.com的時候就會定位到下一個包,定義到一個不存在的內存區域。所以導致段錯誤。

3.         分析的出是tcp包但是分析不出是http包:

      錯誤原因:這個錯誤本來應該是不會出現的,就是我把usleep(1000),改為了sleep(1),都是停止一秒鐘。在while循環裡用sleep(1)可以讓程序暫停執行一秒鐘效果很明顯,但是usleep(1000)就不是很明顯了。在while循環裡用sleep(1)就明顯減慢了抓包的速度,所以就出現抓漏了包的情況。把while循環裡的sleep(1)改成usleep(1000);就行了。

程序過程:

首先抓住經過網卡的數據包,首先檢測他是不是ip包,如果是剝去包頭,然後看是不是tcp包,如果是則檢測它的端口是不是80端口。如果是則證明傳輸的是http協議。然後就可以分析是不是存在“get”字段,是不是存在“host”字段。然後取“host”後面的一個字符串,即我們要得到的主機訪問的域名,即上網記錄。

具體代碼如下:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <net/ethernet.h>

#include <netinet/in.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>

 


#define NOT_UNICAST(e) ((e[0] & 0x01) != 0)


#define APP_NAME "pppc"
#define APP_VER  "0.1.0"

#define PPPOE_DISCOVER  0x8863
#define PPPOE_SESSION   0x8864

#define ETH_ALEN      6
#define NET_FACE_LEN  8

#define TRUE  1
#define FALSE 0

#ifndef ETH_DATA_LEN
#define ETH_DATA_LEN  ETHERMTU
#endif


#pragma pack(1)

typedef struct __st_pconn
{
    unsigned char  myName[NET_FACE_LEN];
    unsigned char  myEth[ETH_ALEN];
    unsigned char  peerEth[ETH_ALEN];
   
    unsigned short session_id;
    int            net_socket;
   
} tPconn;

typedef struct __st_eth_head
{
    unsigned char  dst[ETH_ALEN];
    unsigned char  src[ETH_ALEN];
    unsigned short proto;
   
} tEthHead;

typedef struct __st_pppoe_head
{
    unsigned char  ver:4;
    unsigned char  type:4;
    unsigned char  code;
    unsigned short sid;
    unsigned short len;
   
} tPPPPOEHead;

typedef struct __st_pppoe_pkt_info
{
    tEthHead      ethHead;
    tPPPPOEHead   pppoeHead;
    unsigned char payload[32];
   
} tPPPOEPkt;

typedef struct __st_ip_pkt_head
{
   //unsigned char  hlen:4;
   //unsigned char  ver:4;
   unsigned char  vhlen;
   unsigned char  tos;
   unsigned short tlen;
   unsigned short ipid;
   unsigned short flag;
   unsigned char  ttl;
   unsigned char  proto;
   unsigned short checksum;
   unsigned long  sip;
   unsigned long  dip;
   unsigned char  data[1];
  
} tIPktHead;


typedef struct _st_tcp
{
   unsigned short sport;
   unsigned short dport;
   unsigned long  seq;
   unsigned long  ack;
   unsigned char  offset;
   unsigned char  code;
   unsigned short window;
   unsigned short cksum;
   unsigned short urg;
   unsigned char  data[1];
   
} tTcp;


#pragma pack()

Copyright © Linux教程網 All Rights Reserved