首页
社区
课程
招聘
[讨论]win7 64 ARP -A 是怎么获取网关的MAC地址的,不是传说中这API
发表于: 2016-7-22 11:17 9277

[讨论]win7 64 ARP -A 是怎么获取网关的MAC地址的,不是传说中这API

2016-7-22 11:17
9277
收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我记得好像是获取一个全局变量的,没有API操作的
2016-7-22 13:08
0
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
怪不得拦截不了

神奇的全局,我好好看看

谢谢提醒
2016-7-22 13:45
0
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
实践证明,是读ARP表的 12000b

SenARP 是 12000f
2016-7-23 22:04
0
雪    币: 30030
活跃值: (2467)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
基础太差了。。。
只要你安装了SDK,里面都有例子的。。。
举VC6年代的SDK为例子吧。。。。

Microsoft SDK\Samples\netds\IPHelp\IPArp\

/*---------------------------------------------------------------------------
    Copyright (c) 1998 - 2000  Microsoft Corporation
    Module Name: IpArp.exe   
    File       : IpArp.cpp
    Description: This file demonstrates the use of IP Helper APIs to
                 manipulate ARP cache.
    Author:
    Frank Li           April 16, 1998

   
    Revision History:
    Who         When        What
    --------    --------    ----------------------------------
    Frank Li    04-16-98    created   
---------------------------------------------------------------------------*/

#include "IpArp.h"

void Usage(char * pszProgramName)
{
    printf("%s -s inet_addr eth_addr [if_addr]\n", pszProgramName);
    printf("%s -d inet_addr [if_addr]\n", pszProgramName);
    printf("%s -a\n", pszProgramName);

    printf("-a            Displays current ARP entries by interrogating the current\n");
    printf("              protocol data.\n");
    printf("-d            Deletes the host specified by inet_addr.\n");
    printf("-s            Adds the host and associates the Internet address inet_addr\n");
    printf("              with the Physical address eth_addr.  The Physical address is\n");
    printf("              given as 6 hexadecimal bytes separated by hyphens. The entry\n");
    printf("              is permanent.\n");
    printf("eth_addr      Specifies a physical address.\n");
    printf("if_addr       If present, this specifies the Internet address of the\n");
    printf("              interface whose address translation table should be modified.\n");
    printf("              If not present, the first applicable interface will be used.\n");
    printf("Example:\n");
    printf("   >IpArp -s 157.55.85.212   00-aa-bb-cc-dd-ee 0x2000003 .... Add a static\n");
    printf("                                  arp entry on interface number 0x2000003.\n");
    printf("   >IpArp -a                                    ....Displays the arp table.\n");
    printf("   >IpArp -d 157.55.85.212                      ....Delete an entry.\n");
    WSACleanup();
    exit(1);
}

void _cdecl main(int argc, char **argv)
{
    WORD wVersionRequested = MAKEWORD(1,1);
    WSADATA wsaData;
    int nRet;

    nRet = WSAStartup(wVersionRequested, &wsaData);
    if (wsaData.wVersion != wVersionRequested)
    {   
        fprintf(stderr,"\n Wrong version\n");
        return;
    }

    if ((argc < 2) || (argv[1][0] != '-'))        
        Usage("IpArp");
    if (strlen(argv[1]) > 2)     
        Usage("IpArp");  

    switch(argv[1][1])
    {   
    case 'a':
        // Print arp table
        DoGetIpNetTable();
        break;     
    case 's':      
        //Update or add an ARP Internet/Ethernet Address entry
        if (argc == 4)
            DoSetIpNetEntry(argv[2], argv[3]);
        else if (argc == 5)
            DoSetIpNetEntry(argv[2], argv[3], argv[4]);
        else
            Usage("IpArp");
        break;   
    case 'd':     
        //Delete an Internet/Ethernet Address pair from the ARP table
        if (argc == 3)
            DoDeleteIpNetEntry(argv[2]);
        else if (argc == 4)
            DoDeleteIpNetEntry(argv[2], argv[3]);
        else
            Usage("IpArp");               
        break;  
    default:   
        // help
        Usage("IpArp");        
        break;   
    }
    WSACleanup();
}

