txm888 发表于 2016-4-15 22:51:30

用已知MAC地址返回IP地址的方案探讨,高手进

本帖最后由 txm888 于 2016-4-17 10:26 编辑

最近很苦恼的烦心事儿,在局域网内有一大批路由器需要管理,且路由器的wan接口是动态获取IP的,这些路由器是跨网段的,想登陆路由器管理,得去现场。

脑洞大开,想要是能用每个路由器的mac地址返回IP再登陆管理界面操作不是更方便吗?
在论坛搜索了2天,只有ip mac扫描工具,1-255尽然最快也要花3/4秒,如果跨网段速度慢得不惊人,
请问大师们,能否进行UDP广播包的方式,套出IP对应mac的IP地址?
如果有思路,可付费索取,期待,谢谢!

mac地址扫描的有很多,如纯au3 P版大侠杰作:http://www.autoitx.com/forum.php?mod=viewthread&tid=39847&highlight=mac%2B%C9%A8%C3%E8


如下代码可能是个办法,但是JAVA的办法,要是能翻译为AU3的就好了Java远程获取MAC地址代码

java
Java代码
package com.thunisoft.shxt.support.macAddr;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* 主机A向主机B发送“UDP-NetBIOS-NS”询问包,即向主机B的137端口,发Query包来询问主机B的NetBIOS Names信息。
* 其次,主机B接收到“UDP-NetBIOS-NS”询问包,
* 假设主机B正确安装了NetBIOS服务........... 而且137端口开放,
* 则主机B会向主机A发送一个“UDP-NetBIOS-NS”应答包,即发Answer包给主机A。
* 并利用UDP(NetBIOS Name Service)来快速获取远程主机MAC地址的方法
* @author lijt
*/

public class UdpGetClientMacAddr {
      
    private static Log log = LogFactory.getLog(UdpGetClientMacAddr.class);
      
    private String         remoteAddr;
    private int            remotePort = 137;
    private byte[]         buffer      = new byte;
    private DatagramSocket ds          = null;

    public UdpGetClientMacAddr(String strAddr) throws Exception {
      remoteAddr = strAddr;
      ds = new DatagramSocket();
    }

