有什么方法可以发现您网络上的Android设备?

时间:2012-11-02 15:49:01

标签: android discovery service-discovery

我希望能够在我的网络上发现Android设备,并可能检索有关它们的设备信息。 Apple设备使用Bonjour服务非常容易。但是,我似乎无法在Android上运行任何类似的服务。

这必须在不修改Android设备,安装某些服务或打开某个端口的情况下工作。这意味着以Bonjour帮助您找到香草Apple设备的方式使用vanilla Android设备。即使只是能够验证设备是否正在运行Android就足够了。


选择答案:虽然它还不是最受好评的答案,但请看看路易斯的回复。正如他所提到的,您可以使用DNS查找(使用本地DNS服务器)来发现Android设备。我发现这有100%的成功率,因为​​Android强制设备使用主机名android- _ ____ 。这显然很难在手机上改变,即使它是根深蒂固的。所以我认为这是一种非常准确的方法。谢谢,路易斯!

Example:
$ nslookup 192.168.1.104 192.168.1.1
Server:     192.168.1.1
Address:    192.168.1.1#53

104.1.168.192.in-addr.arpa  name = android-711c129e251f14cf.\001.

示例代码:如果您想在Java中实现此功能(例如,在Android上运行),则无法轻松使用getHostName(),因为它使用外部DNS服务器。例如,您希望在路由器上使用本地DNS服务器。 Luis在下面提到你可以修改Wifi连接的DNS服务器,但这可能会破坏其他东西。相反,我发现dnsjava库对发送目标DNS请求非常有帮助。以下是使用该库的一些示例代码:

        String ipAddress = "104.1.168.192";
        String dnsblDomain = "in-addr.arpa";
        Record[] records;
        Lookup lookup = new Lookup(ipAddress + "." + dnsblDomain, Type.PTR);
        SimpleResolver resolver = new SimpleResolver();
        resolver.setAddress(InetAddress.getByName("192.168.1.1"));
        lookup.setResolver(resolver);
        records = lookup.run();

        if(lookup.getResult() == Lookup.SUCCESSFUL) {
              for (int i = 0; i < records.length; i++) {
                if(records[i] instanceof PTRRecord) {
                  PTRRecord ptr = (PTRRecord) records[i];
                  System.out.println("DNS Record: " + records[0].rdataToString());
                }
              }
        } else {
            System.out.println("Failed lookup");
        }

    } catch(Exception e) { 
        System.out.println("Exception: " + e);
    }

这给了我输出:

DNS Record: android-711c129e251f14cf.\001.

宾果

7 个答案:

答案 0 :(得分:31)

有一种非常简单的方法可以在少数不同的设备上给我带来积极的结果。

当设备连接到路由器时,它会收到IP(即DHCP)并在DNS中注册名称。注册的名称似乎始终采用android_nnnnnnnn

的形式

对于cource,您可以使用相同的方法命名任何计算机并欺骗检查,从而导致误报......

此外,我无法确保所有设备供应商都遵循相同的方法,但我发现它可以在我测试的不同品牌(包括不同的SDK级别)的少数设备中正常工作。

- 编辑 -

怎么做