void DoGetIpNetTable()
{
    DWORD dwStatus;
    PMIB_IPNETTABLE pIpArpTab = NULL;

    if ( (dwStatus = MyGetIpNetTable(pIpArpTab, TRUE)) == NO_ERROR)
    {
        PrintIpNetTable(pIpArpTab);
        free(pIpArpTab);
        return;
    }
    else if ( dwStatus == ERROR_NO_DATA)
    {
        printf("No entries in arp cache.\n");
        if (pIpArpTab)
            free (pIpArpTab);
        return;
    }
    else
    {
        if (pIpArpTab)
            free (pIpArpTab);
        printf("IpArp returned 0x%x\n", dwStatus);
        return;
    }

}

//----------------------------------------------------------------------------
// Add an arp entry with ip dotted decimal address of "pszDottedInetAddr" and
// physical address of "pszPhysAddr" in 00-aa-bb-cc-dd-ee format on interface
// index of "pszInterface" in hex form.
//----------------------------------------------------------------------------
void DoSetIpNetEntry(char* pszDottedInetAddr, char* pszPhysAddr, char* pszInterface)
{
    DWORD dwInetAddr = 0; // ip address
    DWORD dwStatus;
    BYTE bPhysAddr[MAXLEN_PHYSADDR];

    if (pszDottedInetAddr == NULL || pszPhysAddr == NULL)
    {
        printf("IpArp: Bad Argument\n");
        return;
    }

    dwInetAddr = inet_addr(pszDottedInetAddr); // convert dotted ip addr. to ip addr.
    if (dwInetAddr == INADDR_NONE)
    {
        printf("IpArp: Bad Argument %s\n", pszDottedInetAddr);
        return;
    }

    if (StringToPhysAddr(pszPhysAddr, (char*)bPhysAddr ) != 0)
    {
        printf("IpArp: Bad Argument %s\n", pszPhysAddr);
        return;
    }
    MIB_IPNETROW arpEntry; // an arp entry
    if (pszInterface)
    {
        // User provides a interface index number
        sscanf(pszInterface, "%X",&(arpEntry.dwIndex));
    }
    else
    {
        // add this to the first available interface
        PMIB_IPADDRTABLE pIpAddrTable = NULL;
        if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR)
        {
            printf("IpArp: Couldn't find a interface number to add your arp entry\n");
            return;
        }
        arpEntry.dwIndex = pIpAddrTable->table[0].dwIndex;
        free(pIpAddrTable);
    }
    arpEntry.dwPhysAddrLen = 6;
    memcpy(arpEntry.bPhysAddr, bPhysAddr, 6);
    arpEntry.dwAddr = dwInetAddr;
    arpEntry.dwType = MIB_IPNET_TYPE_STATIC; //static arp entry
    dwStatus = SetIpNetEntry(&arpEntry);
    if (dwStatus != NO_ERROR)
    {
        printf("IpArp: couldn't add (%s, %s), dwStatus = %lu.\n",
                    pszDottedInetAddr, pszPhysAddr, dwStatus);
    }
}
//----------------------------------------------------------------------------
// Delete an arp entry with ip dotted decimal address of "pszDottedInetAddr"
// and interface index of "pszInterface" in hex form.
//----------------------------------------------------------------------------
void DoDeleteIpNetEntry(char* pszDottedInetAddr, char* pszInterface)
{
    DWORD dwInetAddr = 0; // ip address
    DWORD dwStatus;

    if (pszDottedInetAddr == NULL)
    {
        printf("IpArp: Bad Argument\n");
        return;
    }
    dwInetAddr = inet_addr(pszDottedInetAddr); // convert dotted ip addr. to ip addr.
    if (dwInetAddr == INADDR_NONE)
    {
        printf("IpArp: Bad Argument %s\n", pszDottedInetAddr);
        return;
    }

    MIB_IPNETROW arpEntry; // an arp entry
    if (pszInterface)
    {
        // User provides a interface index number
        sscanf(pszInterface, "%X",&(arpEntry.dwIndex));
    }
    else
    {
        // try to delete this from first available interface
        PMIB_IPADDRTABLE pIpAddrTable = NULL;
        if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR)
        {
            printf("IpArp: Couldn't find a interface number to add your arp entry\n");
            return;
        }
        arpEntry.dwIndex = pIpAddrTable->table[0].dwIndex;
        free(pIpAddrTable);
    }
   
    arpEntry.dwAddr = dwInetAddr;
    dwStatus = DeleteIpNetEntry(&arpEntry);
    if (dwStatus != NO_ERROR)
    {
        printf("IpArp: couldn't delete (%s), dwStatus = %lu.\n",
                    pszDottedInetAddr, dwStatus);
    }

}
//----------------------------------------------------------------------------
// Inputs: pIpAddrTable is the IP address table
//         dwIndex is the Interface Number
// Output: If it returns TRUE, str contains the ip address of the interface
//----------------------------------------------------------------------------
bool InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[])
{
    struct in_addr inadTmp;
    char* szIpAddr;

    if (pIpAddrTable == NULL ||  str == NULL)
        return FALSE;
    str[0] = '\0';
    for (DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++)
    {
        if (dwIndex == pIpAddrTable->table[dwIdx].dwIndex)
        {
            inadTmp.s_addr = pIpAddrTable->table[dwIdx].dwAddr;
            szIpAddr = inet_ntoa(inadTmp);
            if (szIpAddr)
            {
                strcpy(str, szIpAddr);
                return TRUE;
            }
            else
                return FALSE;
        }
    }
    return FALSE;

}

