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:
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user