用Perl实现高级远程操作系统探测


创建时间:2001-05-24
文章属性:翻译
文章来源: [url]http://www.xfocus.org/[/url]
文章提交: stardust (bugmail_at_telekbird.com.cn)

------------------------------------------------------------------
------[ Feb 03, 2001 - by f0bic - [url]http://www.low-level.net[/url] ]------


"Half of the work that is done is this world,
is to make things appear what they are not."
                        -- Elias Root Beadle



摘要

这个文档从PERL编程的角度讨论操作系统探测的理论和实践。深入的讨论了
远程操作系统探测的方法和概念,并用PERL实现。



I. 介绍

几年来,许多关于如何确定一个远程主机上运行的操作系统的方法和技术被
公布出来。因为这些操作系统探测方法依赖于特定的因素,而这些因素并不
总是存在的,所以这些操作系统的探测并不能保证100%的准确性。



II. 基本的操作系统探测方法

在涉及到高级的操作系统探测概念之前,我要简要介绍一下几种其他几种探
测远程主机操作系统的方法。这些方法可能是很老,但它们可以使我们完成
探测。


   (1) 抓取telnet标识

我想这很容易理解。比如说你连接到远程主机的上telnetd ,就可以看到登
录的时候telnet打出了什么标识。 :)

   (2) 抓取FTP标识

和telnet的概念一样,只要针对ftpd而不是telnetd。

   (3) http的head方法

你可以通过检查web服务器(httpd)的方法来确定目标上运行的操作系统。比
如Web是Microsoft-IIS,那么操作系统基本上就是WindowsNT/2k了。


好了,我想已经基本上总结了现今的几种基本的操作系统的探测方法了。



III. 远程操作系统探测和方式路径追踪概念

有许多种技术用来探测一个主机的操作系统。这个文档讨论了以下四种:

    * telnetd 指纹:
   依靠telnet会话协商和选项。

    * identd 指纹:
     依靠identd/auth (113)是否打开。
    
    * TCP 协议堆指纹:
     依靠数据包中的Window,TTL,ToS和DF等参数。
    
    * Queso 指纹:
      依靠数据包中的Window,Seq,Ack_seq等参数。
      依靠各种 IP/TCP 头标记。

    * 被动指纹:
      与TCP 协议堆指纹很接近。
      依靠Window,TTL,ToS和DF等参数。
      依靠网络流量。
      
在以下的几节中我将深入的讨论上面提到的几种方法。


一些术语:

  * Window:TCP包中的窗口值,在未收到确认的情况下包中所能发送的最大
    数据量。
    
  * TTL:存活时间,一个包在被丢弃之前所能通过的最大节点数。
  
  * ToS:服务的类型

  * DF:不分片标记位
    
  * MSS:最大的段大小
  
  
这些因素可以被用来决定一个远程机器上运行了什么操作系统。依靠所有以
上这些标记的组合,与一个标记数据库进行比对就可以猜测出操作系统。下
面是一个入站连接的tcpdump片断:

00:44:09.194998 eth0 < 203.9.66.52.www > my.ip.com.domain:
S 2006693595:2006693595(0) ack 1 win 9112 <mss 536> (DF)
(ttl 232, id 25119)

我们忽略包中的一些其他信息,可以得到下面的东西:

+-> 设备                    +-> 目的地址          +-> 不分片位
|                             |                      |
eth0 < 203.9.66.52.www > my.ip.com.domain: win 9112 (DF) (ttl 232)
               |                                 |        |
               +-> 源地址                      |        +-> 存活时间值
                                                 |
                                                 +-> TCP 窗口值
  


Tcpdump 收集了包中的以下信息:

+++++++++++++++++++++++++++++++++++++++++++++
+ 目的地址   : my.ip.com                    +
+ 目的端口   : domain (53)                  +
+ 源地址     : 203.9.66.52 ( [url]www.sun.com.au[/url]) +
+ 源端口     : www (80)                     +
+ 窗口值     : 9112 (0x2398)                +
+ 存活时间值 : 232                          +
+ 服务类型值 : 0                            +
+ 不分片位   : ON                           +
+ 最大片断值 : 536                          +
+++++++++++++++++++++++++++++++++++++++++++++


从窗口值看可能是一个Solaris机器。存活时间值和服务类型值看也符合Solaris
系统的特征。Solaris系统的默认存活时间值是255,在数据包沿它的路径到达
目标地址的过程中,经过一定数量的节点,存活时间值可能会减到232。