这取决于您运行代码以发现Android设备的位置。假设您将在Android设备中运行代码:

  1. 首先发现响应网络中Ping的设备。您可以在我对这篇文章的回答中使用代码:execComd()来运行ping命令。
  2. 使用以下代码获取响应设备的名称:

    InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);

    String name = inetAddress.getCanonicalHostName();

  3. - 编辑2 -

    概念证明

    下面的方法只是我在上面写的内容的概念。

    我正在使用isReachable()方法来生成ICMP请求,这在许多帖子中都有说法,这些帖子仅适用于有根设备,这是用于测试它的设备的情况。但是,我没有为运行此代码的应用程序授予root权限,因此我认为它无法设置SIUD位,这就是为什么某些绑定此方法失败的原因。我希望有人在非root用户设备上测试它。

    致电使用:

    ArrayList<String> hosts = scanSubNet("192.168.1.");
    

    它在hosts中返回响应ping请求的设备的名称列表。

    private ArrayList<String> scanSubNet(String subnet){
        ArrayList<String> hosts = new ArrayList<String>();
    
        InetAddress inetAddress = null;
        for(int i=1; i<10; i++){
            Log.d(TAG, "Trying: " + subnet + String.valueOf(i));
            try {
                inetAddress = InetAddress.getByName(subnet + String.valueOf(i));
                if(inetAddress.isReachable(1000)){
                    hosts.add(inetAddress.getHostName());
                    Log.d(TAG, inetAddress.getHostName());
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        return hosts;
    }
    

    问候。

答案 1 :(得分:21)

Android不会像iOS一样简单。没有Bonjour等价物。

Android 4.0,Ice Cream Sandwich,介绍了Wi-Fi Direct Peer to Peer网络。起初我希望它能够按照您的思维方式进行扫描,但它可以帮助Android设备在没有接入点的情况下进行通信,因此他们并不真正在您的网络上进行通信&#34;。此外,ICS仅运行一小部分Android设备。

与其采用有效的网络扫描方法,您将采用被动监控方式。如果您的网络是安全的,可以嗅探加密数据包,但不方便。你必须

  • 将您的网络接口放入monitor mode
  • 捕获4-way handshake
  • 使用网络的预共享密钥
  • 对其进行解密
  • 这将为您提供解密流量所需的密钥

如果您想看到这一点,Wireshark支持WPA decryption

一旦您能够查看Wi-Fi流量,您就会发现Android设备倾向于与某些Google服务器通信,并且其HTTP连接具有User Agent strings that can be identified。 这是可行的被动解决方案的基础。

Tenable Network Security提供似乎采用此类方法的产品。

另一个想法

@Michelle Cannon提到了Libelium的Meshlium Xtreme,它的方法不会让你一直到那里(不是没有最新的MAC地址范围表)。但它可能是实现较小目标的一部分。 你可以:

  • 检测所有无线设备
  • 使用MAC的组织唯一标识符(OUI)消除Apple设备
  • 通过监控信号强度来判断移动设备是否正在移动(移动设备往往会显示并消失)
  • 您可以使用MAC OUI作为暗示它的Android
  • 您可以使用MAC OUI作为暗示它不是Android(但是笔记本电脑或无线网卡等)。

如果您愿意检测可能 Android的设备,这可能是可行的。

DHCP指纹识别

@Michelle Cannon建议使用DHCP指纹识别。起初我不确定,但我要感谢他建议看起来像是简单被动扫描的最佳选择。作为警示尾巴,我想解释为什么我迟到了。

我们知道的事情,认为我们不知道,以及我们认为我们知道但却错误的事情。

在很多方面,Android使用Linux内核很不错。但是,如果您想在网络上发现Android设备,那就不好了。 Android的TCP / IP堆栈就是因为Android设备看起来像Linux设备,所以我一开始就想到了。但后来我意识到Linux已经很多的构建配置参数,所以在网络上看到Android时会有一些与众不同的东西,但是什么呢?

DHCP指纹识别使用设备请求的确切DHCP选项加上时序。为此,您通常需要一个最新的指纹数据库来匹配。起初,fingerbank看起来像是在寻找这些数据,但后来我注意到他们的文件已经更新了近一年。对于所有不同的Android设备类型,我认为为单个项目保留更新的指纹是不切实际的。

但后来我查看了Android的实际DHCP签名,我注意到了这一点:

Android 1.0:     dhcpvendorcode=dhcpcd 4.0.0-beta9
Android 1.5-2.1: dhcpvendorcode=dhcpcd 4.0.1
Android 2.2:     dhcpvendorcode=dhcpcd 4.0.15
Android 3.0:     dhcpvendorcode=dhcpcd-5.2.10 

Linux通常使用dhclient作为其DHCP客户端,但Android使用的是dhcpcd。 Android强烈倾向于尽可能使用BSD风格的软件,dhcpcd使用BSD许可证。似乎dhcpvendorcode可以用作移动设备运行Android的强大指标。

DHCP监控

客户端在加入网络时使用DHCP获取IP地址,因此它在没有IP地址的情况下启动。它通过使用UDP广播进行初始交换来解决这个问题。在Wi-Fi上,即使使用WPA,广播流量也不会加密。因此,您可以在UDP端口67上侦听客户端到服务器的流量,而68则反向侦听。您甚至不需要将网络接口置于混杂模式。您可以使用Wireshark等协议分析器轻松监控此流量。

我更喜欢编写代码来监控流量,并决定使用Python。我选择了pydhcplib来处理DHCP的细节。我对这个图书馆的经验并不顺利。我需要手动下载并放置IN.py和TYPES.py支持文件。他们的数据包转换为字符串将dhcpvendorcode留空。它确实正确解析了DHCP数据包,因此我只编写了自己的打印代码。

这是监控从客户端到服务器的DHCP流量的代码:

#!/usr/bin/python
from pydhcplib.dhcp_packet import *
from pydhcplib.dhcp_network import *
from pydhcplib.dhcp_constants import *


netopt = {
    'client_listen_port':"68",
    'server_listen_port':"67",
    'listen_address':"0.0.0.0"
}

class Server(DhcpServer):
    def __init__(self, options):
        DhcpServer.__init__(
            self,options["listen_address"],
            options["client_listen_port"],
            options["server_listen_port"])

    def PrintOptions(self, packet, options=['vendor_class', 'host_name', 'chaddr']):

        # uncomment next line to print full details
        # print packet.str()

        for option in options:
            # chaddr is not really and option, it's in the fixed header
            if option == 'chaddr':
                begin = DhcpFields[option][0]
                end = begin+6
                opdata = packet.packet_data[begin:end]
                hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
                print option+':', ':'.join([(hex[i/16]+hex[i%16]) for i in opdata])
            else:
                opdata = packet.options_data.get(option)
                if opdata:
                    print option+':', ''.join([chr(i) for i in opdata if i != 0])
        print

    def HandleDhcpDiscover(self, packet):
        print "DHCP DISCOVER"
        self.PrintOptions(packet)
    def HandleDhcpRequest(self, packet):
        print "DHCP REQUEST"
        self.PrintOptions(packet)

    ##  def HandleDhcpDecline(self, packet):
    ##      self.PrintOptions(packet)
    ##  def HandleDhcpRelease(self, packet):
    ##      self.PrintOptions(packet)
    ##  def HandleDhcpInform(self, packet):
    ##      self.PrintOptions(packet)


server = Server(netopt)

while True :
    server.GetNextDhcpPacket()

此代码基于pydhcplib的服务器示例,因为它会侦听客户端请求,例如服务器。

当我的Nexus 7 Android 4.2平板电脑连接时,这些有趣的信息被捕获(编辑):

DHCP REQUEST
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff

DHCP DISCOVER
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff

主机名似乎具有固定格式并且易于解析。如果需要IP地址,可以监控服务器到客户端的流量。注意:仅当新客户端首次显示没有IP地址时才进行初始交换。未来的租约延期等不会被广播。

Reverse DNS Lookup

@Luis发布了一个很好的解决方案,演示了更简单的更好。即使在看到Android的DHCP客户端将host_name设置为android-5c1b97cdffffffff后,我也没想到要使用反向DNS查询向路由器询问它的名称列表。路由器将host_name添加到它的DNS服务器中,这样如果IP地址发生变化,您仍然可以访问该设备。

在DHCP租约期间,host_name应该仍然在DNS中列出。您可以pinging检查设备是否仍然存在。

取决于host_name的一个缺点是有一些方法可以更改。设备制造商或运营商可以轻松更改host_name(虽然在搜索之后,我仍然无法找到他们曾经拥有的任何证据)。有apps to change host name,但它们需要root,因此最多只是一个边缘情况。

最后有一个开放的Android Issue 6111: Allow a hostname to be specified,目前有629颗星。在将来的某个时刻在Android设置中看到可配置的host_name也许不会感到惊讶。因此,如果您开始依赖host_name来识别Android设备,请意识到它可能会从您身下被拉出来。

如果您正在进行实时跟踪,则反向DNS查找的另一个潜在问题是您必须决定扫描的频率。 (当然,如果您只是拍摄一次性快照,这不是问题。)频繁扫描会消耗网络资源,不经常会让您收到陈旧数据。以下是添加DHCP监控可以提供帮助的方法:

  • 启动时使用反向DNS查找来查找设备
  • Ping设备以查看它们是否仍处于活动状态
  • 监控DHCP流量以立即检测新设备
  • 有时会重新运行DNS查找以查找可能错过的设备
  • 如果您需要注意设备离开,请按所需的时间分辨率ping设备

虽然它并不容易(也不是100%准确),但有几种技术可以可能来发现网络上的Android设备。

答案 2 :(得分:5)

AFAIK,Android系统在其内置系统应用/服务堆栈上不提供任何zeroconf应用/服务。要在连接到本地网络的实际设备上启用自动发现,您需要安装一些第三方zeroconf应用程序或开发自己的应用程序/服务并将其安装在实际设备上,一些API选项是:

  • JmDNS(适用于Apple的bonjour协议)
  • Cling(适用于Microsoft的UPnP协议)
  • Android NSD API(自Android 4.1以来推出)

我不太清楚你的要求,如果你想在类似香草的Android设备上有类似的东西(即自动发现和连接),你可以使用Wi-Fi direct,现在可以在以后运行Android 4.0的设备上使用Connecting Devices Wirelessly,但是,它需要两个设备都支持Wi-Fi Direct,并且只在关闭Wi-Fi的情况下创建一个ad-hoc P2P连接,就像更长距离的蓝牙连接一样:

enter image description here

有关Wi-Fi Direct API支持,请查看官方指南 - {{3}}。

答案 3 :(得分:2)

我正在考虑这个想法

http://www.libelium.com/smartphones_iphone_android_detection

特别注意这个

用户是否需要安装特定的应用程序或以某种方式进行交互以进行检测?

不,扫描是静默执行的,Meshlium只检测由智能手机中集成的Wifi和蓝牙无线电发起的“信标帧”。用户只需要打开两个无线接口中的至少一个。

很久以前我用我的mac上的一个名为stumbler的应用来寻找wifi网络,我觉得这很相似

其他想法

好吧,如果我需要在本地网络上确定Android手机,我该怎么办呢。没有运行dns服务我只有几种可能性

SSID如果被广播 - 不能告诉我任何东西ip地址 - android让你有很多控制主机命名所以我猜你可以为你的Android设备定义一个特定的IP范围。 - 没有用。

或者让我说我在网络上看到一个未知设备,如果蓝牙已打开,那么我正在播放蓝牙设备签名SDPP,我可以使用它来推断我的设备类型。

如果我正在运行支持android的服务,并且我想在我的网络上发现特定的Android设备,那么我可以为这些设备注册mac地址并在网络上观察它们。

除此之外,你需要在设备上运行bonjour(dns-sd)或upnpp dameon。

答案 4 :(得分:1)

更新回复

抱歉,我没有正确理解原始问题。只有您的评论让我非常清楚您不想在目标设备上安装任何,但您只是想在网络中发现随机手机。

我不确定这是否真的可以按照你想要的方式实现。如果没有在Android上运行任何网络发现服务,您将无法找到该设备。当然你可以使用一些低级别的网络协议,但这只会给你一个指示,表明它有什么但不是它的东西(作为Android设备,PC,其他任何东西)。

最有希望的方法是检查具有某种网络功能的预安装应用程序。例如。三星设备有Kies Air(如果用户启用它),摩托罗拉正在使用UPnP作为他们的媒体服务器而HTC也有自己的东西,如果我没记错的话。但是,并非所有供应商和运营商的所有Android设备上都安装了应用程序。因此,您不能仅依赖其中一个,而是需要使用其特定协议和行为检查各种不同的服务,以获取有关该设备的其他信息。当然,用户必须启用该功能才能使用它。

旧回复

高通的另一个替代yorkw的列表是AllJoyn。这是我过去自己使用过的开源跨平台发现和点对点通信框架。

虽然高通公司是AllJoyn的大赞助商,但这并不意味着你需要在你的定义中使用高通芯片组。事实上,AllJoyn适用于任何芯片组,包括Intel和nVidia。它不需要root电话或对Android框架的任何其他修改,只需使用Wi-Fi和/或蓝牙作为配对方法“开箱即用”。

答案 5 :(得分:1)

我从这个主题中学到了很多东西。

还有一种叫做dhcp指纹识别的东西,显然不同的设备与我们讨论过的那种网络扫描行为不同,例如使用NMAP和Linux扫描程序。这些探测器的行为图可在互联网上找到。

http://www.enterasys.com/company/literature/device-profiling-sab.pdf

https://media.defcon.org/dc-19/presentations/Bilodeau/DEFCON-19-Bilodeau-FingerBank.pdf

http://community.arubanetworks.com/t5/ArubaOS-and-Mobility-Controllers/COTD-DHCP-Fingerprinting-how-to-ArubaOS-6-0-1-0-and-above/td-p/11164

http://myweb.cableone.net/xnih/

答案 6 :(得分:0)

此处有一个内线,用于ping网络中的所有计算机(假设您的网络为192.168.1.x)并对其名称进行反向查找:

for i in {1..255}; do echo ping -t 4 192.168.1.${i} ; done | parallel -j 0 --no-notice 2> /dev/null | awk '/ttl/ { print $4 }' | sort | uniq | sed 's/://' | xargs -n 1 host 

需要GNU并行工作。您可以使用&#34; brew install parallel&#34;

在OSX上安装它

通过此,您可以查看名为android-c40a2b8027d663dd.home.的设备或其他任何设备。

然后,您可以尝试在设备上运行nmap -O,看看还能找到什么:

sudo nmap -O android-297e7f9fccaa5b5f.home.

但它并不是那么富有成效。