16.2 ARP 主機探測技術

来源:https://www.cnblogs.com/LyShark/archive/2023/10/21/17778431.html
-Advertisement-
Play Games

ARP (Address Resolution Protocol,地址解析協議),是一種用於將 `IP` 地址轉換為物理地址(`MAC地址`)的協議。它在 `TCP/IP` 協議棧中處於鏈路層,為了在區域網中能夠正確傳輸數據包而設計,由協議數據單元和對應的操作命令組成。`ARP` 既可以由操作系統處... ...


ARP (Address Resolution Protocol,地址解析協議),是一種用於將 IP 地址轉換為物理地址(MAC地址)的協議。它在 TCP/IP 協議棧中處於鏈路層,為了在區域網中能夠正確傳輸數據包而設計,由協議數據單元和對應的操作命令組成。ARP 既可以由操作系統處理,也可以由網卡處理。

該協議的作用是通過一個區域網上的互聯網協議(IP)地址來查詢對應的物理硬體地址,如數據包發送到路由器時,ARP 協議將使用嵌入在數據包中的目的 IP 地址查找對應的物理地址,路由器根據獲取的 MAC 地址轉發數據包到下一個網路。

協議工作過程如下:

  • 主機A通過查找其ARP緩存表,比對目標的IP地址是否存在於ARP緩存表中。
  • 如果目標機器的IP地址不存在於本地ARP緩存表中,則主機A需要進行ARP請求過程,它廣播一個ARP請求。
  • 當其他主機收到這個請求時,它會比對主機A設置的這個目標IP地址和自己的IP地址是否一致。
  • 如果一致的話,說明被查詢的這個IP地址正是自己的IP地址,此時這個主機就會直接向主機A發送ARP響應數據包。
  • 主機A在獲得了目標主機的MAC地址信息之後,會把這個MAC地址信息存儲到自己的ARP緩存表中,以便以後再次使用。

ARP主機探測原理是通過發送 ARP 查詢報文,來獲取目標主機的 MAC 地址,進而獲取目標主機的 IP 地址。

主機探測的具體實現步驟如下:

  • 構造一個ARP查詢報文,報文中的目標IP地址為需要探測的主機IP地址,源IP地址為探測主機的IP地址,源MAC地址為探測主機網卡的MAC地址。
  • 發送ARP查詢報文。如果目標主機線上,且相應功能正常,它將返回一個ARP響應報文,其中包含目標主機的MAC地址。
  • 接收到ARP響應報文之後,分析報文,從中提取出目標主機的MAC地址和IP地址等信息。

Windows系統下,我們可以調用SendARP()函數實現ARP探測,該函數用於發送ARP請求到指定的 IP 地址,以獲取其 MAC 地址。該函數參數傳入目標 IP 地址時能夠返回對應 MAC 地址。

SendARP 函數原型如下:

DWORD SendARP(
    IN IPAddr DestIP,             // 目標 IP 地址
    IN IPAddr SrcIP,              // 源 IP 地址(可以為 0)
    OUT PULONG pMacAddr,          // 接收目標 MAC 地址
    IN OUT PULONG PhyAddrLen      // 接收目標 MAC 地址的緩衝區大小,單位為位元組
);

該函數的第一個參數為目標IP地址,第二個參數為本地主機IP地址(可以填 0),第三個參數為接收返回的目標 MAC 地址的指針,第四個參數為指向緩衝區大小的指針。

當調用 SendARP() 函數時,如果目標 IP 地址是在同一物理網路中,則返回目標 IP 地址對應的 MAC 地址,並且函數返回值為 NO_ERROR。如果目標 IP 地址無效,或者無法獲得對應的 MAC 地址,則函數返回值為錯誤代碼,應該根據錯誤代碼來進行處理。

如下代碼實現了掃描區域網中指定ARP主機地址的功能。代碼主要使用了SendARP()函數來查詢目標主機的MAC地址,並將結果輸出。具體實現步驟如下:

#include <stdio.h>
#include <winsock2.h>
#include <IPHlpApi.h>