    //发送数据包
    protected final DatagramPacket send(final byte[] bytes) throws IOException {
      DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(remoteAddr), remotePort);
      ds.send(dp);
      return dp;
    }
    //接收数据包
    protected final DatagramPacket receive() {
      DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
      try {
            ds.setSoTimeout(3000);
            ds.receive(dp);   
      }catch(SocketTimeoutExceptionex) {   
         log.info("接收数据超时...,不能获取客户端MAC地址");
          //throw new SocketTimeoutException("连接超时");
      }catch (SocketException e1) {
            log.error("发生Sorcket异常..."+e1.getMessage());
            e1.printStackTrace();
      }catch (IOException e2) {
            log.error("发生IO异常..."+e2.getMessage());
      }
      return dp;
    }

    // 询问包结构:
    // Transaction ID 两字节(16位) 0x00 0x00
    // Flags 两字节(16位) 0x00 0x10
    // Questions 两字节(16位) 0x00 0x01
    // AnswerRRs 两字节(16位) 0x00 0x00
    // AuthorityRRs 两字节(16位) 0x00 0x00
    // AdditionalRRs 两字节(16位) 0x00 0x00
    // Name:array 0x20 0x43 0x4B 0x41(30个) 0x00 ;
    // Type:NBSTAT 两字节 0x00 0x21
    // Class:INET 两字节(16位)0x00 0x01
    protected byte[] getQueryCmd() throws Exception {
      byte[] t_ns = new byte;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x10;
      t_ns = 0x00;
      t_ns = 0x01;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x20;
      t_ns = 0x43;
      t_ns = 0x4B;

      for (int i = 15; i < 45; i++) {
            t_ns = 0x41;
      }

      t_ns = 0x00;
      t_ns = 0x00;
      t_ns = 0x21;
      t_ns = 0x00;
      t_ns = 0x01;
      return t_ns;
    }

    // 表1 “UDP-NetBIOS-NS”应答包的结构及主要字段一览表
    // 序号 字段名 长度
    // 1 Transaction ID 两字节(16位)
    // 2 Flags 两字节(16位)
    // 3 Questions 两字节(16位)
    // 4 AnswerRRs 两字节(16位)
    // 5 AuthorityRRs 两字节(16位)
    // 6 AdditionalRRs 两字节(16位)
    // 7 Name<Workstation/Redirector> 34字节(272位)
    // 8 Type:NBSTAT 两字节(16位)
    // 9 Class:INET 两字节(16位)
    // 10 Time To Live 四字节(32位)
    // 11 Length 两字节(16位)
    // 12 Number of name 一个字节(8位)
    // NetBIOS Name Info 18×Number Of Name字节
    // Unit ID 6字节(48位

    protected final String getMacAddr(byte[] brevdata) throws Exception {
      // 获取计算机名
   //   System.out.println(new String(brevdata, 57, 18));
   //   System.out.println(new String(brevdata, 75, 18));
   //   System.out.println(new String(brevdata, 93, 18));
      int i = brevdata * 18 + 56;
      String sAddr = "";
      StringBuffer sb = new StringBuffer(17);
      // 先从第56字节位置,读出Number Of Names(NetBIOS名字的个数,其中每个NetBIOS Names Info部分占18个字节)
      // 然后可计算出“Unit ID”字段的位置=56+Number Of Names×18,最后从该位置起连续读取6个字节,就是目的主机的MAC地址。
      for (int j = 1; j < 7; j++) {
            sAddr = Integer.toHexString(0xFF & brevdata);
            if (sAddr.length() < 2) {
                sb.append(0);
            }
            sb.append(sAddr.toUpperCase());
            if (j < 6) sb.append('-');
      }
      return sb.toString();
    }

    public final void close() {
      try {
            ds.close();
      } catch (Exception ex) {
            ex.printStackTrace();
      }
    }

    /**
   * 获取远程主机的mac地址
   * @return
   * @throws Exception
   */
    public final String getRemoteMacAddr() throws Exception {
      byte[] bqcmd = getQueryCmd();
      this.send(bqcmd);
      DatagramPacket dp = receive();
      String smac ="";
      smac = getMacAddr(dp.getData());
      this.close();
      return smac;
    }
   public static voidmain(String[] args) throws Exception
   {
       UdpGetClientMacAddradd = new UdpGetClientMacAddr("172.16.26.52");
       System.out.println(add.getRemoteMacAddr());
   }

}http://thinkblog.iteye.com/blog/1499877

txm888 发表于 2016-4-17 10:14:58

找到了下面这篇文章,但不知道如何弄:
http://bbs.csdn.net/topics/70071564

lin6051 发表于 2016-4-18 09:15:59

插WAN口 要把路由器的远程管理开起来才可以管理的吧

txm888 发表于 2016-4-18 13:20:32

回复 3# lin6051


    发现也不是个办法,上级把wan口各IP隔立起来了,扫描不到
只有一个办法,拨号成功后,向某台电脑发个消息,但需要路由器支持

虫子樱桃 发表于 2016-4-18 13:41:00

[参考如下代码(转自官网)]

#include <Date.au3>