一点有关窗口值的小说明:

一般来说,一个高的窗口值意味着是一个UNIX机器,而一个低的窗口值
则很可能是一个windows机器,路由器,交换机等....


下面的traceroute证实了我们存活时间值接近255的猜测:


1  my.ip.com (127.0.0.1)  148.010 ms  138.609 ms  118.812 ms
2  ??.kpnbelgium.be (194.119.225.185)  129.111 ms  138.566 ms  118.877 ms
3  ??.kpnbelgium.be (194.119.228.161)  119.008 ms  119.300 ms  128.546 ms  
...
...
20  fddi0-0.chw1.sydney.telstra.net (139.130.36.227)  509.930 ms  519.879 ms  
509.941 ms
21  sunmi1.lnk.telstra.net (139.130.37.142)  538.911 ms !X  509.879 ms !X  
549.903 ms !X


节点21是我们进出internet的最后节点,那个 !X 信号意思是通讯出于管理
目的被禁止的意思。


我们的存活时间值 : 232
节点数          :  21
               + ---
总存活时间值     : 253

到达Solaris系统默认的存活时间值255,少了两个节点,所以我们知道了
在节点21后还有两个节点。第一个为位于内网的网际互联设备,第二个就是
目标主机(203.9.66.52),它有Solaris系统的存活时间值255。现在我们
可以说(以相当的肯定程序上)说203.9.66.52是一个Solaris机器。

远程主机的路径追踪对操作系统的指纹来说是一个很重要的问题。一个数据
包所走过的路径可明显地决定操作系统指纹的匹配。所以,对这些存活时间
上区别做些缓冲有很大用处。



IV. 用Perl实现远程系统的探测的方法



1. Telnetd 会话协商(TSN)和Telnet选项。

这项技术涉及到远程系统上运行的telnetd,允许你去连接。当与telnetd的
socket连接初始化完成后,我们执行sysread()操作来收集telnet会话的协商
指纹信息。这个指纹看起来会是这样的:


Linux <= 2.2.16 : 齘X???


为了使用telnet守护进程来确定操作系统,我们需要知道在telnet.h中定义
的TELOPT(Telnet选项)的顺序。除了个别例处,每个操作系统有它自己的
顺序。

一旦我们得到我们的指纹信息,我们必须首先把它转换为十进制的数(1-
255),然后各自地把十进制值和它相应的TELOPT值想匹配。


Ascii 值 : 齘X???
十进制值 : 255 253 24 255 253 32 255 253 35 255 253 39
Telopts 值 : IAC DO  TELOPT_TTYPE IAC DO TELOPT_LINEMODE IAC DO TELOPT_XDISPLOC IAC DO

TELOPT_NEW_ENVIRON


虽然这些TELOPT值可以在 /usr/include/arpa/telnet.h 中找到,但我也把
它们放到了下面,这样如果你想做一些 telnetd指纹检查的时候可以用到:


  /* telnet protocol definitions */

255     IAC         /* interpret as command: */
254    DONT         /* you are not to use option */
253    DO         /* please, you use option */
252    WONT        /* I won't use option */
251    WILL        /* I will use option */
250    SB         /* interpret as subnegotiation */
249    GA         /* you may reverse the line */
248    EL         /* erase the current line */
247    EC         /* erase the current character */
246    AYT        /* are you there */
245    AO        /* abort output--but let prog finish */
244    IP        /* interrupt process--permanently */
243    BREAK         /* break */
242    DM        /* data mark--for connect. cleaning */
241    NOP        /* nop */
240    SE        /* end sub negotiation */
239    EOR        /* end of record (transparent mode) */
238    ABORT        /* Abort process */
237    SUSP        /* Suspend process */
236    xEOF        /* End of file: EOF is already used... */


  /* telnet options */

  0    TELOPT_BINARY        /* 8-bit data path */
  1     TELOPT_ECHO        /* echo */
  2     TELOPT_RCP        /* prepare to reconnect */
  3    TELOPT_SGA          /* suppress go ahead */
  4    TELOPT_NAMS        /* approximate message size */
  5    TELOPT_STATUS        /* give status */
  6    TELOPT_TM         /* timing mark */
  7    TELOPT_RCTE        /* remote controlled transmission and echo */
  8    TELOPT_NAOL        /* negotiate about output line width */
  9    TELOPT_NAOP        /* negotiate about output page size */
