61

我希望能够在我的网络上发现 Android 设备,并可能检索一些关于它们的设备信息。这对于 Apple 设备来说非常容易,因为它们运行 Bonjour 服务。但是,我似乎找不到在 Android 上运行的任何类似服务。

这必须在不修改 Android 设备、安装某些服务或打开某些端口的情况下工作。它旨在以 Bonjour 帮助您找到普通 Apple 设备的方式与普通 Android 设备一起使用。即使能够验证设备是否运行 Android 就足够了。


选择的答案:虽然它不是最高评价的答案(还),但请看一下 Luis 的回复。正如他所提到的,您可以使用 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.

答对了。

4

7 回答 7

34

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

当设备连接到您的路由器时,它会收到一个 IP(即 DHCP)并在 DNS 中注册一个名称。注册的名称似乎总是以android_nnnnnnnn.

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

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

--已编辑--

怎么做

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

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

  2. 使用代码获取响应设备的名称:

    InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);

    字符串名称 = inetAddress.getCanonicalHostName();

--编辑2--

概念证明

下面的方法只是我上面写的概念的证明。

我正在使用isReachable()方法来生成 ICMP 请求,据说在许多帖子中它只适用于有根设备,用于测试它的设备就是这种情况。但是,我没有为运行此代码的应用程序授予 root 权限,因此我认为它无法设置 SIUD 位,这就是为什么有人声称此方法失败的原因。我想从有人在非根设备上测试它的角度来做这件事。

调用使用:

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

问候。

于 2012-11-23T21:43:21.843 回答
21

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

Android 4.0 Ice Cream Sandwich 引入了Wi-Fi Direct Peer to Peer 网络。起初我希望它可以按照你的想法进行扫描,但它可以帮助 Android 设备在没有接入点的情况下进行通信,因此它们并不是真正“在你的网络上”。此外,ICS 仅在一小部分 Android 设备上运行。

与主动 netscan 方法不同,您将获得被动监控方法。如果您的网络是安全的,则可以嗅探加密数据包,但不方便。你必须

  • 将您的网络接口置于监控模式
  • 捕捉四次握手
  • 使用网络的预共享密钥对其进行解密
  • 这将为您提供解密流量所需的密钥

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

一旦您能够查看 Wi-Fi 流量,您会注意到 Android 设备倾向于与某些 Google 服务器进行通信,并且它们的 HTTP 连接具有可以识别的用户代理字符串。这是可行的被动解决方案的基础。

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 堆栈是 Linux 的,因此 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 地址时,才会被广播。不广播未来的租约延期等。

反向 DNS 查找

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

在 DHCP 租用期间,host_name 预计将在 DNS 中保持列出。您可以通过ping来检查设备是否仍然存在。

依赖 host_name 的一个缺点是可以通过多种方式进行更改。设备制造商或运营商很容易更改主机名(尽管经过搜索,我无法找到他们曾经拥有的任何证据)。有一些应用程序可以更改主机名,但它们需要 root,所以这最多是一个边缘情况。

最后还有一个开放的Android 问题 6111:允许指定当前有 629 颗星的主机名。在将来的某个时候,也许很快,在 Android 设置中看到可配置的 host_name 也就不足为奇了。因此,如果您开始依赖 host_name 来识别 Android 设备,请意识到它可能会从您下面被拉出来。

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

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

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

于 2012-11-21T17:36:56.107 回答
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 的某些更高版本的设备上使用,但是,它需要这两款设备都支持 Wi-Fi Direct,并且仅在关闭 Wi-Fi 的情况下创建临时 P2P 连接,就像具有更长范围的蓝牙连接一样:

在此处输入图像描述

有关 Wi-Fi Direct API 支持,请查看官方指南 -无线连接设备

于 2012-11-18T04:49:34.567 回答
2

我在看这个想法

http://www.libelium.com/smartphones_iphone_android_detection

特别注意这一点

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

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

很久以前,我在我的mac上使用一个叫做stumbler的应用程序来查找wifi网络,我认为这是相似的

其他想法

好吧,如果我需要确定本地网络上的安卓手机,我会怎么做。如果没有运行 dns 服务,我只有几种可能

如果 SSID 正在广播 - 什么都不能告诉我 IP 地址 - android 让您对主机命名有很多控制,所以我想您可以为您的 android 设备定义一个特定的 IP 范围。- 没用。

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

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

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

于 2012-11-21T20:20:48.467 回答
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/

于 2012-11-22T00:09:04.860 回答
1

更新的回应

抱歉,我没有正确理解原始问题。只有您的评论让我非常清楚,您不想在目标设备上安装任何东西,而只是想要一种在网络中发现随机电话的方法。

我不确定这是否真的可以按照您想要的方式进行。如果没有在 Android 上运行的任何网络发现服务,您将不会首先找到该设备。当然,您可以使用一些低级网络协议,但这只会让您知道存在某些东西,而不是它是什么(作为 Android 设备、PC 或其他任何东西)。

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

旧回应

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

尽管 Qualcomm 是 AllJoyn 的主要赞助商,但这并不意味着您需要在定义中使用 Qualcomm 芯片组。事实上,AllJoyn 适用于任何芯片组,包括 Intel 和 nVidia。它不需要根植手机或对 Android 框架进行任何其他修改,只需使用 Wi-Fi 和/或蓝牙作为配对方法“开箱即用”即可。

于 2012-11-18T16:14:45.443 回答
-1

这是一个 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 并行工作。您可以使用“brew install parallel”在 OSX 上安装它

从这里您可以查看命名的设备android-c40a2b8027d663dd.home.或其他任何内容。

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

sudo nmap -O android-297e7f9fccaa5b5f.home.

但这并没有那么富有成效。

于 2014-12-01T17:53:40.977 回答