;===============================================================================
;
; Description:      Get DHCP Client Attributes by IP Address, MAC or Name
; Parameter(s):   $sDHCP - IP Address of DHCP Server
;                   $ClientID - Client IP, MAC or Name (String or Native Format)
;                     Integer - native format for IP Address/Mask
;                     Binary- native format for MAC Address (6 bytes)
;                   $iIDType - type of ClientID information:
;                     0 - Auto-define by value
;                     1 - Client IP address
;                     2 - Client Hardware (MAC) address
;                     3 - Client Name
;                   $iFlags - Config Flags:
;                     0x1- Output Format (0-Text, 1-Native)
; Requirement(s):   Testing
; Return Value(s):On Success - The array of parameters with indexes
;                     0 - Client IP address
;                     1 - Client IP subnet mask
;                     2 - Client MAC address
;                     3 - Client Name
;                     4 - Client Comment
;                     5 - Client Lease Expires Time
;                   On Failure - Null, @error set to
;                     1 - Client not found on DHCP server
;                     2 - Invalid ClientID parameter
;                     3 - Operating System not supported
;                     4 - Any Runtime Error, API Error Code set to @extended
; Author(s):         amel27 (Alexander Melnichuk)
; Note(s):         Client Name is case sensitive
;
;===============================================================================