10    TELOPT_NAOCRD        /* negotiate about CR disposition */
11    TELOPT_NAOHTS        /* negotiate about horizontal tabstops */
12    TELOPT_NAOHTD        /* negotiate about horizontal tab disposition */
13    TELOPT_NAOFFD         /* negotiate about formfeed disposition */
14    TELOPT_NAOVTS         /* negotiate about vertical tab stops */
15    TELOPT_NAOVTD        /* negotiate about vertical tab disposition */
16    TELOPT_NAOLFD         /* negotiate about output LF disposition */
17    TELOPT_XASCII        /* extended ascii character set */
18    TELOPT_LOGOUT         /* force logout */
19    TELOPT_BM         /* byte macro */
20    TELOPT_DET         /* data entry terminal */
21    TELOPT_SUPDUP        /* supdup protocol */
22    TELOPT_SUPDUPOUTPUT    /* supdup output */
23    TELOPT_SNDLOC         /* send location */
24    TELOPT_TTYPE        /* terminal type */
25    TELOPT_EOR         /* end of record */
26    TELOPT_TUID         /* TACACS user identification */
27    TELOPT_OUTMRK        /* output marking */
28    TELOPT_TTYLOC        /* terminal location number */
29    TELOPT_3270REGIME    /* 3270 regime */
30    TELOPT_X3PAD         /* X.3 PAD */
31    TELOPT_NAWS        /* window size */
32    TELOPT_TSPEED        /* terminal speed */
33    TELOPT_LFLOW         /* remote flow control */
34    TELOPT_LINEMODE        /* Linemode option */
35    TELOPT_XDISPLOC        /* X Display location */
36    TELOPT_OLD_ENVIRON    /* Old - Environmental variables */
37    TELOPT_AUTHENTICATION     /* Authenticate */
38    TELOPT_ENCRYPT         /* Encryption option */
39    TELOPT_NEW_ENVIRON    /* New - Environmental variables */
255    TELOPT_EXOPL        /* extended options list */


当对telnetd 进行指纹探测的时候,应该记住这些检测非常依赖于在主机上
默认的telnetd安装方式。如果你不是在Linux机器上运行in.telnetd,那么
这种方法可能会使你觉得运行了别的操作系统而不是实际的运行的。

这是我telnetd指纹文件的一部份:


    # daemon, daemon version, os, os version, architecture, fingerprint

    # 3Com SuperStack_II Switch
    ,,3Com,,SuperStack_II Switch,齘C,

    # HP-UX B.10.20
    ,,HP-UX,B.10.20,HP 9000,?,

    # Linux 2.2.9
    ,,Linux,2.2.9,x86,齘X???,

        # Cobalt Linux 3.0
    ,,Cobalt Linux,3.0,mips,齘X???,
      

在有些时候,用这种指纹探测方法我们可能碰上问题,几个操作系统可以有
相同类型的指纹,会使操作系统的区分变得困难。当然,有问题就会有解决
的方法。

除了只是对telnetd用sysread()收集信息,我们可以发送telnet选项给目标
主机,收集它的回应,与一个指纹数据库进行比对。通过发送诸如:
IAC/DO/DONT/WILL/WONT 的命令,我们就会对每个操作系统如何对命令作出
反应有一个清楚的认识,因而对可能的操作系统有一个比较准确的猜测。


进行TSN指纹探测的一个示例代码:

