Qt:Qt实现飞秋拦截助手—Mac地址扫描器
Qt實現飛秋攔截助手—Mac地址掃描器
前言
準備好了就開干,利用業余時間,開始著手寫 飛秋攔截助手,按照Qt:Qt實現飛秋攔截助手—介紹 中的4步驟來走。4步驟中,Mac地址掃描器是第一步,因為網絡傳輸中 最底層協議 就是網卡層,得到了局域網中的所有IP和對應的物理地址 才會有攻擊的目標,攔截的對象。后面的ARP欺騙和飛秋消息攔截和飛秋欺騙會在這個基礎上添加。
效果
什么都不說,先看看MAC地址掃描器的效果。1.2本機無線網卡,1.6是虛擬機,1.4,1.3是2臺手機,1.1是網關。
關于網卡信息
為啥要讓用戶選擇網卡呢?因為一個主機可能有多個網卡,所以上網的網卡不定,給用戶選擇。本機網卡信息 怎樣獲取呢?請參考:C/C++:Windows編程—代碼獲取本地所有網卡信息(網卡描述,IP地址,子網掩碼,MAC地址)
關于廠商MAC
這里為了方便知道聯網的設備的一些信息,所以加了個網卡廠商,每臺聯網設備的物理地址的前3個字節 表示的是 生產該網卡的廠商,如何獲取呢?http://standards.ieee.org/develop/regauth/oui/oui.txt 這個網站是最新的網卡廠商,這里更新廠商mac,就是從這里去下載廠商列表,然后解析成json文件,從而獲取設備的網卡廠商。
關于Mac地址掃描器原理
這個仍然得從協議說起,因為網絡協議是人為規定好的,必須遵守。在網絡接口層中有一個ARP協議,叫做地址解析協議,比如說A 主機 想要和 C 主機通信,必須知道C主機的物理地址,主機A 就需要 發送一個ARP請求包,發送給C 然后C收到后 會給A回一個ARP應答包 會攜帶A的物理地址,這樣主機A 的ARP緩存中就會存放 主機C的物理地址,下次發送信息的時候后,就會在以太網首部 填寫主機C的物理地址,就 可以找到目的主機了。
那么我們給局域網的每個IP都發送一個ARP請求包,那么他們給了應答包了 我們不就得到了所有的IP對應的Mac地址了。
來,我們談下具體細節了。
ARP報文結構
我們先ARP報文結構
我們代碼中當然得按照報文結構進行組包。結構體設置如下:
這里我們字段類型最長的uint16_t是2個字節,剛好我們組包也是偶數個字節,根據字節對齊原理,結構體組包后是42字節。注意的是,我們的以太網的目的地址為二進制全1 表示廣播地址,接受的主機 必須無條件接受 并應答,這就是協議 大家必須遵守的。還有字節序問題,2字節及以上才存在字節序問題。
關于Windows下如何發送ARP報文
Windows API中沒有提供接口直接操作網卡層的方法,最底層協議包 操作也只是到 網絡層,那么怎么辦呢?我也是后面發現Windows API 實現不了 才去找的,使用 WinPcap 庫可以實現ARP報文的發送和接受。WinPcap中文技術文檔。
關于使用WireShark抓包工具分析
這工具,博主在大學用過,當時覺得好難好難,這次寫這個軟件,遇到問題了必須分析報文,去用了下,還挺好使的,我們開發肯定不是一下就把報文包 組好然后 就成功的發送了,中間肯定會存在問題,這是需要結合抓包工具配合分析了。下面是成功發送的 ARP報文和ARP應答報文圖。
核心代碼
發送APR請求報文代碼
// 發送ARP報文 void ArpSendThread::run() {if( this->mAdapterHandle == nullptr){qDebug() << "網卡設備沒有開啟";return;}char tmp[18] = {0};Utils::macToHexString(this->mMacAddr,tmp);qDebug() <<"begin:" << tmp;// 構造ARP請求包 ,2字節及以上的 存在大小端對齊問題,需要轉換為網絡字節序ArpPackage package;// 以太網 頭部uint64_t ethBroadcastAddr = 0xffffffffffff;// 6字節 以太網 廣播地址,局域網主機無條件接受memcpy(package.ethHead.destEthAddr,ðBroadcastAddr,6);memcpy(package.ethHead.srcEthAddr,this->mMacAddr,6);package.ethHead.frameType = htons(0x0806);memset(tmp,0,18);Utils::macToHexString(this->mMacAddr,tmp);qDebug() <<"origin:" << tmp;memset(tmp,0,18);Utils::macToHexString(package.ethHead.srcEthAddr,tmp);qDebug() <<"now:" << tmp;// 構造ARP請求體內容package.arpBody.hardType = htons(1);// 以太網地址package.arpBody.protocolType = htons(0x0800); // IP地址package.arpBody.hardLen = 6;package.arpBody.protocolLen = 4;package.arpBody.op = htons(1);memcpy(package.arpBody.srcEthAddr,this->mMacAddr,6);// 硬件廠商 Mac地址 http://standards-oui.ieee.org/oui/oui.txtUtils::htonN(reinterpret_cast<uint8_t*>(&(this->mCurIPAddr)),package.arpBody.srcIpAddr,4);memset(package.arpBody.destEthAddr,0,6);int i = 1;// 往當前局域網中所有IP發送 ARP報文for(uint32_t ipAddr = mNetworkAddr+1; ipAddr < mBroadcastAddr; ipAddr++,i++){if(this->isScan == false)break;if( ipAddr == this->mCurIPAddr)continue;struct in_addr addr;addr.S_un.S_addr = htonl(ipAddr);qDebug() << inet_ntoa( addr);Utils::htonN(reinterpret_cast<uint8_t*>(&(ipAddr)),package.arpBody.destIpAddr,4);int ret = pcap_sendpacket(this->mAdapterHandle,reinterpret_cast<unsigned char*>(&package),42);if( ret != 0){qDebug() << inet_ntoa( addr) << " 發送失敗!" ;}emit sendOne(i);Sleep(100);}// 關閉設備pcap_close(this->mAdapterHandle);// arp數據包發送完畢,通知主線程emit sendDone(); }接受ARP應答報文代碼
void ArpAcceptThread::run(){if( this->mAdapterHandle == nullptr){qDebug() << "網卡設備沒有開啟";return;}int res;struct tm *ltime;char timestr[16];struct pcap_pkthdr *header;const u_char *pkt_data;time_t local_tv_sec;struct bpf_program fcode;QMap<QString,QString> info;// 表達式 (arp[16:2]&0x00010!=0) and (dst host 192.168.1.2)// (arp[6:2]&0x0002!=0) 過濾ARP應答// http://www.ferrisxu.com/WinPcap/html/group__language.html 過濾表達QString exp = QString("(arp[6:2]&0x0002!=0)");// compile the filterif (pcap_compile(this->mAdapterHandle, &fcode, exp.toStdString().c_str() , 1, 0) < 0){qDebug() << "pcap_compile error:" << pcap_geterr(this->mAdapterHandle);}// set the filterif (pcap_setfilter(this->mAdapterHandle, &fcode) < 0){qDebug() << "pcap_setfilter error";}// 獲取數據包while((res = pcap_next_ex( this->mAdapterHandle, &header, &pkt_data)) >= 0){if( this->isAccept == false)break;if(res == 0)// 超時時間到continue;// 將時間戳轉換成可識別的格式local_tv_sec = header->ts.tv_sec;ltime=localtime(&local_tv_sec);strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);fflush(stdout);const ArpPackage *package = reinterpret_cast<const ArpPackage*>(pkt_data);struct in_addr addr ;memcpy(&addr.S_un.S_addr,package->arpBody.srcIpAddr,4);info["ip"] = inet_ntoa(addr);qDebug() << "ip=" << inet_ntoa(addr);// 從視覺上看 macCh已經轉為本地字節序char macCh[18] = {0};Utils::macToHexString(package->arpBody.srcEthAddr,macCh);qDebug() << "mac=" << macCh;info["mac"] = QString(macCh);emit acceptArp(info);}if(res == -1){qDebug() << "Error reading the packets: "<< pcap_geterr(this->mAdapterHandle);}emit acceptDone(); }完整代碼
總的代碼還是挺多的,需要完整工程的點這里進行下載。
總結
以上是生活随笔為你收集整理的Qt:Qt实现飞秋拦截助手—Mac地址扫描器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 十六、定义数据、定义栈
- 下一篇: C 语言的io流