|=---=[       基于ICMP的远程操作系统TCP/IP堆栈辩识技术              ]=---=|
|=-----------------------------------------------------------------------=|
|=---=[ ICMP based remote OS TCP/IP stack fingerprinting techniques ]=---=|
|=-----------------------------------------------------------------------=|
|=---------------=[ Ofir Arkin & Fyodor Yarochkin ]=---------------------=|
|=---------------=[ translate to chinese by xundi ]=---------------------=|

--[基于ICMP的辩识方法]--

    现今的基于TCP的传统远程操作系统辩识技术相对来说比较旧了，这里我们会介绍一种基于ICMP响应的模式来远程判断操作系统，根据接收来自远程主机响应的信息来判断相关的操作系统。对于某些系统和操作平台如Win*可以达到比基于TCP传统辩识模式更精确的级别。
    
    与基于TCP传统辩识模式类似，ICMP辩识技术利用几个测试来执行对远程操作系统TCP/IP堆栈的探测，但是不同于基于TCP辩识，目前开发阶段来说基于ICMP的辩识技术只需要1到4个测试包就可以鉴别一个操作系统类别。
    
    ICMP辩识模式基于发现各种操作系统返回的ICMP应答各种细微不同来判别（多数是由于不正确或者不一致实现造成的），此判别技术在Ofir Arkin的"ICMP Usage in Scanning" 研究项目中已经描述 ，随后Ofir Arkin把这些发现在"X project"中归纳到逻辑决策树中并在'Xprobe'工具中实现。
    
--[基于ICMP辩识所产生的信息/干扰信息率]--

    上面提过，通过基于ICMP辩识方法对远程目标主机进行探测我们只发送和接收很少数量的数据包，可以说非常少来形容。实际上我们发送一个数据包然后接收一个应答就可以帮助我们辩识出8个不同类型的操作系统(或者同一操作系统各种版本)。当前开发阶段Xprobe工具最多需要发送的数据包来辩识一个操作系统的数据是4个，通过分析4个远程主机的应答来进行分析判断。这就使的基于ICMP的辩识非常高速。

    基于ICMP的探测可以构建很隐蔽，因为不同于普通的辩识方法，Xprobe没有使用任何畸形的/破坏的/不正常的数据包来鉴别操作系统类型，当前核心分析针对接收到的合法的ICMP响应数据包。而且Xprobe发送的包在一般的网络上每天基本成堆的显示，只有很少IDS系统会开启探测这些通信的功能，如果真的要开启这些功能，IDS系统将会接收到很多干扰信息和相当复杂的配置。
    
--[为何Xprobe这么简单探测还能工作?]--

   由于由各种不同RFC标准(开始是RFC 792，后来增加RFC 1122等)，部分或者不完整的ICMP支持(各种ICMP请求不是在任意地方都支持)来处理ICMP实现，又各种TCP/IP堆栈带有对这些不同实现的处理不同；ICMP错误信息数据对待的重要性不同；ICMP协议实现的错误或者不理解等等导致我们可以利用Xprobe来进行简单的探测。
   