--cut--


        #!/usr/bin/perl
        #
        # TSN fingerprint example (by f0bic)
        # usage: ./tsn <host> (telnetd-port)
        # It is also possible to check for the DONT's
        # instead of for the DO's.
        
        use Socket;
        $h=$ARGV[0];
        $p="23" unless $ARGV[1];
        socket(S, PF_INET, SOCK_STREAM, 6);
        $iaddr=inet_aton($h);$paddr=sockaddr_in($p,$iaddr);
        if(connect(S, $paddr)) {
          sysread(S, $fprint, 200); # gathering telnetd fingerprint
          print "\n[$h - connected]\n\nfingerprint: $fprint\n";
          @ords = split(//, $fprint);print "ordinal: ";
      foreach $tval (@ords){print ord($tval);print " ";} # ordinal
      print "\n\n";
        } else {
        print "$host: cant connect!\n\n";
        }
    

--cut--

一旦你用tsn.pl得到了指纹信息,你就可以与一个数据库进行比对看看是不
是有成功的匹配。


---
优点:快,不需要超级用户权限
缺点:不太可靠,容易被记录
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Telnet会话协商指纹工具:

1. Telnetfp

Author: palmers / teso
Download: [url]http://teso.scene.at/releases/telnetfp_0.1.2.tar.gz[/url]

2. Prod-1.0

Author: f0bic / low-level
Download: [url]http://www.low-level.net/f0bic/releases/prod-1.0/[/url]
Info: this is a perl implementation of the telnetd fingerprint
      technique.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



2. Identd 指纹探测

这种指纹探测需要远程主机运行identd服务而且我们可以连接它。通过与远
程主机上的守护进程建立连接,我们可以收集关于它的版本信息,通过与一
个指纹信息文件中的identd的类型,版本和编译日期等信息的比对就可以对
操作系统进行猜测。下面是一个例子,在里面对远程机器的identd服务器做
了一个连接:


   ::(ninja)-([f0bic]--[/sys])$ telnet [url]www.chemie.fu-berlin.de[/url] 113
   Trying 160.45.22.11...
   Connected to ester.chemie.fu-berlin.de (160.45.22.11).
   Escape character is '^]'.
   VERSION
   0 , 0 : X-VERSION : pidentd 3.0.7 for IRIX64 6.5 (Sep 15 1999 11:21:21)    


参照RFC 1413,一个identd的回应的语法是这样的:


   <port-on-server> , <port-on-client> : <resp-type> : <add-info>


在我们的例子里我们只是查询版本,所以显示的服务器与客户端的端口都为
0。返回的类型是X-VERSION,附加的信息是pidentd 3.0.7 for IRIX64 6.5
(Sep 15 1999 11:21:21)。这告诉我们远程的守护进程是pidentd版本是3.0.7
在IRIX64 6.5上运行,在Sep 15 1999 11:21:21编译。大多数identd的回应
信息不象IRIX那样显示那么多信息。下面的ident是一个FreeBSD 4.2-stable
的:


   0 , 0 : X-VERSION : 2.8.5 (Compiled: 11:18:59 Oct 23 2000)


在上面的例子里,我们不能直接确定出远程机器上运行的是什么系统。然而
我们也不需要那么多信息,也可以通过比对版本和编译日期来确定出
FreeBSD 4.2-stable的。


---
优点:快,不需要超级用户权限。
缺点:不太可靠,容易被记录,运行需要认证
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Identd 操作系统指纹工具:

ldistfp

Author scut / teso
Download: [url]http://teso.scene.at/releases/ldistfp-0.1.2.tar.gz[/url]


identfp

Author: f0bic / lowlevel -- dethy / synnergy
Download: [url]http://www.synnergy.net/Archives/Utilities/dethy/identfp.tar.gz[/url]
Info: this is a perl implementation of the identd fingerprint
      technique.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



3. 基于TCP协议栈的指纹推测                                                                  

  

这个技术涉及数据包的处理,更可靠。因为我们需要构造数据包,所以需要
超级用户权限。我们必须用到SOCK_RAW (或者 Net::RawIP),这种技术是象
下面描述的这样工作的:



+---------------+              SYN                +-------------------+
|               | ------------------------------> |                   |
|     Source    |                                 |    Destination    |
|               | <------------------------------ |                   |
+---------------+            SYN|ACK              +-------------------+
                               |
                               |
                               |
                    +----------------------+
                    | Packet Information:  |
                    |----------------------|
                    |                      |
                    | Source: <src-addr>   |
                    | Src-Port: <src-port> |
                    | Dest.: <dst-addr>    |
                    | Dst-Port: <dst-port> |
                    |                      |
                    |----------------------|
                    |                      |
                    | Window: <windowsize> |
                    | TTL: <TTL value>     |
                    | ToS: <ToS value>     |
                    | DF: <ON or OFF>      |
                    | MSS: <MSS value>     |
                    |                      |
                    +----------------------+

就象你上面看到的图示那样,我们收到了一个SYN|ACK回应,它暗示端口处
于监听状态。如果端口不是处于监听状态,我们将收到一个RST|ACK回应。

当我们收到一个SYN|ACK回应,在开始收集操作系统的指纹信息前就连续发
生了很多事情:

        +---------+
        | SYN|ACK |
        +---------+
            |
            |      +-------------------+
             ----> | <1> 收集信息       |
                   +-------------------+                
                                |                              
                                |    +--------------------+
                                ---> | <2> 值匹配吗?是或否 |
                                     +--------------------+
                                                 |
                                                 |
                                -------------------------------
                                |                             |
                                v                             v
                   +------------------------+     +------------------------+          
                   |     是:继续匹配         |     | 否:不能识别的指纹信息    |
                   +------------------------+     +------------------------+
                                |
                                |
                                v
                      +-----------------------+
                      | <3> 主机路径追踪依旧    |
                      |     匹配?是或否        |
                      +-----------------------+
                                |  
                                |    +---------------------+
                                |--> | 否:不能识别的指纹信息 |
                                |    +---------------------+
                                |
                                |    +---------------------+
                                |--> | 是:鉴别系统          |
                                     +------------------- -+



    <1> 信息收集
            
        因为我们需要收集Window, TTL, DF的值,所以我们要先建立一个近似匹配的指纹
        数据库。这个指纹数据库由缺省windowsizes, ttl值, tos值, 和DF(打开或关闭)
        。为了适应这种格式,要建立一个能精确评估TCP Stack指纹是/否的树结构图表。

        TSF数据文件的例子:
  
            # os,version,architecture,window,ttl,tos,df
            # DF - 1 for ON / 0 for OFF

            AIX,4.2,,65535,64,0,1
            AIX,3.0,,16384,64,0,1
            Cisco IOS,11.3,Cisco Router,4128,255,16,1
            Solaris,,x86,9112,255,0,1
            Solaris,8,sparc,24656,64,0,1
  

        <2> TCP Stack 值匹配

        我们收集了这些值以后,要把这些值和数据库已知的指纹进行比较是否匹配。TTL
        并不是一个常值,它依赖于包从源主机到目的主机经过的节点数。因此,我们将接
        收这个匹配并且留下TTL匹配主机路径追踪检查。

        我们将再用 [url]www.sun.com.au[/url]来做示范:)
            
            # 从 [url]www.sun.com.au[/url]接收来的包信息

            Window: 9112 / TTL: 232 / ToS: 0 / DF: ON

            # Window, ToS, DF 都和Solaris操作系统相似,另一方面TTL值却依旧不可信,
            # 因为不是正确的255。这是主机路径追踪的终点。
              

        <3> 主机路径追踪 (HPP)

        追踪包穿越的路径,我们可以确定大概正确的TTL值并且猜测大概操作系统。

        当处理TTL值的时候有一个经验,从数据库取TTL的值并且让它位于它和之前
        的TTL值加1。


           +------------------------------------+
           | TTL Value       |   TTL good match |
           |------------------------------------|
           |   32            |          0 -  32 |
           |   64            |         33 -  64 |
           |  128            |         65 - 128 |
           |  255            |        129 - 255 |
           +------------------------------------+


       如果我们的TTL值在上面的表里,我们给出下列推测:

       包的TTL值232位于TTL匹配值129-255,所以我们可以假设TTL在目标机器里可能是255,
       给我们一个明确匹配:


                x86 Solaris Operating System (Solaris,,x86,9112,255,0,1)


       实际上,TTL的255值并不总是从129来的,因为那有126个节点,看起来不可行:) 但是这
       却总是一个正确匹配的好经验。