#pragma comment (lib,"ws2_32.lib")  
#pragma comment (lib,"iphlpapi.lib")

// 掃描區域網中指定ARP主機地址
void ArpScan(char *LocalIP,char *TargetIP)
{
  ULONG localIP = inet_addr(LocalIP);
  ULONG targetIP = inet_addr(TargetIP);

  ULONG macBuf[2] = { 0 };
  ULONG macLen = 6;

  DWORD retValue = SendARP(targetIP, localIP, macBuf, &macLen);

  unsigned char *mac = (unsigned char*)macBuf;
  printf("IP: %-12s --> MAC: ", TargetIP);
  for (int x = 0; x < macLen; x++)
  {
    printf("%.2X", mac[x]);
    if (x != macLen - 1)
      printf("-");
  }
  printf("\n");
}

int main(int argc,char * argv[])
{
  for (int x = 1; x < 100; x++)
  {
    char target[32] = { 0 };
    sprintf(target, "192.168.1.%d", x);
    ArpScan("192.168.1.2", target);
  }
  system("pause");
  return 0;
}

根據埠探測中所使用的方法,實現多線程也很容易,如下代碼實現了使用多線程方式掃描區域網記憶體活的主機。代碼中使用 SendARP() 函數來探測目標主機是否存活,並使用多線程方式來加快掃描速度,同時使用臨界區來控制多線程條件下的輸出效果。

具體實現過程如下:

  • 定義 checkActive() 函數,該函數使用 SendARP() 函數來判斷目標主機是否存活。如果目標主機存活,則在屏幕上輸出其 IPMAC 地址。

  • 定義 threadProc() 函數來作為多線程的回調函數。該函數接收一臺主機的 IP 地址,並調用 checkActive() 函數來探測該主機是否線上。

  • main() 函數中,定義開始和結束的 IP 地址,並使用 for 迴圈遍歷這個 IP 地址段。在迴圈中,使用 CreateThread() 函數來創建多個線程,每個線程負責探測其中一臺主機是否線上。

  • checkActive() 函數中,多線程會涉及到在界面上的輸出,為了控制多線程在輸出上的次序,使用了 EnterCriticalSection()LeaveCriticalSection() 函數來表示臨界區,只有進入臨界區的線程能夠列印輸出,其他線程需要等待進入臨界區。

#include <stdio.h>
#include <winsock2.h>
#include <iphlpapi.h>

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"iphlpapi.lib")

// 臨界區,控制多線程列印順序
CRITICAL_SECTION g_critical;

bool checkActive(in_addr ip)
{
  ULONG dstMac[2] = { 0 };
  memset(dstMac, 0xff, sizeof(dstMac));
  ULONG size = 6;
  HRESULT re = SendARP(ip.S_un.S_addr, 0, dstMac, &size);

  if (re == NO_ERROR && size == 6)
  {
    // 線程進入臨界區,其他線程不能再進入,控制多線程在界面上的列印順序
    EnterCriticalSection(&g_critical);

    printf("[+] 發現存活主機: %-15s ---> MAC :", inet_ntoa(ip));
    BYTE *bPhysAddr = (BYTE *)& dstMac;
    for (int i = 0; i < (int)size; i++)
    {
      // 如果是mac地址的最後一段,就輸出換行
      if (i == (size - 1))
      {
        printf("%.2X\n", (int)bPhysAddr[i]);
      }
      else
      {
        // 否則沒有到最後一段,依舊輸出,但不換行
        printf("%.2X-", (int)bPhysAddr[i]);
      }
    }

    // 線程離開臨界區,其他線程能夠繼續進入
    LeaveCriticalSection(&g_critical);
    return true;
  }
  else
  {
    return false;
  }
}

// 啟動多線程
DWORD WINAPI threadProc(LPVOID lpThreadParameter)
{
  in_addr ip;
  ip.S_un.S_addr = (ULONG)lpThreadParameter;
  checkActive(ip);
  return 0;
}