//-------------------------------------------------------------------------
// Input: str points to an ethernet address of the form 00-aa-bb-cc-dd-ee
// If it returns 0, ret contains the 6 bytes ethernet address.
//-------------------------------------------------------------------------

int StringToPhysAddr(char* szInEther,  char* szOutEther)
{
    const char DASH = '-';
    register char c;   
    register int val;   

    // check szInEther for the correct format
    if (strlen(szInEther) != 17)
        return (-1);
    if (szInEther[2] != DASH || szInEther[5] != DASH || szInEther[8] != DASH ||
        szInEther[8] != DASH || szInEther[14] != DASH)
        return (-1);
    if (!isxdigit(szInEther[0]) || !isxdigit(szInEther[1]) ||
        !isxdigit(szInEther[3]) || !isxdigit(szInEther[4]) ||
        !isxdigit(szInEther[6]) || !isxdigit(szInEther[7]) ||
        !isxdigit(szInEther[9]) || !isxdigit(szInEther[10]) ||
        !isxdigit(szInEther[12]) || !isxdigit(szInEther[13]) ||
        !isxdigit(szInEther[15]) || !isxdigit(szInEther[16]))
        return (-1);
    // convert the 12 hex decimals back to 6 digit decimals
    for (int i = 0; i < 6; i++)
    {
        val = 0;
        c = toupper(szInEther[i*3]);
        c = c - (isdigit(c) ? '0' : ('A' - 10)); //offset adjustment
        val += c;
        val = (val << 4); // val * 16
        c = toupper(szInEther[i*3 + 1]);
        c = c - (isdigit(c) ? '0' : ('A' - 10)); // offset adjustement
        val += c;
        szOutEther[i] = val;
    }
    return (0);
}