下面是一些TSF的范例代码,我没有提供整个sock_raw连接,只是采指纹部分,可以在包里面发现它。如
果你希望知道怎样用Perl写SOCK_RAW连接,我强烈推荐你下载Net::RawIP(你一定需要它)然后看它的
"man"。


    #!/usr/bin/perl

    use Net::RawIP;
    
        # here's where the SOCK_RAW connection goes.
        # you can either use Socket w/ SOCK_RAW or use Net::RawIP.
        #
        # You can set whatever flags you want depending on which type
        # of scan you want to perform. Just edit the syntax:)
        #
        # $packet->set({ ip => { saddr => $src, daddr => $daddr},
        #                tcp => { source => $sport, dest => $dport, syn => 1, psh => 1 } });

        
        #


        sub fingerprint_it {
            
            $packet->bset(substr($_[2],$offset));
            my ($tos, $ttl, $saddr, $desaddr, $soport, $deport, $windowsize) =
            $packet->get( {ip => [qw(tos ttl saddr daddr)],
                           tcp => [qw(source dest window)]
                           });                                
            if($windowsize) { # yay! we've got a window!!!
              if($windowsize eq "9112") { # windowsize matching
                 if(($ttl <= "255") && ($ttl >= "129")) { # HPP TTL matching
                     $os="Solaris";
                 }
              }
              # here's where you can add some more OS matches
              # ...
              # ...
              else {
               print "\n\n Unknown Fingerprint\n\n";
               exit(0);
              }
            }
            print "\n\n-- Operating System Guess: $os\n\n";
        }
        