Func _DHCP_GetClientInfo($sDHCP, $ClientID, $iIDType=0, $iFlags=0)
    ; Create DHCP_SEARCH_INFO Structure
    Local $tSearchInfo= DllStructCreate("int SearchType;int DataLength;ptr DataPtr")
    Local $iSearchInfoPtr = DllStructGetPtr($tSearchInfo), $aSubnets=, $iType=0
    Local $tBinaryData = DllStructCreate("dword SubnetIPAddress;ubyte HardwareID;ubyte MACAddress")
    ; Check Client ID Parameter and Define SearchInfo Type
    If IsInt($ClientID) Then
      If $iIDType=0 Or $iIDType=1 Then $iType = 1
    ElseIf IsBinary($ClientID) Then
      If BinaryLen($ClientID)=6 And ($iIDType=0 Or $iIDType=2) Then $iType = 2
    ElseIf IsString($ClientID) Then
      If StringRegExp($ClientID, "^(\d+\.){3}\d+$") Then
            ; Get IP DWord type from String
            Local $aOctets = StringSplit($ClientID, "."), $iClientIP = 0
            For $i=1 To 4
                If BitAND($aOctets[$i], 0xFFFFFF00) Then Return SetError(2) ; ERR: Invalid Client IP Address
                $iClientIP = BitOR(BitRotate($iClientIP, 8, "D"), $aOctets[$i])
            Next
            $ClientID = $iClientIP
            If $iIDType=0 Or $iIDType=1 Then $iType = 1
      ElseIf StringRegExp($ClientID,"^(0)?[[:xdigit:]]{2}((:|-)?[[:xdigit:]]{2}){5}$") Then
            $ClientID = Binary("0x"& StringRegExpReplace($ClientID,"(0|:|-)",""))
            If $iIDType=0 Or $iIDType=2 Then $iType = 2
      Else
            If $iIDType=0 Or $iIDType=3 Then $iType = 3
      EndIf
    EndIf
    If $iType =0 Then Return SetError(2)
    ; Route the filling of DHCP_SEARCH_INFO structure
    Switch $iType
      Case 1
            ; Filling DHCP_SEARCH_INFO for search by client IP address
            Local $tSearchInfo_IP = DllStructCreate("int SearchType;dword ClientIPAddress", $iSearchInfoPtr)
            DllStructSetData($tSearchInfo_IP, "SearchType", 0)
            DllStructSetData($tSearchInfo_IP, "ClientIPAddress", $ClientID)
      Case 2
            ; Filling DHCP_SEARCH_INFO for search by client MAC address
            DllStructSetData($tSearchInfo, "SearchType", 1)
            DllStructSetData($tSearchInfo, "DataLength", 11)
            DllStructSetData($tSearchInfo, "DataPtr", DllStructGetPtr($tBinaryData))
            ; Filling DHCP_BINARY_DATA
            DllStructSetData($tBinaryData, "HardwareID", 0x01)
            DllStructSetData($tBinaryData, "MACAddress", $ClientID)
            ; Get Array of DHCP Subnets
            $aSubnets = _DHCP_EnumSubnets($sDHCP, 1)
            If @error=1 Then Return SetError(1)
            If @error=2 Then Return SetError(4, @extended)
      Case 3
            ; Filling DHCP_SEARCH_INFO for search by client Name
            Local $tSearchInfo_Name = DllStructCreate("int SearchType;ptr ClientNamePtr", $iSearchInfoPtr)
            Local $tClientNameString= DllStructCreate("wchar ClientName["& StringLen($ClientID)+1 &"]")
            DllStructSetData($tSearchInfo_Name, "SearchType", 2)
            DllStructSetData($tSearchInfo_Name, "ClientNamePtr", DllStructGetPtr($tClientNameString))
            DllStructSetData($tClientNameString, "ClientName", $ClientID)
    EndSwitch
    ; CallDhcpGetClientInfo API function
    Local $tClientInfo_Ptr = DllStructCreate("ptr"), $aRet, $aRes
    For $i=1 To $aSubnets
      DllStructSetData($tBinaryData, "SubnetIPAddress", $aSubnets[$i])
      $aRet = DllCall("Dhcpsapi.dll", "int", "DhcpGetClientInfo", _
            "wstr", $sDHCP, _
            "ptr", $iSearchInfoPtr, _
            "ptr", DllStructGetPtr($tClientInfo_Ptr) )
      If @error Then Return SetError(3, @error) ; ERR: Invalid DLL or Function Name
      If $aRet<>20013 Then ExitLoop
    Next
    If $aRet=20013 Then Return SetError(1, $aRet) ; ERR: Client not found
    If $aRet Then Return SetError(4, $aRet) ; ERR: Any runtime errors
    ; DHCP_CLIENT_INFO structure
    Local $tClientInfo = DllStructCreate("dword ClientIpAddress;dword SubnetMask;int BinaryLen;ptr BinaryPtr;" & _
      "ptr ClientNamePtr;ptr ClientCommentPtr;ubyte ClientLeaseExpires;dword OwnerHostIPAddress;" & _
      "ptr OwnerHostNetBiosNamePtr;ptr OwnerHostNamePtr", DllStructGetData($tClientInfo_Ptr,1))
    Local $tClientBinary = DllStructCreate("ubyte BinaryData", DllStructGetData($tClientInfo, "BinaryPtr"))
    ; Get IP Address
    $aRes = DllStructGetData($tClientInfo, "ClientIpAddress")
    If BitAND($iFlags,1)=0 Then $aRes = BitRotate(BitAND($aRes,0xFF000000), 8,"D") &"."& _
      BitRotate(BitAND($aRes,0x00FF0000),16,"D") &"."& _
      BitRotate(BitAND($aRes,0x0000FF00),-8,"W") &"."& BitAND($aRes,0x000000FF)
    ; Get IP Mask
    $aRes = DllStructGetData($tClientInfo, "SubnetMask")
    If BitAND($iFlags,1)=0 Then $aRes=BitRotate(BitAND($aRes,0xFF000000), 8,"D") &"."& _
      BitRotate(BitAND($aRes,0x00FF0000),16,"D") &"."& _
      BitRotate(BitAND($aRes,0x0000FF00),-8,"W") &"."& BitAND($aRes,0x000000FF)
    ; Get MAC Address
    $aRes = DllStructGetData($tClientBinary, "BinaryData")
    If BitAND($iFlags,1)=0 Then $aRes = String($aRes)
    ; Get Client Name
    Local $tClientNameString = DllStructCreate("wchar ClientName", DllStructGetData($tClientInfo, "ClientNamePtr"))
    $aRes = DllStructGetData($tClientNameString, "ClientName")
    ; Get Client Comment
    Local $tClientNameString = DllStructCreate("wchar ClientComment", DllStructGetData($tClientInfo, "ClientCommentPtr"))
    $aRes = DllStructGetData($tClientNameString, "ClientComment")
    ; Get Client Lease Expire Time
    $aRes = DllStructGetData($tClientInfo, "ClientLeaseExpires")
    If BitAND($iFlags,1)=0 Then
      $aRes = _Date_Time_FileTimeToLocalFileTime(DllStructGetPtr($tClientInfo, "ClientLeaseExpires"))
      $aRes = _Date_Time_FileTimeToStr($aRes)
    EndIf
    ; Freeing a memory
    DllCall("Dhcpsapi.dll", "none", "DhcpRpcFreeMemory", "ptr", DllStructGetData($tClientInfo_Ptr,1))
    Return $aRes
