zoukankan      html  css  js  c++  java
  • VC++实现IP与ARP信息获取,可以同理实现APR攻击


    ARP(Address Resolution Protocol,地址解析协议)是获取物理地址的一个TCP/IP协议。某节点的IP地址的ARP请求被广播到网络上后,这个节点会收到确认 其物理地址的应答,这样的数据包才能被传送出去。RARP(逆向ARP)经常在无盘工作站上使用,以获得它的逻辑IP地址。


    地址解析协议(Address Resolution Protocol,ARP)是在仅知道主机的IP地址时确  地址解析协议定其物理地址的一种协议。

    因IPv4和以太网的广泛应用,其主要用作将IP地址翻译为以太网的MAC地址,但其也能在ATM( 异步传输模式)和FDDIIP(Fiber Distributed Data Interface 光纤分布式数据接口)网络中使用。

    从IP地址到物理地址的映射有两种方式:表格方式和非表格方式。

    ARP具体说来就是将网络层(IP层,也就是相当于OSI的第三层)地址解析为数据连接层(MAC层,也就是相当于OSI的第二层)的MAC地址。
     

    在TCP/IP协议中,A给B发送IP包,在报头中需要填写B的IP为目标地址,但这个IP包在以太网上传输的时候,还需要进行一次以太包的封装,在这个以太包中,目标地址就是B的MAC地址.


      计算机A是如何得知B的MAC地址的呢?解决问题的关键就在于ARP协议。


      在A不知道B的MAC地址的情况下,A就广播一个ARP请求包,请求包中填有B的IP(192.168.1.2),以太网中的所有计算机都会接收这个请求,而正常的情况下只有B会给出ARP应答包,包中就填充上了B的MAC地址,并回复给A。


      A得到ARP应答后,将B的MAC地址放入本机缓存,便于下次使用。


      本机MAC缓存是有生存期的,生存期结束后,将再次重复上面的过程。


      ARP协议并不只在发送了ARP请求才接收ARP应答。当计算机接收到ARP应答数据包的时候,就会对本地的ARP缓存进行更新,将应答中的IP和MAC地址存储在ARP缓存中。因此,当局域网中的某台机器B向A发送一个自己伪造的ARP应答,而如果这个应答是B冒充C伪造来的,即IP地址为C的IP,而MAC地址是伪造的,则当A接收到B伪造的ARP应答后,就会更新本地的ARP缓存,这样在A看来C的IP地址没有变,而它的MAC地址已经不是原来那个了。由于局域网的网络流通不是根据IP地址进行,而是按照MAC地址进行传输。所以,那个伪造出来的MAC地址在A上被改变成一个不存在的MAC地址,这样就会造成网络不通,导致A不能Ping通C!这就是一个简单的ARP欺骗。


    #include <stdio.h>
    #include <windows.h>
    #include <Iphlpapi.h>
    
    #pragma comment(lib, "Iphlpapi.lib")
    #pragma comment(lib, "WS2_32.lib")
    
    
    PMIB_IPNETTABLE MyGetIpNetTable(BOOL bOrder);
    void MyFreeIpNetTable(PMIB_IPNETTABLE pIpNetTable);
    PMIB_IPADDRTABLE MyGetIpAddrTable(BOOL bOrder);
    void MyFreeIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable);
    BOOL InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[]);
    
    
    // 根据IP地址表,将接口索引转化为IP地址
    // pIpAddrTable是IP地址表
    // dwIndex是接口索引
    // 函数执行成功之后,str将包含接口的IP地址
    BOOL InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[])
    {
        char* szIpAddr;
    
        if(pIpAddrTable == NULL ||  str == NULL)
            return FALSE;
        str[0] = '\0';
    	// 遍历IP地址表,查找索引dwIndex对应的IP地址
        for(DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++)
        {
            if(dwIndex == pIpAddrTable->table[dwIdx].dwIndex)
            {
    			// 以字符串的形式返回查询结果
                szIpAddr = inet_ntoa(*((in_addr*)&pIpAddrTable->table[dwIdx].dwAddr));
                if(szIpAddr)
                {
                    strcpy(str, szIpAddr);
                    return TRUE;
                }
                else
                    return FALSE;
            }
        }
        return FALSE;
    }
    
    //----------------------------------------------------------------------------
    //   ARP表将以如下格式打印出来:
    // Interface: 157.61.239.34 on Interface 2
    //   Internet Address      Physical Address      Type
    //   159.61.230.39         00-aa-00-61-5d-a4     dynamic
    //
    // Interface: 157.54.178.219 on Interface 3
    //   Internet Address      Physical Address      Type
    //   159.54.170.1          00-10-54-42-c0-88     dynamic
    //   159.54.170.113        00-aa-00-c0-80-2e     dynamic
    //----------------------------------------------------------------------------
    
    int main()
    {
        DWORD i, dwCurrIndex;
        char szPrintablePhysAddr[256];
        char szType[128];
        char szIpAddr[128];
    
    	// 首先获取ARP表
    	PMIB_IPNETTABLE pIpNetTable = MyGetIpNetTable(TRUE); 
        if (pIpNetTable == NULL)
        {
            printf( "pIpNetTable == NULL in line %d\n", __LINE__);
            return -1;
        }
    
    	// 获取IP地址表,以便根据它将ARP表项中的接口索引转化为IP地址
    	PMIB_IPADDRTABLE pIpAddrTable = MyGetIpAddrTable(TRUE);
    
    	// 当前的适配器索引。注意,ARP表应该按照接口索引排序
        dwCurrIndex = pIpNetTable->table[0].dwIndex;
        if(InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr))
        {
            printf("\nInterface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex);
            printf("  Internet Address      Physical Address      Type\n");
        }
        else
        {
            printf("Error: Could not convert Interface number 0x%X to IP address.\n",
                        pIpNetTable->table[0].dwIndex);
            return -1;
        }
        
    	// 打印出索引为dwCurrIndex的适配器上的ARP表项
        for(i = 0; i < pIpNetTable->dwNumEntries; ++i)
        {
    		// 不相等则说明要打印下一个适配器上的ARP表项了
            if(pIpNetTable->table[i].dwIndex != dwCurrIndex)
            {
                dwCurrIndex = pIpNetTable->table[i].dwIndex;
                if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr))
                {
                    printf("Interface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex);
                    printf("  Internet Address      Physical Address      Type\n");
                }
                else
                {
                    printf("Error: Could not convert Interface number 0x%X to IP address.\n",
                        pIpNetTable->table[0].dwIndex);
                    return -1;
                }
            }
    
    			// 打印出此ARP表项中的数据
    		// MAC地址
    		u_char *p = pIpNetTable->table[i].bPhysAddr;
            wsprintf(szPrintablePhysAddr, "%02X-%02X-%02X-%02X-%02X-%02X", p[0], p[1], p[2], p[3], p[4], p[5]);
    		// IP地址
    		struct in_addr inadTmp;
            inadTmp.s_addr = pIpNetTable->table[i].dwAddr;
    		// 类型
            switch (pIpNetTable->table[i].dwType)
            {
            case 1:
                strcpy(szType,"other");
                break;
            case 2:
                strcpy(szType,"invalidated");
                break;
            case 3:
                strcpy(szType,"dynamic");
                break;
            case 4: 
                strcpy(szType,"static");
                break;
            default:
                strcpy(szType,"invalidType");
            }
            printf("  %-16s      %-17s     %-11s\n", inet_ntoa(inadTmp), szPrintablePhysAddr, szType);
            
        }
    	return 0;
    }
    
    // 获取IP地址到适配器的映射关系,即ARP表
    
    PMIB_IPNETTABLE MyGetIpNetTable(BOOL bOrder)
    {
    	PMIB_IPNETTABLE pIpNetTable = NULL;
    	DWORD dwActualSize = 0;
    
    	// 查询所需缓冲区的大小
    	if(::GetIpNetTable(pIpNetTable, 
    					&dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
    	{
    		// 为MIB_IPNETTABLE结构申请内存
    		pIpNetTable = (PMIB_IPNETTABLE)::GlobalAlloc(GPTR, dwActualSize);
    		// 获取ARP表
    		if(::GetIpNetTable(pIpNetTable, 
    						&dwActualSize, bOrder) == NO_ERROR)
    		{
    			return pIpNetTable;
    		}
    		::GlobalFree(pIpNetTable);
    	}
    	return NULL;
    }
    
    void MyFreeIpNetTable(PMIB_IPNETTABLE pIpNetTable)
    {
    	if(pIpNetTable != NULL)
    		::GlobalFree(pIpNetTable);
    }
    
    
    PMIB_IPADDRTABLE MyGetIpAddrTable(BOOL bOrder)
    {
    	PMIB_IPADDRTABLE pIpAddrTable = NULL;
    	DWORD dwActualSize = 0;
    
    	// 查询所需缓冲区的大小
    	if(::GetIpAddrTable(pIpAddrTable, 
    					&dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
    	{
    		// 为MIB_IPADDRTABLE结构申请内存
    		pIpAddrTable = (PMIB_IPADDRTABLE)::GlobalAlloc(GPTR, dwActualSize);
    		// 获取IP地址表
    		if(::GetIpAddrTable(pIpAddrTable, 
    						&dwActualSize, bOrder) == NO_ERROR)
    			return pIpAddrTable;
    		::GlobalFree(pIpAddrTable);
    	}
    	return NULL;
    }
    
    void MyFreeIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable)
    {
    	if(pIpAddrTable != NULL)
    		::GlobalFree(pIpAddrTable);
    }
    
    
    
    
    
    
    
    
    
    
    
    /*
    
    
    
    
    
    
    
    void PrintIpAddrTable()
    {
        DWORD i;
        struct in_addr inadTmp1;
        struct in_addr inadTmp2;
        char szAddr[128];
        char szMask[128];
    	
    	PMIB_IPADDRTABLE pIpAddrTable = MyGetIpAddrTable(TRUE);
    
        if (pIpAddrTable == NULL)
        {
            printf( "pIpAddrTable == NULL in line %d\n", __LINE__);
            return;
        }
        printf("ipAdEntAddr\t ifAdEntIfIndex\t ipAdEntNetMask\t ipAdEntBcastAddr\t ipAdEntReasmMaxSize\n");
        for (i = 0; i < pIpAddrTable->dwNumEntries; ++i)
        {
            inadTmp1.s_addr = pIpAddrTable->table[i].dwAddr;
            strcpy(szAddr, inet_ntoa(inadTmp1));
            inadTmp2.s_addr = pIpAddrTable->table[i].dwMask;
            strcpy(szMask, inet_ntoa(inadTmp2));
            printf("  %s\t 0x%X\t %s\t %s\t %u\n",
                    szAddr, 
                    pIpAddrTable->table[i].dwIndex,
                    szMask,
                    (pIpAddrTable->table[i].dwBCastAddr ? "255.255.255.255" : "0.0.0.0"),
                    pIpAddrTable->table[i].dwReasmSize);
    
        }
    
    	MyFreeIpAddrTable(pIpAddrTable);
    }
    
    
    
      */


  • 相关阅读:
    Django入门
    RCNN 研究相关
    [Android UI]View滑动方式总结
    [Android UI]View基础知识
    [Android]Android开发艺术探索第1章笔记
    [Leetcode]017. Letter Combinations of a Phone Number
    java之this关键字
    POJ 1000 A+B
    [Leetcode]016. 3Sum Closest
    [Leetcode]015. 3Sum
  • 原文地址:https://www.cnblogs.com/new0801/p/6177706.html
Copyright © 2011-2022 走看看