你可以把所有的Window, TTL, ToS, DF的值读入到数组,把代码变的更简练、易懂。就象用"if"结构
显示采集指纹的工作。


---
优点:快,比TSN指纹更准确
缺点:需要超级用户权限
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
基于TCP Stack指纹的工具:

1. nmap
作者: Fyodor
下载: [url]http://www.insecure.org/nmap[/url]

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  

4. 基于多标记TCP Stack指纹 (Queso 方法).

比较基于TCP Stack指纹,Queso依靠7次检查而不是一次。当采Queso指纹时,将从源主机发送7个不同
标志的包到目标主机。下面是Queso指纹扫描类型的概念图:


   +----------------+
   | QueSO Concepts |
   +-----------------------------------------------------+
   | SEND           | INFO                               |
   |-----------------------------------------------------|
   |                |                                    |
   | SYN            |     Determine State of Port        |
   |                |                                    |
   | SYN+ACK        |     SYN|ACK test                   |
   |                |                                    |
   | FIN            |     FIN test                       |
   |                |                                    |
   | FIN+ACK        |     FIN|ACK test                   |
   |                |                                    |
   | SYN+FIN        |     SYN|FIN test                   |
   |                |                                    |
   | PSH            |     PSH test                       |
   |                |                                    |
   | SYN+XXX+YYY    |     SYN|XXX|YYY test               |
   |                |                                    |
   +-----------------------------------------------------+
                                          
  

   测定端口状态

   首先,一个SYN包发送去测定端口是否处于监听状态。如果是,我们将收到SYN|ACK,否则,我们将
   收到RST|ACK回答。除了回答外,7个检查的每个方法都将测定seqnum, acknum, window是否在
   包头出现。

  
   头伪造


   为了缩小大范围可能的操作系统,一个被发送到网上的Queso包(不管是SYN, SYN|ACK, FIN,...)
   包含了伪造的IP和TCP头信息,而且附加信息里装入两个不常用的TCP标志(XXX和YYY)。TCP不常用
   的标志,XXX和YYY分别使用在例子里,通常不要修改包的状态并且安全的和其它头的值保持协同。

   下面是伪造的IP和TCP头的表,连同它的伪造值。这个表的包含信息在queso远程系统检测工具的
   "tcpip.c"里定义。你可能需要修改它们的值来使他们符合要求,这取决于你用什么类型的指纹文件。

  
   +-------------------+
   | Forged IP Header  |
   |------------------------------------------+
   | header length     |   5                  |
   | ip version        |   4 (IPv4)           |
   | tos               |   0                  |
   | total length      |   40                 |
   | offset            |   0                  |
   | id                |   31337 + <src-port> |
   | ttl               |   255                |                              
   | source            |   <src-addr>         |
   | destination       |   <dest-addr>        |
   | ip checksum       |   variable           |
   | protocol          |   tcp                |
   +------------------------------------------+

  
   +-------------------+
   | Forged TCP Header |
   |------------------------------------------+
   | source port       |   <src-port>         |
   | destination port  |   <dest-port>        |
   | seq               |   variable           |
   | ack               |   0                  |
   | ( x2_offset       |   0x50 (80) )        |
   | x2 (unused)       |   0 unless x2_offset |
   | offset            |   5 unless x2_offset |
   | flags             |   variable           |
   | tcp checksum      |   variable           |
   | window            |   0x1234 (4660)      |
   | urgent pointer    |   0                  |
   +------------------------------------------+
  
  
   这些伪造的IP和TCP头是非常重要的准确测试的TCP标志。下面是一个对linux 2.0.35机器
   的完全Queso扫描:(T1-7 == test1 到 test7)


   T1 - SYN
  
   +------------+                SYN                   +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+              SYN|ACK                 +-------------------+
                                 |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|
                      |                         |
                      |  reply: SYN|ACK         |
                      |    seq: 1 (yes)         |
                      |    ack: 1 (yes)         |
                      | window: 0x7FE0 (32736)  |
                      +-------------------------+
                      |    T1:SA:1:1:0x7FE0     |
                      +-------------------------+

  
   T2 - SYN|ACK

   +------------+              SYN|ACK                 +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+                RST                   +-------------------+
                                  |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|                              
                      |                         |
                      |  reply: RST             |
                      |    seq: 0 (no)          |
                      |    ack: 0 (no)          |
                      | window: 0 (no)          |
                      +-------------------------+
                      |        T2:R:0:0:0       |
                      +-------------------------+


   T3 - FIN

   +------------+                FIN                   +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+              no reply                +-------------------+
                                  |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|
                      |                         |
                      |  reply: - (none)        |
                      |    seq: - (none)        |
                      |    ack: - (none)        |
                      | window: - (none)        |
                      +-------------------------+
                      |        T3:-:-:-:-       |
                      +-------------------------+    


   T4 - FIN|ACK

   +------------+              FIN|ACK                 +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+                RST                   +-------------------+
                                  |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|
                      |                         |
                      |  reply: RST             |
                      |    seq: 0 (no)          |
                      |    ack: 0 (no)          |
                      | window: 0 (no)          |
                      +-------------------------+
                      |        T4:R:0:0:0       |
                      +-------------------------+                                            

                  


   T5 - SYN|FIN

   +------------+              SYN|FIN                 +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+            SYN|FIN|ACK               +-------------------+
                                  |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|
                      |                         |
                      |  reply: SYN|FIN|ACK     |
                      |    seq: 1 (yes)         |
                      |    ack: 1 (yes)         |
                      | window: 0x7FE0 (32736)  |
                      +-------------------------+
                      |    T5:SFA:1:1:0x7FE0    |
                      +-------------------------+            


   T6 - PSH

   +------------+                PSH                   +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+              no reply                +-------------------+
                                  |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|
                      |                         |
                      |  reply: - (none)        |
                      |    seq: - (none)        |
                      |    ack: - (none)        |
                      | window: - (none)        |
                      +-------------------------+
                      |        T6:-:-:-:-       |
                      +-------------------------+    


   T7 - SYN|XXX|YYY

   +------------+            SYN|XXX|YYY               +-------------------+
   |            | -----------------------------------> |                   |
   |   Source   |                                      |    Destination    |
   |            | <----------------------------------- |                   |
   +------------+              SYN|ACK                 +-------------------+
                                  |
                      +-------------------------+
                      | Packet Information:     |
                      |-------------------------|
                      |                         |
                      |  reply: SYN|ACK         |
                      |    seq: 1 (yes)         |
                      |    ack: 1 (yes)         |
                      | window: 0x7FE0 (32736)  |
                      +-------------------------+
                      |     T7:SA:1:1:0x7FE0    |
                      +-------------------------+          


   当我们执行了7次测试发现匹配(或没有:))它们。
  
    T1:SA:1:1:0x7FE0
    T2:R:0:0:0
    T3:-:-:-:-
    T4:R:0:0:0
    T5:SFA:1:1:0x7FE0
    T6:-:-:-:-
    T7:SA:1:1:0x7FE0

   我们好像发现一个匹配:Linux 2.0.35
  
  
   执行了7次测试并且伪造了TCP和IP头,我们对可能的系统有了更准确的描述。不同的操作系统处理这


   测试,这些伪造头有它们自己的各自的风格,这使采集指纹变的容易多了。这是"更多,更好"的方法


   你发送更多的东西到操作系统,你将得到更多你希望的更准确、详细的匹配。