//----------------------------------------------------------------------------
// Inputs: PhysAddr is the hardware address in bytes
//         PhysAddrLen is the length of the PhysAddr
// Outputs: if it returns TRUE, str is the hex formated string of the hardware
//          address.
// NOTE: make sure str is TRIPLE as big as PhysAddrLen
//----------------------------------------------------------------------------
bool PhysAddrToString(BYTE PhysAddr[], DWORD PhysAddrLen, char str[])
{
    if (PhysAddr == NULL || PhysAddrLen == 0 || str == NULL)
        return FALSE;
    str[0] = '\0';
    for (DWORD dwIdx = 0; dwIdx < PhysAddrLen; dwIdx++)
    {
        if (dwIdx == PhysAddrLen-1)
            sprintf(str+(dwIdx*3), "%02X", ((int)PhysAddr[dwIdx])&0xff);
        else
            sprintf(str+(dwIdx*3), "%02X-", ((int)PhysAddr[dwIdx])&0xff);
        
    }
    return TRUE;
}
//----------------------------------------------------------------------------
//   arp table format to be printed:
// 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
//----------------------------------------------------------------------------
void PrintIpNetTable(PMIB_IPNETTABLE pIpNetTable)
{
    DWORD i, dwStatus, dwCurrIndex;
    struct in_addr inadTmp;
    char szPrintablePhysAddr[256];
    char szType[128];
    char szIpAddr[128];
    PMIB_IPADDRTABLE pIpAddrTable = NULL;

    if (pIpNetTable == NULL)
    {
        printf( "pIpNetTable == NULL in line %d\n", __LINE__);
        return;
    }
    // get IP Address Table for mapping interface index number to ip address
    if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR)
    {
        printf("GetIpAddrTable returned 0x%x\n", dwStatus);
        if (pIpAddrTable)
            free(pIpAddrTable);
        return;
    }
    assert(pIpAddrTable);
    // Note: the ARP table should be sorted in interface index
    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;
    }
   
   
    for (i = 0; i < pIpNetTable->dwNumEntries; ++i)
    {
        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;
            }
        }
        PhysAddrToString(pIpNetTable->table[i].bPhysAddr, pIpNetTable->table[i].dwPhysAddrLen, szPrintablePhysAddr);
        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);
        
    }
    if (pIpAddrTable)
        free(pIpAddrTable);
}

//----------------------------------------------------------------------------
//  Format of IP Address Table:
//  ipAdEntAddr   ifAdEntIfIndex  ipAdEntNetMask   ipAdEntBcastAddr  ipAdEntReasmMaxSize
//----------------------------------------------------------------------------
void PrintIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable)
{
    DWORD i;
    struct in_addr inadTmp1;
    struct in_addr inadTmp2;
    char szAddr[128];
    char szMask[128];

    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);

    }
}

//----------------------------------------------------------------------------
// Input : fOrder -- sorts the output IP Addr Table
// Output: If it returns NO_ERROR, pIpAddrTable points to the IP Addr Table
//----------------------------------------------------------------------------
DWORD MyGetIpAddrTable(PMIB_IPADDRTABLE& pIpAddrTable, bool fOrder)
{
    DWORD status = NO_ERROR;
    DWORD statusRetry = NO_ERROR;
    DWORD dwActualSize = 0;

    // query for buffer size needed
    status = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder);

    if (status == NO_ERROR)
    {
        printf("No error\n");
        return status;
    }
    else if (status == ERROR_INSUFFICIENT_BUFFER)
    {
        // need more space

        pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwActualSize);
        assert(pIpAddrTable);
        
        statusRetry = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder);
        return statusRetry;
    }
    else
    {
        return status;
    }
}

