merge: testing → main (reconcile 2-week divergence)
This commit is contained in:
27
decnet/prober/osfp/__init__.py
Normal file
27
decnet/prober/osfp/__init__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""Passive + active OS fingerprinting providers.
|
||||
|
||||
Consumed by the profiler's `sniffer_rollup` (and, longer-term, by a
|
||||
dedicated prober pass). Each provider implements `base.Provider`: given
|
||||
a dict of observed TCP/IP quirks (window, wscale, mss, options
|
||||
signature, TTL, etc.), return a best-match OS label with confidence.
|
||||
|
||||
Layout mirrors `decnet/geoip/` and `decnet/bus/`: `base.py` defines the
|
||||
protocol, `factory.py` is the only sanctioned accessor, and each
|
||||
concrete source (p0f today, nmap-osdb / DECNET-observed later) lives in
|
||||
its own subpackage. Don't import concrete provider classes directly —
|
||||
use :func:`factory.get_provider` or :func:`factory.get_all_providers`.
|
||||
"""
|
||||
from decnet.prober.osfp.base import OsMatch, Provider
|
||||
from decnet.prober.osfp.factory import (
|
||||
get_all_providers,
|
||||
get_provider,
|
||||
reset_cache,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"OsMatch",
|
||||
"Provider",
|
||||
"get_all_providers",
|
||||
"get_provider",
|
||||
"reset_cache",
|
||||
]
|
||||
59
decnet/prober/osfp/base.py
Normal file
59
decnet/prober/osfp/base.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""OS-fingerprint provider protocol + OsMatch result shape.
|
||||
|
||||
Each concrete provider (p0f v2 today; nmap-osdb / DECNET-observed DB
|
||||
later) implements `Provider`. Callers go through
|
||||
:func:`decnet.prober.osfp.factory.get_provider` or
|
||||
:func:`decnet.prober.osfp.factory.get_all_providers` — direct imports
|
||||
of a concrete class are forbidden, mirroring the convention in
|
||||
``decnet/geoip`` and ``decnet/bus``.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class OsMatch:
|
||||
"""The result of matching an observation against a provider's DB.
|
||||
|
||||
Consumers should prefer higher ``confidence``. Providers compute
|
||||
confidence as the fraction of signature fields that matched exactly
|
||||
(vs. wildcard / modulo / "any" predicates) — a signature with every
|
||||
field constrained scoring 1.0, one with every field wildcarded
|
||||
approaching 0.0. This is explicit so the profiler can pick the
|
||||
most-specific match when multiple providers fire.
|
||||
"""
|
||||
|
||||
os: str
|
||||
flavor: str
|
||||
confidence: float
|
||||
provider: str
|
||||
is_userland: bool = False
|
||||
|
||||
def __str__(self) -> str:
|
||||
tag = "userland" if self.is_userland else self.os
|
||||
return f"{tag} {self.flavor} ({self.confidence:.2f} via {self.provider})"
|
||||
|
||||
|
||||
class Provider(ABC):
|
||||
"""Abstract OS-fingerprint source.
|
||||
|
||||
Providers consume a dict of observed TCP/IP quirks (``window``,
|
||||
``wscale``, ``mss``, ``options_sig``, ``ttl``, ``df``,
|
||||
``total_len``, ``quirks`` — not all fields required) and return a
|
||||
best-match :class:`OsMatch` or ``None`` when nothing matches.
|
||||
|
||||
Providers MUST NOT raise on malformed or partial input — the
|
||||
upstream caller (`profiler/fingerprint.py::sniffer_rollup`) runs
|
||||
on data that may be missing any or all fields depending on the
|
||||
event mix, and a raising provider would wedge every attacker
|
||||
profile rebuild. Return ``None`` instead.
|
||||
"""
|
||||
|
||||
name: str
|
||||
|
||||
@abstractmethod
|
||||
def match(self, obs: dict[str, Any]) -> Optional[OsMatch]:
|
||||
"""Return best-match OsMatch for *obs*, or None."""
|
||||
87
decnet/prober/osfp/factory.py
Normal file
87
decnet/prober/osfp/factory.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""OS-fingerprint provider factory.
|
||||
|
||||
Dispatch is env-driven (``DECNET_OSFP_PROVIDERS``, comma-separated),
|
||||
with ``p0f-v2`` as the current default. Structure mirrors
|
||||
:mod:`decnet.geoip.factory` exactly: lazy singletons, a ``reset_cache``
|
||||
for tests, no dialect-specific globals past this module.
|
||||
|
||||
Callers have two entry points:
|
||||
|
||||
- :func:`get_provider` — fetch one provider by name (or the default).
|
||||
Used by anything that wants a single authoritative answer.
|
||||
- :func:`get_all_providers` — fetch the full priority chain as a list.
|
||||
Used by the profiler's :func:`~decnet.profiler.fingerprint.sniffer_rollup`
|
||||
to try each provider in turn and take the highest-confidence match
|
||||
across all of them.
|
||||
|
||||
Reserved names ``dbip`` / ``maxmind`` don't apply here — we use
|
||||
``nmap-osdb`` (pending Fyodor's grant) and ``decnet-observed`` (our
|
||||
own DB of honeypot-captured signatures) as the reserved slots that
|
||||
raise :class:`NotImplementedError` until their subpackages ship.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from decnet.prober.osfp.base import Provider
|
||||
|
||||
|
||||
_DEFAULT_PROVIDERS = "p0f-v2"
|
||||
|
||||
# Lazy singletons, one per name, keyed by the env-selected order so
|
||||
# resetting the env (via reset_cache in tests) rebuilds cleanly.
|
||||
_cached: dict[str, Provider] = {}
|
||||
|
||||
|
||||
def _configured_names() -> list[str]:
|
||||
raw = os.environ.get("DECNET_OSFP_PROVIDERS", _DEFAULT_PROVIDERS)
|
||||
return [n.strip() for n in raw.split(",") if n.strip()]
|
||||
|
||||
|
||||
def _build(name: str) -> Provider:
|
||||
if name == "p0f-v2":
|
||||
from decnet.prober.osfp.p0f.provider import P0fV2Provider
|
||||
return P0fV2Provider()
|
||||
if name in ("nmap-osdb", "decnet-observed"):
|
||||
raise NotImplementedError(
|
||||
f"OS-fingerprint provider {name!r} is reserved but not yet wired."
|
||||
)
|
||||
raise ValueError(f"Unsupported OS-fingerprint provider: {name!r}")
|
||||
|
||||
|
||||
def get_provider(name: Optional[str] = None) -> Provider:
|
||||
"""Return a single provider — *name* if given, otherwise the first
|
||||
entry of ``DECNET_OSFP_PROVIDERS`` (default ``p0f-v2``).
|
||||
|
||||
Lazily built, memoised. Callers MUST go through this or
|
||||
:func:`get_all_providers` — direct imports of the concrete
|
||||
provider class are forbidden per the provider-subpackage convention.
|
||||
"""
|
||||
if name is None:
|
||||
names = _configured_names()
|
||||
name = names[0] if names else _DEFAULT_PROVIDERS
|
||||
cached = _cached.get(name)
|
||||
if cached is not None:
|
||||
return cached
|
||||
provider = _build(name)
|
||||
_cached[name] = provider
|
||||
return provider
|
||||
|
||||
|
||||
def get_all_providers() -> list[Provider]:
|
||||
"""Return every configured provider, in priority order.
|
||||
|
||||
Declared order in ``DECNET_OSFP_PROVIDERS`` IS priority order. The
|
||||
consumer (``sniffer_rollup``) iterates and picks the best-scoring
|
||||
match across all of them; a later provider CAN beat an earlier one
|
||||
if its signature is more specific, so the "priority" is a tiebreaker,
|
||||
not a short-circuit.
|
||||
"""
|
||||
return [get_provider(n) for n in _configured_names()]
|
||||
|
||||
|
||||
def reset_cache() -> None:
|
||||
"""Forget memoised providers — tests use this when monkeypatching
|
||||
``DECNET_OSFP_PROVIDERS`` or ``decnet/prober/osfp/p0f/data/``."""
|
||||
_cached.clear()
|
||||
6
decnet/prober/osfp/p0f/__init__.py
Normal file
6
decnet/prober/osfp/p0f/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""p0f v2 fingerprint database provider.
|
||||
|
||||
Upstream: https://lcamtuf.coredump.cx/p0f.shtml (p0f v2.0.8, 2006)
|
||||
License: LGPL-2.1 (preserved in data/LICENSE.p0f-upstream)
|
||||
Used in DECNET under GPL-3.0 via LGPL-2.1 §3 — see data/README.md.
|
||||
"""
|
||||
498
decnet/prober/osfp/p0f/data/LICENSE.p0f-upstream
Normal file
498
decnet/prober/osfp/p0f/data/LICENSE.p0f-upstream
Normal file
@@ -0,0 +1,498 @@
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
72
decnet/prober/osfp/p0f/data/README.md
Normal file
72
decnet/prober/osfp/p0f/data/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# p0f v2 fingerprint database (vendored)
|
||||
|
||||
This directory contains the p0f v2.0.8 TCP/IP fingerprint database as
|
||||
published by Michal Zalewski in 2006, vendored here so DECNET's prober
|
||||
and profiler can do passive / active OS fingerprinting without a runtime
|
||||
network fetch.
|
||||
|
||||
## What's in here
|
||||
|
||||
| File | Purpose | Sigs |
|
||||
|-----------------------|-----------------------------------------------|------|
|
||||
| `p0f.fp` | SYN fingerprints (passive, incoming) | 262 |
|
||||
| `p0fa.fp` | SYN-ACK fingerprints (active probe responses) | 61 |
|
||||
| `p0fr.fp` | RST+ fingerprints (reset-response quirks) | 46 |
|
||||
| `p0fo.fp` | "stray" fingerprints | 6 |
|
||||
| `LICENSE.p0f-upstream`| Verbatim LGPL-2.1 text from upstream | — |
|
||||
|
||||
## Provenance
|
||||
|
||||
**Authoritative source:** Debian snapshot archive, `p0f_2.0.8.orig.tar.gz`.
|
||||
|
||||
- Archive URL: `https://snapshot.debian.org/archive/debian-archive/20120328T092752Z/debian/pool/main/p/p0f/p0f_2.0.8.orig.tar.gz`
|
||||
- SHA-1 (upstream-recorded by Debian): `7b4d5b2f24af4b5a299979134bc7f6d7b1eaf875`
|
||||
|
||||
Files in this directory are byte-identical copies of the corresponding
|
||||
files inside `p0f_2.0.8.orig.tar.gz::p0f/{doc/COPYING, *.fp}`.
|
||||
|
||||
## License + DECNET-side licensing stance
|
||||
|
||||
Upstream files are licensed under the **GNU Lesser General Public
|
||||
License, version 2.1** (see `LICENSE.p0f-upstream` — verbatim copy of
|
||||
upstream's `doc/COPYING`). Attribution belongs to Michal Zalewski and
|
||||
the named contributors in the original upstream `CREDITS` file.
|
||||
|
||||
DECNET is licensed under **GPL-3.0-or-later**. LGPL-2.1 §3 explicitly
|
||||
permits converting an LGPL-2.1 work to any version of the GPL at the
|
||||
recipient's choice. DECNET exercises that conversion for the vendored
|
||||
files: when consumed as part of DECNET they are effectively under
|
||||
GPL-3.0. The upstream LGPL-2.1 notice is preserved so:
|
||||
|
||||
- Recipients of DECNET see the full chain (original LGPL-2.1 → §3
|
||||
conversion → GPL-3.0), and
|
||||
- Anyone who wants to use these signatures under LGPL-2.1 terms
|
||||
(e.g. in an unrelated library) can still do so by pulling the files
|
||||
directly from upstream.
|
||||
|
||||
## Modifications to upstream
|
||||
|
||||
**None.** The four `.fp` files in this directory are verbatim copies.
|
||||
Any DECNET-authored additions go into a sibling file (`p0f-decnet.fp`,
|
||||
currently absent) under GPL-3.0, loaded by the same parser. Keeping
|
||||
upstream untouched means:
|
||||
|
||||
1. Syncing future upstream changes is a one-step file replacement.
|
||||
2. Attribution is unambiguous: entries in `p0f*.fp` here are Michal's,
|
||||
entries in `p0f-decnet.fp` are DECNET's.
|
||||
3. If we ever want to contribute signatures back to upstream, it's a
|
||||
one-file diff.
|
||||
|
||||
## Refreshing upstream
|
||||
|
||||
```
|
||||
curl -O https://snapshot.debian.org/archive/debian-archive/20120328T092752Z/debian/pool/main/p/p0f/p0f_2.0.8.orig.tar.gz
|
||||
echo "7b4d5b2f24af4b5a299979134bc7f6d7b1eaf875 p0f_2.0.8.orig.tar.gz" | sha1sum -c
|
||||
tar xzf p0f_2.0.8.orig.tar.gz
|
||||
cp p0f/p0f.fp p0f/p0fa.fp p0f/p0fr.fp p0f/p0fo.fp decnet/prober/osfp/p0f/data/
|
||||
cp p0f/doc/COPYING decnet/prober/osfp/p0f/data/LICENSE.p0f-upstream
|
||||
```
|
||||
|
||||
p0f v2 is no longer actively maintained upstream (last release 2006),
|
||||
so refreshes are effectively N/A — but the procedure is recorded for
|
||||
the case where a mirror we trust publishes a signed rebuild.
|
||||
834
decnet/prober/osfp/p0f/data/p0f.fp
Normal file
834
decnet/prober/osfp/p0f/data/p0f.fp
Normal file
@@ -0,0 +1,834 @@
|
||||
#
|
||||
# p0f - SYN fingerprints
|
||||
# ----------------------
|
||||
#
|
||||
# .-------------------------------------------------------------------------.
|
||||
# | The purpose of this file is to cover signatures for incoming TCP/IP |
|
||||
# | connections (SYN packets). This is the default mode of operation for |
|
||||
# | p0f. This is also the biggest and most up-to-date set of signatures |
|
||||
# | shipped with this project. The file also contains a detailed discussion |
|
||||
# | of all metrics examined by p0f, and some practical notes on how to |
|
||||
# | add new signatures. |
|
||||
# `-------------------------------------------------------------------------'
|
||||
#
|
||||
# (C) Copyright 2000-2006 by Michal Zalewski <lcamtuf@coredump.cx>
|
||||
#
|
||||
# Each line in this file specifies a single fingerprint. Please read the
|
||||
# information below carefully before attempting to append any signatures
|
||||
# reported by p0f as UNKNOWN to this file to avoid mistakes. Note that
|
||||
# this file is compatible only with the default operation mode, and not
|
||||
# with -R or -A options (SYN+ACK and RST+ modes).
|
||||
#
|
||||
# We use the following set metrics for fingerprinting:
|
||||
#
|
||||
# - Window size (WSS) - a highly OS dependent setting used for TCP/IP
|
||||
# performance control (max. amount of data to be sent without ACK).
|
||||
# Some systems use a fixed value for initial packets. On other
|
||||
# systems, it is a multiple of MSS or MTU (MSS+40). In some rare
|
||||
# cases, the value is just arbitrary.
|
||||
#
|
||||
# NEW SIGNATURE: if p0f reported a special value of 'Snn', the number
|
||||
# appears to be a multiple of MSS (MSS*nn); a special value of 'Tnn'
|
||||
# means it is a multiple of MTU ((MSS+40)*nn). Unless you notice the
|
||||
# value of nn is not fixed (unlikely), just copy the Snn or Tnn token
|
||||
# literally. If you know this device has a simple stack and a fixed
|
||||
# MTU, you can however multiply S value by MSS, or T value by MSS+40,
|
||||
# and put it instead of Snn or Tnn. One system may exhibit several T
|
||||
# or S values. In some situations, this might be a source of some
|
||||
# additional information about the setup if you have some time to dig
|
||||
# thru the kernel sources; in some other cases, like Windows, there seem
|
||||
# to be a multitude of variants and WSS selection algorithms, but it's
|
||||
# rather difficult to find a pattern without having the source.
|
||||
#
|
||||
# If WSS looks like a regular fixed value (for example is a power of two),
|
||||
# or if you can confirm the value is fixed by looking at several
|
||||
# fingerprints, please quote it literaly. If there's no apparent pattern
|
||||
# in WSS chosen, you should consider wildcarding this value - but this
|
||||
# should be the last option.
|
||||
#
|
||||
# NOTE: Some NAT devices, such as Linux iptables with --set-mss, will
|
||||
# modify MSS, but not WSS. As a result, MSS is changed to reflect
|
||||
# the MTU of the NAT device, but WSS remains a multiple of the original
|
||||
# MSS. Fortunately for us, the source device would almost always be
|
||||
# hooked up to Ethernet. P0f handles it automatically for the original
|
||||
# MSS of 1460, by adding "NAT!" tag to the result.
|
||||
#
|
||||
# In certain configurations, Linux erratically (?) uses MTU from another
|
||||
# interface on the default gw interface. This only happens on systems with
|
||||
# two network interfaces. Thus, some Linux systems that do not go thru NAT,
|
||||
# but have multiple interfaces instead, will be also tagged this way.
|
||||
#
|
||||
# P0f recognizes and automatically wildcards WSS of 12345, as generated
|
||||
# by sendack and sendsyn utilities shipped with the program, when
|
||||
# reporting a new signature. See test/sendack.c and test/sendsyn.c for more
|
||||
# information about this.
|
||||
#
|
||||
# - Overall packet size - a function of all IP and TCP options and bugs.
|
||||
# While this is partly redundant in the real world, we record this value
|
||||
# to capture rare cases when there are IP options (which we do not currently
|
||||
# examine) or packet data past the headers. Both situations are rare.
|
||||
#
|
||||
# Packet size MAY be wildcarded, but the meaning of the wildcard is
|
||||
# very special, and means the packet must be larger than PACKET_BIG
|
||||
# (defined in config.h as 100). This is usually not necessary, except
|
||||
# for some really broken implementations in RST+ mode. For more information,
|
||||
# see p0fr.fp. P0f automatically wildcards big packets when reporting
|
||||
# new signatures.
|
||||
#
|
||||
# NEW SIGNATURE: Copy this value literally.
|
||||
#
|
||||
# - Initial TTL - We check the actual TTL of a received packet. It can't
|
||||
# be higher than the initial TTL, and also shouldn't be dramatically
|
||||
# lower (maximum distance is defined in config.h as 40 hops).
|
||||
#
|
||||
# NEW SIGNATURE: *Never* copy TTL from a p0f-reported signature literally.
|
||||
# You need to determine the initial TTL. The best way to do it is to
|
||||
# check the documentation for a remote system, or check its settings.
|
||||
# A fairly good method is to simply round the observed TTL up to
|
||||
# 32, 64, 128, or 255, but it should be noted that some obscure devices
|
||||
# might not use round TTLs (in particular, some shoddy appliances and
|
||||
# IRIX and Tru64 are known to use "original" initial TTL settings). If not
|
||||
# sure, use traceroute or mtr to see how far you are from the host.
|
||||
#
|
||||
# Note that -F option overrides this check if no signature can be found.
|
||||
#
|
||||
# - Don't fragment flag (DF) - some modern OSes set this to implement PMTU
|
||||
# discovery. Others do not bother.
|
||||
#
|
||||
# NEW SIGNATURE: Copy this value literally. Note: this setting is
|
||||
# sometimes cleared by firewalls and/or certain connectivity clients.
|
||||
# Try to find out what's the actual state for a given OS if you see both,
|
||||
# and add the right one. P0f will automatically detect a case when a
|
||||
# firewall removed the DF flag and will append "(firewall!)" suffix to
|
||||
# the signature, so if the DF version is the right one, don't add no-DF
|
||||
# variant, unless it has a different meaning.
|
||||
#
|
||||
# - Maximum segment size (MSS) - this setting is usually link-dependent. P0f
|
||||
# uses it to determine link type of the remote host.
|
||||
#
|
||||
# NEW SIGNATURE: Always wildcard this value, except for rare cases when
|
||||
# you have an appliance with a fixed value, know the system supports only
|
||||
# a very limited number of network interface types, or know the system
|
||||
# is using a value it pulled out of nowhere. I use specific unique MSS
|
||||
# to tell Google crawlbots from the rest of Linux population, for example.
|
||||
#
|
||||
# If a specific MSS/MTU is unique to a certain link type, be sure to
|
||||
# add it to mtu.h instead of creating several variants of each signature.
|
||||
#
|
||||
# - Window scaling (WSCALE) - this feature is used to scale WSS.
|
||||
# It extends the size of a TCP/IP window to 32 bits, of sorts. Some modern
|
||||
# systems implement this feature.
|
||||
#
|
||||
# NEW SIGNATURE: Observe several signatures. Initial WSCALE is often set
|
||||
# to zero or other low value. There's usually no need to wildcard this
|
||||
# parameter.
|
||||
#
|
||||
# - Timestamp - some systems that implement timestamps set them to
|
||||
# zero in the initial SYN. This case is detected and handled appropriately.
|
||||
#
|
||||
# NEW SIGNATURE: Copy T or T0 option literally.
|
||||
#
|
||||
# - Selective ACK permitted - a flag set by systems that implement
|
||||
# selective ACK functionality,
|
||||
#
|
||||
# NEW SIGNATURE: copy S option literally.
|
||||
#
|
||||
# - NOP option - its presence, count and sequence is a useful OS-dependent
|
||||
# characteristic,
|
||||
#
|
||||
# NEW SIGNATURE: copy N options literally.
|
||||
#
|
||||
# - Other and unrecognized options (TTCP-related and such) - implemented by
|
||||
# some eccentric or very buggy TCP/IP stacks ;-),
|
||||
#
|
||||
# NEW SIGNATURE: copy ? options literally.
|
||||
#
|
||||
# - EOL option. Contrary to the popular belief, the presence of EOL
|
||||
# option is actually quite rare, most systems just NOP-pad to the
|
||||
# packet boundary.
|
||||
#
|
||||
# NEW SIGNATURE: copy E option literally.
|
||||
#
|
||||
# - The sequence of TCP all options mentioned above - this is very
|
||||
# specific to the implementation,
|
||||
#
|
||||
# NEW SIGNATURE: Copy the sequence literally.
|
||||
#
|
||||
# - Quirks. Some buggy stacks set certain values that should be zeroed in a
|
||||
# TCP packet to non-zero values. This has no effect as of today, but is
|
||||
# a valuable source of information. Some systems actually seem to leak
|
||||
# memory there. Other systems just exhibit harmful but very specific
|
||||
# behavior. This section captures all unusual yes-no properties not
|
||||
# related to the main and expected header layout. We detect the following:
|
||||
#
|
||||
# - Data past the headers. Neither SYN nor SYN+ACK packets are supposed
|
||||
# to carry any payload. If they do, we should take notice. The actual
|
||||
# payload is not examined, but will be displayed if use the -X option.
|
||||
# Note that payload is not unusual in RST+ mode (see p0fr.fp), very
|
||||
# rare otherwise.
|
||||
#
|
||||
# - Options past EOL. Some systems have some trailing data past EOL
|
||||
# in the options section of TCP/IP headers. P0f does not examine this
|
||||
# data as of today, simply detects its presence. If there is a
|
||||
# confirmed sizable population of systems that have data past EOL, it
|
||||
# might be a good idea to look at it. Until then, you have to recompile
|
||||
# p0f with DEBUG_EXTRAS set or use -x to display this data,
|
||||
#
|
||||
# - Zero IP ID. This again is a (mostly) harmless setting to use a fixed
|
||||
# IP ID for packets with DF set. Some systems reportedly use zero ID,
|
||||
# most OSes do not. There is a very slight probability of a false
|
||||
# positive when IP ID is "naturally" chosen to be zero on a system
|
||||
# that otherwise does set proper values, but the probability is
|
||||
# neglible (if it becomes a problem, recompile p0f with IGNORE_ZEROID
|
||||
# set in the sources).
|
||||
#
|
||||
# - IP options specified. Usually, packets do not have any IP options
|
||||
# set, but there can be some. Until there is a confirmed sizable
|
||||
# population of systems that do have IP options in a packet, p0f
|
||||
# does not examine those in detail, but it might change (use
|
||||
# DEBUG_EXTRAS or -x to display IP options if any found),
|
||||
#
|
||||
# - URG pointer value. SYN packets do not have URG flag set, so the
|
||||
# value in URG pointer in TCP header is ignored. Most systems set it
|
||||
# to zero, but some OSes (some versions of Windows, for example) do
|
||||
# not zero this field or even simply leak memory; the actual value is
|
||||
# not examined, because most cases seem to be just random garbage
|
||||
# (you can use DEBUG_EXTRAS or -x to report this information though);
|
||||
# see doc/win-memleak.txt for more information,
|
||||
#
|
||||
# - "Unused" field value. This should be always zero, but some systems
|
||||
# forget to clear it. This might result in some funny issues in the
|
||||
# future. P0f checks for non-zero value (and will display it if
|
||||
# DEBUG_EXTRAS is set, or you can use -x),
|
||||
#
|
||||
# - ACK number non-zero. ACK value in SYN packets with no ACK flag
|
||||
# is disregarded and is usually set to zero (just like with URG
|
||||
# pointer), but some systems forget to do it. The exact value is
|
||||
# not examined (but will be displayed with DEBUG_EXTRAS, or you can
|
||||
# use -x). Note that this is not an anomaly in SYN+ACK and RST+ modes,
|
||||
#
|
||||
# - Non-zero second timestamp. The initial SYN packet should have the
|
||||
# second timestamp always zeroed. SYN+ACK and RST+ may "legally" have
|
||||
# this quirk though,
|
||||
#
|
||||
# - Unusual flags. If, in addition to SYN (or SYN+ACK), there are some
|
||||
# auxilinary flags that do not modify the very meaning of a packet,
|
||||
# p0f records this (this can be URG, PUSH, or something else).
|
||||
#
|
||||
# Note: ECN flags (ECE and CWR) are ignored and denoted in a separate
|
||||
# way. ECN is never by default, because some systems can't handle it,
|
||||
# and it probably does not make much sense to include it in signatures
|
||||
# right now.
|
||||
#
|
||||
# - TCP option segment parsing problems. If p0f fails to decode options
|
||||
# because of a badly broken packet, it records this fact.
|
||||
#
|
||||
# There are several other quirks valid only in RST+ mode, see p0fr.fp for
|
||||
# more information. Those quirks are unheard of in SYN and SYN+ACK
|
||||
# modes.
|
||||
#
|
||||
# NEW SIGNATURE: Copy "quirks" section literally.
|
||||
#
|
||||
# We DO NOT use ToS for fingerprinting. While the original TCP/IP
|
||||
# fingerprinting research believed this value would be useful for this
|
||||
# purpose, it is not. The setting is way too often tweaked by network
|
||||
# devices.
|
||||
#
|
||||
# To wildcard MSS, WSS or WSCALE, replace it with '*'. You can also use a
|
||||
# modulo operator to match any values that divide by nnn - '%nnn' (and,
|
||||
# as stated above, WSS also supports special values Snn and Tnn).
|
||||
#
|
||||
# Fingerprint entry format:
|
||||
#
|
||||
# wwww:ttt:D:ss:OOO...:QQ:OS:Details
|
||||
#
|
||||
# wwww - window size (can be * or %nnn or Sxx or Txx)
|
||||
# "Snn" (multiple of MSS) and "Tnn" (multiple of MTU) are allowed.
|
||||
# ttt - initial TTL
|
||||
# D - don't fragment bit (0 - not set, 1 - set)
|
||||
# ss - overall SYN packet size (* has a special meaning)
|
||||
# OOO - option value and order specification (see below)
|
||||
# QQ - quirks list (see below)
|
||||
# OS - OS genre (Linux, Solaris, Windows)
|
||||
# details - OS description (2.0.27 on x86, etc)
|
||||
#
|
||||
# If OS genre starts with '*', p0f will not show distance, link type
|
||||
# and timestamp data. It is useful for userland TCP/IP stacks of
|
||||
# network scanners and so on, where many settings are randomized or
|
||||
# bogus.
|
||||
#
|
||||
# If OS genre starts with @, it denotes an approximate hit for a group
|
||||
# of operating systems (signature reporting still enabled in this case).
|
||||
# Use this feature at the end of this file to catch cases for which
|
||||
# you don't have a precise match, but can tell it's Windows or FreeBSD
|
||||
# or whatnot by looking at, say, flag layout alone.
|
||||
#
|
||||
# If OS genre starts with - (which can prefix @ or *), the entry is
|
||||
# not considered to be a real operating system (but userland stack
|
||||
# instead). It is important to mark all scanners and so on with -,
|
||||
# so that they are not used for masquerade detection (also add this
|
||||
# prefix for signatures of application-induced behavior, such as
|
||||
# increased window size with Opera browser).
|
||||
#
|
||||
# Option block description is a list of comma or space separated
|
||||
# options in the order they appear in the packet:
|
||||
#
|
||||
# N - NOP option
|
||||
# E - EOL option
|
||||
# Wnnn - window scaling option, value nnn (or * or %nnn)
|
||||
# Mnnn - maximum segment size option, value nnn (or * or %nnn)
|
||||
# S - selective ACK OK
|
||||
# T - timestamp
|
||||
# T0 - timestamp with zero value
|
||||
# ?n - unrecognized option number n.
|
||||
#
|
||||
# P0f can sometimes report ?nn among the options. This means it couldn't
|
||||
# recognize this option (option number nn). It's either a bug in p0f, or
|
||||
# a faulty TCP/IP stack, or, if the number is listed here:
|
||||
#
|
||||
# http://www.iana.org/assignments/tcp-parameters
|
||||
#
|
||||
# ...the stack might be simply quite exotic.
|
||||
#
|
||||
# To denote no TCP options, use a single '.'.
|
||||
#
|
||||
# Quirks section is usually an empty list ('.') of oddities or bugs of this
|
||||
# particular stack. List items are not separated in any way. Possible values:
|
||||
#
|
||||
# P - options past EOL,
|
||||
# Z - zero IP ID,
|
||||
# I - IP options specified,
|
||||
# U - urg pointer non-zero,
|
||||
# X - unused (x2) field non-zero,
|
||||
# A - ACK number non-zero,
|
||||
# T - non-zero second timestamp,
|
||||
# F - unusual flags (PUSH, URG, etc),
|
||||
# D - data payload,
|
||||
# ! - broken options segment.
|
||||
#
|
||||
# WARNING WARNING WARNING
|
||||
# -----------------------
|
||||
#
|
||||
# Do not add a system X as OS Y just because NMAP says so. It is often
|
||||
# the case that X is a NAT firewall. While nmap is talking to the
|
||||
# device itself, p0f is fingerprinting the guy behind the firewall
|
||||
# instead.
|
||||
#
|
||||
# When in doubt, use common sense, don't add something that looks like
|
||||
# a completely different system as Linux or FreeBSD or LinkSys router.
|
||||
# Check DNS name, establish a connection to the remote host and look
|
||||
# at SYN+ACK (p0f -A -S should do) - does it look similar?
|
||||
#
|
||||
# Some users tweak their TCP/IP settings - enable or disable RFC1323,
|
||||
# RFC1644 or RFC2018 support, disable PMTU discovery, change MTU, initial
|
||||
# TTL and so on. Always compare a new rule to other fingerprints for
|
||||
# this system, and verify the system isn't "customized". It is OK to
|
||||
# add signature variants caused by commonly used software (PFs, security
|
||||
# packages, etc), but it makes no sense to try to add every single
|
||||
# possible /proc/sys/net/ipv4/* tweak on Linux or so.
|
||||
#
|
||||
# KEEP IN MIND: Some packet firewalls configured to normalize outgoing
|
||||
# traffic (OpenBSD pf with "scrub" enabled, for example) will, well,
|
||||
# normalize packets. Signatures will not correspond to the originating
|
||||
# system (and probably not quite to the firewall either).
|
||||
#
|
||||
# NOTE: Try to keep this file in some reasonable order, from most to
|
||||
# least likely systems. This will speed up operation. Also keep most
|
||||
# generic and broad rules near ehe end.
|
||||
#
|
||||
# Still decided to add signature? Let us know - mail a copy of your discovery
|
||||
# to lcamtuf@coredump.cx. You can help make p0f better, and I can help you
|
||||
# make your signature more accurate.
|
||||
#
|
||||
|
||||
##########################
|
||||
# Standard OS signatures #
|
||||
##########################
|
||||
|
||||
# ----------------- AIX ---------------------
|
||||
|
||||
# AIX is first because its signatures are close to NetBSD, MacOS X and
|
||||
# Linux 2.0, but it uses a fairly rare MSSes, at least sometimes...
|
||||
# This is a shoddy hack, though.
|
||||
|
||||
45046:64:0:44:M*:.:AIX:4.3
|
||||
|
||||
16384:64:0:44:M512:.:AIX:4.3.2 and earlier
|
||||
|
||||
16384:64:0:60:M512,N,W%2,N,N,T:.:AIX:4.3.3-5.2 (1)
|
||||
32768:64:0:60:M512,N,W%2,N,N,T:.:AIX:4.3.3-5.2 (2)
|
||||
65535:64:0:60:M512,N,W%2,N,N,T:.:AIX:4.3.3-5.2 (3)
|
||||
|
||||
65535:64:0:64:M*,N,W1,N,N,T,N,N,S:.:AIX:5.3 ML1
|
||||
|
||||
# ----------------- Linux -------------------
|
||||
|
||||
S1:64:0:44:M*:A:Linux:1.2.x
|
||||
512:64:0:44:M*:.:Linux:2.0.3x (1)
|
||||
16384:64:0:44:M*:.:Linux:2.0.3x (2)
|
||||
|
||||
# Endian snafu! Nelson says "ha-ha":
|
||||
2:64:0:44:M*:.:Linux:2.0.3x (MkLinux) on Mac (1)
|
||||
64:64:0:44:M*:.:Linux:2.0.3x (MkLinux) on Mac (2)
|
||||
|
||||
S4:64:1:60:M1360,S,T,N,W0:.:Linux:2.4 (Google crawlbot)
|
||||
S4:64:1:60:M1430,S,T,N,W0:.:Linux:2.4-2.6 (Google crawlbot)
|
||||
|
||||
S2:64:1:60:M*,S,T,N,W0:.:Linux:2.4 (large MTU?)
|
||||
S3:64:1:60:M*,S,T,N,W0:.:Linux:2.4 (newer)
|
||||
S4:64:1:60:M*,S,T,N,W0:.:Linux:2.4-2.6
|
||||
|
||||
S3:64:1:60:M*,S,T,N,W1:.:Linux:2.6, seldom 2.4 (older, 1)
|
||||
S4:64:1:60:M*,S,T,N,W1:.:Linux:2.6, seldom 2.4 (older, 2)
|
||||
S3:64:1:60:M*,S,T,N,W2:.:Linux:2.6, seldom 2.4 (older, 3)
|
||||
S4:64:1:60:M*,S,T,N,W2:.:Linux:2.6, seldom 2.4 (older, 4)
|
||||
T4:64:1:60:M*,S,T,N,W2:.:Linux:2.6 (older, 5)
|
||||
|
||||
S4:64:1:60:M*,S,T,N,W5:.:Linux:2.6 (newer, 1)
|
||||
S4:64:1:60:M*,S,T,N,W6:.:Linux:2.6 (newer, 2)
|
||||
S4:64:1:60:M*,S,T,N,W7:.:Linux:2.6 (newer, 3)
|
||||
T4:64:1:60:M*,S,T,N,W7:.:Linux:2.6 (newer, 4)
|
||||
|
||||
|
||||
S20:64:1:60:M*,S,T,N,W0:.:Linux:2.2 (1)
|
||||
S22:64:1:60:M*,S,T,N,W0:.:Linux:2.2 (2)
|
||||
S11:64:1:60:M*,S,T,N,W0:.:Linux:2.2 (3)
|
||||
|
||||
# Popular cluster config scripts disable timestamps and
|
||||
# selective ACK:
|
||||
|
||||
S4:64:1:48:M1460,N,W0:.:Linux:2.4 in cluster
|
||||
|
||||
# This happens only over loopback, but let's make folks happy:
|
||||
32767:64:1:60:M16396,S,T,N,W0:.:Linux:2.4 (loopback)
|
||||
32767:64:1:60:M16396,S,T,N,W2:.:Linux:2.6 (newer, loopback)
|
||||
S8:64:1:60:M3884,S,T,N,W0:.:Linux:2.2 (loopback)
|
||||
|
||||
# Opera visitors:
|
||||
16384:64:1:60:M*,S,T,N,W0:.:-Linux:2.2 (Opera?)
|
||||
32767:64:1:60:M*,S,T,N,W0:.:-Linux:2.4 (Opera?)
|
||||
|
||||
# Some fairly common mods & oddities:
|
||||
S22:64:1:52:M*,N,N,S,N,W0:.:Linux:2.2 (tstamp-)
|
||||
S4:64:1:52:M*,N,N,S,N,W0:.:Linux:2.4 (tstamp-)
|
||||
S4:64:1:52:M*,N,N,S,N,W2:.:Linux:2.6 (tstamp-)
|
||||
S4:64:1:44:M*:.:Linux:2.6? (barebone, rare!)
|
||||
T4:64:1:60:M1412,S,T,N,W0:.:Linux:2.4 (rare!)
|
||||
|
||||
# ----------------- FreeBSD -----------------
|
||||
|
||||
16384:64:1:44:M*:.:FreeBSD:2.0-4.2
|
||||
16384:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.4 (1)
|
||||
|
||||
1024:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.4 (2)
|
||||
|
||||
57344:64:1:44:M*:.:FreeBSD:4.6-4.8 (RFC1323-)
|
||||
57344:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.6-4.9
|
||||
|
||||
32768:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.8-5.1 (or MacOS X 10.2-10.3)
|
||||
65535:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.7-5.2 (or MacOS X 10.2-10.4) (1)
|
||||
65535:64:1:60:M*,N,W1,N,N,T:.:FreeBSD:4.7-5.2 (or MacOS X 10.2-10.4) (2)
|
||||
|
||||
65535:64:1:60:M*,N,W0,N,N,T:Z:FreeBSD:5.1 (1)
|
||||
65535:64:1:60:M*,N,W1,N,N,T:Z:FreeBSD:5.1 (2)
|
||||
65535:64:1:60:M*,N,W2,N,N,T:Z:FreeBSD:5.1 (3)
|
||||
65535:64:1:64:M*,N,N,S,N,W1,N,N,T:.:FreeBSD:5.3-5.4
|
||||
65535:64:1:64:M*,N,W1,N,N,T,S,E:P:FreeBSD:6.x (1)
|
||||
65535:64:1:64:M*,N,W0,N,N,T,S,E:P:FreeBSD:6.x (2)
|
||||
|
||||
65535:64:1:44:M*:Z:FreeBSD:5.2 (RFC1323-)
|
||||
|
||||
# 16384:64:1:60:M*,N,N,N,N,N,N,T:.:FreeBSD:4.4 (tstamp-)
|
||||
|
||||
# ----------------- NetBSD ------------------
|
||||
|
||||
16384:64:0:60:M*,N,W0,N,N,T:.:NetBSD:1.3
|
||||
65535:64:0:60:M*,N,W0,N,N,T0:.:-NetBSD:1.6 (Opera)
|
||||
16384:64:1:60:M*,N,W0,N,N,T0:.:NetBSD:1.6
|
||||
65535:64:1:60:M*,N,W1,N,N,T0:.:NetBSD:1.6W-current (DF)
|
||||
65535:64:1:60:M*,N,W0,N,N,T0:.:NetBSD:1.6X (DF)
|
||||
32768:64:1:60:M*,N,W0,N,N,T0:.:NetBSD:1.6Z or 2.0 (DF)
|
||||
32768:64:1:64:M1416,N,W0,S,N,N,N,N,T0:.:NetBSD:2.0G (DF)
|
||||
32768:64:1:64:M*,N,W0,S,N,N,N,N,T0:.:NetBSD:3.0 (DF)
|
||||
|
||||
# ----------------- OpenBSD -----------------
|
||||
|
||||
16384:64:1:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.0-3.9
|
||||
57344:64:1:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.3-3.4
|
||||
16384:64:0:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.0-3.4 (scrub)
|
||||
65535:64:1:64:M*,N,N,S,N,W0,N,N,T:.:-OpenBSD:3.0-3.4 (Opera?)
|
||||
32768:64:1:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.7
|
||||
|
||||
# ----------------- Solaris -----------------
|
||||
|
||||
S17:64:1:64:N,W3,N,N,T0,N,N,S,M*:.:Solaris:8 (RFC1323 on)
|
||||
S17:64:1:48:N,N,S,M*:.:Solaris:8 (1)
|
||||
S17:255:1:44:M*:.:Solaris:2.5-7 (1)
|
||||
|
||||
# Sometimes, just sometimes, Solaris feels like coming up with
|
||||
# rather arbitrary MSS values ;-)
|
||||
|
||||
S6:255:1:44:M*:.:Solaris:2.5-7 (2)
|
||||
S23:64:1:48:N,N,S,M*:.:Solaris:8 (2)
|
||||
S34:64:1:48:M*,N,N,S:.:Solaris:9
|
||||
S34:64:1:48:M*,N,N,N,N:.:Solaris:9 (no sack)
|
||||
S44:255:1:44:M*:.:Solaris:7
|
||||
|
||||
4096:64:0:44:M1460:.:SunOS:4.1.x
|
||||
|
||||
S34:64:1:52:M*,N,W0,N,N,S:.:Solaris:10 (beta)
|
||||
32850:64:1:64:M*,N,N,T,N,W1,N,N,S:.:Solaris:10 (1203?)
|
||||
32850:64:1:64:M*,N,W1,N,N,T,N,N,S:.:Solaris:9.1
|
||||
|
||||
# ----------------- IRIX --------------------
|
||||
|
||||
49152:60:0:44:M*:.:IRIX:6.2-6.4
|
||||
61440:60:0:44:M*:.:IRIX:6.2-6.5
|
||||
49152:60:0:52:M*,N,W2,N,N,S:.:IRIX:6.5 (RFC1323+) (1)
|
||||
49152:60:0:52:M*,N,W3,N,N,S:.:IRIX:6.5 (RFC1323+) (2)
|
||||
|
||||
61440:60:0:48:M*,N,N,S:.:IRIX:6.5.12-6.5.21 (1)
|
||||
49152:60:0:48:M*,N,N,S:.:IRIX:6.5.12-6.5.21 (2)
|
||||
|
||||
49152:60:0:64:M*,N,W2,N,N,T,N,N,S:.:IRIX:6.5 IP27
|
||||
|
||||
# ----------------- Tru64 -------------------
|
||||
# Tru64 and OpenVMS share the same stack on occassions.
|
||||
# Relax.
|
||||
|
||||
32768:60:1:48:M*,N,W0:.:Tru64:4.0 (or OS/2 Warp 4)
|
||||
32768:60:0:48:M*,N,W0:.:Tru64:5.0 (or OpenVMS 7.x on Compaq 5.0 stack)
|
||||
8192:60:0:44:M1460:.:Tru64:5.1 (no RFC1323) (or QNX 6)
|
||||
61440:60:0:48:M*,N,W0:.:Tru64:v5.1a JP4 (or OpenVMS 7.x on Compaq 5.x stack)
|
||||
|
||||
# ----------------- OpenVMS -----------------
|
||||
|
||||
6144:64:1:60:M*,N,W0,N,N,T:.:OpenVMS:7.2 (Multinet 4.3-4.4 stack)
|
||||
|
||||
# ----------------- MacOS -------------------
|
||||
|
||||
S2:255:1:48:M*,W0,E:.:MacOS:8.6 classic
|
||||
|
||||
16616:255:1:48:M*,W0,E:.:MacOS:7.3-8.6 (OTTCP)
|
||||
16616:255:1:48:M*,N,N,N,E:.:MacOS:8.1-8.6 (OTTCP)
|
||||
32768:255:1:48:M*,W0,N:.:MacOS:9.0-9.2
|
||||
|
||||
32768:255:1:48:M1380,N,N,N,N:.:MacOS:9.1 (OT 2.7.4) (1)
|
||||
65535:255:1:48:M*,N,N,N,N:.:MacOS:9.1 (OT 2.7.4) (2)
|
||||
|
||||
# ----------------- Windows -----------------
|
||||
|
||||
# Windows TCP/IP stack is a mess. For most recent XP, 2000 and
|
||||
# even 98, the pathlevel, not the actual OS version, is more
|
||||
# relevant to the signature. They share the same code, so it would
|
||||
# seem. Luckily for us, almost all Windows 9x boxes have an
|
||||
# awkward MSS of 536, which I use to tell one from another
|
||||
# in most difficult cases.
|
||||
|
||||
8192:32:1:44:M*:.:Windows:3.11 (Tucows)
|
||||
S44:64:1:64:M*,N,W0,N,N,T0,N,N,S:.:Windows:95
|
||||
8192:128:1:64:M*,N,W0,N,N,T0,N,N,S:.:Windows:95b
|
||||
|
||||
# There were so many tweaking tools and so many stack versions for
|
||||
# Windows 98 it is no longer possible to tell them from each other
|
||||
# without some very serious research. Until then, there's an insane
|
||||
# number of signatures, for your amusement:
|
||||
|
||||
S44:32:1:48:M*,N,N,S:.:Windows:98 (low TTL) (1)
|
||||
8192:32:1:48:M*,N,N,S:.:Windows:98 (low TTL) (2)
|
||||
%8192:64:1:48:M536,N,N,S:.:Windows:98 (13)
|
||||
%8192:128:1:48:M536,N,N,S:.:Windows:98 (15)
|
||||
S4:64:1:48:M*,N,N,S:.:Windows:98 (1)
|
||||
S6:64:1:48:M*,N,N,S:.:Windows:98 (2)
|
||||
S12:64:1:48:M*,N,N,S:.:Windows:98 (3
|
||||
T30:64:1:64:M1460,N,W0,N,N,T0,N,N,S:.:Windows:98 (16)
|
||||
32767:64:1:48:M*,N,N,S:.:Windows:98 (4)
|
||||
37300:64:1:48:M*,N,N,S:.:Windows:98 (5)
|
||||
46080:64:1:52:M*,N,W3,N,N,S:.:Windows:98 (RFC1323+)
|
||||
65535:64:1:44:M*:.:Windows:98 (no sack)
|
||||
S16:128:1:48:M*,N,N,S:.:Windows:98 (6)
|
||||
S16:128:1:64:M*,N,W0,N,N,T0,N,N,S:.:Windows:98 (7)
|
||||
S26:128:1:48:M*,N,N,S:.:Windows:98 (8)
|
||||
T30:128:1:48:M*,N,N,S:.:Windows:98 (9)
|
||||
32767:128:1:52:M*,N,W0,N,N,S:.:Windows:98 (10)
|
||||
60352:128:1:48:M*,N,N,S:.:Windows:98 (11)
|
||||
60352:128:1:64:M*,N,W2,N,N,T0,N,N,S:.:Windows:98 (12)
|
||||
|
||||
# What's with 1414 on NT?
|
||||
T31:128:1:44:M1414:.:Windows:NT 4.0 SP6a (1)
|
||||
64512:128:1:44:M1414:.:Windows:NT 4.0 SP6a (2)
|
||||
8192:128:1:44:M*:.:Windows:NT 4.0 (older)
|
||||
|
||||
# Windows XP and 2000. Most of the signatures that were
|
||||
# either dubious or non-specific (no service pack data)
|
||||
# were deleted and replaced with generics at the end.
|
||||
|
||||
65535:128:1:48:M*,N,N,S:.:Windows:2000 SP4, XP SP1+
|
||||
%8192:128:1:48:M*,N,N,S:.:Windows:2000 SP2+, XP SP1+ (seldom 98)
|
||||
S20:128:1:48:M*,N,N,S:.:Windows:SP3
|
||||
S45:128:1:48:M*,N,N,S:.:Windows:2000 SP4, XP SP1+ (2)
|
||||
40320:128:1:48:M*,N,N,S:.:Windows:2000 SP4
|
||||
|
||||
S6:128:1:48:M*,N,N,S:.:Windows:XP, 2000 SP2+
|
||||
S12:128:1:48:M*,N,N,S:.:Windows:XP SP1+ (1)
|
||||
S44:128:1:48:M*,N,N,S:.:Windows:XP SP1+, 2000 SP3
|
||||
64512:128:1:48:M*,N,N,S:.:Windows:XP SP1+, 2000 SP3 (2)
|
||||
32767:128:1:48:M*,N,N,S:.:Windows:XP SP1+, 2000 SP4 (3)
|
||||
|
||||
# Windows 2003 & Vista
|
||||
|
||||
8192:128:1:52:M*,W8,N,N,N,S:.:Windows:Vista (beta)
|
||||
32768:32:1:52:M1460,N,W0,N,N,S:.:Windows:2003 AS
|
||||
65535:64:1:52:M1460,N,W2,N,N,S:.:Windows:2003 (1)
|
||||
65535:64:1:48:M1460,N,N,S:.:Windows:2003 (2)
|
||||
|
||||
# Odds, ends, mods:
|
||||
|
||||
S52:128:1:48:M1260,N,N,S:.:Windows:XP/2000 via Cisco
|
||||
65520:128:1:48:M*,N,N,S:.:Windows:XP bare-bone
|
||||
16384:128:1:52:M536,N,W0,N,N,S:.:Windows:2000 w/ZoneAlarm?
|
||||
2048:255:0:40:.:.:Windows:.NET Enterprise Server
|
||||
44620:64:0:48:M*,N,N,S:.:Windows:ME no SP (?)
|
||||
S6:255:1:48:M536,N,N,S:.:Windows:95 winsock 2
|
||||
32000:128:0:48:M*,N,N,S:.:Windows:XP w/Winroute?
|
||||
16384:64:1:48:M1452,N,N,S:.:Windows:XP w/Sygate? (1)
|
||||
17256:64:1:48:M1460,N,N,S:.:Windows:XP w/Sygate? (2)
|
||||
|
||||
# No need to be more specific, it passes:
|
||||
*:128:1:48:M*,N,N,S:U:-Windows:XP/2000 while downloading (leak!)
|
||||
|
||||
# ----------------- HP/UX -------------------
|
||||
|
||||
32768:64:1:44:M*:.:HP-UX:B.10.20
|
||||
32768:64:1:48:M*,W0,N:.:HP-UX:11.00-11.11
|
||||
|
||||
# Whoa. Hardcore WSS.
|
||||
0:64:0:48:M*,W0,N:.:HP-UX:B.11.00 A (RFC1323+)
|
||||
|
||||
# ----------------- RiscOS ------------------
|
||||
|
||||
16384:64:1:68:M1460,N,W0,N,N,T,N,N,?12:.:RISC OS:3.70-4.36 (inet 5.04)
|
||||
12288:32:0:44:M536:.:RISC OS:3.70 inet 4.10
|
||||
4096:64:1:56:M1460,N,N,T:T:RISC OS:3.70 freenet 2.00
|
||||
|
||||
# ----------------- BSD/OS ------------------
|
||||
|
||||
8192:64:1:60:M1460,N,W0,N,N,T:.:BSD/OS:3.1-4.3 (or MacOS X 10.2)
|
||||
|
||||
# ---------------- NetwonOS -----------------
|
||||
|
||||
4096:64:0:44:M1420:.:NewtonOS:2.1
|
||||
|
||||
# ---------------- NeXTSTEP -----------------
|
||||
|
||||
S8:64:0:44:M512:.:NeXTSTEP:3.3 (1)
|
||||
S4:64:0:44:M1024:.:NeXTSTEP:3.3 (2)
|
||||
|
||||
# ------------------ BeOS -------------------
|
||||
|
||||
1024:255:0:48:M*,N,W0:.:BeOS:5.0-5.1
|
||||
12288:255:0:44:M*:.:BeOS:5.0.x
|
||||
|
||||
# ------------------ OS/400 -----------------
|
||||
|
||||
8192:64:1:60:M1440,N,W0,N,N,T:.:OS/400:V4R4/R5
|
||||
8192:64:0:44:M536:.:OS/400:V4R3/M0
|
||||
4096:64:1:60:M1440,N,W0,N,N,T:.:OS/400:V4R5 + CF67032
|
||||
|
||||
28672:64:0:44:M1460:A:OS/390:?
|
||||
|
||||
# ------------------ ULTRIX -----------------
|
||||
|
||||
16384:64:0:40:.:.:ULTRIX:4.5
|
||||
|
||||
# ------------------- QNX -------------------
|
||||
|
||||
S16:64:0:44:M512:.:QNX:demodisk
|
||||
16384:64:0:60:M1460,N,W0,N,N,T0:.:QNX:6.x
|
||||
|
||||
# ------------------ Novell -----------------
|
||||
|
||||
16384:128:1:44:M1460:.:Novell:NetWare 5.0
|
||||
6144:128:1:44:M1460:.:Novell:IntranetWare 4.11
|
||||
6144:128:1:44:M1368:.:Novell:BorderManager ?
|
||||
|
||||
# According to rfp:
|
||||
6144:128:1:52:M*,W0,N,S,N,N:.:Novell:Netware 6 SP3
|
||||
|
||||
# -------------- SCO UnixWare ---------------
|
||||
|
||||
S3:64:1:60:M1460,N,W0,N,N,T:.:SCO:UnixWare 7.1
|
||||
S17:64:1:60:M*,N,W0,N,N,T:.:SCO:UnixWare 7.1.x
|
||||
S23:64:1:44:M1380:.:SCO:OpenServer 5.0
|
||||
|
||||
# ------------------- DOS -------------------
|
||||
|
||||
2048:255:0:44:M536:.:DOS:Arachne via WATTCP/1.05
|
||||
T2:255:0:44:M984:.:DOS:Arachne via WATTCP/1.05 (eepro)
|
||||
16383:64:0:44:M536:.:DOS:Unknown via WATTCP (epppd)
|
||||
|
||||
# ------------------ OS/2 -------------------
|
||||
|
||||
S56:64:0:44:M512:.:OS/2:4
|
||||
28672:64:0:44:M1460:.:OS/2:Warp 4.0
|
||||
|
||||
# ----------------- TOPS-20 -----------------
|
||||
|
||||
# Another hardcore MSS, one of the ACK leakers hunted down.
|
||||
0:64:0:44:M1460:A:TOPS-20:version 7
|
||||
|
||||
# ------------------ AMIGA ------------------
|
||||
|
||||
S32:64:1:56:M*,N,N,S,N,N,?12:.:AMIGA:3.9 BB2 with Miami stack
|
||||
|
||||
# ------------------ Minix ------------------
|
||||
|
||||
# Not quite sure.
|
||||
# 8192:210:0:44:M1460:X:@Minix:?
|
||||
|
||||
# ------------------ Plan9 ------------------
|
||||
|
||||
65535:255:0:48:M1460,W0,N:.:Plan9:edition 4
|
||||
|
||||
# ----------------- AMIGAOS -----------------
|
||||
|
||||
16384:64:1:48:M1560,N,N,S:.:AMIGAOS:3.9 BB2 MiamiDX
|
||||
|
||||
# ----------------- FreeMiNT ----------------
|
||||
|
||||
S44:255:0:44:M536:.:FreeMiNT:1 patch 16A (Atari)
|
||||
|
||||
###########################################
|
||||
# Appliance / embedded / other signatures #
|
||||
###########################################
|
||||
|
||||
# ---------- Firewalls / routers ------------
|
||||
|
||||
S12:64:1:44:M1460:.:@Checkpoint:(unknown 1)
|
||||
S12:64:1:48:N,N,S,M1460:.:@Checkpoint:(unknown 2)
|
||||
4096:32:0:44:M1460:.:ExtremeWare:4.x
|
||||
|
||||
S32:64:0:68:M512,N,W0,N,N,T,N,N,?12:.:Nokia:IPSO w/Checkpoint NG FP3
|
||||
S16:64:0:68:M1024,N,W0,N,N,T,N,N,?12:.:Nokia:IPSO 3.7 build 026
|
||||
|
||||
S4:64:1:60:W0,N,S,T,M1460:.:FortiNet:FortiGate 50
|
||||
|
||||
8192:64:1:44:M1460:.:@Eagle:Secure Gateway
|
||||
|
||||
# ------- Switches and other stuff ----------
|
||||
|
||||
4128:255:0:44:M*:Z:Cisco:7200, Catalyst 3500, etc
|
||||
S8:255:0:44:M*:.:Cisco:12008
|
||||
S4:255:0:44:M536:Z:Cisco:IOS 11.0
|
||||
60352:128:1:64:M1460,N,W2,N,N,T,N,N,S:.:Alteon:ACEswitch
|
||||
64512:128:1:44:M1370:.:Nortel:Contivity Client
|
||||
|
||||
# ---------- Caches and whatnots ------------
|
||||
|
||||
8190:255:0:44:M1428:.:Google:Wireless Transcoder (1)
|
||||
8190:255:0:44:M1460:.:Google:Wireless Transcoder (2)
|
||||
8192:64:1:64:M1460,N,N,S,N,W0,N,N,T:.:NetCache:5.2
|
||||
16384:64:1:64:M1460,N,N,S,N,W0,N:.:NetCache:5.3
|
||||
65535:64:1:64:M1460,N,N,S,N,W*,N,N,T:.:NetCache:5.3-5.5 (or FreeBSD 5.4)
|
||||
20480:64:1:64:M1460,N,N,S,N,W0,N,N,T:.:NetCache:4.1
|
||||
S44:64:1:64:M1460,N,N,S,N,W0,N,N,T:.:NetCache:5.5
|
||||
|
||||
32850:64:1:64:N,W1,N,N,T,N,N,S,M*:.:NetCache:Data OnTap 5.x
|
||||
|
||||
65535:64:0:60:M1460,N,W0,N,N,T:.:CacheFlow:CacheOS 4.1
|
||||
8192:64:0:60:M1380,N,N,N,N,N,N,T:.:CacheFlow:CacheOS 1.1
|
||||
|
||||
S4:64:0:48:M1460,N,N,S:.:Cisco:Content Engine
|
||||
|
||||
27085:128:0:40:.:.:Dell:PowerApp cache (Linux-based)
|
||||
|
||||
65535:255:1:48:N,W1,M1460:.:Inktomi:crawler
|
||||
S1:255:1:60:M1460,S,T,N,W0:.:LookSmart:ZyBorg
|
||||
|
||||
16384:255:0:40:.:.:Proxyblocker:(what's this?)
|
||||
|
||||
65535:255:0:48:M*,N,N,S:.:Redline: T|X 2200
|
||||
|
||||
# ----------- Embedded systems --------------
|
||||
|
||||
S9:255:0:44:M536:.:PalmOS:Tungsten T3/C
|
||||
S5:255:0:44:M536:.:PalmOS:3/4
|
||||
S4:255:0:44:M536:.:PalmOS:3.5
|
||||
2948:255:0:44:M536:.:PalmOS:3.5.3 (Handera)
|
||||
S29:255:0:44:M536:.:PalmOS:5.0
|
||||
16384:255:0:44:M1398:.:PalmOS:5.2 (Clie)
|
||||
S14:255:0:44:M1350:.:PalmOS:5.2.1 (Treo)
|
||||
16384:255:0:44:M1400:.:PalmOS:5.2 (Sony)
|
||||
|
||||
S23:64:1:64:N,W1,N,N,T,N,N,S,M1460:.:SymbianOS:7
|
||||
8192:255:0:44:M1460:.:SymbianOS:6048 (Nokia 7650?)
|
||||
8192:255:0:44:M536:.:SymbianOS:(Nokia 9210?)
|
||||
S22:64:1:56:M1460,T,S:.:SymbianOS:? (SE P800?)
|
||||
S36:64:1:56:M1360,T,S:.:SymbianOS:60xx (Nokia 6600?)
|
||||
S36:64:1:60:M1360,T,S,W0,E:.:SymbianOS:60xx
|
||||
|
||||
32768:32:1:44:M1460:.:Windows:CE 3
|
||||
|
||||
# Perhaps S4?
|
||||
5840:64:1:60:M1452,S,T,N,W1:.:Zaurus:3.10
|
||||
|
||||
32768:128:1:64:M1460,N,W0,N,N,T0,N,N,S:.:PocketPC:2002
|
||||
|
||||
S1:255:0:44:M346:.:Contiki:1.1-rc0
|
||||
|
||||
4096:128:0:44:M1460:.:Sega:Dreamcast Dreamkey 3.0
|
||||
T5:64:0:44:M536:.:Sega:Dreamcast HKT-3020 (browser disc 51027)
|
||||
S22:64:1:44:M1460:.:Sony:Playstation 2 (SOCOM?)
|
||||
|
||||
S12:64:0:44:M1452:.:AXIS:Printer Server 5600 v5.64
|
||||
|
||||
3100:32:1:44:M1460:.:Windows:CE 2.0
|
||||
|
||||
####################
|
||||
# Fancy signatures #
|
||||
####################
|
||||
|
||||
1024:64:0:40:.:.:-*NMAP:syn scan (1)
|
||||
2048:64:0:40:.:.:-*NMAP:syn scan (2)
|
||||
3072:64:0:40:.:.:-*NMAP:syn scan (3)
|
||||
4096:64:0:40:.:.:-*NMAP:syn scan (4)
|
||||
|
||||
1024:64:0:40:.:A:-*NMAP:TCP sweep probe (1)
|
||||
2048:64:0:40:.:A:-*NMAP:TCP sweep probe (2)
|
||||
3072:64:0:40:.:A:-*NMAP:TCP sweep probe (3)
|
||||
4096:64:0:40:.:A:-*NMAP:TCP sweep probe (4)
|
||||
|
||||
1024:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (1)
|
||||
2048:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (2)
|
||||
3072:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (3)
|
||||
4096:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (4)
|
||||
|
||||
1024:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (1)
|
||||
2048:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (2)
|
||||
3072:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (3)
|
||||
4096:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (4)
|
||||
|
||||
32767:64:0:40:.:.:-*NAST:syn scan
|
||||
|
||||
12345:255:0:40:.:A:-p0f:sendsyn utility
|
||||
|
||||
# UFO - see tmp/*:
|
||||
56922:128:0:40:.:A:-@Mysterious:port scanner (?)
|
||||
5792:64:1:60:M1460,S,T,N,W0:T:-@Mysterious:NAT device (2nd tstamp)
|
||||
S12:128:1:48:M1460,E:P:@Mysterious:Chello proxy (?)
|
||||
S23:64:1:64:N,W1,N,N,T,N,N,S,M1380:.:@Mysterious:GPRS gateway (?)
|
||||
|
||||
#####################################
|
||||
# Generic signatures - just in case #
|
||||
#####################################
|
||||
|
||||
*:128:1:52:M*,N,W0,N,N,S:.:@Windows:XP/2000 (RFC1323+, w, tstamp-)
|
||||
*:128:1:52:M*,N,W*,N,N,S:.:@Windows:XP/2000 (RFC1323+, w+, tstamp-)
|
||||
*:128:1:52:M*,N,N,T0,N,N,S:.:@Windows:XP/2000 (RFC1323+, w-, tstamp+)
|
||||
*:128:1:64:M*,N,W0,N,N,T0,N,N,S:.:@Windows:XP/2000 (RFC1323+, w, tstamp+)
|
||||
*:128:1:64:M*,N,W*,N,N,T0,N,N,S:.:@Windows:XP/2000 (RFC1323+, w+, tstamp+)
|
||||
|
||||
*:128:1:48:M536,N,N,S:.:@Windows:98
|
||||
*:128:1:48:M*,N,N,S:.:@Windows:XP/2000
|
||||
|
||||
|
||||
208
decnet/prober/osfp/p0f/data/p0fa.fp
Normal file
208
decnet/prober/osfp/p0f/data/p0fa.fp
Normal file
@@ -0,0 +1,208 @@
|
||||
#
|
||||
# p0f - SYN+ACK fingerprints
|
||||
# --------------------------
|
||||
#
|
||||
# .-------------------------------------------------------------------------.
|
||||
# | The purpose of this file is to cover signatures for outgoing TCP/IP |
|
||||
# | connections (SYN+ACK packets). This mode of operation can be enabled |
|
||||
# | with -A option. Please refer to p0f.fp for information on the metrics |
|
||||
# | used to create a signature, and for a guide on adding new entries to |
|
||||
# | those files. This database is somewhat neglected, and is looking for a |
|
||||
# | caring maintainer. |
|
||||
# `-------------------------------------------------------------------------'
|
||||
#
|
||||
# (C) Copyright 2000-2006 by Michal Zalewski <lcamtuf@coredump.cx>
|
||||
#
|
||||
# Plenty of signatures contributed in bulk by rain forest puppy, Paul Woo and
|
||||
# Michael Bauer.
|
||||
#
|
||||
# Submit all additions to the authors. Read p0f.fp before adding any
|
||||
# signatures. Run p0f -A -C after making any modifications. This file is
|
||||
# NOT compatible with SYN, RST+, or stray ACK modes. Use only with -A option.
|
||||
#
|
||||
# Feel like contributing? You can run p0f -A -K, then test/tryid -iR nnn...
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT THE INTERDEPENDENCY OF SYNs AND SYN+ACKs
|
||||
# --------------------------------------------------------------------
|
||||
#
|
||||
# Some systems would have different SYN+ACK fingerprints depending on
|
||||
# the system that sent SYN. More specifically, RFC1323, RFC2018 and
|
||||
# RFC1644 extensions sometimes show up only if SYN had them enabled.
|
||||
#
|
||||
# Also, some silly systems may copy WSS from the SYN packet you've sent,
|
||||
# in which case, you need to wildcard the value. Use test/sendsyn.c, which
|
||||
# uses a distinct WSS of 12345, to test for this condition if unsure.
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT DIFFERENCES IN COMPARISON TO p0f.fp:
|
||||
# ----------------------------------------------------------------
|
||||
#
|
||||
# - 'A' quirk would be present on almost every signature here. ACK number
|
||||
# is unusual for SYN packets, but is a commonplace in SYN+ACK packets,
|
||||
# of course. It is still possible to have a signature without 'A', when
|
||||
# the ACK flag is present but the value is zero - this, however, is
|
||||
# very uncommon.
|
||||
#
|
||||
# - 'T' quirk would show up on almost all signatures for systems implementing
|
||||
# RFC1323. The second timestamp is only unusual for SYN packets. SYN+ACK
|
||||
# are expected to have it set.
|
||||
#
|
||||
|
||||
##########################
|
||||
# Standard OS signatures #
|
||||
##########################
|
||||
|
||||
# ---------------- Linux -------------------
|
||||
|
||||
32736:64:0:44:M*:A:Linux:2.0
|
||||
S22:64:1:60:M*,S,T,N,W0:AT:Linux:2.2
|
||||
S22:64:1:52:M*,N,N,S,N,W0:A:Linux:2.2 w/o timestamps
|
||||
|
||||
5792:64:1:60:M*,S,T,N,W0:AT:Linux:older 2.4
|
||||
5792:64:1:60:M*,S,T,N,W0:ZAT:Linux:recent 2.4 (1)
|
||||
S4:64:1:44:M*:ZA:Linux:recent 2.4 (2)
|
||||
5792:64:1:44:M*:ZA:Linux:recent 2.4 (3)
|
||||
|
||||
S4:64:1:52:M*,N,N,S,N,W0:ZA:Linux:2.4 w/o timestamps
|
||||
|
||||
# --------------- Windows ------------------
|
||||
|
||||
65535:128:1:64:M*,N,W0,N,N,T0,N,N,S:A:Windows:2000 SP4
|
||||
S44:128:1:64:M*,N,W0,N,N,T0,N,N,S:A:Windows:XP SP1
|
||||
S12:128:1:64:M*,N,W0,N,N,T0,N,N,S:A:Windows:2000 (SP1+)
|
||||
S6:128:1:44:M*:A:Windows:NT 4.0 SP1+
|
||||
65535:128:1:48:M*,N,N,S:A:Windows:98 (SE)
|
||||
65535:128:1:44:M*:A:Windows:2000 (1)
|
||||
16616:128:1:44:M*:A:Windows:2003
|
||||
16384:128:1:44:M*:A:Windows:2000 (2)
|
||||
S16:128:1:44:M*:A:Windows:2000 (3)
|
||||
|
||||
# ------------------- OpenBSD --------------
|
||||
|
||||
17376:64:1:64:M*,N,N,S,N,W0,N,N,T:AT:OpenBSD:3.3
|
||||
|
||||
# ------------------- NetBSD ----------------
|
||||
|
||||
16384:64:0:60:M*,N,W0,N,N,T0:AT:NetBSD:1.6
|
||||
|
||||
# ----------------- HP/UX ------------------
|
||||
|
||||
32768:64:1:44:M*:A:HPUX:10.20
|
||||
|
||||
# ----------------- Tru64 ------------------
|
||||
|
||||
S23:60:0:48:M*,N,W0:A:Tru64:5.0 (1)
|
||||
65535:64:0:44:M*:A:Tru64:5.0 (2)
|
||||
|
||||
# ----------------- Novell -----------------
|
||||
|
||||
6144:128:1:52:M*,W0,N,S,N,N:A:Novell:Netware 6.0 (SP3)
|
||||
32768:128:1:44:M*:A:Novell:Netware 5.1
|
||||
|
||||
# ------------------ IRIX ------------------
|
||||
|
||||
60816:60:1:60:M*,N,W0,N,N,T:AT:IRIX:6.5.0
|
||||
|
||||
# ----------------- Solaris ----------------
|
||||
|
||||
49232:64:1:64:N,N,T,M*,N,W0,N,N,S:AT:Solaris:9 (1)
|
||||
S1:255:1:60:N,N,T,N,W0,M*:AT:Solaris:7
|
||||
24656:64:1:44:M*:A:Solaris:8
|
||||
33304:64:1:60:N,N,T,M*,N,W1:AT:Solaris:9 (2)
|
||||
|
||||
# ----------------- FreeBSD ----------------
|
||||
|
||||
65535:64:1:60:M*,N,W1,N,N,T:AT:FreeBSD:5.0
|
||||
57344:64:1:44:M*:A:FreeBSD:4.6-4.8
|
||||
65535:64:1:44:M*:A:FreeBSD:4.4
|
||||
|
||||
57344:64:1:48:M1460,N,W0:A:FreeBSD:4.6-4.8 (wscale)
|
||||
57344:64:1:60:M1460,N,W0,N,N,T:AT:FreeBSD:4.6-4.8 (RFC1323)
|
||||
|
||||
# ------------------- AIX ------------------
|
||||
|
||||
S17:255:1:44:M536:A:AIX:4.2
|
||||
|
||||
S12:64:0:44:M1460:A:AIX:5.2 ML04 (1)
|
||||
S42:64:0:44:M1460:A:AIX:5.2 ML04 (2)
|
||||
|
||||
# ------------------ BSD/OS ----------------
|
||||
|
||||
S6:64:1:60:M1460,N,W0,N,N,T:AT:BSD/OS:4.0.x
|
||||
|
||||
# ------------------ OS/390 ----------------
|
||||
|
||||
2048:64:0:44:M1460:A:OS/390:?
|
||||
|
||||
# ------------------ Novell ----------------
|
||||
|
||||
6144:128:1:44:M1400:A:Novell:iChain 2.2
|
||||
|
||||
# ------------------ MacOS -----------------
|
||||
|
||||
33304:64:1:60:M*,N,W0,N,N,T:AT:MacOS:X 10.2.6
|
||||
|
||||
#################################################################
|
||||
# Contributed by Ryan Kruse <rkruse@alterpoint.com> - trial run #
|
||||
#################################################################
|
||||
|
||||
# S4:255:0:44:M1024:A:Cisco:LocalDirector
|
||||
# 1024:255:0:44:M536:A:Cisco,3COM,Nortel:CatIOS,SuperStack,BayStack
|
||||
# S16:64:0:44:M512:A:Nortel:Contivity
|
||||
# 8192:64:0:44:M1460:A:Cisco,Nortel,SonicWall,Tasman:Aironet,BayStack Switch,Soho,1200
|
||||
# 4096:255:0:44:M1460:A:Cisco:PIX,CatOS
|
||||
# 8192:128:0:44:M1460:A:Cisco:VPN Concentrator
|
||||
# 8192:128:0:60:M1460,N,W0,N,N,T:AT:Cisco:VPN Concentrator
|
||||
# 4096:32:0:44:M1460:A:Cisco,3COM,Extreme,Nortel:Catalyst Switch CatOS,CoreBuilder,Summit,Passport
|
||||
# S4:255:0:44:M536:ZA:Cisco:IOS
|
||||
# 1024:32:0:44:M1480:UA:Nortel:BayStack Switch
|
||||
# 4096:60:0:44:M1460:A:Adtran:NetVanta
|
||||
# 4096:64:0:44:M1008:A:Adtran:TSU
|
||||
# S4:32:0:44:M1024:A:Alcatel:Switch
|
||||
# S8:255:0:44:M536:ZA:Cisco:IOS
|
||||
# 50:255:0:44:M536:ZA:Cisco:CatIOS
|
||||
# 512:64:0:40:.:A:Dell:Switch
|
||||
# 4096:64:0:40:.:A:Enterasys:Vertical Horizon Switch
|
||||
# 17640:64:1:44:M1460:A:F5,Juniper,RiverStone:BigIP,Juniper OS,Router 7.0+
|
||||
# 16384:64:0:44:M1460:A:Foundry,SonicWall:BigIron,TZ
|
||||
# 4096:64:0:44:M1452:A:HP:ProCurve Switch
|
||||
# 1024:64:0:44:M1260:A:Marconi:ES
|
||||
# 10240:30:0:44:M1460:A:Milan:Switch
|
||||
# 4096:64:0:44:M1380:A:NetScreen:Firewall
|
||||
# S32:64:0:44:M512:A:Nokia:CheckPoint
|
||||
# 1024:64:0:44:M536:A:Nortel:BayStack Switch
|
||||
# 4128:255:0:44:M*:ZA:Cisco:IOS
|
||||
# 1024:16:0:44:M536:A:Nortel:BayStack Switch
|
||||
# 1024:30:0:44:M1480:A:Nortel:BayStack Switch
|
||||
# S4:64:0:44:M1460:A:Symbol:Spectrum Access Point
|
||||
# S2:255:0:44:M512:A:ZyXEL:Prestige
|
||||
# S16:255:0:44:M1024:A:ZyXEL:ZyAI
|
||||
|
||||
###########################################
|
||||
# Appliance / embedded / other signatures #
|
||||
###########################################
|
||||
|
||||
16384:64:1:44:M1460:A:F5:BigIP LB 4.1.x (sometimes FreeBSD)
|
||||
4128:255:0:44:M*:ZA:Cisco:Catalyst 2900 12.0(5)
|
||||
4096:60:0:44:M*:A:Brother:HL-1270N
|
||||
S1:30:0:44:M1730:A:Cyclades:PR3000
|
||||
8192:64:1:44:M1460:A:NetApp:Data OnTap 6.x
|
||||
5792:64:1:60:W0,N,N,N,T,M1460:ZAT:FortiNet:FortiGate 50
|
||||
S1:64:1:44:M1460:A:NetCache:5.3.1
|
||||
S1:64:0:44:M512:A:Printer:controller (?)
|
||||
4096:128:0:40:.:A:Sequent:DYNIX 4.2.x
|
||||
S16:64:0:44:M512:A:3Com:NBX PBX (BSD/OS 2.1)
|
||||
16000:64:0:44:M1442:A:CastleNet:DSL router
|
||||
S2:64:0:44:M32728:A:D-Link:DSL-500
|
||||
S4:60:0:44:M1460:A:HP:JetDirect A.05.32
|
||||
8576:64:1:44:M*:A:Raptor:firewall
|
||||
S12:64:1:44:M1400:A:Cequrux Firewall:4.x
|
||||
2048:255:0:44:M1400:A:Netgear:MR814
|
||||
16384:128:0:64:M1460,N,W0,N,N,T0,N,N,S:A:Akamai:??? (1)
|
||||
16384:128:0:60:M1460,N,W0,N,N,T0:A:Akamai:??? (2)
|
||||
|
||||
8190:255:0:44:M1452:A:Citrix:Netscaler 6.1
|
||||
|
||||
# Whatever they run. EOL boys...
|
||||
S6:128:1:48:M1460,E:PA:@Slashdot:or BusinessWeek (???)
|
||||
|
||||
|
||||
48
decnet/prober/osfp/p0f/data/p0fo.fp
Normal file
48
decnet/prober/osfp/p0f/data/p0fo.fp
Normal file
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# p0f - stray ACK signatures
|
||||
# --------------------------
|
||||
#
|
||||
# .-------------------------------------------------------------------------.
|
||||
# | The purpose of this file is to cover signatures for stray ACK packets |
|
||||
# | (established session data). This mode of operation is enabled with -O |
|
||||
# | option and is HIGHLY EXPERIMENTAL. Please refer to p0f.fp for more |
|
||||
# | information on the metrics used and for a guide on adding new entries |
|
||||
# | to this file. This database is looking for a caring maintainer. |
|
||||
# `-------------------------------------------------------------------------'
|
||||
#
|
||||
# (C) Copyright 2000-2006 by Michal Zalewski <lcamtuf@coredump.cx>
|
||||
#
|
||||
# Submit all additions to the authors. Read p0f.fp before adding any
|
||||
# signatures. Run p0f -O -C after making any modifications. This file is
|
||||
# NOT compatible with SYN, SYN+ACK or RST+ modes. Use only with -O option.
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT THE INTERDEPENDENCY OF SYNs AND ACKs
|
||||
# ----------------------------------------------------------------
|
||||
#
|
||||
# Some systems would have different ACK fingerprints depending on the initial
|
||||
# SYN or SYN+ACK received from the other party. More specifically, RFC1323,
|
||||
# RFC2018 and RFC1644 extensions sometimes show up only if the other party had
|
||||
# them enabled. Hence, the reliability of ACK fingerprints may be affected.
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT DIFFERENCES IN COMPARISON TO p0f.fp:
|
||||
# ----------------------------------------------------------------
|
||||
#
|
||||
# - Packet size MUST be wildcarded. ACK packets, by their nature, have
|
||||
# variable sizes, depending on the amount of data carried as a payload.
|
||||
#
|
||||
# - Similarly, 'D' quirk is not checked for, and is not allowed in signatures
|
||||
# in this file. A good number of ACK packets have payloads.
|
||||
#
|
||||
# - PUSH flag is excluded from 'F' quirk checks in this mode.
|
||||
#
|
||||
# - 'A' quirk is not a bug; all AC packets should have it set; also,
|
||||
# 'T' quirk is not an anomaly; its absence on systems with T option is.
|
||||
#
|
||||
|
||||
32767:64:1:*:N,N,T:AT:Linux:2.4.2x (local?)
|
||||
*:64:1:*:.:A:Linux:2.4.2x
|
||||
32736:64:0:*:.:A:Linux:2.0.3x
|
||||
|
||||
57600:64:1:*:N,N,T:AT:FreeBSD:4.8
|
||||
%12:128:1:*:.:A:Windows:XP
|
||||
S44:128:1:*:.:A:Windows:XP
|
||||
193
decnet/prober/osfp/p0f/data/p0fr.fp
Normal file
193
decnet/prober/osfp/p0f/data/p0fr.fp
Normal file
@@ -0,0 +1,193 @@
|
||||
#
|
||||
# p0f - RST+ signatures
|
||||
# ---------------------
|
||||
#
|
||||
# .-------------------------------------------------------------------------.
|
||||
# | The purpose of this file is to cover signatures for reset packets |
|
||||
# | (RST and RST+ACK). This mode of operation can be enabled with -A option |
|
||||
# | and is considered to be least accurate. Please refer to p0f.fp for more |
|
||||
# | information on the metrics used and for a guide on adding new entries |
|
||||
# | to this file. This database is looking for a caring maintainer. |
|
||||
# `-------------------------------------------------------------------------'
|
||||
#
|
||||
# (C) Copyright 2000-2006 by Michal Zalewski <lcamtuf@coredump.cx>
|
||||
#
|
||||
# Submit all additions to the authors. Read p0f.fp before adding any
|
||||
# signatures. Run p0f -R -C after making any modifications. This file is
|
||||
# NOT compatible with SYN, SYN+ACK, or stray ACK modes. Use only with -R
|
||||
# option.
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT THE INTERDEPENDENCY OF SYNs AND RST+ACKs
|
||||
# --------------------------------------------------------------------
|
||||
#
|
||||
# Some silly systems may copy WSS from the SYN packet you've sent,
|
||||
# in which case, you need to wildcard the value. Use test/sendsyn.c for
|
||||
# "connection refused" and test/sendack.c for "connection dropped" signatures
|
||||
# - both tools use a distinct WSS of 12345, which is an easy way to tell
|
||||
# if WSS should be wildcarded.
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT COMMON IMPLEMENTATION FLAWS
|
||||
# -------------------------------------------------------
|
||||
#
|
||||
# There are several types of RST packets you will surely encounter.
|
||||
# Some systems, including most reputable ones, are severily brain-damaged
|
||||
# and generate some illegal combinations from time to time. This is WAY
|
||||
# more common than with other packet types, because a broken RST does not
|
||||
# have any immediately noticable consequences; besides, the RFC793 is fairly
|
||||
# difficult to comprehend when it comes to this type of responses.
|
||||
#
|
||||
# P0f will give you a hint on new RST signatures, but it is your duty to
|
||||
# diagnose the problem and append the proper description when adding the
|
||||
# signature. Below is a list of valid and invalid states:
|
||||
#
|
||||
# - "Connection refused" message: this is a RST+ACK packet, SEQ number
|
||||
# set to zero, ACK number non-zero. This is a valid response and
|
||||
# is denoted by p0f as "refused" (quirk combination: K, 0, A).
|
||||
#
|
||||
# There are some very cases when this is incorrectly sent in response
|
||||
# to an unexpected ACK packet.
|
||||
#
|
||||
# - Illegal combination: RST+ACK packet, SEQ number set to zero, ACK
|
||||
# number zero. This is denoted by p0f as "invalid-K0" (quirk combination:
|
||||
# K and 0, no A).
|
||||
#
|
||||
# - Illegal combination: RST+ACK, SEQ number non-zero, ACK number zero
|
||||
# or non-zero. This is denoted by p0f as "invalid-K" and
|
||||
# "invalid-KA", respectively (quirk combinations, K, sometimes A, no 0).
|
||||
#
|
||||
# This combination is frequently generated by Cisco routers in certain
|
||||
# configurations in response to ACK (!). Brain dead, by all means, and
|
||||
# usually a result of (incorrectly) setting ACK flag on a valid RST packet.
|
||||
#
|
||||
# - "Connection dropped": RST, sequence number non-zero, ACK zero or
|
||||
# non-zero. This is denoted as "dropped" and "dropped 2" respectively
|
||||
# (quirk combinations: no K, sometimes A, no 0). While the ACK value should
|
||||
# be zeroed, it is not strictly against the RFC, and some systems either
|
||||
# leak memory there or set it to the value of SEQ.
|
||||
#
|
||||
# The latter variant, with non-zero ACK, is particularly common on
|
||||
# Windows.
|
||||
#
|
||||
# - Ilegal combination: RST, SEQ number zero, ACK zero or non-zero.
|
||||
# Denoted as "invalid-0" and "invalid-0A". Obviously incorrect, and
|
||||
# will not have the desired effect.
|
||||
#
|
||||
# Ok. That's it. RFC793 does not get much respect nowadays.
|
||||
#
|
||||
# IMPORTANT INFORMATION ABOUT DIFFERENCES IN COMPARISON TO p0f.fp:
|
||||
# ----------------------------------------------------------------
|
||||
#
|
||||
# - Packet size may be wildcarded. The meaning of wildcard is, however,
|
||||
# hardcoded as 'size > PACKET_BIG' (defined as 100 in config.h). This is
|
||||
# because some stupid devices (including Ciscos) tend to send back RST
|
||||
# packets quoting anything you have sent them in ACK packet previously.
|
||||
# Use sparingly, only if -X confirms the device actually bounces back
|
||||
# whatever you send.
|
||||
#
|
||||
# - A new quirk, 'K', is introduced to denote RST+ACK packets (as opposed
|
||||
# to plain RST). This quirk is only compatible with this mode.
|
||||
#
|
||||
# - A new quirk, 'Q', is used to denote SEQ number equal to ACK number.
|
||||
# This happens from time to time in RST and RST+ACK packets, but
|
||||
# is practically unheard of in other modes.
|
||||
#
|
||||
# - A new quirk, '0', is used to denote packets with SEQ number set to 0.
|
||||
# This happens on some RSTs, and is once again unheard of in other modes.
|
||||
#
|
||||
# - 'D' quirk is not a bug; some devices send verbose text messages
|
||||
# describing why a connection got dropped; it's actually suggested
|
||||
# by RFC1122. Of course, some systems have their own standards, and
|
||||
# put all kinds of crap in their RST responses (including FreeBSD and
|
||||
# Cisco). Use -X to examine those values.
|
||||
#
|
||||
# - 'A' and 'T' quirks are not an anomaly in certain cases for the reasons
|
||||
# described in p0fa.fp.
|
||||
#
|
||||
|
||||
################################
|
||||
# Connection refused - RST+ACK #
|
||||
################################
|
||||
|
||||
0:255:0:40:.:K0A:Linux:2.0/2.2 (refused)
|
||||
0:64:1:40:.:K0A:FreeBSD:4.8 (refused)
|
||||
0:64:1:40:.:K0ZA:Linux:recent 2.4 (refused)
|
||||
|
||||
0:128:0:40:.:K0A:Windows:XP/2000 (refused)
|
||||
0:128:0:40:.:K0UA:-Windows:XP/2000 while browsing (refused)
|
||||
|
||||
######################################
|
||||
# Connection dropped / timeout - RST #
|
||||
######################################
|
||||
|
||||
0:64:1:40:.:.:FreeBSD:4.8 (dropped)
|
||||
0:255:0:40:.:.:Linux:2.0/2.2 or IOS 12.x (dropped)
|
||||
0:64:1:40:.:Z:Linux:recent 2.4 (dropped)
|
||||
0:255:1:40:.:Z:Linux:early 2.4 (dropped)
|
||||
0:32:0:40:.:.:Xylan:OmniSwitch / Linksys WAP11 AP (dropped)
|
||||
0:64:1:40:.:U:NetIron:load balancer (dropped)
|
||||
|
||||
0:128:1:40:.:QA:Windows:XP/2000 (dropped 2)
|
||||
0:128:1:40:.:A:-Windows:XP/2000 while browsing (1) (dropped 2)
|
||||
0:128:1:40:.:QUA:-Windows:XP/2000 while browsing (2) (dropped 2)
|
||||
0:128:1:40:.:UA:-Windows:XP/2000 while browsing a lot (dropped 2)
|
||||
0:128:1:40:.:.:@Windows:98 (?) (dropped)
|
||||
|
||||
0:64:0:40:.:A:Ascend:TAOS or BayTech (dropped 2)
|
||||
|
||||
*:255:0:40:.:QA:Cisco:LocalDirector (dropped 2)
|
||||
|
||||
0:64:1:40:.:A:Hasbani:WindWeb (dropped 2)
|
||||
S23:255:1:40:.:.:Solaris:2.5 (dropped)
|
||||
|
||||
#######################################################
|
||||
# Connection dropped / timeout - RST with description #
|
||||
#######################################################
|
||||
|
||||
0:255:1:58:.:D:MacOS:9.x "No TCP/No listener" (seldom SunOS 5.x) (dropped)
|
||||
0:255:1:53:.:D:MacOS:8.5 "no tcp, reset" (dropped)
|
||||
0:255:1:65:.:D:MacOS:X "tcp_close, during connect" (dropped)
|
||||
0:255:1:54:.:D:MacOS:X "tcp_disconnect" (dropped)
|
||||
0:255:1:62:.:D:HP/UX:? "tcp_fin_wait_2_timeout" (dropped)
|
||||
32768:255:1:54:.:D:MacOS:8.5 "tcp_disconnect" (dropped)
|
||||
0:255:1:63:.:D:@Unknown: "Go away" device (dropped)
|
||||
|
||||
0:255:0:62:.:D:SunOS:5.x "new data when detached" (1) (dropped)
|
||||
32768:255:1:62:.:D:SunOS:5.x "new data when detached" (2) (dropped)
|
||||
0:255:1:67:.:D:SunOS:5.x "tcp_lift_anchor, can't wait" (dropped)
|
||||
|
||||
0:255:0:46:.:D:HP/UX:11.00 "No TCP" (dropped)
|
||||
|
||||
# More obscure ones:
|
||||
# 648:255:1:54:.:D:MacOS:??? "tcp_disconnect" (dropped)
|
||||
# 0:45:1:53:.:D:MacOS:7.x "no tcp, reset" (dropped)
|
||||
|
||||
##############################################
|
||||
# Connection dropped / timeout - broken RSTs #
|
||||
##############################################
|
||||
|
||||
S12:255:1:58:.:KAD:Solaris:2.x "tcp_disconnect" (dropped, lame)
|
||||
S43:64:1:40:.:KA:AOL:proxy (dropped, lame)
|
||||
*:64:1:40:.:KA:FreeBSD:4.8 (dropped, lame)
|
||||
*:64:1:52:N,N,T:KAT:Linux:2.4 (?) (dropped, lame)
|
||||
0:255:0:40:.:KAF:3Com:SuperStack II (dropped, lame)
|
||||
*:255:0:40:.:KA:Intel:Netport print server (dropped, lame)
|
||||
*:150:0:40:.:KA:Linksys:BEF router (dropped, lame)
|
||||
|
||||
*:32:0:44:.:KZD:@NetWare:??? "ehnc" (dropped, lame)
|
||||
0:64:0:40:.:KQ0:BayTech:RPC-3 telnet host (dropped, lame)
|
||||
|
||||
#############################################
|
||||
# Connection dropped / timeout - extra data #
|
||||
#############################################
|
||||
|
||||
*:255:0:*:.:KAD:Cisco:IOS/PIX NAT + data (1) (dropped, lame)
|
||||
0:255:0:*:.:D:Windows:NT 4.0 SP6a + data (dropped)
|
||||
0:255:0:*:.:K0AD:Isolation:Infocrypt accelerator + data (dropped, lame)
|
||||
|
||||
*:255:0:*:.:AD:Cisco:IOS/PIX NAT + data (2) (dropped)
|
||||
|
||||
*:64:1:*:N,N,T:KATD:Linux:2.4 (?) + data (dropped, lame)
|
||||
*:64:1:*:.:KAD:FreeBSD:4.8 + data (dropped, lame)
|
||||
|
||||
|
||||
|
||||
243
decnet/prober/osfp/p0f/format.py
Normal file
243
decnet/prober/osfp/p0f/format.py
Normal file
@@ -0,0 +1,243 @@
|
||||
"""p0f v2 ``.fp`` file parser.
|
||||
|
||||
Format (from the DSL spec at the top of every shipped ``.fp`` file):
|
||||
|
||||
wwww:ttt:D:ss:OOO:QQ:OS:Details
|
||||
|
||||
Where:
|
||||
wwww — window size: literal int | '*' | '%nnn' | 'Snn' | 'Tnn'
|
||||
ttt — initial TTL (literal int: 32/64/128/255 typically)
|
||||
D — DF bit: '0' or '1'
|
||||
ss — total IP packet length: literal int | '*' | '%nnn'
|
||||
OOO — option order: comma/space-separated tokens, or '.' for none.
|
||||
Tokens: N, E, S, T, T0, P, Wnnn/W*/W%nnn, Mnnn/M*/M%nnn, ?n
|
||||
QQ — quirks: concatenated single-letter flags, or '.' for none.
|
||||
Flags: P, Z, I, U, X, A, T, F, D, !, K, Q, 0, R
|
||||
OS — genre, optionally prefixed '-' (userland), '@' (group),
|
||||
'*' (random/bogus), or combinations (e.g. '-@Windows').
|
||||
Details — free-text flavor/version.
|
||||
|
||||
Lines starting with '#' and blank lines are skipped.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from decnet.prober.osfp.p0f.signature import (
|
||||
IntSpec,
|
||||
OptionToken,
|
||||
Signature,
|
||||
WindowSpec,
|
||||
precompute_specificity,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("decnet.prober.osfp.p0f.format")
|
||||
|
||||
_OPTION_TOKEN_RE = re.compile(r"^([NESTPE]|T0|[MW\?])(\*|%\d+|\d+)?$")
|
||||
|
||||
|
||||
class P0fParseError(ValueError):
|
||||
"""Raised on genuinely malformed signature lines. The loader
|
||||
catches these and skips the offending line with a logger warning —
|
||||
one bad row doesn't disable the whole DB."""
|
||||
|
||||
|
||||
def parse_p0f_v2(path: Path) -> list[Signature]:
|
||||
"""Parse a p0f v2 ``.fp`` file and return a list of Signatures.
|
||||
|
||||
Malformed lines are logged at WARNING and skipped rather than
|
||||
aborting the whole load — the vendored DB has ~375 entries and one
|
||||
corrupt row shouldn't prevent the other 374 from being usable.
|
||||
"""
|
||||
out: list[Signature] = []
|
||||
with path.open("r", encoding="utf-8", errors="replace") as fh:
|
||||
for lineno, raw in enumerate(fh, 1):
|
||||
line = raw.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
try:
|
||||
sig = _parse_line(line)
|
||||
except P0fParseError as exc:
|
||||
logger.warning(
|
||||
"p0f parse: skipping %s:%d — %s", path.name, lineno, exc,
|
||||
)
|
||||
continue
|
||||
out.append(sig)
|
||||
logger.debug("p0f parse: loaded %d signatures from %s", len(out), path.name)
|
||||
return out
|
||||
|
||||
|
||||
def _parse_line(line: str) -> Signature:
|
||||
parts = line.split(":", 7)
|
||||
if len(parts) < 7:
|
||||
raise P0fParseError(f"expected 7+ colon-delimited fields, got {len(parts)}")
|
||||
if len(parts) == 7:
|
||||
parts = [*parts, ""] # empty details
|
||||
wss_s, ttl_s, df_s, tot_s, opts_s, quirks_s, os_s, details = parts
|
||||
|
||||
wss = _parse_wss(wss_s)
|
||||
ttl = _parse_int_field(ttl_s, field="ttl")
|
||||
df = _parse_df(df_s)
|
||||
total_len = _parse_int_spec(tot_s)
|
||||
options = _parse_options(opts_s)
|
||||
quirks = _parse_quirks(quirks_s)
|
||||
os_name, is_userland, is_approx, is_random = _parse_os_genre(os_s)
|
||||
|
||||
sig = Signature(
|
||||
wss=wss,
|
||||
ttl=ttl,
|
||||
df=df,
|
||||
total_len=total_len,
|
||||
options=options,
|
||||
quirks=quirks,
|
||||
os=os_name,
|
||||
flavor=details.strip(),
|
||||
notes="",
|
||||
is_userland=is_userland,
|
||||
is_approximate=is_approx,
|
||||
is_random=is_random,
|
||||
)
|
||||
# Replace specificity (frozen dataclass field default) with the
|
||||
# computed value via dataclasses.replace.
|
||||
from dataclasses import replace
|
||||
return replace(sig, specificity=precompute_specificity(sig))
|
||||
|
||||
|
||||
def _parse_wss(s: str) -> WindowSpec:
|
||||
s = s.strip()
|
||||
if s == "*":
|
||||
return WindowSpec("any")
|
||||
if s.startswith("%"):
|
||||
try:
|
||||
return WindowSpec("mod", int(s[1:]))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad mod window {s!r}") from exc
|
||||
if s.startswith("S"):
|
||||
try:
|
||||
return WindowSpec("mss_mul", int(s[1:]))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad Snn window {s!r}") from exc
|
||||
if s.startswith("T"):
|
||||
try:
|
||||
return WindowSpec("mtu_mul", int(s[1:]))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad Tnn window {s!r}") from exc
|
||||
try:
|
||||
return WindowSpec("literal", int(s))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad literal window {s!r}") from exc
|
||||
|
||||
|
||||
def _parse_int_field(s: str, *, field: str) -> int:
|
||||
"""Parse a bare int field (used for TTL). No wildcards allowed."""
|
||||
try:
|
||||
return int(s.strip())
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad {field}: {s!r}") from exc
|
||||
|
||||
|
||||
def _parse_df(s: str) -> Optional[bool]:
|
||||
s = s.strip()
|
||||
if s == "*":
|
||||
return None
|
||||
if s == "0":
|
||||
return False
|
||||
if s == "1":
|
||||
return True
|
||||
raise P0fParseError(f"bad DF {s!r}; expected 0/1/*")
|
||||
|
||||
|
||||
def _parse_int_spec(s: str) -> IntSpec:
|
||||
s = s.strip()
|
||||
if s == "*":
|
||||
return IntSpec("any")
|
||||
if s.startswith("%"):
|
||||
try:
|
||||
return IntSpec("mod", int(s[1:]))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad mod int {s!r}") from exc
|
||||
try:
|
||||
return IntSpec("literal", int(s))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad literal int {s!r}") from exc
|
||||
|
||||
|
||||
def _parse_options(s: str) -> tuple[OptionToken, ...]:
|
||||
s = s.strip()
|
||||
if s in (".", ""):
|
||||
return (OptionToken("."),)
|
||||
normalized = s.replace(",", " ")
|
||||
tokens: list[OptionToken] = []
|
||||
for raw in normalized.split():
|
||||
tok = raw.strip()
|
||||
if not tok:
|
||||
continue
|
||||
tokens.append(_parse_option_token(tok))
|
||||
if not tokens:
|
||||
return (OptionToken("."),)
|
||||
return tuple(tokens)
|
||||
|
||||
|
||||
def _parse_option_token(raw: str) -> OptionToken:
|
||||
# T0 — timestamp zero (not the TCP option '?0').
|
||||
if raw == "T0":
|
||||
return OptionToken("T0")
|
||||
m = _OPTION_TOKEN_RE.match(raw)
|
||||
if not m:
|
||||
raise P0fParseError(f"bad option token {raw!r}")
|
||||
kind, val_raw = m.group(1), m.group(2)
|
||||
if kind in ("N", "E", "S", "T", "P"):
|
||||
return OptionToken(kind)
|
||||
# M / W / ? expect a numeric predicate (or wildcard).
|
||||
if val_raw is None:
|
||||
raise P0fParseError(f"option {kind!r} missing required value")
|
||||
if val_raw == "*":
|
||||
spec = IntSpec("any")
|
||||
elif val_raw.startswith("%"):
|
||||
try:
|
||||
spec = IntSpec("mod", int(val_raw[1:]))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad {kind} mod value {val_raw!r}") from exc
|
||||
else:
|
||||
try:
|
||||
spec = IntSpec("literal", int(val_raw))
|
||||
except ValueError as exc:
|
||||
raise P0fParseError(f"bad {kind} literal value {val_raw!r}") from exc
|
||||
return OptionToken(kind, spec)
|
||||
|
||||
|
||||
def _parse_quirks(s: str) -> frozenset[str]:
|
||||
s = s.strip()
|
||||
if s == "." or not s:
|
||||
return frozenset()
|
||||
# Quirks are a concatenated string of single-letter flags. '!' is a
|
||||
# valid quirk too.
|
||||
return frozenset(c for c in s if not c.isspace())
|
||||
|
||||
|
||||
def _parse_os_genre(s: str) -> tuple[str, bool, bool, bool]:
|
||||
"""Strip p0f's genre-prefix modifiers and return (os_name, is_userland, is_approx, is_random)."""
|
||||
is_userland = False
|
||||
is_approx = False
|
||||
is_random = False
|
||||
s = s.strip()
|
||||
# Prefixes can stack in any order — strip them all.
|
||||
changed = True
|
||||
while changed and s:
|
||||
changed = False
|
||||
if s.startswith("-"):
|
||||
is_userland = True
|
||||
s = s[1:]
|
||||
changed = True
|
||||
elif s.startswith("@"):
|
||||
is_approx = True
|
||||
s = s[1:]
|
||||
changed = True
|
||||
elif s.startswith("*"):
|
||||
is_random = True
|
||||
s = s[1:]
|
||||
changed = True
|
||||
return s, is_userland, is_approx, is_random
|
||||
109
decnet/prober/osfp/p0f/provider.py
Normal file
109
decnet/prober/osfp/p0f/provider.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""p0f v2 Provider — loads the vendored .fp databases and matches
|
||||
against observed TCP quirks.
|
||||
|
||||
Four databases ship under ``data/``:
|
||||
|
||||
p0f.fp — SYN fingerprints (passive / sniffer-captured inbound).
|
||||
p0fa.fp — SYN-ACK fingerprints (prober active-probe responses).
|
||||
p0fr.fp — RST+ fingerprints (reset-response quirks).
|
||||
p0fo.fp — "stray" packet fingerprints.
|
||||
|
||||
The provider routes incoming observations to the right sig list based
|
||||
on ``obs["context"]`` — see :meth:`P0fV2Provider.match` — and returns
|
||||
the highest-specificity matching :class:`OsMatch` or ``None``.
|
||||
|
||||
DECNET-authored additions can land in ``p0f-decnet.fp`` (same
|
||||
directory, loaded if present) under GPL-3.0. None exist today — the
|
||||
plan deferred writing any to a later commit — but the provider
|
||||
already picks it up when it appears.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
from decnet.prober.osfp.base import OsMatch, Provider
|
||||
from decnet.prober.osfp.p0f.format import parse_p0f_v2
|
||||
from decnet.prober.osfp.p0f.signature import Signature
|
||||
|
||||
logger = logging.getLogger("decnet.prober.osfp.p0f.provider")
|
||||
|
||||
|
||||
# Directory containing the vendored .fp files.
|
||||
_DATA_DIR: Path = Path(__file__).resolve().parent / "data"
|
||||
|
||||
# Which .fp files feed each observation context.
|
||||
_CONTEXT_DBS: dict[str, tuple[str, ...]] = {
|
||||
"syn": ("p0f.fp", "p0f-decnet.fp"),
|
||||
"synack": ("p0fa.fp",),
|
||||
"rst": ("p0fr.fp",),
|
||||
"stray": ("p0fo.fp",),
|
||||
}
|
||||
|
||||
|
||||
class P0fV2Provider(Provider):
|
||||
"""Match observations against the p0f v2 database."""
|
||||
|
||||
name = "p0f-v2"
|
||||
|
||||
def __init__(self, data_dir: Optional[Path] = None) -> None:
|
||||
self._data_dir = (data_dir or _DATA_DIR).resolve()
|
||||
self._sigs_by_context: dict[str, list[Signature]] = {}
|
||||
self._load()
|
||||
|
||||
def _load(self) -> None:
|
||||
for context, filenames in _CONTEXT_DBS.items():
|
||||
merged: list[Signature] = []
|
||||
for name in filenames:
|
||||
path = self._data_dir / name
|
||||
if not path.is_file():
|
||||
# p0f-decnet.fp is optional; all others are required.
|
||||
if name.startswith("p0f-decnet"):
|
||||
continue
|
||||
logger.warning("p0f-v2: missing required DB file %s", path)
|
||||
continue
|
||||
try:
|
||||
merged.extend(parse_p0f_v2(path))
|
||||
except OSError as exc:
|
||||
logger.warning("p0f-v2: could not load %s: %s", path, exc)
|
||||
self._sigs_by_context[context] = merged
|
||||
logger.debug("p0f-v2: %s context loaded %d signatures", context, len(merged))
|
||||
|
||||
def match(self, obs: dict[str, Any]) -> Optional[OsMatch]:
|
||||
"""Return the highest-specificity matching signature, or None.
|
||||
|
||||
``obs["context"]`` selects the DB slice; default is "syn"
|
||||
(passive observation, which is 80%+ of the event stream).
|
||||
Invalid contexts return None rather than raising.
|
||||
"""
|
||||
context = obs.get("context", "syn")
|
||||
sigs = self._sigs_by_context.get(context)
|
||||
if not sigs:
|
||||
return None
|
||||
|
||||
best: tuple[float, Signature] | None = None
|
||||
for sig in sigs:
|
||||
score = sig.score(obs)
|
||||
if score is None:
|
||||
continue
|
||||
if best is None or score > best[0]:
|
||||
best = (score, sig)
|
||||
# Short-circuit on a perfect match — can't beat 1.0.
|
||||
if best[0] >= 1.0:
|
||||
break
|
||||
|
||||
if best is None:
|
||||
return None
|
||||
score, sig = best
|
||||
return OsMatch(
|
||||
os=sig.os,
|
||||
flavor=sig.flavor,
|
||||
confidence=score,
|
||||
provider=self.name,
|
||||
is_userland=sig.is_userland,
|
||||
)
|
||||
|
||||
def signature_counts(self) -> dict[str, int]:
|
||||
"""For diagnostics / tests — how many sigs loaded per context."""
|
||||
return {ctx: len(sigs) for ctx, sigs in self._sigs_by_context.items()}
|
||||
287
decnet/prober/osfp/p0f/signature.py
Normal file
287
decnet/prober/osfp/p0f/signature.py
Normal file
@@ -0,0 +1,287 @@
|
||||
"""p0f v2 signature + observation matching/scoring.
|
||||
|
||||
A :class:`Signature` is one parsed row from a ``.fp`` file. A match
|
||||
against an observation dict (the kind ``sniffer_rollup`` hands us)
|
||||
returns a confidence score in [0, 1], with higher scores indicating
|
||||
more-specific matches. Wildcards and modulo predicates match but
|
||||
contribute less to the confidence than an exact literal match, so
|
||||
when multiple signatures fire against one observation we can pick the
|
||||
most-specific one.
|
||||
|
||||
Observation dict shape (all keys optional — a provider returns None
|
||||
if too few match-relevant fields are present):
|
||||
|
||||
{
|
||||
"window": int | None, # TCP window size
|
||||
"mss": int | None, # TCP MSS option value
|
||||
"wscale": int | None, # TCP window-scale option value
|
||||
"ttl": int | None, # initial-TTL bucket (32/64/128/255)
|
||||
"df": bool | None, # IP Don't-Fragment flag
|
||||
"total_len": int | None, # IP total length (SYN)
|
||||
"options_sig": str | None, # e.g. "M,N,W,T" or "M1460,N,W7,S"
|
||||
"quirks": frozenset[str] | None, # e.g. {"Z", "P"}
|
||||
}
|
||||
|
||||
The scoring is our extension — upstream p0f is "first match wins"
|
||||
using the order of entries in ``.fp``. We score so the factory can
|
||||
compare across multiple DB files (p0f.fp + p0fa.fp) and return the
|
||||
winner objectively.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
# ─── Field predicates ──────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class WindowSpec:
|
||||
"""Parsed 'wss' field. Encodes p0f v2's window-size predicate DSL:
|
||||
|
||||
- 'literal' → observed window == value
|
||||
- 'mss_mul' → observed window == MSS * value (p0f "Snn")
|
||||
- 'mtu_mul' → observed window == (MSS+40) * value (p0f "Tnn")
|
||||
- 'mod' → observed window % value == 0 (p0f "%nnn")
|
||||
- 'any' → wildcard (p0f "*")
|
||||
"""
|
||||
|
||||
kind: str
|
||||
value: Optional[int] = None
|
||||
|
||||
def matches(self, window: Optional[int], mss: Optional[int]) -> bool:
|
||||
if self.kind == "any":
|
||||
return True
|
||||
if window is None:
|
||||
return False
|
||||
if self.kind == "literal":
|
||||
return window == self.value
|
||||
if self.kind == "mod":
|
||||
return self.value is not None and self.value > 0 and (window % self.value == 0)
|
||||
if self.kind == "mss_mul":
|
||||
return mss is not None and self.value is not None and window == mss * self.value
|
||||
if self.kind == "mtu_mul":
|
||||
return mss is not None and self.value is not None and window == (mss + 40) * self.value
|
||||
return False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class IntSpec:
|
||||
"""Wildcard-or-modulo int predicate, used for MSS / wscale / total_len."""
|
||||
|
||||
kind: str # 'literal' | 'mod' | 'any'
|
||||
value: Optional[int] = None
|
||||
|
||||
def matches(self, observed: Optional[int]) -> bool:
|
||||
if self.kind == "any":
|
||||
return True
|
||||
if observed is None:
|
||||
return False
|
||||
if self.kind == "literal":
|
||||
return observed == self.value
|
||||
if self.kind == "mod":
|
||||
return self.value is not None and self.value > 0 and (observed % self.value == 0)
|
||||
return False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class OptionToken:
|
||||
"""One TCP option as it appears in a signature's options list.
|
||||
|
||||
- kind='N' EOL 'E' SACK-permitted 'S' timestamp 'T' zero-timestamp 'T0'
|
||||
- kind='M' MSS option, value = IntSpec
|
||||
- kind='W' window-scale option, value = IntSpec
|
||||
- kind='?' unknown option number, value = IntSpec (literal = option number)
|
||||
- kind='.' no-options sentinel (singleton — matches only empty option list)
|
||||
"""
|
||||
|
||||
kind: str
|
||||
value: Optional[IntSpec] = None
|
||||
|
||||
def matches_literal(self, token: "OptionToken") -> bool:
|
||||
"""True when *this* signature token matches an observed *token*.
|
||||
|
||||
Signature-side carries the wildcard/modulo predicate; observed
|
||||
side is always a literal (or kind-only for flag options).
|
||||
"""
|
||||
if self.kind != token.kind:
|
||||
return False
|
||||
if self.value is None:
|
||||
return True
|
||||
if token.value is None:
|
||||
return False
|
||||
# Both have IntSpecs — match via predicate.
|
||||
return self.value.matches(token.value.value)
|
||||
|
||||
|
||||
# ─── Signature ─────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Signature:
|
||||
"""One parsed row from a p0f v2 .fp file.
|
||||
|
||||
``label_prefix`` captures p0f's os-genre modifiers:
|
||||
- ``-`` userland stack (not a real OS; flagged scanner/browser)
|
||||
- ``@`` approximate / group match
|
||||
- ``*`` random or bogus userland
|
||||
These prefixes are stripped from ``os``; the flags survive here
|
||||
for the profiler to decide e.g. "do I promote nmap to tool_guesses?"
|
||||
"""
|
||||
|
||||
wss: WindowSpec
|
||||
ttl: int
|
||||
df: Optional[bool]
|
||||
total_len: IntSpec
|
||||
options: tuple[OptionToken, ...] # in order; use (OptionToken('.'),) for none
|
||||
quirks: frozenset[str]
|
||||
os: str
|
||||
flavor: str
|
||||
notes: str
|
||||
is_userland: bool = False # '-' prefix
|
||||
is_approximate: bool = False # '@' prefix
|
||||
is_random: bool = False # '*' prefix (distinct from wildcard)
|
||||
|
||||
# Cache: a crude "specificity budget" precomputed at parse time.
|
||||
# Higher = more constrained fields, used as a tie-breaker when two
|
||||
# signatures match the same observation.
|
||||
specificity: float = field(default=0.0)
|
||||
|
||||
def score(self, obs: dict[str, Any]) -> Optional[float]:
|
||||
"""Return a confidence in [0, 1] on match, or None if any field
|
||||
rejects the observation.
|
||||
|
||||
Soft-field semantics: ``df`` and ``total_len`` are treated as
|
||||
"skip check when observation is missing" — the sniffer doesn't
|
||||
currently emit either, and a literal-constraint sig shouldn't
|
||||
reject a match solely because the observation is upstream-
|
||||
incomplete. Hard fields (``window``, ``ttl``, ``options_sig``,
|
||||
``quirks``) still hard-reject on absent or mismatched input —
|
||||
those are the real discriminators."""
|
||||
mss = obs.get("mss")
|
||||
# Window (hard)
|
||||
if not self.wss.matches(obs.get("window"), mss):
|
||||
return None
|
||||
# TTL — initial-TTL bucket must match exactly. The profiler is
|
||||
# expected to have rounded the observed TTL up to the nearest
|
||||
# bucket already via decnet.sniffer.p0f.initial_ttl. (hard)
|
||||
obs_ttl = obs.get("ttl")
|
||||
if obs_ttl is None or obs_ttl != self.ttl:
|
||||
return None
|
||||
# DF (soft — skip when unknown)
|
||||
if self.df is not None:
|
||||
obs_df = obs.get("df")
|
||||
if obs_df is not None and bool(obs_df) != self.df:
|
||||
return None
|
||||
# Total length (soft — skip when unknown)
|
||||
obs_total = obs.get("total_len")
|
||||
if obs_total is not None and not self.total_len.matches(obs_total):
|
||||
return None
|
||||
# Options (hard)
|
||||
if not _options_match(self.options, obs.get("options_sig")):
|
||||
return None
|
||||
# Quirks — must match as a set. (hard)
|
||||
obs_quirks = obs.get("quirks") or frozenset()
|
||||
if not isinstance(obs_quirks, frozenset):
|
||||
obs_quirks = frozenset(obs_quirks)
|
||||
if self.quirks != obs_quirks:
|
||||
return None
|
||||
# All fields matched — return the precomputed specificity.
|
||||
return self.specificity
|
||||
|
||||
|
||||
def _options_match(sig_opts: tuple[OptionToken, ...], obs_sig: Optional[str]) -> bool:
|
||||
"""Match signature option sequence against observation's comma/space-
|
||||
separated option string."""
|
||||
obs_tokens = _parse_observation_options(obs_sig)
|
||||
# Special case: signature is '.' (no-options sentinel).
|
||||
if len(sig_opts) == 1 and sig_opts[0].kind == ".":
|
||||
return len(obs_tokens) == 0
|
||||
if len(sig_opts) != len(obs_tokens):
|
||||
return False
|
||||
return all(s.matches_literal(o) for s, o in zip(sig_opts, obs_tokens))
|
||||
|
||||
|
||||
_OBS_TOKEN_RE = re.compile(r"^([A-Z\?])(\d+)?$")
|
||||
|
||||
|
||||
def _parse_observation_options(opts_sig: Optional[str]) -> list[OptionToken]:
|
||||
"""Convert the observation-side options string (from
|
||||
tcp_syn_fingerprint / tcpfp_fingerprint SD fields) into a list of
|
||||
literal OptionTokens. Accepts comma or space delimiters and tokens
|
||||
like 'M1460', 'W7', 'T', 'T0', 'N', 'E', '?47'.
|
||||
"""
|
||||
if not opts_sig:
|
||||
return []
|
||||
normalized = opts_sig.replace(",", " ")
|
||||
out: list[OptionToken] = []
|
||||
for raw in normalized.split():
|
||||
token = raw.strip()
|
||||
if not token:
|
||||
continue
|
||||
if token == "T0": # nosec B105 — TCP option name ("Timestamp zero"), not a credential
|
||||
out.append(OptionToken("T0"))
|
||||
continue
|
||||
m = _OBS_TOKEN_RE.match(token)
|
||||
if not m:
|
||||
# Unknown token — represent as opaque "?" with no value so
|
||||
# nothing matches it. Better than raising.
|
||||
out.append(OptionToken("?", IntSpec("literal", -1)))
|
||||
continue
|
||||
kind, num = m.group(1), m.group(2)
|
||||
if num is None:
|
||||
out.append(OptionToken(kind))
|
||||
else:
|
||||
out.append(OptionToken(kind, IntSpec("literal", int(num))))
|
||||
return out
|
||||
|
||||
|
||||
def precompute_specificity(sig: Signature) -> float:
|
||||
"""Crude specificity score used when comparing matching signatures.
|
||||
|
||||
Each field contributes a weight; wildcards and modulo predicates
|
||||
contribute less. Tuned so a fully-literal signature scores ~1.0 and
|
||||
a near-wildcard signature scores ~0.1.
|
||||
"""
|
||||
w = 0.0
|
||||
total = 0.0
|
||||
# Window (weight 3 — very discriminating)
|
||||
total += 3
|
||||
if sig.wss.kind == "literal":
|
||||
w += 3.0
|
||||
elif sig.wss.kind in ("mss_mul", "mtu_mul"):
|
||||
w += 2.5
|
||||
elif sig.wss.kind == "mod":
|
||||
w += 1.5
|
||||
# TTL — always literal, contributes a flat 1
|
||||
total += 1
|
||||
w += 1.0
|
||||
# DF (weight 1)
|
||||
total += 1
|
||||
if sig.df is not None:
|
||||
w += 1.0
|
||||
# Total length (weight 1)
|
||||
total += 1
|
||||
if sig.total_len.kind == "literal":
|
||||
w += 1.0
|
||||
elif sig.total_len.kind == "mod":
|
||||
w += 0.5
|
||||
# Options (weight 3 — highly discriminating when literal)
|
||||
total += 3
|
||||
if not (len(sig.options) == 1 and sig.options[0].kind == "."):
|
||||
literal_opts = sum(
|
||||
1 for o in sig.options
|
||||
if o.value is None or o.value.kind == "literal"
|
||||
)
|
||||
if sig.options:
|
||||
w += 3.0 * (literal_opts / len(sig.options))
|
||||
else:
|
||||
# "no options" is itself a signal.
|
||||
w += 2.0
|
||||
# Quirks (weight 1 — most sigs have no quirks so this is a small edge)
|
||||
total += 1
|
||||
if sig.quirks:
|
||||
w += 1.0
|
||||
return round(w / total, 4)
|
||||
Reference in New Issue
Block a user