下面是基于多标志TCP Stack指纹的示例代码(Queso方法)。这里没有给出完整的代码,否则整个篇幅都
将被代码代替。在下面的代码片断里你可以编辑什么标志位来建立这7个请求。

  
    
        #!/usr/bin/perl

        use Net::RawIP;

        # QueSO.pl [ by f0bic ]
        # [ well atleast part of it:) ]
        #
        # here's where the SOCK_RAW connection goes.
        # you can either use Socket w/ SOCK_RAW or use Net::RawIP.
        #
        # You can set whatever flags you want depending on which type
        # of scan you want to perform. Just edit the syntax:)
        #
        # $id = "31337" + $sport;
        # $csum = rand();
        #
        # Test 5 - SYN|FIN
        #
        # $packet->set({ ip => { saddr => $src, daddr => $daddr, ihl => "5", version => "4",
        #                        tos => "0", tot_len => "40", frag_off => "0", ttl => "255",
        #                        id => $id, check => $csum },
        #
        #                tcp => { source => $sport, dest => $dport, syn => 1, fin => 1,
        #                         seq => $seq, ack_seq => "0", doff => "5", check => $csum,
        #                         window => "0x1234", urg_ptr => "0"} });
        #                          
        # Houston, we have liftoff:)
        #

        sub fingerprint_syn_fin { # here's the fingerprinting process for the SYN|FIN scan;
            
            $packet->bset(substr($_[2],$offset));
            my ($saddr, $desaddr, $soport, $deport, $windowsize, $ack, $fin, $syn, $psh,

$urg, $rst, $seq, $seq_ack) =
            $packet->get( {ip => [qw(saddr daddr)],
                           tcp => [qw(source dest window ack fin syn psh urg rst seq

seq_ack)]
                           });                            
            # I'm sure from this point on you can figure it out on your own.
            # fin (=1 for yes / =0 for no), etc.. etc.. :)

        }