//----------------------------------------------------------------------------
// Input : fOrder -- sorts the output IP Net Table
// Output: If it returns NO_ERROR, pIpNetTable points to the IP Net Table
//----------------------------------------------------------------------------
DWORD MyGetIpNetTable(PMIB_IPNETTABLE& pIpNetTable, bool fOrder)
{
    DWORD status = NO_ERROR;
    DWORD statusRetry = NO_ERROR;
    DWORD dwActualSize = 0;
   
    // query for buffer size needed
    dwActualSize = 0;
    status = GetIpNetTable(pIpNetTable, &dwActualSize, fOrder);

    if (status == NO_ERROR)
    {
        return status;
    }
    else if (status == ERROR_INSUFFICIENT_BUFFER)
    {
        // need more space

        pIpNetTable = (PMIB_IPNETTABLE) malloc(dwActualSize);
        assert(pIpNetTable);
        
        statusRetry = GetIpNetTable(pIpNetTable, &dwActualSize, fOrder);

        if (statusRetry != NO_ERROR)
        {
#ifdef _DEBUG
            printf("Retry failed.\n");
#endif
            return statusRetry;
        }
        else
        {
            return statusRetry;
        }
    }
    else
    {
#ifdef _DEBUG
        printf("first getipnettable call failed\n");
#endif
        return status;
    }
}
2016-7-29 17:23
0
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不是为了获取,是要搞清楚怎么通过驱动得到

目前实现,在驱动,拦截了

那个数据结构网上搜没见,没公开
2016-7-29 19:49
0
雪    币: 30030
活跃值: (2467)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
驱动层就更简单了,一个ARP请求包就OK。
2016-7-31 20:16
0
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
那你写个HOOK掉 arp-a 获取网关的 驱动

给大家学习下
2016-7-31 20:32
0
雪    币: 30030
活跃值: (2467)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
实在不明白你想干什么。
还是给你讲一些基础知识吧,如果你已经很牛,就略过吧。

1、局域网内的机器通讯是依靠MAC地址,IP地址其实只是作为参考。

例如:电脑A,IP地址为192.168.1.4,MAC地址为00:00:00:00:04
         电脑B,IP地址为192.168.1.5,MAC地址为00:00:00:00:05
         网关C,IP地址为192.168.1.1,MAC地址为00:00:00:00:01

电脑A往电脑B发送一个数据包(例如发起一个TCP连接),如果从以太网数据帧的角度来看,至少包含了以下内容:

发送方的MAC     接收方的MAC  数据帧类型  具体的数据帧

然后根据数据帧类型,判断出是IP包,则再解释出源IP和目的IP地址等等。

上面这个例子中,电脑B的MAC是什么?实际上,Windows里面包含有一个ARP缓冲区,这个缓冲区是经常刷新的,你可以把它看作是一个内存数据库。arp -a就是查看这个的。当然,还有其它的API可以编辑这个节点之类。
这个内存数据库,节点内容是时刻更新的。比如说,你第一次访问电脑B(例如:ping 192.168.1.5),操作系统先从这个缓存查看,如果没有这条纪录,则发送一个arp请求广播包,询问这个IP对应的MAC,当收到回复,则添加到缓存。你可以验证以下:
arp -d//清除缓存
arp -a//显示缓存
ping 192.168.1.5//触发系统发送ARP请求包
arp -a//显示缓存

当然,即使你的电脑不发送请求包,恶意程序也可以直接发送ARP回复包,操作系统一样会更新对应的缓存(这也是ARP欺骗的理论基础)。

2、如果是访问互联网的电脑,数据包的MAC目的地址是网关,但IP地址是目标IP(比如说163的)。网关收到这个数据包后,会建立一个纪录,就是这个源IP和源MAC的对应关系,然后把数据包的源MAC修改为自己的,源IP不变,然后目的MAC修改为下一级的路由投递出去。

所以我实在不明白你是想干什么。arp -a只是获取缓存记录罢了,至于sendarp这个API,是给开发人员使用的,没有谁告诉你操作系统也是调用这个。实际上,sendarp内部是调用ResolveIpNetEntry2函数,这个函数再调用NsiGetAllParameters。
2016-8-1 16:38
0
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
为了在驱动欺骗那个网关MAC而已

不懂网络编程因而发帖问
2016-8-1 18:11
0
雪    币: 25
活跃值: (506)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
太流弊了
2016-8-2 11:01
0
游客
登录 | 注册 方可回帖
返回
//