EndFunc ;==> _DHCP_GetClientInfo


;===============================================================================
;
; Description:      Get List of DHCP Scopes
; Parameter(s):   $sDHCP - IP Address of DHCP Server
;                   $iFlags - Config Flags:
;                     0x1- Output Format (0-Text, 1-Native)
; Requirement(s):   Testing
; Return Value(s):On Success - The array subnet of IP Addresses
;                     element with index 0 is count of scopes
;                   On Failure - @error set to
;                     1 - Scopes not defined, returned empty array
;                     2 - Any Runtime Error, invalid array,
;                         API Error Code set to @extended
; Author(s):         amel27 (Alexander Melnichuk)
; Note(s):
;
;===============================================================================
Func _DHCP_EnumSubnets($sDHCP, $iFlags=0)
    Local $tEnumSubnetsParms = DllStructCreate("hwnd ResumeHandle;ptr EnumInfoPtr;int ElementsRead;int ElementsTotal")
    Local $aSubnets=, $tIPArray, $tAddress, $aRet
    Do
      $aRet = DllCall("Dhcpsapi.dll", "int", "DhcpEnumSubnets", _
            "wstr", $sDHCP, _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "ResumeHandle"), _
            "int", 100, _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "EnumInfoPtr") , _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "ElementsRead"), _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "ElementsTotal") )
      If $aRet Then Return SetError(2, $aRet) ; ERR: Any runtime errors
      If DllStructGetData($tEnumSubnetsParms,"EnumInfoPtr")=0 Then Return SetError(1, 0, $aSubnets) ; ERR: Not Found
      $tIPArray = DllStructCreate("int NumElements;ptr Elements", DllStructGetData($tEnumSubnetsParms,"EnumInfoPtr"))
      ReDim $aSubnets[$aSubnets + DllStructGetData($tIPArray,"NumElements") +1]
      For $i=$aSubnets+1 To UBound($aSubnets)-1
            $tAddress = DllStructCreate("dword SubNetAddess", DllStructGetData($tIPArray,2) + ($i-$aSubnets-1)*4)
            $aSubnets[$i]=DllStructGetData($tAddress, "SubNetAddess")
            If BitAND($iFlags,1)=0 Then $aSubnets[$i] = BitRotate(BitAND($aSubnets[$i],0xFF000000), 8,"D") _
                &"."& BitRotate(BitAND($aSubnets[$i],0x00FF0000),16,"D") _
                &"."& BitRotate(BitAND($aSubnets[$i],0x0000FF00),-8,"W") _
                &"."& BitAND($aSubnets[$i],0x000000FF)
      Next
      $aSubnets += DllStructGetData($tIPArray,"NumElements")
    Until DllStructGetData($tEnumSubnetsParms,"ElementsRead") = DllStructGetData($tEnumSubnetsParms,"ElementsTotal")
    ; Freeing a memory
    DllCall("Dhcpsapi.dll", "none", "DhcpRpcFreeMemory", "ptr", DllStructGetData($tEnumSubnetsParms,"EnumInfoPtr"))
    Return $aSubnets
EndFunc ; => _DHCP_EnumSubnets

txm888 发表于 2016-4-19 10:47:01

回复 5# 虫子樱桃


    老大,没明白上面代码是操作什么的,能解释下或示范下吗?TKS
页: [1]
查看完整版本: 用已知MAC地址返回IP地址的方案探讨,高手进