---
优点: 快,比TSN和TSF指纹更准确
缺点: 需要超级用户,多重扫描可能被IDS系统记录
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
基于多标志TCP Stack指纹(Queso)的工具:

1. nmap
作者: Fyodor
下载: [url]http://www.insecure.org/nmap[/url]

2. QueSO
作者: savage / apostols.org
下载: [url]http://packetstorm.securify.com/UNIX/scanners/queso-980922.tar.gz[/url]

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


                                                              
5. 被动OS采集指纹/网络映射

Lance Spitzner发布了对于这个课题真正有趣的文档(下面列出),他描述了采集主机指纹技术无需了解

它。
这个技术最基本的概念是设置网卡混杂模式并且从接收的包里采集指纹。这有点象基于TCP Stack指纹采

集(TSF)
,但是我们减去第一步--发送一个包出去--因而我们监听网络传输。使用这个技术,也同样可以得到

端口
打开的信息。换句话说,映射整个英特网(Copyright Subterrain.Net @ Toorcon/Defcon)。

因为这个技术和基于TCP Stack采集指纹非常相似,我不再详细的说明了。这是基本概念图:




             +--> stream of network traffic (yea i know, looks lame)
         |
             |
  ====================================================================
                                    |
                                    |
                           +-----------------+
                           |                 |
                           | Passive Sniffer |
                           |                 |
                           +-----------------+
                             |              
                 +---------------------------+
                 | Packets Sniffed:          |          
                 |---------------------------|
                 |#1 - Source: <src-addr>    |
                 |     Dest. : <dst-addr>    |
                 |     S-port: <src-port>    |
                 |     D-port: <dst-port>    |
                 |     window: <windowsize>  |
                 |     tos   : <tos>         |
                 |     ttl   : <ttl>         |
                 |     mss   : <mss>         |
                 |     DF    : ON/OFF        |
                 |---------------------------|
                 |#2 - ......                |
                 |                           |
                 +---------------------------+



基于这些值采集了以后,我们可以或多或少用TSF的方法来猜测操作系统。我们也可以用一个指纹匹配文


来试图合并这些收集的值作为指纹文件的值。


因为Craig Smith开发了passfing,一个用perl写的被动OS指纹采集工具。所以我决定不提供perl代码
,你可以去找他的程序。


Lance Spitzner's Passive Fingerprinting paper:
[url]http://packetstorm.securify.com/papers/IDS/fingerprinting.txt[/url]


---
优点: 快,和TSF一样准确,完全隐蔽。
缺点: 需要超级用户,无目标。
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
被动OS指纹/网络映射工具:

1. Siphon
作者: bind & aempirei / subterrain security group
下载: [url]http://www.subterrain.net/projects/siphon/[/url]

2. Passfing
作者: Craig Smith
下载: [url]http://packetstorm.securify.com/UNIX/IDS/passfing.tar.gz[/url]

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        



V. 结束语

虽然这些操作系统检测技术非常准确,能清晰的给出主机可能运行的操作系统,但是它们并
不总能给出一个操作系统的版本。 一些操作系统有时用的是相同的指纹匹配,这使产生准
确的结果有些困难。 不过不久新的技术可能使我们采集指纹更简单,而且更隐蔽。



参考资料及感谢:


TESO
  TelnetFP
   [url]http://teso.scene.at/[/url]

Subterrain Security Group
  The Siphon Project
   [url]http://www.subterrain.net/projects/siphon/[/url]
  
El Apostols
  For making Queso possible

Nmap OS detection
   [url]http://www.insecure.org/nmap/nmap-fingerprinting-article.html[/url]

Dethy
  Synnergy Networks ( [url]http://www.synnergy.net[/url])
  1. For inspiring me to write this paper
  2. For making Net::RawIP elite ;)

Craig Smith
  Passfing

Lance Spitzner
  "IDing Remote Hosts without them knowing about it"
  Passive Fingerprinting Article



Contact:

  [email]f0bic@low-level.net[/email]
   [url]http://www.low-level.net[/url]