--[我们可辩识哪些信息:]-- 

    基于ICMP辩识利用各种操作系统的细微不同来鉴别类型：
    
    应答的数据包中夹带的原始消息部分(即我们发送的数据包)中的IP域将被检查：
    
    *IP 总长度
    
    一些操作系统(如BSD家族系列)会在原始IP总长度域上增加20字节(sizeof(ipheader))，这是因为其内部错误处理数据包的结果。(必须注意的是同样的数据包如果从SOCK_RAW读取的话，返回的数据包ip_len字段将会减掉20字节).

    
    某些操作系统会在返回的数据包中在原始IP总长度域上减掉20字节。
    
    而有些系统会正常响应这个域的值。
    
    * IP ID
    
    一些系统不会正确的响应这个域，如其值的位置顺序会改变。
    
    * IP 头校验和
    
    一些操作系统会错误计算这个域，某些系统会填充0值，而有些系统能正确响应这个值。
    
    * UDP 头校验和(在UDP数据包中)
    
    一些操作系统会错误计算这个域，某些系统会填充0值，而有些系统能正确响应这个值。
    
    所应答的ICMP包中的IP头也将被检查：
    
    * 优先权子段位：
    
    每个IP数据包包含一个称为'TOS'服务类型占8位的字段，代表了IP所支持的优先权和服务类型处理。
    
    'ToS'服务字段包含3个字段：
    
    优先权字段{rfc791}是3位长度，用于处理IP数据包的优先权，包含8个级别的优先处理，其中高优先权的通信需要比低优先权的通信提前发送。
    
    第二个字段4位长度，表示服务类型字段，由于描述网络所运用的服务类型包括：最小延迟，最大吞吐量，最高可靠性和最小费用。
    
    最后一个字段是为未用位，必须设置为0值，路由器和主机将忽略最后一个字段，这个字段站1为长度，TOS位和最后一字段在服务类型机制实施的时候将被替换，所有4位为0表示一般服务。
    
    RFC 1812-Requires following for IP Version 4 Routers中的4.3.2.5 TOS and Precedence 一节有如下描述：
    
    "ICMP源站抑制(Source Quench)错误信息包含的IP优先字段必须与发送方ICMP源站抑制(Source Quench)信息中的IP优先字段相同. 所有其他ICMP错误信息(目的不可达，重定向，超时和参数问题)必须把其优先字段值设置为6(INTERNETWORK CONTROL) 或者 7 (NETWORK   CONTROL)。这些错误信息的IP优先字段值是可设置的"
    
    Linux内核2.0.x, 2.2.x, 2.4.x的行为和路由器一样会在ICMP错误信息中设置优先字段位值为0xc0，网络设备基于IOS 11.x-12.x的Cisco路由器和Foundry Networks交换机具有相同操作行为.
    
    * DF位响应
    
    一些TCP/IP堆栈会在ICMP错误数据包中响应DF位，其他的(如Linux)会拷贝全部八位位组，并部分位清零，再有的是会忽略这个位而设置其自身相关的值。
    
    * IP ID字段(linux 2.4.0 - 2.4.4 内核)
    
    基于linux 2.4.0 - 2.4.4 内核的Linux机器会在ICMP查询请求和应答信息中设置IP标识为零值。
    
    这部分在Linux2.4.5和以上版本中得到改正。
    
    * IP ttl字段(TTL可以衡量数据包经过了多少路由器，可以对目标系统有一定程度的距离衡量)
    
    “发送者设置了TTL字段值代表数据包允许在Internet上经过的最多路由器数”。
    
    这个值在经过每个点之后IP头数据包就会被处理而减少，RFC791陈述这个值的减少量反映了数据包处理的时间，这个TTL值以秒为单位计值。RFC还陈述了最大TTL时间应该设置为255秒，等于4.25分钟。如果此字段的值在到达目标端之前递减为0时，数据包将被丢弃。
    
    相关这个值的时间度量各种设备有一定的差池，一些路由器处理数据包的数据不到一秒，而某些处理数据包的时间需要超过一秒。
    
    TTL值设置的实际目的就是设置一个数据包生存时间上限，这样可以限制不能递送的数据包不会无限循环阻塞Internet网络。
    
    对数据包设置生存时间上限也可以帮助我们防止老的数据包在一段时间后到达目的地，当我们由于某种原因收到信息包重传时就必须防止老的数据包已经被丢弃和再被进程接口处理。

    ICMP数据包的IP TTL字段有两个独立的值，一个是为ICMP查询信息而另一个是为ICMP查询应答设置。
    
    IP TTL字段可以帮助我们鉴别部分操作系统和操作系统组，当我们查询其他主机或者监听通信时也能作为另一项检测标准。
    
    基于TTL的辩识技术需要预先对TTL距离进行计算，然后经过比较才能进行辨别(除非对本地网络系统进行辩识)。
    
    下面的URL有对各种操作系统类型的TTL相关统计，比较详细：
    
    http://www.switch.ch/docs/ttl_default.html
    
    (研究的论文上都是默认的TTL值)
    
    * TOS 字段
    
    RFC 1349定义了ICMP信息中服务类型字段的使用，它描述了在ICMP错误信息(目的不可达, 源站抑制, 重定向, 超时,和参数问题), ICMP请求信息(请求回现, 路由请求, 时间戳, 信息请求, 地址掩码请求)和ICMP应答信息(回现应答, 路由通告, 时间戳应答, 信息应答, 地址掩码应答)之间的区别。
    
    定义如下简单规则：
    
    * ICMP错误信息一般只以默认TOS值(0x0000)发送。
    
    * ICMP请求信息在TOS字段可以以任意值发送，“一机制允许用户在多种应用程序中指定TOS值来实现多种功能来生成ICMP请求信息”。
    
    RFC进一步指出虽然ICMP请求信息一般以默认TOS值发送，但有时存在某种良好原因以其他TOS值来发送。
    
    *ICMP应答信息应该使用与相应ICMP请求信息中相同的TOS字段值。
    
    而一些操作系统当发送ICMP回显应答信息时会忽略RFC1349，就是说发回的ICMP应答信息于相应ICMP请求信息中的TOS字段值不同。
    
    响应ICMP包的ICMP头：
    
    * ICMP错误信息引用(Quoting)大小
    
    所有ICMP错误信息包含一个IP头，ICMP头和部分原始数据包(触发错误的包)数据。
    
    根据RFC792在ICMP错误信息中只包含64位(8个八位组)，但是RFC1122建议数据可达576个八位组。
    
    许多"旧的"TCP堆栈实现在ICMP错误信息中包含8个八位组，Linux/HPUX 11.x, Solaris, MacOS等其他一些系统会包含更多的数据。
    
    一个有趣的情况是Solaris的工程师可能没有正确的阅读RFC，Solaris 2.x系统中使用了64个八位组(512位)而不是64位(误读了64 octets and 64 bits).
    
    * ICMP错误信息应答完整性
    
    另外一个需要注意的是一些堆栈实现当发回ICMP错误信息时，会更改触发其引起错误信息原始包的IP头和下面的协议数据。
    
    由于这个错误，各种TCP/IP堆栈程序员的不同操作和系统的不同响应，通过分析可使攻击者鉴别目标操作系统的类型。
    
    其他的一些细微差别：
    
    * 使用在ICMP回现请求0代码段的不同性
    
    当ICMP请求回显信息(类型8)中ICMP代码段值不等于0时，操作系统会使用ICMP回显应答对我们的查询进行回答，基于Microsoft的操作系统会发回在ICMP回显应答中ICMP代码段值设置为0的数据包，而其他操作系统和网络设备则会使用ICMP回现请求中相同的ICMP代码段值。
    
    基于Microsoft饿操作系统操作与RFC792描述的相反，会指示应答操作系统只改变ICMP类型为回现应答(type 0)，重新计算校验和并发送ICMP回显应答。
    
    * ICMP查询信息使用了DF位
    
    针对此类ICMP错误信息，一些TCP堆栈会响应这些请求而其他系统不会。
    
    * 其他ICMP信息：
    
      - ICMP时间戳请求
      - ICMP信息请求
      - ICMP地址掩码请求
      
      针对这些信息一些TCP/IP堆栈支持这些信息并响应这些请求，而某些操作系统不会。
      
