1
0
mirror of https://github.com/nmap/nmap.git synced 2026-02-06 21:46:34 +00:00

Change the structure of host.os tables.

Previously they were a flat list intermixing human-readable names and
CPE strings. Now they reflect the structure that we use to represent
them. In brief:

host.os = {
  {
    name = "Microsoft Windows XP",
    classes = {
      {
        vendor = "Microsoft",
        osfamily = "Windows",
        osgen = "XP",
        type = "general purpose",
        cpe = {
          "cpe:/o:microsoft:windows_xp"
        }
      },
      ... more classes ...
    },
  },
  ... more OS matches ...
}
This commit is contained in:
david
2012-03-09 02:32:30 +00:00
parent 426a8f03d2
commit b5a9bca6dc
2 changed files with 126 additions and 26 deletions

View File

@@ -1643,20 +1643,87 @@ LUALIB_API int luaopen_openssl(lua_State *L) {
</term>
<listitem>
<para>
The <literal>os</literal> entry in the host table is
an array of strings. The strings (as many as eight) are the
names of the operating systems the target is possibly
running. Strings are only entered in this array if the
target machine is a perfect match for one or more OS
database entries. If Nmap was run without the
<option>-O</option> option, then
<literal>host.os</literal> is <literal>nil</literal>.
An array of OS match tables. An OS match consists of a
human-readable name and an array of OS classes. Each OS
class consists of a vendor, OS family, OS generation,
device type, and an array of
CPE<indexterm><primary>CPE</primary></indexterm> entries
for the class. (See <xref linkend="osdetect-ref-format"/>
for a description of OS match fields.) Fields may be
<varname>nil</varname> if they are not defined. The
<varname>host.os</varname> table has this overall
structure:
</para>
<programlisting>
host.os = {
{
name = <replaceable>string</replaceable>,
classes = {
{
vendor = <replaceable>string</replaceable>,
osfamily = <replaceable>string</replaceable>,
osgen = <replaceable>string</replaceable>,
type = <replaceable>string</replaceable>,
cpe = {
"cpe:/<replaceable>...</replaceable>",
<optional>More CPE</optional>
}
},
<optional>More classes</optional>
},
},
<optional>More OS matches</optional>
}
</programlisting>
<para>
Additionally the table can contain CPE codes for the detected
operating system. These codes, as described in
<ulink url="http://cpe.mitre.org">the official CPE specification
</ulink> all start with the <literal>cpe:/</literal> prefix.
For example, an OS match on this
<filename>nmap-os-db</filename><indexterm><primary><filename>nmap-os-db</filename></primary></indexterm>
entry:
</para>
<programlisting>
Fingerprint Linux 2.6.32 - 3.2
Class Linux | Linux | 2.6.X | general purpose
CPE cpe:/o:linux:kernel:2.6
Class Linux | Linux | 3.X | general purpose
CPE cpe:/o:linux:kernel:3
</programlisting>
<para>
will result in this <varname>host.os</varname> table:
</para>
<programlisting>
host.os = {
{
name = "Linux 2.6.32 - 3.2",
classes = {
{
vendor = "Linux",
osfamily = "Linux",
osgen = "2.6.X",
type = "general purpose",
cpe = { "cpe:/o:linux:kernel:2.6" }
},
{
vendor = "Linux",
osfamily = "Linux",
osgen = "3.X",
type = "general purpose",
cpe = { "cpe:/o:linux:kernel:3" }
}
},
}
}
</programlisting>
<para>
Only entries corresponding to perfect OS matches are put
in the <varname>host.os</varname> table. If Nmap was run
without the <option>-O</option> option, then
<literal>host.os</literal> is <literal>nil</literal>.
</para>
</listitem>
</varlistentry>

View File

@@ -110,6 +110,49 @@ static void push_bin_ip(lua_State *L, const struct sockaddr_storage *ss)
}
}
static void set_string_or_nil(lua_State *L, const char *fieldname, const char *value) {
if (value != NULL) {
lua_pushstring(L, value);
lua_setfield(L, -2, fieldname);
}
}
static void push_osclass_table(lua_State *L,
const struct OS_Classification *osclass) {
unsigned int i;
lua_newtable(L);
set_string_or_nil(L, "vendor", osclass->OS_Vendor);
set_string_or_nil(L, "osfamily", osclass->OS_Family);
set_string_or_nil(L, "osgen", osclass->OS_Generation);
set_string_or_nil(L, "type", osclass->Device_Type);
lua_newtable(L);
for (i = 0; i < osclass->cpe.size(); i++) {
lua_pushstring(L, osclass->cpe[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "cpe");
}
static void push_osmatch_table(lua_State *L, const FingerMatch *match,
const OS_Classification_Results *OSR) {
int i;
lua_newtable(L);
lua_pushstring(L, match->OS_name);
lua_setfield(L, -2, "name");
lua_newtable(L);
for (i = 0; i < OSR->OSC_num_matches; i++) {
push_osclass_table(L, OSR->OSC[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "classes");
}
/* set host ip, host name and target name onto the
* table which is currently on the stack
* set name of the os run by the host onto the
@@ -191,23 +234,13 @@ void set_hostinfo(lua_State *L, Target *currenths) {
FPR->overall_results == OSSCAN_SUCCESS && FPR->num_perfect_matches > 0 &&
FPR->num_perfect_matches <= 8 )
{
int i, classno;
int i;
const OS_Classification_Results *OSR = FPR->getOSClassification();
lua_newtable(L);
// this will run at least one time and at most 8 times, see if condition
for(i = 0; FPR->accuracy[i] == 1; i++) {
lua_pushstring(L, FPR->matches[i]->OS_name);
lua_rawseti(L, -2, i+1);
}
for (classno = 0; classno < OSR->OSC_num_matches; classno++) {
size_t j;
for (j = 0; j < OSR->OSC[classno]->cpe.size(); j++) {
lua_pushstring(L, OSR->OSC[classno]->cpe[j]);
lua_rawseti(L, -2, ++i);
}
for (i = 0; i < FPR->num_perfect_matches; i++) {
push_osmatch_table(L, FPR->matches[i], OSR);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "os");
}