int main(int argc, char *argv[])
{
  in_addr ip_start, ip_end;

  // 定義開始IP
  ip_start.S_un.S_addr = inet_addr("192.168.9.1");

  // 定義結束IP
  ip_end.S_un.S_addr = inet_addr("192.168.9.254");

  // 迴圈探測主機

  //初始臨界區
  InitializeCriticalSection(&g_critical);

  for (in_addr ip = ip_start; ip.S_un.S_addr < ip_end.S_un.S_addr; ip.S_un.S_un_b.s_b4++)
  {
    printf("探測: %s \r", inet_ntoa(ip));
    CreateThread(NULL, 0, threadProc, (LPVOID)ip.S_un.S_addr, 0, 0);
  }

  system("pause");
  return 0;
}

編譯並運行上述代碼片段,則會探測192.168.9.1192.168.9.254網段記憶體活的主機,並輸出該主機的MAC信息,輸出效果圖如下所示;

本文作者: 王瑞
本文鏈接: https://www.lyshark.com/post/57dc46.html
版權聲明: 本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!

文章作者:lyshark
文章出處:https://www.cnblogs.com/LyShark/p/17778431.html
本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通過前面13天的學習,對Dart基礎有了系統的熟悉,今天我們開始學習Dart類和對象,本文主要學習Dart類,包括類方法,構造器,對象類型,實例變數,隱性介面,類變數和類方法等…… ...
  • Python有兩個基本的迴圈命令: while迴圈 for迴圈 while迴圈 使用while迴圈,我們可以在條件為真的情況下執行一組語句。 示例,列印i,只要i小於6: i = 1 while i < 6: print(i) i += 1 註意:記得增加i的值,否則迴圈將永遠繼續下去。 while ...
  • 目錄 Spring簡介 Spring項目 Bean管理 基於xml的Bean管理 創建對象 屬性註入 基於xml+註解的Bean管理 創建對象 屬性註入 基於純註解的Bean管理 內容 Spring簡介 Spring是什麼 Spring是於2003 年興起的一個輕量級的Java的開放源代碼的設計層面 ...
  • 目錄1 本章預覽2 簡單題舉例2.1 題目描述2.2 題目解析2.3 題解2.4 涉及基礎語法3 中等題舉例3.1 題目描述3.2 題目解析3.3 題解3.4 涉及基礎語法4 本章小結 1 本章預覽 事實上本章並不會去講述go語言的基礎情況,而是去介紹如何使用Leetcode去幫助我們去學習go語言 ...
  • 安裝: go install github.com/jan-bar/interesting/findModVer@latest 執行:findModVer d:\myproject 結果如下圖所示: 根據結果可以找到哪個依賴導致google.golang.org/grpc v1.45.0使用了這個版 ...
  • 本文介紹在C++語言中,使用一個函數,並返回兩個及以上、同類型或不同類型的返回值的具體方法。 對於C++語言而言,其不能像Python等語言一樣在一個函數中返回多個返回值;但是我們也會經常遇到需要返回兩個甚至更多個值的需求。針對這種情況,我們可以通過pair、tuple(元組)等數據結構,實現C++ ...
  • 1. 什麼是虛擬線程 虛擬線程是JDK21版本正式發佈的一個新特性。虛擬線程和平臺線程主要區別在於,虛擬線程在運行周期內不依賴操作系統線程:它們與硬體脫鉤,因此被稱為“虛擬”。這種解耦是由JVM提供的抽象層賦予的。 虛擬線程的運行成本遠低於平臺線程。它們消耗的記憶體要少得多。這就是為什麼我們可以創建數 ...
  • 大家好,我是大彬~ 今天跟大家分享知識星球小伙伴關於【非科班轉碼如何補基礎】的提問。 往期星球提問整理: 讀博?找工作? 性格測試真的很重要 想找一份實習工作,需要準備什麼 球友提問: 大彬大佬,想問下非科班要補哪些基礎? 求推薦視頻,國內國外都行。 大彬的回答: 你好,我也是非科班轉碼的,Java ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...