--[Xprobe 实现]--
 
    当前Xprobe使用硬性的逻辑树展开进行判断，初始化UDP数据包发送给关闭的端口来触发ICMP错误信息：ICMP不可达/端口不可达(对于目标系统的限制是至少一个端口没有被过滤而且没有服务监听，也旧司说ICMP不可达数据包可以使用)。如果一个不够判断，在发送多个组合(icmp可不达内容，DF位，TOS..)集合在一个查询中的测试。根据接收到的ICMP不可达数据包，对这些包内容进行检查并做详细的判断，如果需要更进一步的测试，根据逻辑树，发送更多的查询来获得更详细信息。
    
--[ 逻辑树 ]---

    下面是逻辑树的简单介绍：
    
    初始所有TCP/IP堆栈实现被划分2个组，一些回应优先字段位，一些不回应优先字段位，回应优先字段位的系统包括：linux 2.0.x, 2.2.x, 2.4.x, cisco IOS 11.x-12.x, Extreme Network Switches等将进一步通过ICMP错误引用(quoting)大小来区别,Linux遵循RFC1122会在ICMP错误信息中回现包含576八位组大小数据，而这子组中的其他系统只会包含64位(8个八位组)，进一步通过回现集成检查用来判断CISCO路由器和Extreme Network switches。
    
    TTL值和ICMP回现应答包中的IP ID字段将被用来辨别各种Linux内核。
    
    同样途径方法用来辩识其他TCP/IP堆栈，数据回显确认(回现中原始数据包的大小，校验和确认等)，如果需要更多的信息来区分两个类似的IP堆栈，在增加其他查询进行区分辨别。请参考http://www.sys-security.com/html/projects/X.html 获得更纤细信息。
    
    其中一个比较严重的问题是逻辑树，不断增加新的系统类型会变的比较"臃肿"，因此使用基于签名标识(signature)的辨别模式将在后续项目中起用。
    
--[基于签名标识(signature)的途径方法]--

    基于签名标识(signature)的途径方法是我们当前的注重点，我们相信远程基于ICMP辨别方法以后将会变的更稳定，可靠，更灵活。
    
    基于签名标识(signature)的方法将会使用5种不同测试，将可选择的包含每一个操作系统特征。开始的时候系统将会进行较少的检查(一般先使用ICMP不可达进行测试)。
    
    如果接收到的签名标识(signature)没有单一的OS堆栈可以确定，这些堆栈将如果匹配到某一部分组特征，再选择其他方法进行测试。验证将持续到OS堆栈被确定，完全匹配到某个签名标识(signature)为止，或者一个全新系统我们退出测试。
    
    当前将根据下面的测试展开：
    
    * ICMP不可达测试(UDP端口关闭，主机不可达，网络不可达)
    * ICMP回现请求/应答测试
    * ICMP时间戳请求
    * ICMP信息请求 
    * ICMP地址掩码请求

--[后续实现/开发的计划]--

    下面是后续项目中要实现的内容：
    
    * 识别数据库(当前正在测试)
    * 动态基于AI逻辑(当前正在测试)
    * 严重依靠网络拓扑的测试
    * 目标路径测试(计算目标的HOP距离)来进行过滤设备探测
    * 使用实际应用程序数据来检查被发现的机会
    * 其他网络映射能力包括网络作用识别，搜索关闭UDP端口，可达性测试等.
    
--[相关代码信息]--

    下面的URL是相关当前实现代码的获取地址：
        
    http://www.sys-security.com/html/projects/X.html

    http://xprobe.sourceforge.net
  
    http://www.notlsd.net/xprobe/

Ofir Arkin <ofir@sys-security.com>
Fyodor Yarochkin <fygrave@tigerteam.net>
translate to chinese by xundi <xundi@xfocus.org>

|=[ EOF ]=---------------------------------------------------------------=|

