Whew -- big reorganization to allow ethernet sends of IP packets

This commit is contained in:
fyodor 2005-07-19 05:07:51 +00:00
parent 0595d89f96
commit 555c986ac3
29 changed files with 1963 additions and 1362 deletions

View file

@ -25,21 +25,27 @@ o Chagned the interesting ports array from a 65K-member array of
some cases, and should also give a slight runtime performance
boost. This patch was written by Paul Tarjan (ptarjan(a)gmail.com).
o Integrated a bunch of nmap-service-probes fingerprints from Doug
o Integrated a ton of nmap-service-probes fingerprints from Doug
Hoyte (doug(a)hcsw.org)
o The OS fingerprint is now provided in XML output if debugging is
enabled (-d) or verbosity is at least 2 (-v -v). This patch was
sent by Okan Demirmen (okan(a)demirmen.com)
o Integrated many nmap-service-probes changes from Bo Jiang
(jiangbo(a)brandeis.edu)
o Added a stripped-down version of Dug Song's excellent libdnet
networking library (v. 1.10). This allows Nmap to send raw ethernet
frames for the new ARP ping feature.
o The OS fingerprint is now provided in XML output if debugging is
enabled (-d) or verbosity is at least 2 (-v -v). This patch was
sent by Okan Demirmen (okan(a)demirmen.com)
o Fixed the way tcp connect scan (-sT) respons to ICMP network
unreachable responses (patch by Richard Moore
(rich(a)westpoint.ltd.uk).
o Changed routethrough() to use libdnet rather than all of my custom
code.
o Fixed a crash problem related to non-portable varargs (vsnprintf)
usage. Reports of this crash came from Alan William Somers
(somers(a)its.caltech.edu) and Christophe (chris.branch(a)gmx.de).
@ -94,6 +100,11 @@ o ultra_scan() now sets pseudo-random ACK values (rather than 0) for
o Added a bunch of RPC numbers from nmap-rpc maintainer Eilon Gishri
(eilon(a)aristo.tau.ac.il)
o Added 'leet ASCII art to the confugrator! ARTIST NOTE: If you think
the ASCII art sucks, feel free to send me alternatives. Note that
only people compiling the UNIX source code get this. (ASCII artist
unknown).
o Added a distcc probes and a bunch of smtp matches from Dirk Mueller
(mueller(a)kde.org) to nmap-service-probes. Also added AFS version
probe and matches from Lionel Cons (lionel.cons(a)cern.ch). And
@ -126,11 +137,6 @@ o Changed from CVS to Subversion source control system (which
change users will see is that "Id" tags in file headers use the SVN
format for version numbering and such.
o Added 'leet ASCII art to the confugrator! ARTIST NOTE: If you think
the ASCII art sucks, feel free to send me alternatives. Note that
only people compiling the UNIX source code get this. (ASCII artist
unknown).
Nmap 3.81
o Nmap now ships with and installs (in the same directory as other

View file

@ -1,4 +1,4 @@
export NMAP_VERSION = 3.83
export NMAP_VERSION = 3.83.SOC1
NMAP_NAME= nmap
NMAP_URL= http://www.insecure.org/nmap/
NMAP_PLATFORM=@host@

View file

@ -190,6 +190,7 @@ void NmapOps::Initialize() {
debugging = DEBUGGING;
verbose = DEBUGGING;
randomize_hosts = 0;
sendpref = PACKET_SEND_NOPREF;
spoofsource = 0;
device[0] = '\0';
interactivemode = 0;
@ -328,6 +329,13 @@ void NmapOps::ValidateOptions() {
fatal("Ping scan is not valid with any other scan types (the other ones all include a ping scan");
}
if (sendpref == PACKET_SEND_NOPREF) {
#ifdef WIN32
sendpref = PACKET_SEND_ETH_STRONG;
#else
sendpref = PACKET_SEND_IP_WEAK;
#endif
}
/* We start with stuff users should not do if they are not root */
if (!isr00t) {

View file

@ -122,6 +122,9 @@ class NmapOps {
int TimeSinceStartMS(struct timeval *now=NULL);
struct in_addr v4source();
const struct in_addr *v4sourceip();
bool TCPScan(); /* Returns true if at least one chosen scan type is TCP */
bool UDPScan(); /* Returns true if at least one chosen scan type is UDP */
@ -138,6 +141,26 @@ class NmapOps {
user). */
int isr00t;
int debugging;
#define PACKET_SEND_NOPREF 1
#define PACKET_SEND_ETH_WEAK 2
#define PACKET_SEND_ETH_STRONG 4
#define PACKET_SEND_ETH 6
#define PACKET_SEND_IP_WEAK 8
#define PACKET_SEND_IP_STRONG 16
#define PACKET_SEND_IP 24
/* How should we send raw IP packets? Nmap can generally use either
ethernet or raw ip sockets. Which is better depends on platform
and goals. A _STRONG preference means that Nmap should use the
preferred method whenever it is possible (obviously it isn't
always possible -- sending ethernet frames won't work over a PPP
connection). This is useful when the other type doesn't work at
all. A _WEAK preference means that Nmap may use the other type
where it is substantially more efficient to do so. For example,
Nmap will still do an ARP ping scan of a local network even when
the pref is SEND_IP_WEAK */
int sendpref;
bool packetTrace() { return (debugging >= 3)? true : pTrace; }
bool versionTrace() { return packetTrace()? true : vTrace; }
// Note that packetTrace may turn on at high debug levels even if

View file

@ -119,17 +119,21 @@ void Target::Initialize() {
osscan_performed = 0;
wierd_responses = flags = 0;
memset(&to, 0, sizeof(to));
device[0] = '\0';
memset(&targetsock, 0, sizeof(targetsock));
memset(&sourcesock, 0, sizeof(sourcesock));
targetsocklen = sourcesocklen = 0;
memset(&nexthopsock, 0, sizeof(nexthopsock));
targetsocklen = sourcesocklen = nexthopsocklen = 0;
directly_connected = -1;
targetipstring[0] = '\0';
nameIPBuf = NULL;
memset(&MACaddress, 0, sizeof(MACaddress));
memset(&SrcMACaddress, 0, sizeof(SrcMACaddress));
MACaddress_set = SrcMACaddress_set = false;
memset(&NextHopMACaddress, 0, sizeof(NextHopMACaddress));
MACaddress_set = SrcMACaddress_set = NextHopMACaddress_set = false;
htn.msecs_used = 0;
htn.toclock_running = false;
interface_type = devt_other;
devname[0] = devfullname[0] = '\0';
}
void Target::Recycle() {
@ -177,7 +181,8 @@ void Target::GenerateIPString() {
/* Fills a sockaddr_storage with the AF_INET or AF_INET6 address
information of the target. This is a preferred way to get the
address since it is portable for IPv6 hosts. Returns 0 for
success. */
success. ss_len must be provided. It is not examined, but is set
to the size of the sockaddr copied in. */
int Target::TargetSockAddr(struct sockaddr_storage *ss, size_t *ss_len) {
assert(ss);
assert(ss_len);
@ -307,6 +312,41 @@ const char *Target::NameIP() {
return NameIP(nameIPBuf, MAXHOSTNAMELEN + INET6_ADDRSTRLEN);
}
/* Returns the next hop for sending packets to this host. Returns true if
next_hop was filled in. It might be false, for example, if
next_hop has never been set */
bool Target::nextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len) {
if (nexthopsocklen <= 0)
return false;
assert(nexthopsocklen <= sizeof(*next_hop));
if (next_hop)
memcpy(next_hop, &nexthopsock, nexthopsocklen);
if (next_hop_len)
*next_hop_len = nexthopsocklen;
return true;
}
/* If the host is directly connected on a network, set and retrieve
that information here. directlyConnected() will abort if it hasn't
been set yet. */
void Target::setDirectlyConnected(bool connected) {
directly_connected = connected? 1 : 0;
}
bool Target::directlyConnected() {
assert(directly_connected == 0 || directly_connected == 1);
return directly_connected;
}
/* Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
to sockaddr_storage */
void Target::setNextHop(struct sockaddr_storage *next_hop, size_t next_hop_len) {
assert(next_hop_len > 0 && next_hop_len <= sizeof(nexthopsock));
memcpy(&nexthopsock, next_hop, next_hop_len);
nexthopsocklen = next_hop_len;
}
/* Starts the timeout clock for the host running (e.g. you are
beginning a scan). If you do not have the current time handy,
you can pass in NULL. When done, call stopTimeOutClock (it will
@ -360,6 +400,22 @@ int Target::setSrcMACAddress(const u8 *addy) {
return 0;
}
int Target::setNextHopMACAddress(const u8 *addy) {
if (!addy) return 1;
memcpy(NextHopMACaddress, addy, 6);
NextHopMACaddress_set = 1;
return 0;
}
/* Set the device names so that they can be returned by deviceName()
and deviceFullName(). The normal name may not include alias
qualifier, while the full name may include it (e.g. "eth1:1"). If
these are non-null, they will overwrite the stored version */
void Target::setDeviceNames(const char *name, const char *fullname) {
if (name) Strncpy(devname, name, sizeof(devname));
if (fullname) Strncpy(devfullname, fullname, sizeof(devfullname));
}
/* Returns the 6-byte long MAC address, or NULL if none has been set */
const u8 *Target::MACAddress() {
return (MACaddress_set)? MACaddress : NULL;
@ -368,3 +424,7 @@ const u8 *Target::MACAddress() {
const u8 *Target::SrcMACAddress() {
return (SrcMACaddress_set)? SrcMACaddress : NULL;
}
const u8 *Target::NextHopMACAddress() {
return (NextHopMACaddress_set)? NextHopMACaddress : NULL;
}

View file

@ -122,7 +122,8 @@ class Target {
/* Fills a sockaddr_storage with the AF_INET or AF_INET6 address
information of the target. This is a preferred way to get the
address since it is portable for IPv6 hosts. Returns 0 for
success. */
success. ss_len must be provided. It is not examined, but is set
to the size of the sockaddr copied in. */
int TargetSockAddr(struct sockaddr_storage *ss, size_t *ss_len);
/* Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
to sockaddr_storage */
@ -159,6 +160,27 @@ class Target {
/* This next version returns a STATIC buffer -- so no concurrency */
const char *NameIP();
/* If the host is directly connected on a network, set and retrieve
that information here. directlyConnected() will abort if it hasn't
been set yet. */
void setDirectlyConnected(bool connected);
bool directlyConnected();
/* If the host is NOT directly connected, you can set the next hop
value here. It is OK to pass in a sockaddr_in or sockaddr_in6
casted to sockaddr_storage*/
void setNextHop(struct sockaddr_storage *next_hop, size_t next_hop_len);
/* Returns the next hop for sending packets to this host. Returns true if
next_hop was filled in. It might be false, for example, if
next_hop has never been set */
bool nextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len);
/* Sets the interface type to one of:
devt_ethernet, devt_loopback, devt_p2p, devt_other
*/
void setIfType(devtype iftype) { interface_type = iftype; }
/* Returns -1 if it has not yet been set with setIfType() */
devtype ifType() { return interface_type; }
/* Starts the timeout clock for the host running (e.g. you are
beginning a scan). If you do not have the current time handy,
you can pass in NULL. When done, call stopTimeOutClock (it will
@ -177,9 +199,20 @@ class Target {
/* Takes a 6-byte MAC address */
int setMACAddress(const u8 *addy);
int setSrcMACAddress(const u8 *addy);
int setNextHopMACAddress(const u8 *addy); // this should be the target's own MAC if directlyConnected()
/* Returns a pointer to 6-byte MAC address, or NULL if none is set */
const u8 *MACAddress();
const u8 *SrcMACAddress();
const u8 *NextHopMACAddress();
/* Set the device names so that they can be returned by deviceName()
and deviceFullName(). The normal name may not include alias
qualifier, while the full name may include it (e.g. "eth1:1"). If
these are non-null, they will overwrite the stored version */
void setDeviceNames(const char *name, const char *fullname);
const char *deviceName() { return *devname? devname : NULL; }
const char *deviceFullName() { return *devfullname? devfullname : NULL; }
struct seq_info seq;
FingerPrintResults *FPR;
@ -191,26 +224,27 @@ class Target {
int wierd_responses; /* echo responses from other addresses, Ie a network broadcast address */
unsigned int flags; /* HOST_UP, HOST_DOWN, HOST_FIREWALLED, HOST_BROADCAST (instead of HOST_BROADCAST use wierd_responses */
struct timeout_info to;
char device[64]; /* The device we transmit on -- make sure to adjust some str* calls if I ever change this size*/
private:
private:
char *hostname; // Null if unable to resolve or unset
void Initialize();
void FreeInternal(); // Free memory allocated inside this object
// Creates a "presentation" formatted string out of the IPv4/IPv6 address
void GenerateIPString();
struct sockaddr_storage targetsock, sourcesock;
size_t targetsocklen, sourcesocklen;
struct sockaddr_storage targetsock, sourcesock, nexthopsock;
size_t targetsocklen, sourcesocklen, nexthopsocklen;
int directly_connected; // -1 = unset; 0 = no; 1 = yes
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
char targetipstring[INET6_ADDRSTRLEN];
char *nameIPBuf; /* for the NameIP(void) function to return */
u8 MACaddress[6];
bool MACaddress_set;
u8 SrcMACaddress[6];
bool SrcMACaddress_set;
u8 MACaddress[6], SrcMACaddress[6], NextHopMACaddress[6];
bool MACaddress_set, SrcMACaddress_set, NextHopMACaddress_set;
struct host_timeout_nfo htn;
devtype interface_type;
char devname[32], devfullname[32];
};
#endif /* TARGET_H */

View file

@ -177,6 +177,9 @@
<!-- these elements are written by output.c: printosscanoutput() -->
hostname CDATA #IMPLIED
ostype CDATA #IMPLIED
devicetype CDATA #IMPLIED
<!ELEMENT os ( portused* , osclass*, osmatch* ) >
<!ELEMENT portused EMPTY >

View file

@ -1,4 +1,4 @@
Nmap 3.83.DC1 Usage: nmap [Scan Type(s)] [Options] <host or net list>
Nmap 3.83.SOC1 Usage: nmap [Scan Type(s)] [Options] <host or net list>
Some Common Scan Types ('*' options require root privileges)
* -sS TCP SYN stealth port scan (default if privileged (root))
-sT TCP connect() port scan (default for unprivileged users)

View file

@ -149,6 +149,8 @@ struct idle_proxy_info {
initialize_idleproxy) listens for TCP packets from
the probe_port of the proxy box */
int rawsd; /* Socket descriptor for sending probe packets to the proxy */
struct eth_nfo eth; // For when we want to send probes via raw IP instead.
struct eth_nfo *ethptr; // points to eth if filled out, otherwise NULL
};
@ -189,7 +191,7 @@ int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,
gettimeofday(&tv_sent[tries], NULL);
/* Time to send the pr0be!*/
send_tcp_raw(proxy->rawsd, proxy->host.v4sourceip(),
send_tcp_raw(proxy->rawsd, proxy->ethptr, proxy->host.v4sourceip(),
proxy->host.v4hostip(), o.ttl, base_port + tries,
proxy->probe_port,
seq_base + (packet_send_count++ * 500) + 1, ack,
@ -281,7 +283,6 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
char *p, *q;
char *endptr = NULL;
int seq_response_num;
char *dev;
int newipid;
int i;
char filter[512]; /* Libpcap filter string */
@ -297,6 +298,7 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
int distance;
u16 ipids[NUM_IPID_PROBES];
u8 probe_returned[NUM_IPID_PROBES];
struct route_nfo rnfo;
assert(proxy);
assert(proxyName);
@ -330,47 +332,66 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
fatal("Could not resolve idlescan zombie host: %s", name);
}
proxy->host.setTargetSockAddr(&ss, sslen);
/* Lets figure out the appropriate source address to use when sending
the pr0bez */
proxy->host.TargetSockAddr(&ss, &sslen);
if (!route_dst(&ss, &rnfo))
fatal("Unable to find appropriate source address and device interface to use when sending packets to %s", proxyName);
if (o.spoofsource) {
o.SourceSockAddr(&ss, &sslen);
proxy->host.setSourceSockAddr(&ss, sslen);
Strncpy(proxy->host.device, o.device, sizeof(proxy->host.device));
proxy->host.setDeviceNames(o.device, o.device);
} else {
struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
sslen = sizeof(*sin);
memset(sin, 0, sslen);
dev = routethrough(proxy->host.v4hostip(), &(sin->sin_addr));
if (!dev) fatal("Unable to find appropriate source address and device interface to use when sending packets to %s", proxyName);
Strncpy(proxy->host.device, dev, sizeof(proxy->host.device));
sin->sin_family = AF_INET;
#if HAVE_SOCKADDR_SA_LEN
sin->sin_len = sslen;
#endif
proxy->host.setSourceSockAddr((struct sockaddr_storage *) sin, sslen);
proxy->host.setDeviceNames(rnfo.ii.devname, rnfo.ii.devfullname);
proxy->host.setSourceSockAddr(&rnfo.srcaddr, sizeof(rnfo.srcaddr));
}
if (rnfo.direct_connect) {
proxy->host.setDirectlyConnected(true);
} else {
proxy->host.setDirectlyConnected(false);
proxy->host.setNextHop(&rnfo.nexthop,
sizeof(rnfo.nexthop));
}
proxy->host.setIfType(rnfo.ii.device_type);
if (rnfo.ii.device_type == devt_ethernet)
proxy->host.setSrcMACAddress(rnfo.ii.mac);
/* Now lets send some probes to check IPID algorithm ... */
/* First we need a raw socket ... */
if ((proxy->rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
pfatal("socket trobles in get_fingerprint");
unblock_socket(proxy->rawsd);
broadcast_socket(proxy->rawsd);
if ((o.sendpref & PACKET_SEND_ETH) && proxy->host.ifType() == devt_ethernet) {
if (!setTargetNextHopMAC(&proxy->host))
fatal("%s: Failed to determine dst MAC address for Idle proxy",
__FUNCTION__);
memcpy(proxy->eth.srcmac, proxy->host.SrcMACAddress(), 6);
memcpy(proxy->eth.dstmac, proxy->host.NextHopMACAddress(), 6);
proxy->eth.ethsd = eth_open(proxy->host.deviceName());
proxy->rawsd = -1;
proxy->ethptr = &proxy->eth;
} else {
if ((proxy->rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
pfatal("socket trobles in get_fingerprint");
unblock_socket(proxy->rawsd);
broadcast_socket(proxy->rawsd);
#ifndef WIN32
sethdrinclude(proxy->rawsd);
sethdrinclude(proxy->rawsd);
#endif
proxy->eth.ethsd = NULL;
proxy->ethptr = NULL;
}
/* Now for the pcap opening nonsense ... */
/* Note that the snaplen is 152 = 64 byte max IPhdr + 24 byte max link_layer
* header + 64 byte max TCP header. */
proxy->pd = my_pcap_open_live(proxy->host.device, 152, (o.spoofsource)? 1 : 0, 50);
proxy->pd = my_pcap_open_live(proxy->host.deviceName(), 152, (o.spoofsource)? 1 : 0, 50);
p = strdup(proxy->host.targetipstr());
q = strdup(inet_ntoa(proxy->host.v4source()));
snprintf(filter, sizeof(filter), "tcp and src host %s and dst host %s and src port %hu", p, q, proxy->probe_port);
free(p);
free(q);
set_pcap_filter(&(proxy->host), proxy->pd, flt_icmptcp, filter);
set_pcap_filter(proxy->host.deviceName(), proxy->pd, flt_icmptcp, filter);
/* Windows nonsense -- I am not sure why this is needed, but I should
get rid of it at sometime */
@ -391,7 +412,7 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
a response with the exact request for timing purposes. So I
think I'll use TH_SYN, although it is a tough call. */
/* We can't use decoys 'cause that would screw up the IPIDs */
send_tcp_raw(proxy->rawsd, proxy->host.v4sourceip(),
send_tcp_raw(proxy->rawsd, proxy->ethptr, proxy->host.v4sourceip(),
proxy->host.v4hostip(), o.ttl,
o.magic_port + probes_sent + 1, proxy->probe_port,
sequence_base + probes_sent + 1, 0, TH_SYN|TH_ACK,
@ -428,7 +449,6 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
continue;
if (ip->ip_p == IPPROTO_TCP) {
/* readtcppacket((char *) ip, ntohs(ip->ip_len)); */
tcp = ((struct tcphdr *) (((char *) ip) + 4 * ip->ip_hl));
if (ntohs(tcp->th_dport) < (o.magic_port+1) || ntohs(tcp->th_dport) - o.magic_port > NUM_IPID_PROBES || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) {
if (o.debugging > 1) error("Received unexpected response packet from %s during initial ipid zombie testing", inet_ntoa(ip->ip_src));
@ -508,7 +528,8 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
if (first_target) {
for (probes_sent = 0; probes_sent < 4; probes_sent++) {
if (probes_sent) usleep(50000);
send_tcp_raw(proxy->rawsd, first_target, proxy->host.v4hostip(),
send_tcp_raw(proxy->rawsd, proxy->ethptr, first_target,
proxy->host.v4hostip(),
o.ttl, o.magic_port, proxy->probe_port,
sequence_base + probes_sent + 1, 0, TH_SYN|TH_ACK,
ack, NULL, 0, NULL, 0);
@ -634,6 +655,7 @@ int idlescan_countopen2(struct idle_proxy_info *proxy,
int sleeptime;
int lasttry = 0;
int dotry3 = 0;
struct eth_nfo eth;
if (seq == 0) seq = get_random_u32();
@ -643,6 +665,15 @@ int idlescan_countopen2(struct idle_proxy_info *proxy,
if (sent_time) memset(sent_time, 0, sizeof(*sent_time));
if (rcv_time) memset(rcv_time, 0, sizeof(*rcv_time));
if (proxy->rawsd < 0) {
if (!setTargetNextHopMAC(target))
fatal("%s: Failed to determine dst MAC address for Idle proxy",
__FUNCTION__);
memcpy(eth.srcmac, target->SrcMACAddress(), 6);
memcpy(eth.dstmac, target->NextHopMACAddress(), 6);
eth.ethsd = eth_open(target->deviceName());
} else eth.ethsd = NULL;
/* I start by sending out the SYN pr0bez */
for(pr0be = 0; pr0be < numports; pr0be++) {
if (o.scan_delay) enforce_scan_delay(NULL);
@ -652,7 +683,8 @@ int idlescan_countopen2(struct idle_proxy_info *proxy,
but doing it the straightforward way (using the same decoys as
we use in probing the proxy box is risky. I'll have to think
about this more. */
send_tcp_raw(proxy->rawsd, proxy->host.v4hostip(), target->v4hostip(),
send_tcp_raw(proxy->rawsd, eth.ethsd? &eth : NULL, proxy->host.v4hostip(),
target->v4hostip(),
o.ttl, proxy->probe_port, ports[pr0be], seq, 0, TH_SYN, 0,
NULL, 0, o.extra_payload, o.extra_payload_length);
}
@ -739,6 +771,7 @@ int idlescan_countopen2(struct idle_proxy_info *proxy,
if (rcv_time) *rcv_time = latestchange;
}
if (newipid > 0) proxy->latestid = newipid;
if (eth.ethsd) { eth_close(eth.ethsd); eth.ethsd = NULL; }
return openports;
}

View file

@ -91,7 +91,7 @@ AUTOMAKE = ${SHELL} /home/fyodor/nmap/libdnet-stripped/config/missing --run auto
AWK = gawk
CC = gcc
CCDEPMODE = depmode=none
CFLAGS = -g -O2 -Wall
CFLAGS = -g -Wall
CHECKINC =
CHECKLIB =
CPP = gcc -E

View file

@ -96,7 +96,7 @@ AUTOMAKE = ${SHELL} /home/fyodor/nmap/libdnet-stripped/config/missing --run auto
AWK = gawk
CC = gcc
CCDEPMODE = depmode=none
CFLAGS = -g -O2 -Wall
CFLAGS = -g -Wall
CHECKINC =
CHECKLIB =
CPP = gcc -E

View file

@ -119,12 +119,16 @@ intf_t *
intf_open(void)
{
intf_t *intf;
int one = 1;
if ((intf = calloc(1, sizeof(*intf))) != NULL) {
intf->fd = intf->fd6 = -1;
if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return (intf_close(intf));
setsockopt(intf->fd, SOL_SOCKET, SO_BROADCAST,
(const char *) &one, sizeof(one));
#ifdef SIOCGIFNETMASK_IN6
if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
# ifdef EPROTONOSUPPORT
@ -472,6 +476,7 @@ static int
_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
{
struct ifreq *ifr, *lifr;
struct ifreq tmpifr;
struct addr *ap, *lap;
char *p;
@ -492,12 +497,15 @@ _intf_get_aliases(intf_t *intf, struct intf_entry *entry)
if ((p = strchr(ifr->ifr_name, ':')) != NULL)
*p = '\0';
if (strcmp(ifr->ifr_name, entry->intf_name) != 0)
if (strcmp(ifr->ifr_name, entry->intf_name) != 0) {
if (p) *p = ':';
continue;
}
if (p) *p = ':'; /* Fix the name back up */
if (addr_ston(&ifr->ifr_addr, ap) < 0)
continue;
/* XXX */
if (ap->addr_type == ADDR_TYPE_ETH) {
memcpy(&entry->intf_link_addr, ap, sizeof(*ap));
@ -506,6 +514,11 @@ _intf_get_aliases(intf_t *intf, struct intf_entry *entry)
if (ap->addr_ip == entry->intf_addr.addr_ip ||
ap->addr_ip == entry->intf_dst_addr.addr_ip)
continue;
strlcpy(tmpifr.ifr_name, ifr->ifr_name,
sizeof(tmpifr.ifr_name));
if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0)
addr_stob(&tmpifr.ifr_addr, &ap->addr_bits);
}
#ifdef SIOCGIFNETMASK_IN6
else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
@ -547,16 +560,28 @@ intf_get(intf_t *intf, struct intf_entry *entry)
static int
_match_intf_src(const struct intf_entry *entry, void *arg)
{
int matched = 0;
int cnt;
struct intf_entry *save = (struct intf_entry *)arg;
if (entry->intf_addr.addr_type == ADDR_TYPE_IP &&
entry->intf_addr.addr_ip == save->intf_addr.addr_ip) {
/* XXX - truncated result if entry is too small. */
if (save->intf_len < entry->intf_len)
memcpy(save, entry, save->intf_len);
else
memcpy(save, entry, entry->intf_len);
return (1);
if (entry->intf_addr.addr_type == ADDR_TYPE_IP &&
entry->intf_addr.addr_ip == save->intf_addr.addr_ip)
matched = 1;
for (cnt = 0; !matched && cnt < (int) entry->intf_alias_num; cnt++) {
if (entry->intf_alias_addrs[cnt].addr_type != ADDR_TYPE_IP)
continue;
if (entry->intf_alias_addrs[cnt].addr_ip == save->intf_addr.addr_ip)
matched = 1;
}
if (matched) {
/* XXX - truncated result if entry is too small. */
if (save->intf_len < entry->intf_len)
memcpy(save, entry, save->intf_len);
else
memcpy(save, entry, entry->intf_len);
return (1);
}
return (0);
}
@ -678,14 +703,18 @@ intf_loop(intf_t *intf, intf_handler callback, void *arg)
if ((p = strchr(ifr->ifr_name, ':')) != NULL)
*p = '\0';
if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0) {
if (p) *p = ':';
continue;
}
memset(ebuf, 0, sizeof(ebuf));
strlcpy(entry->intf_name, ifr->ifr_name,
sizeof(entry->intf_name));
entry->intf_len = sizeof(ebuf);
/* Repair the alias name back up. */
if (p) *p = ':';
if (_intf_get_noalias(intf, entry) < 0)
return (-1);
if (_intf_get_aliases(intf, entry) < 0)

View file

@ -653,126 +653,7 @@ static void winip_list_interfaces()
}
}
// Find a route to dest. Fill in source, return device
// I will fail this if no raw, so nmap will still work
typedef DWORD (__stdcall *PGBI)(IPAddr, PDWORD);
char *routethrough(const struct in_addr *dest, struct in_addr *source)
{
/*
In theory, GetBestInterface is ideal. But we need
the source address. Even though GetBestInterface
is still the fastest way to get the name,
ipaddr2devname is fast enough. So we use
SIO_ROUTING_INTERFACE_QUERY.
*/
// the raw senders tend to iterate this
// so we cache the results
static DWORD last_dest = 0;
static DWORD last_source;
static char dev[128];
struct sockaddr_in sin_dest, sin_source;
winip_test(0);
if(inited == 3)
{
static int warned = 0;
if(!warned)
printf("routethrough: failing due to lack of any raw support\n");
warned = 1;
}
if(last_dest == dest->s_addr)
{
source->s_addr = last_source;
return dev;
}
ZeroMemory(&sin_dest, sizeof(sin_dest));
sin_dest.sin_family = AF_INET;
sin_dest.sin_addr = *dest;
if(wo.nt4route)
{
MIB_IPFORWARDROW ir;
int ifi;
if(0 != get_best_route(sin_dest.sin_addr.s_addr, &ir))
{
if(o.debugging > 1)
printf("get_best_route failed, so routethrough will fail\n");
return NULL;
}
if(-1 == (ifi = winif2ifi(ir.dwForwardIfIndex)))
fatal("routethrough: got unmappable (new?) interface\n");
if(0 != ifi2ipaddr(ifi, &sin_source.sin_addr))
fatal("routethrough: no IP for device %s\n", ifi2name(ifi));
if(!rawsock_avail && !iftable[ifi].pcapname) return NULL;
strcpy(dev, ifi2name(ifi));
}
else
{
SOCKET s;
DWORD br;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(s == INVALID_SOCKET)
fatal("failed to create socket\n");
if(0 != WSAIoctl(s, SIO_ROUTING_INTERFACE_QUERY,
&sin_dest, sizeof(sin_dest),
&sin_source, sizeof(sin_source), &br, 0, 0))
{
if(o.debugging)
printf("SIO_ROUTING_INTERFACE_QUERY(%s) failed (%d)\n", inet_ntoa(*dest), WSAGetLastError());
closesocket(s);
return NULL;
}
closesocket(s);
}
// localhost scan (fake) support
// this allows localhost, but not 127.0.0.1, scans to seem to work
if(sin_source.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
sin_source.sin_addr.s_addr = dest->s_addr;
if(0 != ipaddr2devname(dev, &sin_source.sin_addr))
{
if(o.debugging)
{
printf("routethrough: %s routes through ", inet_ntoa(*dest));
printf("%s, but inaddr2devname failed\n",
inet_ntoa(sin_source.sin_addr));
}
return 0;
}
if(!rawsock_avail &&
!iftable[ipaddr2ifi(sin_source.sin_addr.s_addr)].pcapname)
return NULL;
last_dest = dest->s_addr;
last_source = sin_source.sin_addr.s_addr;
*source = sin_source.sin_addr;
if(o.debugging > 1)
{
printf("%s will use interface ", inet_ntoa(*(struct in_addr*)&last_dest));
printf("%s\n", inet_ntoa(*(struct in_addr*)&last_source));
}
return dev;
}
// socket and sendto replacements
int win32_sendto(int sd, const char *packet, int len,
@ -816,7 +697,7 @@ void win32_pcap_close(pcap_t *pd)
else rawrecv_close(pd);
}
pcap_t *my_pcap_open_live(char *device, int snaplen, int promisc, int to_ms)
pcap_t *my_pcap_open_live(const char *device, int snaplen, int promisc, int to_ms)
{
int ifi = name2ifi(device);
if(ifi == -1)
@ -856,7 +737,7 @@ void sethdrinclude(int sd)
}
}
void set_pcap_filter(Target *target,
void set_pcap_filter(const char *device,
pcap_t *pd, PFILTERFN filter, char *bpf, ...)
{
va_list ap;
@ -871,7 +752,7 @@ void set_pcap_filter(Target *target,
return;
}
if (pcap_lookupnet(target->device, &localnet, &netmask, err0r) == -1)
if (pcap_lookupnet(device, &localnet, &netmask, err0r) == -1)
; /* fatal("Failed to lookup device subnet/netmask: %s", err0r);*/
va_start(ap, bpf);
@ -884,10 +765,6 @@ void set_pcap_filter(Target *target,
if (o.debugging)
log_write(LOG_STDOUT, "Packet capture filter: %s\n", buf);
/* Due to apparent bug in libpcap */
if (islocalhost(target->v4hostip()))
buf[0] = '\0';
if (pcap_compile(pd, &fcode, buf, 0, netmask) < 0)
fatal("Error compiling our pcap filter: %s\n", pcap_geterr(pd));
if (pcap_setfilter(pd, &fcode) < 0 )

View file

@ -126,7 +126,7 @@ typedef int (*PFILTERFN)(const char *packet, unsigned int len); /* 1 to keep */
// Makes gcc happy
// One wonders why VC doesn't complain...
class Target;
EXTERNC void set_pcap_filter(Target *target, pcap_t *pd, PFILTERFN filter, char *bpf, ...);
EXTERNC void set_pcap_filter(const char *device, pcap_t *pd, PFILTERFN filter, char *bpf, ...);
typedef struct _IPNODE {
@ -173,7 +173,7 @@ EXTERNC int get_best_route(DWORD dest, PMIB_IPFORWARDROW r);
// pcapsend interface
EXTERNC void pcapsend_init();
EXTERNC pcap_t *my_real_pcap_open_live(char *device, int snaplen, int promisc, int to_ms);
EXTERNC pcap_t *my_real_pcap_open_live(const char *device, int snaplen, int promisc, int to_ms);
EXTERNC int pcapsendraw(const char *packet, int len,
struct sockaddr *to, int tolen);

View file

@ -3951,7 +3951,7 @@ PU(Resp=N)
# Brocade Fibre Switch, Firmware 2.6.0
# Cisco Aironet 340 WAP running v 12.03T of the firmware (and VxWorks OS)
Fingerprint Cisco Aironet WAP, Brocade Fibre Switch, or Sun Remote System Console
Class Cisco | vxworks || WAP
Class Cisco | VxWorks || WAP
Class Brocade | embedded || switch
Class Sun | embedded || remote management
TSeq(Class=64K%IPID=I%TS=U)
@ -10791,19 +10791,6 @@ T6(DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
PU(Resp=N)
# Microsoft Windows Longhorn Preview, Version 6.0 Build 4051.idx 02.031001-1340
Fingerprint Microsoft Windows Longhorn Preview
Class Microsoft | Windows | Windows Longhorn | general purpose
TSeq(Class=TR%gcd=<6%IPID=I%TS=100HZ)
T1(DF=Y%W=0%ACK=S++%Flags=AR%Ops=)
T2(Resp=N)
T3(Resp=N)
T4(DF=Y%W=0%ACK=O%Flags=R%Ops=)
T5(DF=Y%W=0%ACK=S++%Flags=AR%Ops=)
T6(DF=Y%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=N)
PU(DF=N%TOS=0%IPLEN=164%RIPTL=148%RID=E%RIPCK=E%UCK=E%ULEN=134%DAT=E)
# Microsoft Windows Server 2003, Enterprise Edition, Build 3790
# Microsoft .NET Enterprise Server RC2 (Version 5.2 build 3718.dnsrv.021114-1947)
Fingerprint Microsoft Windows .NET Enterprise Server RC2 (Version 5.2, build 3718.dnsrv.021114-1947)
@ -12388,6 +12375,19 @@ T6(DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
PU(DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E|F%RIPCK=E%UCK=E%ULEN=134%DAT=E)
# Microsoft Windows Longhorn Preview, Version 6.0 Build 4051.idx 02.031001-1340
Fingerprint Microsoft Windows Longhorn Preview
Class Microsoft | Windows | Windows Longhorn | general purpose
TSeq(Class=TR%gcd=<6%IPID=I%TS=100HZ)
T1(DF=Y%W=0%ACK=S++%Flags=AR%Ops=)
T2(Resp=N)
T3(Resp=N)
T4(DF=Y%W=0%ACK=O%Flags=R%Ops=)
T5(DF=Y%W=0%ACK=S++%Flags=AR%Ops=)
T6(DF=Y%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=N)
PU(DF=N%TOS=0%IPLEN=164%RIPTL=148%RID=E%RIPCK=E%UCK=E%ULEN=134%DAT=E)
# Windows 2000 Pro, Build 2195 SP4
Fingerprint Microsoft Windows 2000 Pro SP4
Class Microsoft | Windows || general purpose

File diff suppressed because it is too large Load diff

15
nmap.cc
View file

@ -275,6 +275,8 @@ int nmap_main(int argc, char *argv[]) {
{"version_trace", no_argument, 0, 0}, /* Display -sV related activity */
{"fuzzy", no_argument, 0, 0}, /* Alias for osscan_guess */
{"data_length", required_argument, 0, 0},
{"send_eth", no_argument, 0, 0},
{"send_ip", no_argument, 0, 0},
{"stylesheet", required_argument, 0, 0},
{"no-stylesheet", no_argument, 0, 0},
{"rH", no_argument, 0, 0},
@ -444,6 +446,10 @@ int nmap_main(int argc, char *argv[]) {
o.extra_payload = (char *) safe_malloc(o.extra_payload_length);
get_random_bytes(o.extra_payload, o.extra_payload_length);
}
} else if (strcmp(long_options[option_index].name, "send_eth") == 0) {
o.sendpref = PACKET_SEND_ETH_STRONG;
} else if (strcmp(long_options[option_index].name, "send_ip") == 0) {
o.sendpref = PACKET_SEND_IP_STRONG;
} else if (strcmp(long_options[option_index].name, "stylesheet") == 0) {
o.setXSLStyleSheet(optarg);
} else if (strcmp(long_options[option_index].name, "no-stylesheet") == 0) {
@ -1085,16 +1091,16 @@ int nmap_main(int argc, char *argv[]) {
}
}
}
if (!*currenths->device)
if (ipaddr2devname( currenths->device, currenths->v4sourceip()) != 0)
fatal("Could not figure out what device to send the packet out on! You might possibly want to try -S (but this is probably a bigger problem). If you are trying to sp00f the source of a SYN/FIN scan with -S <fakeip>, then you must use -e eth0 (or other devicename) to tell us what interface to use.\n");
if (!currenths->deviceName())
fatal("Do not have appropriate device name for target");
/* Groups should generally use the same device as properties
change quite a bit between devices. Plus dealing with a
multi-device group can be a pain programmatically. So if
this Target has a different device the rest, we give it
back. */
if (Targets.size() > 0 && strcmp(Targets[Targets.size() - 1]->device, currenths->device)) {
if (Targets.size() > 0 &&
strcmp(Targets[Targets.size() - 1]->deviceName(), currenths->deviceName())) {
returnhost(hstate);
numhosts_scanned--; numhosts_up--;
break;
@ -1183,6 +1189,7 @@ int nmap_main(int argc, char *argv[]) {
printportoutput(currenths, &currenths->ports);
printmacinfo(currenths);
printosscanoutput(currenths);
printserviceinfooutput(currenths);
}
if (o.debugging)

14
nmap.h
View file

@ -218,15 +218,15 @@ void *realloc();
#include <pwd.h>
#endif
#ifndef NETINET_IN_SYSTEM_H /* why the HELL does OpenBSD not do this? */
#ifndef NETINET_IN_SYSTEM_H /* why does OpenBSD not do this? */
#include <netinet/in_systm.h> /* defines n_long needed for netinet/ip.h */
#define NETINET_IN_SYSTEM_H
#endif
#ifndef NETINET_IP_H /* why the HELL does OpenBSD not do this? */
#ifndef NETINET_IP_H /* why does OpenBSD not do this? */
#include <netinet/ip.h>
#define NETINET_IP_H
#endif
#include <netinet/ip_icmp.h>
// #include <netinet/ip_icmp.h>
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
@ -237,7 +237,7 @@ void *realloc();
#ifndef __FAVOR_BSD
#define __FAVOR_BSD
#endif
#ifndef NETINET_TCP_H /* why the HELL does OpenBSD not do this? */
#ifndef NETINET_TCP_H /* why does OpenBSD not do this? */
#include <netinet/tcp.h> /*#include <netinet/ip_tcp.h>*/
#define NETINET_TCP_H
#endif
@ -314,6 +314,10 @@ void *realloc();
#define MAX_UDP_SCAN_DELAY 1000
#endif
/* Maximum number of extra hostnames, OSs, and devices, we
consider when outputing the extra service info fields */
#define MAX_SERVICE_INFO_FIELDS 5
/* We wait at least 100 ms for a response by default - while that
seems aggressive, waiting too long can cause us to fail to detect
drops until many probes later on extremely low-latency
@ -431,8 +435,6 @@ void printusage(char *name, int rc);
/* print Interactive usage information */
void printinteractiveusage();
/* Scan helper functions */
unsigned long calculate_sleep(struct in_addr target);
int check_ident_port(struct in_addr target);
int ftp_anon_connect(struct ftpinfo *ftp);

View file

@ -108,7 +108,7 @@
extern void CloseLibs(void);
#endif
void fatal(char *fmt, ...) {
void fatal(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
fflush(stdout);
@ -119,7 +119,7 @@ va_end(ap);
exit(1);
}
void error(char *fmt, ...) {
void error(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
fflush(stdout);
@ -130,7 +130,7 @@ va_end(ap);
return;
}
void pfatal(char *err, ...) {
void pfatal(const char *err, ...) {
#ifdef WIN32
int lasterror =0;
char *errstr = NULL;
@ -152,7 +152,7 @@ void pfatal(char *err, ...) {
exit(1);
}
void gh_perror(char *err, ...) {
void gh_perror(const char *err, ...) {
va_list ap;va_start(ap, err);
fflush(stdout);
vfprintf(stderr, err, ap);

View file

@ -126,13 +126,13 @@
#include <unistd.h>
#endif
void fatal(char *fmt, ...)
void fatal(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
void error(char *fmt, ...)
void error(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
void pfatal(char *err, ...)
void pfatal(const char *err, ...)
__attribute__ ((format (printf, 1, 2)));
void gh_perror(char *err, ...)
void gh_perror(const char *err, ...)
__attribute__ ((format (printf, 1, 2)));
#endif /* NMAP_ERROR_H */

View file

@ -162,6 +162,8 @@ int seq_packets_sent = 0;
int seq_response_num; /* response # for sequencing */
double avg_ts_hz = 0.0; /* Avg. amount that timestamps incr. each second */
struct link_header linkhdr;
struct eth_nfo eth;
struct eth_nfo *ethptr; // for passing to send_ functions
if (target->timedOut(NULL))
return NULL;
@ -175,14 +177,24 @@ si->lastboot = 0;
/* Init our fingerprint tests to each be NULL */
memset(FPtests, 0, sizeof(FPtests));
get_random_bytes(&sequence_base, sizeof(unsigned int));
/* Init our raw socket */
if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
pfatal("socket trobles in get_fingerprint");
unblock_socket(rawsd);
broadcast_socket(rawsd);
if ((o.sendpref & PACKET_SEND_ETH) && target->ifType() == devt_ethernet) {
memcpy(eth.srcmac, target->SrcMACAddress(), 6);
memcpy(eth.dstmac, target->NextHopMACAddress(), 6);
eth.ethsd = eth_open(target->deviceName());
rawsd = -1;
ethptr = &eth;
} else {
/* Init our raw socket */
if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
pfatal("socket trobles in get_fingerprint");
unblock_socket(rawsd);
broadcast_socket(rawsd);
#ifndef WIN32
sethdrinclude(rawsd);
sethdrinclude(rawsd);
#endif
ethptr = NULL;
eth.ethsd = NULL;
}
/* Now for the pcap opening nonsense ... */
/* Note that the snaplen is 152 = 64 byte max IPhdr + 24 byte max link_layer
@ -192,7 +204,7 @@ get_random_bytes(&sequence_base, sizeof(unsigned int));
ossofttimeout = MAX(200000, target->to.timeout);
oshardtimeout = MAX(500000, 5 * target->to.timeout);
pd = my_pcap_open_live(target->device, /*650*/ 8192, (o.spoofsource)? 1 : 0, (ossofttimeout + 500)/ 1000);
pd = my_pcap_open_live(target->deviceName(), /*650*/ 8192, (o.spoofsource)? 1 : 0, (ossofttimeout + 500)/ 1000);
if (o.debugging > 1)
log_write(LOG_STDOUT, "Wait time is %dms\n", (ossofttimeout +500)/1000);
@ -202,7 +214,7 @@ if (o.debugging > 1)
snprintf(filter, sizeof(filter), "dst host %s and (icmp or (tcp and src host %s))", inet_ntoa(target->v4source()), target->targetipstr());
set_pcap_filter(target, pd, flt_icmptcp, filter);
set_pcap_filter(target->deviceName(), pd, flt_icmptcp, filter);
target->osscan_performed = 1; /* Let Nmap know that we did try an OS scan */
/* Lets find an open port to use */
@ -241,28 +253,31 @@ if (o.verbose && openport != (unsigned long) -1)
/* Test 1 */
if (!FPtests[1]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port,
openport, sequence_base, 0,TH_ECE|TH_SYN, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port, openport, sequence_base, 0,
TH_ECE|TH_SYN, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
/* Test 2 */
if (!FPtests[2]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port +1,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +1,
openport, sequence_base, 0,0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
/* Test 3 */
if (!FPtests[3]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port +2,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, current_port +2,
openport, sequence_base, 0,TH_SYN|TH_FIN|TH_URG|TH_PUSH, 0,(u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
/* Test 4 */
if (!FPtests[4]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port +3,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +3,
openport, sequence_base, 0,TH_ACK, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
}
@ -270,21 +285,24 @@ if (o.verbose && openport != (unsigned long) -1)
/* Test 5 */
if (!FPtests[5]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port +4,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +4,
closedport, sequence_base, 0,TH_SYN, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
/* Test 6 */
if (!FPtests[6]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port +5,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +5,
closedport, sequence_base, 0,TH_ACK, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
/* Test 7 */
if (!FPtests[7]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl, current_port +6,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +6,
closedport, sequence_base, 0,TH_FIN|TH_PUSH|TH_URG, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
}
@ -370,7 +388,7 @@ if (o.verbose && openport != (unsigned long) -1)
usleep(remaining_us);
}
}
send_tcp_raw_decoys(rawsd, target->v4hostip(), o.ttl,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
o.magic_port + seq_packets_sent + 1,
openport,
sequence_base + seq_packets_sent + 1, 0,
@ -738,7 +756,11 @@ for(i=0; i < 9; i++) {
osscan_timedout:
if (target->timedOut(NULL))
FP = NULL;
close(rawsd);
if (rawsd >= 0)
close(rawsd);
if (ethptr) {
eth_close(ethptr->ethsd);
}
pcap_close(pd);
return FP;
}

157
output.cc
View file

@ -127,6 +127,7 @@ static int getServiceXMLBuf(struct serviceDeductions *sd, char *xmlbuf,
string versionxmlstring;
char rpcbuf[128];
char *xml_product = NULL, *xml_version = NULL, *xml_extrainfo = NULL;
char *xml_hostname = NULL, *xml_ostype = NULL, *xml_devicetype = NULL;
if (xmlbuflen < 1) return -1;
xmlbuf[0] = '\0';
@ -156,6 +157,30 @@ static int getServiceXMLBuf(struct serviceDeductions *sd, char *xmlbuf,
versionxmlstring += '\"';
}
if (sd->hostname) {
xml_hostname = xml_convert(sd->hostname);
versionxmlstring += " hostname=\"";
versionxmlstring += xml_hostname;
free(xml_hostname); xml_hostname = NULL;
versionxmlstring += '\"';
}
if (sd->ostype) {
xml_ostype = xml_convert(sd->ostype);
versionxmlstring += " ostype=\"";
versionxmlstring += xml_ostype;
free(xml_ostype); xml_ostype = NULL;
versionxmlstring += '\"';
}
if (sd->devicetype) {
xml_devicetype = xml_convert(sd->devicetype);
versionxmlstring += " devicetype=\"";
versionxmlstring += xml_devicetype;
free(xml_devicetype); xml_devicetype = NULL;
versionxmlstring += '\"';
}
if (o.rpcscan && sd->rpc_status == RPC_STATUS_GOOD_PROG) {
snprintf(rpcbuf, sizeof(rpcbuf),
" rpcnum=\"%li\" lowver=\"%i\" highver=\"%i\" proto=\"rpc\"",
@ -234,8 +259,7 @@ void printportoutput(Target *currenths, PortList *plist) {
struct protoent *proto;
Port *current;
int numignoredports;
int portno, protocount;
map<u16, Port*> protoarrays[2];
int portno;
char hostname[1200];
int istate = plist->getIgnoredPortState();
numignoredports = plist->state_counts[istate];
@ -318,14 +342,12 @@ void printportoutput(Target *currenths, PortList *plist) {
log_write(LOG_MACHINE,"\t%s: ", (o.ipprotscan)? "Protocols" : "Ports" );
protoarrays[0] = plist->tcp_ports;
protoarrays[1] = plist->udp_ports;
current = NULL;
rowno = 1;
if (o.ipprotscan) {
for (portno = 0; portno < 256; portno++) {
if (!plist->ip_ports[portno]) continue;
current = plist->ip_ports[portno];
if (!plist->ip_prots[portno]) continue;
current = plist->ip_prots[portno];
if (current->state != istate) {
if (!first) log_write(LOG_MACHINE,", ");
else first = 0;
@ -346,10 +368,20 @@ void printportoutput(Target *currenths, PortList *plist) {
}
}
} else {
for(protocount = 0; protocount < 2; protocount++) {
for(map<u16,Port*>::iterator iter = protoarrays[protocount].begin(); iter != protoarrays[protocount].end(); iter++) {
current = (*iter).second;
map<u16,Port*>::iterator tcpIter = plist->tcp_ports.begin();
map<u16,Port*>::iterator udpIter = plist->udp_ports.begin();
while (tcpIter != plist->tcp_ports.end() || udpIter != plist->udp_ports.end()) {
// If the udp iterator is at the end, then we always read from tcp and vica-versa
if (tcpIter != plist->tcp_ports.end() && (udpIter == plist->udp_ports.end() || tcpIter->first <= udpIter->first)) {
current = tcpIter->second;
tcpIter++;
} else {
current = udpIter->second;
udpIter++;
}
if (current->state != istate) {
if (!first) log_write(LOG_MACHINE,", ");
else first = 0;
@ -449,7 +481,7 @@ void printportoutput(Target *currenths, PortList *plist) {
rowno++;
}
}
}
}
/* log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n"); */
if (plist->state_counts[istate] > 0)
@ -1089,7 +1121,7 @@ void printosscanoutput(Target *currenths) {
}
} else { assert(0); }
if (o.debugging || o.verbose > 1) {
if (o.debugging || o.verbose) {
log_write(LOG_XML,"<osfingerprint fingerprint=\"\n%s\" />\n",
mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs,
@ -1159,6 +1191,107 @@ void printosscanoutput(Target *currenths) {
}
}
/* An auxillary function for printserviceinfooutput(). Returns
non-zero if a and b are considered the same hostnames. */
static int hostcmp(const char *a, const char *b) {
return strcasestr(a, b)? 1 : 0;
}
/* Prints the alternate hostname/OS/device information we got from the
* service scan (if it was performed) */
void printserviceinfooutput(Target *currenths) {
Port *p = NULL;
struct serviceDeductions sd;
int i, numhostnames=0, numostypes=0, numdevicetypes=0;
char hostname_tbl[MAX_SERVICE_INFO_FIELDS][MAXHOSTNAMELEN];
char ostype_tbl[MAX_SERVICE_INFO_FIELDS][64];
char devicetype_tbl[MAX_SERVICE_INFO_FIELDS][64];
for (i=0; i<MAX_SERVICE_INFO_FIELDS; i++)
hostname_tbl[i][0] = ostype_tbl[i][0] = devicetype_tbl[i][0] = '\0';
while ((p = currenths->ports.nextPort(p, 0, PORT_OPEN, false))) {
// The following 2 lines (from portlist.h) tell us that we don't
// need to worry about free()ing anything in the serviceDeductions struct.
// pass in an allocated struct serviceDeductions (don't wory about initializing, and
// you don't have to free any internal ptrs.
p->getServiceDeductions(&sd);
if (sd.hostname && !hostcmp(currenths->HostName(), sd.hostname)) {
for (i=0; i<MAX_SERVICE_INFO_FIELDS; i++) {
if (hostname_tbl[i][0] && hostcmp(&hostname_tbl[i][0], sd.hostname))
break;
if (!hostname_tbl[i][0]) {
numhostnames++;
strncpy(&hostname_tbl[i][0], sd.hostname, sizeof(hostname_tbl[i]));
break;
}
}
}
if (sd.ostype) {
for (i=0; i<MAX_SERVICE_INFO_FIELDS; i++) {
if (ostype_tbl[i][0] && !strcmp(&ostype_tbl[i][0], sd.ostype))
break;
if (!ostype_tbl[i][0]) {
numostypes++;
strncpy(&ostype_tbl[i][0], sd.ostype, sizeof(ostype_tbl[i]));
break;
}
}
}
if (sd.devicetype) {
for (i=0; i<MAX_SERVICE_INFO_FIELDS; i++) {
if (devicetype_tbl[i][0] && !strcmp(&devicetype_tbl[i][0], sd.devicetype))
break;
if (!devicetype_tbl[i][0]) {
numdevicetypes++;
strncpy(&devicetype_tbl[i][0], sd.devicetype, sizeof(devicetype_tbl[i]));
break;
}
}
}
}
if (!numhostnames && !numostypes && !numdevicetypes) return;
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, "Service Info:");
if (numhostnames) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, " Host%s: %s", numhostnames==1? "" : "s", &hostname_tbl[0][0]);
for (i=1; i<MAX_SERVICE_INFO_FIELDS; i++)
if (hostname_tbl[i][0])
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, ", %s", &hostname_tbl[i][0]);
}
if (numostypes) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, " OS%s: %s", numostypes==1? "" : "s", &ostype_tbl[0][0]);
for (i=1; i<MAX_SERVICE_INFO_FIELDS; i++)
if (ostype_tbl[i][0])
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, ", %s", &ostype_tbl[i][0]);
}
if (numdevicetypes) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, " Device%s: %s", numdevicetypes==1? "" : "s", &devicetype_tbl[0][0]);
for (i=1; i<MAX_SERVICE_INFO_FIELDS; i++)
if (devicetype_tbl[i][0])
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, ", %s", &devicetype_tbl[i][0]);
}
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, "\n");
}
/* Prints the statistics and other information that goes at the very end
of an Nmap run */
void printfinaloutput(int numhosts_scanned, int numhosts_up,

View file

@ -191,6 +191,10 @@ void write_host_status(Target *currenths, int resolve_all);
if an OS Scan was performed */
void printosscanoutput(Target *currenths);
/* Prints the alternate hostname/OS/device information we got from the
service scan (if it was performed) */
void printserviceinfooutput(Target *currenths);
/* Prints the statistics and other information that goes at the very end
of an Nmap run */
void printfinaloutput(int numhosts_scanned, int numhosts_up,

View file

@ -173,24 +173,6 @@ static void populateFullVersionString(struct serviceDeductions *sd) {
spaceleft -= strlen(sd->extrainfo) + 3;
}
if (sd->hostname && spaceleft >= (strlen(sd->hostname) + 7)) {
strncat(dst, " Host: ", spaceleft);
strncat(dst, sd->hostname, spaceleft);
spaceleft -= strlen(sd->hostname) + 7;
}
if (sd->ostype && spaceleft >= (strlen(sd->ostype) + 5)) {
strncat(dst, " OS: ", spaceleft);
strncat(dst, sd->ostype, spaceleft);
spaceleft -= strlen(sd->ostype) + 5;
}
if (sd->devicetype && spaceleft >= (strlen(sd->devicetype) + 9)) {
strncat(dst, " Device: ", spaceleft);
strncat(dst, sd->devicetype, spaceleft);
spaceleft -= strlen(sd->devicetype) + 9;
}
}
@ -425,18 +407,18 @@ PortList::~PortList() {
for(map<u16,Port*>::iterator iter = tcp_ports.begin(); iter != tcp_ports.end(); iter++)
{
delete (*iter).second;
delete iter->second;
}
for(map<u16,Port*>::iterator iter = udp_ports.begin(); iter != udp_ports.end(); iter++)
{
delete (*iter).second;
delete iter->second;
}
for(map<u16,Port*>::iterator iter = ip_ports.begin(); iter != ip_ports.end(); iter++)
for(map<u16,Port*>::iterator iter = ip_prots.begin(); iter != ip_prots.end(); iter++)
{
delete (*iter).second;
delete iter->second;
}
if (idstr) {
@ -478,10 +460,10 @@ int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
portarray = &udp_ports;
} else if (protocol == IPPROTO_IP) {
assert(portno < 256);
portarray = &ip_ports;
portarray = &ip_prots;
} else fatal("addPort: attempted port insertion with invalid protocol");
if ((*portarray)[portno]) {
if (portarray->find(portno) == portarray->end()) {
/* We must discount our statistics from the old values. Also warn
if a complete duplicate */
current = (*portarray)[portno];
@ -496,8 +478,8 @@ int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
} else
state_counts_ip[current->state]--;
} else {
(*portarray)[portno] = new Port();
current = (*portarray)[portno];
current = new Port();
(*portarray)[portno] = current;
numports++;
current->portno = portno;
}
@ -517,10 +499,13 @@ int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
free(current->owner);
current->owner = strdup(owner);
}
/* printf("\nCurrent Port List\n");
/*
printf("\nCurrent Port List\n");
for(map<u16,Port*>::iterator iter = (*portarray).begin(); iter != (*portarray).end(); iter++)
printf("%d %d\n", (*iter).first, (*iter).second);
printf("(%d %d) ", iter->first, iter->second->portno);
printf("\n");
*/
@ -541,8 +526,8 @@ int PortList::removePort(u16 portno, u8 protocol) {
answer = udp_ports[portno];
udp_ports.erase(portno);
} else if (protocol == IPPROTO_IP) {
answer = ip_ports[portno];
ip_ports.erase(portno);
answer = ip_prots[portno];
ip_prots.erase(portno);
}
if (!answer)
@ -582,7 +567,7 @@ Port *PortList::lookupPort(u16 portno, u8 protocol) {
return udp_ports[portno];
if (protocol == IPPROTO_IP)
return ip_ports[portno];
return ip_prots[portno];
return NULL;
}
@ -620,40 +605,52 @@ int PortList::getIgnoredPortState() {
Port *PortList::nextPort(Port *afterthisport,
u8 allowed_protocol, int allowed_state,
bool allow_portzero) {
/* These two are chosen because they come right "before" port 1/tcp */
unsigned int current_portno = 0;
unsigned int current_proto = IPPROTO_TCP;
unsigned int current_proto = IPPROTO_TCP;
map<u16,Port*>::iterator iter = tcp_ports.begin();
if (afterthisport) {
current_portno = afterthisport->portno;
current_proto = afterthisport->proto; /* (afterthisport->proto == IPPROTO_TCP)? IPPROTO_TCP : IPPROTO_UDP; */
current_portno++; /* Start on the port after the one we were given */
current_proto = afterthisport->proto;
// This will advacne to one after the current
while (iter != tcp_ports.end() && iter->second->portno <= afterthisport->portno) {
iter++;
}
}
if (!allow_portzero && current_portno == 0) current_portno++;
/* if (afterthisport)
printf("Next Port After %d, %d\n", afterthisport->portno, iter->second->portno); fflush(0);
*/
if (!allow_portzero && iter->second->portno == 0) iter++;
/* First we look for TCP ports ... */
if (current_proto == IPPROTO_TCP) {
if ((allowed_protocol == 0 || allowed_protocol == IPPROTO_TCP) &&
current_proto == IPPROTO_TCP)
for(; current_portno < 65536; current_portno++) {
if (tcp_ports[current_portno] &&
(!allowed_state || tcp_ports[current_portno]->state == allowed_state))
return tcp_ports[current_portno];
}
if ((allowed_protocol == 0 || allowed_protocol == IPPROTO_TCP) &&
current_proto == IPPROTO_TCP)
while (iter != tcp_ports.end()) {
if (!allowed_state || iter->second->state == allowed_state) {
//printf("Returning %d\n", iter->second->portno);
return iter->second;
}
iter++;
}
/* Uh-oh. We have tried all tcp ports, lets move to udp */
current_portno = 0;
current_proto = IPPROTO_UDP;
iter = udp_ports.begin();
}
if ((allowed_protocol == 0 || allowed_protocol == IPPROTO_UDP) &&
current_proto == IPPROTO_UDP) {
for(; current_portno < 65536; current_portno++) {
if (udp_ports[current_portno] &&
(!allowed_state || udp_ports[current_portno]->state == allowed_state))
return udp_ports[current_portno];
while (iter != udp_ports.end()) {
if (!allowed_state || iter->second->state == allowed_state) {
//printf("Returning %d\n", iter->second->portno);
return iter->second;
}
iter++;
}
}

View file

@ -187,7 +187,7 @@ class Port {
~Port();
// pass in an allocated struct serviceDeductions (don't wory about initializing, and
// you don't have to free any inernal ptrs. See the serviceDeductions definition for
// you don't have to free any internal ptrs. See the serviceDeductions definition for
// the fields that are populated. Returns 0 if at least a name is available.
int getServiceDeductions(struct serviceDeductions *sd);
@ -279,7 +279,7 @@ class PortList {
Port *lookupPort(u16 portno, u8 protocol);
map < u16, Port* > udp_ports;
map < u16, Port* > tcp_ports;
map < u16, Port* > ip_ports;
map < u16, Port* > ip_prots;
int state_counts[PORT_HIGHEST_STATE]; /* How many ports in list are in each
state */

View file

@ -1061,24 +1061,30 @@ void UltraScanInfo::Init(vector<Target *> &Targets, struct scan_lists *pts, styp
rawsd = -1;
ethsd = NULL;
if ((tcp_scan || udp_scan || prot_scan) && scantype != CONNECT_SCAN) {
/* Initialize a raw socket */
if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
pfatal("socket troubles in UltraScanInfo::Init");
/* We do not wan't to unblock the socket since we want to wait
if kernel send buffers fill up rather than get ENOBUF, and
we won't be receiving on the socket anyway
unblock_socket(rawsd);*/
broadcast_socket(rawsd);
if ((tcp_scan || udp_scan || prot_scan || ping_scan_arp) &&
scantype != CONNECT_SCAN) {
if (ping_scan_arp || ((o.sendpref & PACKET_SEND_ETH) &&
Targets[0]->ifType() == devt_ethernet)) {
/* We'll send ethernet packets with dnet */
ethsd = eth_open(Targets[0]->deviceName());
if (ethsd == NULL)
fatal("dnet: Failed to open device %s", Targets[0]->deviceName());
rawsd = -1;
} else {
/* Initialize a raw socket */
if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
pfatal("socket troubles in UltraScanInfo::Init");
/* We do not wan't to unblock the socket since we want to wait
if kernel send buffers fill up rather than get ENOBUF, and
we won't be receiving on the socket anyway
unblock_socket(rawsd);*/
broadcast_socket(rawsd);
#ifndef WIN32
sethdrinclude(rawsd);
sethdrinclude(rawsd);
#endif
} else if (ping_scan_arp) {
ethsd = eth_open(Targets[0]->device);
if (ethsd == NULL)
fatal("dnet: Failed to open device %s", o.device);
}
ethsd = NULL;
}
}
}
/* Consults with the group stats, and the hstats for every
@ -1918,7 +1924,16 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
u32 ack = 0;
u16 sport;
u16 ipid = get_random_u16();
struct eth_nfo eth;
struct eth_nfo *ethptr = NULL;
if (USI->ethsd) {
memcpy(eth.srcmac, hss->target->SrcMACAddress(), 6);
memcpy(eth.dstmac, hss->target->MACAddress(), 6);
eth.ethsd = USI->ethsd;
eth.devname[0] = '\0';
ethptr = &eth;
}
if (pingseq > 0) {
if (tryno > 0) assert(0); /* tryno + pingseq not currently supported */
sport = o.magic_port_set? o.magic_port : o.magic_port + USI->perf.tryno_cap + pingseq;
@ -1946,7 +1961,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
send_ip_packet(USI->rawsd, packet, packetlen);
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
} else if (USI->udp_scan) {
@ -1959,7 +1974,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
send_ip_packet(USI->rawsd, packet, packetlen);
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
} else if (USI->prot_scan) {
@ -1996,7 +2011,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
send_ip_packet(USI->rawsd, packet, packetlen);
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
@ -2942,7 +2957,7 @@ static void begin_sniffer(UltraScanInfo *USI, vector<Target *> &Targets) {
}
filterlen = 0;
USI->pd = my_pcap_open_live(Targets[0]->device, 100, (o.spoofsource)? 1 : 0, 2);
USI->pd = my_pcap_open_live(Targets[0]->deviceName(), 100, (o.spoofsource)? 1 : 0, 2);
/* Windows nonsense */
flt_srchost = Targets[0]->v4host().s_addr;
flt_dsthost = Targets[0]->v4source().s_addr;
@ -2982,7 +2997,7 @@ static void begin_sniffer(UltraScanInfo *USI, vector<Target *> &Targets) {
filterlen = len;
} else assert(0); /* Other scan types? */
if (o.debugging > 2) printf("Pcap filter: %s\n", pcap_filter);
set_pcap_filter(Targets[0], USI->pd, flt_all, pcap_filter);
set_pcap_filter(Targets[0]->deviceName(), USI->pd, flt_all, pcap_filter);
/* pcap_setnonblock(USI->pd, 1, NULL); */
return;

View file

@ -260,13 +260,14 @@ static void arpping(Target *hostbatch[], int num_hosts,
if (islocal) {
log_write(LOG_STDOUT|LOG_NORMAL,
"ARP ping: Considering %s UP because it is a local IP, despite no MAC address for device %s\n",
hostbatch[targetno]->NameIP(), hostbatch[targetno]->device);
hostbatch[targetno]->NameIP(), hostbatch[targetno]->deviceName());
hostbatch[targetno]->flags &= ~(HOST_DOWN|HOST_FIREWALLED);
hostbatch[targetno]->flags |= HOST_UP;
} else {
log_write(LOG_STDOUT|LOG_NORMAL,
"ARP ping: Considering %s DOWN because no MAC address found for device %s.\n",
hostbatch[targetno]->NameIP(), hostbatch[targetno]->device);
hostbatch[targetno]->NameIP(),
hostbatch[targetno]->deviceName());
hostbatch[targetno]->flags &= ~HOST_FIREWALLED;
hostbatch[targetno]->flags |= HOST_DOWN;
}
@ -294,11 +295,16 @@ void returnhost(HostGroupState *hs) {
Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group,
struct scan_lists *ports, int *pingtype) {
int hidx;
char *device;
int i;
struct sockaddr_storage ss;
size_t sslen;
struct intf_entry *ifentry;
u32 ifbuf[200] ;
struct route_nfo rnfo;
bool arpping_done = false;
ifentry = (struct intf_entry *) ifbuf;
ifentry->intf_len = sizeof(ifbuf); // TODO: May want to use a larger buffer if interface aliases prove important.
if (hs->next_batch_no < hs->current_batch_sz) {
/* Woop! This is easy -- we just pass back the next host struct */
return hs->hostbatch[hs->next_batch_no++];
@ -323,7 +329,7 @@ do {
if (o.spoofsource) {
o.SourceSockAddr(&ss, &sslen);
hs->hostbatch[hidx]->setSourceSockAddr(&ss, sslen);
Strncpy(hs->hostbatch[hidx]->device, o.device, 64);
hs->hostbatch[hidx]->setDeviceNames(o.device, o.device);
} else {
/* We figure out the source IP/device IFF
1) We are r00t AND
@ -336,44 +342,38 @@ do {
|| (*pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS))
#endif // WIN32
)) {
struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
sslen = sizeof(*sin);
sin->sin_family = AF_INET;
#if HAVE_SOCKADDR_SA_LEN
sin->sin_len = sslen;
#endif
device = routethrough(hs->hostbatch[hidx]->v4hostip(),
&(sin->sin_addr));
hs->hostbatch[hidx]->setSourceSockAddr(&ss, sslen);
hs->hostbatch[hidx]->TargetSockAddr(&ss, &sslen);
if (!route_dst(&ss, &rnfo)) {
fatal("%s: failed to determine route to %s", __FUNCTION__, hs->hostbatch[hidx]->NameIP());
}
if (rnfo.direct_connect) {
hs->hostbatch[hidx]->setDirectlyConnected(true);
} else {
hs->hostbatch[hidx]->setDirectlyConnected(false);
hs->hostbatch[hidx]->setNextHop(&rnfo.nexthop,
sizeof(rnfo.nexthop));
}
hs->hostbatch[hidx]->setIfType(rnfo.ii.device_type);
if (rnfo.ii.device_type == devt_ethernet) {
hs->hostbatch[hidx]->setSrcMACAddress(rnfo.ii.mac);
}
hs->hostbatch[hidx]->setSourceSockAddr(&rnfo.srcaddr, sizeof(rnfo.srcaddr));
if (hidx == 0) /* Because later ones can have different src addy and be cut off group */
o.decoys[o.decoyturn] = hs->hostbatch[hidx]->v4source();
if (!device) {
if (*pingtype == PINGTYPE_NONE) {
fatal("Could not determine what interface to route packets through, run again with -e <device>");
} else {
#if WIN32
fatal("Unable to determine what interface to route packets through to %s", hs->hostbatch[hidx]->targetipstr());
#endif
error("WARNING: Could not determine what interface to route packets through to %s, changing ping scantype to ICMP ping only", hs->hostbatch[hidx]->targetipstr());
*pingtype = PINGTYPE_ICMP_PING;
}
} else {
Strncpy(hs->hostbatch[hidx]->device, device, 64);
}
hs->hostbatch[hidx]->setDeviceNames(rnfo.ii.devname, rnfo.ii.devfullname);
// printf("Target %s %s directly connected, goes through local iface %s, which %s ethernet\n", hs->hostbatch[hidx]->NameIP(), hs->hostbatch[hidx]->directlyConnected()? "IS" : "IS NOT", hs->hostbatch[hidx]->deviceName(), (hs->hostbatch[hidx]->ifType() == devt_ethernet)? "IS" : "IS NOT");
}
}
/* If this is an ARP scan, we must determine the device's MAC address */
if (*pingtype & PINGTYPE_ARP) {
setTargetSrcMACAddressFromDevName(hs->hostbatch[hidx]);
}
/* In some cases, we can only allow hosts that use the same device
in a group. */
/* In some cases, we can only allow hosts that use the same
device in a group. Similarly, we don't mix
directly-connected boxes with those that aren't */
if (o.af() == AF_INET && o.isr00t && hidx > 0 &&
*hs->hostbatch[hidx]->device &&
hs->hostbatch[hidx]->deviceName() &&
(hs->hostbatch[hidx]->v4source().s_addr != hs->hostbatch[0]->v4source().s_addr ||
strcmp(hs->hostbatch[0]->device, hs->hostbatch[hidx]->device) != 0)) {
strcmp(hs->hostbatch[0]->deviceName(),
hs->hostbatch[hidx]->deviceName()) != 0)
|| hs->hostbatch[hidx]->directlyConnected() != hs->hostbatch[0]->directlyConnected()) {
/* Cancel everything! This guy must go in the next group and we are
outtof here */
hs->current_expression.return_last_host();
@ -403,23 +403,34 @@ if (hs->randomize) {
hoststructfry(hs->hostbatch, hs->current_batch_sz);
}
/* First I'll do the ARP ping if necessary */
if (*pingtype & PINGTYPE_ARP) {
/* First I'll do the ARP ping if all of the machines in the group are
directly connected over ethernet. I may need the MAC addresses
later anyway. */
if (hs->hostbatch[0]->ifType() == devt_ethernet &&
hs->hostbatch[0]->directlyConnected() &&
o.sendpref != PACKET_SEND_IP_STRONG) {
arpping(hs->hostbatch, hs->current_batch_sz, ports);
}
/* TODO: For efficiency, at some point it might be nice to usually do ARP
ping before mass ping (and so get rid of else below) */
/* Then we do the mass ping (if required - IP-level pings) */
else if ((*pingtype &
(PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS) ) ||
((!o.isr00t || o.af() == AF_INET6 || hs->hostbatch[0]->v4host().s_addr) &&
(*pingtype != PINGTYPE_NONE)))
massping(hs->hostbatch, hs->current_batch_sz, ports, *pingtype);
/* Otherwise -P0 so we just consider every host up */
else for(i=0; i < hs->current_batch_sz; i++) {
initialize_timeout_info(&hs->hostbatch[i]->to);
hs->hostbatch[i]->flags |= HOST_UP; /*hostbatch[i].up = 1;*/
arpping_done = true;
}
if ((o.sendpref & PACKET_SEND_ETH) &&
hs->hostbatch[0]->ifType() == devt_ethernet) {
if (!setTargetNextHopMAC(hs->hostbatch[hidx]))
fatal("%s: Failed to determine dst MAC address for target %s",
__FUNCTION__, hs->hostbatch[hidx]->NameIP());
}
/* TODO: Maybe I should allow real ping scan of directly connected
ethernet hosts? */
/* Then we do the mass ping (if required - IP-level pings) */
if (*pingtype == PINGTYPE_NONE) {
for(i=0; i < hs->current_batch_sz; i++) {
initialize_timeout_info(&hs->hostbatch[i]->to);
hs->hostbatch[i]->flags |= HOST_UP; /*hostbatch[i].up = 1;*/
}
} else if (!arpping_done)
massping(hs->hostbatch, hs->current_batch_sz, ports, *pingtype);
return hs->hostbatch[hs->next_batch_no++];
}
@ -595,7 +606,7 @@ if (ptech.rawicmpscan || ptech.rawtcpscan || ptech.rawudpscan) {
16 bytes of the TCP header
---
= 104 byte snaplen */
pd = my_pcap_open_live(hostbatch[0]->device, 104, o.spoofsource, 20);
pd = my_pcap_open_live(hostbatch[0]->deviceName(), 104, o.spoofsource, 20);
flt_dsthost = hostbatch[0]->v4source().s_addr;
flt_baseport = sportbase;
@ -606,7 +617,7 @@ if (ptech.rawicmpscan || ptech.rawtcpscan || ptech.rawudpscan) {
sportbase , sportbase + 1, sportbase + 2, sportbase + 3,
sportbase + 4);
set_pcap_filter(hostbatch[0], pd, flt_icmptcp_5port, filter);
set_pcap_filter(hostbatch[0]->deviceName(), pd, flt_icmptcp_5port, filter);
}
blockinc = (int) (0.9999 + 8.0 / probes_per_host);
@ -840,7 +851,7 @@ else {
o.decoys[o.decoyturn].s_addr = target->v4source().s_addr;
send_udp_raw_decoys( rawsd, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, seq, o.extra_payload, o.extra_payload_length);
send_udp_raw_decoys( rawsd, NULL, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, seq, o.extra_payload, o.extra_payload_length);
return 0;
@ -864,10 +875,10 @@ else {
o.decoys[o.decoyturn].s_addr = target->v4source().s_addr;
if (pingtype & PINGTYPE_TCP_USE_SYN) {
send_tcp_raw_decoys( rawsd, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, myseq, myack, TH_SYN, 0, NULL, 0, o.extra_payload,
send_tcp_raw_decoys( rawsd, NULL, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, myseq, myack, TH_SYN, 0, NULL, 0, o.extra_payload,
o.extra_payload_length);
} else {
send_tcp_raw_decoys( rawsd, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, myseq, myack, TH_ACK, 0, NULL, 0, o.extra_payload,
send_tcp_raw_decoys( rawsd, NULL, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, myseq, myack, TH_ACK, 0, NULL, 0, o.extra_payload,
o.extra_payload_length);
}
@ -976,7 +987,7 @@ if (ptech.icmpscan) {
fprintf(stderr, "sendto: %s\n", strerror(sock_err));
}
} else {
send_ip_raw( rawsd, &o.decoys[decoy], target->v4hostip(), o.ttl, IPPROTO_ICMP, ping, icmplen);
send_ip_raw( rawsd, NULL, &o.decoys[decoy], target->v4hostip(), o.ttl, IPPROTO_ICMP, ping, icmplen);
}
}

793
tcpip.cc

File diff suppressed because it is too large Load diff

152
tcpip.h
View file

@ -241,12 +241,17 @@ extern "C" {
#include <setjmp.h>
#include <errno.h>
#include <signal.h>
#include <dnet.h>
#include <netinet/ip_icmp.h>
typedef enum { devt_ethernet, devt_loopback, devt_p2p, devt_other } devtype;
#include "nmap_error.h"
#include "utils.h"
#include "nmap.h"
#include "global_structures.h"
#ifndef DEBUGGING
#define DEBUGGING 0
#endif
@ -323,10 +328,46 @@ struct link_header {
u8 header[MAX_LINK_HEADERSZ];
};
/* Relevant (to Nmap) information about an interface */
struct interface_info {
char name[64];
struct in_addr addr;
struct in_addr netmask;
char devname[16];
char devfullname[16]; /* can include alias info, such as eth0:2. */
struct sockaddr_storage addr;
u16 netmask_bits; /* CIDR-style. So 24 means class C (255.255.255.0)*/
devtype device_type; /* devt_ethernet, devt_loopback, devt_p2p, devt_other */
bool device_up; /* True if the device is up (enabled) */
u8 mac[6]; /* Interface MAC address if device_type is devt_ethernet */
};
struct route_nfo {
struct interface_info ii;
/* true if the target is directly connected on the network (no routing
required. */
bool direct_connect;
/* This is the source address that should be used by the packets. It
may be different than ii.addr if you are using localhost interface
to scan the IP of another interface on the machine */
struct sockaddr_storage srcaddr;
/* If direct_connect is 0, this is filled in with the next hop
required to route to the target */
struct sockaddr_storage nexthop;
};
struct sys_route {
struct interface_info *device;
u32 dest;
u32 netmask;
struct in_addr gw; /* gateway - 0 if none */
};
struct eth_nfo {
char srcmac[6];
char dstmac[6];
eth_t *ethsd; // Optional, but improves performance. Set to NULL if unavail
char devname[16]; // Only needed if ethsd is NULL.
};
#ifndef HAVE_STRUCT_IP
@ -522,26 +563,41 @@ int resolve(char *hostname, struct sockaddr_storage *ss, size_t *sslen,
result in ip . returns 0 if hostname cannot
be resolved */
int resolve(char *hostname, struct in_addr *ip);
/* An awesome function to determine what interface a packet to a given
destination should be routed through. It returns NULL if no appropriate
interface is found, oterwise it returns the device name and fills in the
source parameter */
char *routethrough(const struct in_addr * const dest, struct in_addr *source);
/* Takes a destination address (dst) and tries to determine the
source address and interface necessary to route to this address.
If no route is found, false is returned and rnfo is undefined. If
a route is found, true is returned and rnfo is filled in with all
of the routing details */
bool route_dst(const struct sockaddr_storage *const dst, struct route_nfo *rnfo);
/* Determines what interface packets destined to 'dest' should be
routed through. It can also discover the appropriate next hop (if
any) for ethernet routing. If direct_connect is passed in, it will
be set to 1 if dst is directly connected on the ifentry network and
0 if it requires routing. If nexthop_ip is not NULL, and routing
is required, the next hop is filled into nexthop_ip. This function
returns false if no apporpiate interface or route was found and
true if it succeeds. */
bool routethrough(const struct sockaddr_storage * const dest,
struct intf_entry *ifentry,
int *direct_connect, struct sockaddr_storage *nexthop_ip);
unsigned short in_cksum(u16 *ptr,int nbytes);
/* Build and send a raw tcp packet. If TTL is -1, a partially random
(but likely large enough) one is chosen */
int send_tcp_raw( int sd, const struct in_addr *source,
int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
u16 datalen);
int send_udp_raw( int sd, struct in_addr *source, const struct in_addr *victim,
int ttl, u16 sport, u16 dport, u16 ipid, char *data,
u16 datalen);
int send_udp_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
const struct in_addr *victim, int ttl, u16 sport,
u16 dport, u16 ipid, char *data, u16 datalen);
int send_ip_raw( int sd, struct in_addr *source, const struct in_addr *victim,
int ttl, u8 proto, char *data, u16 datalen);
int send_ip_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
const struct in_addr *victim, int ttl, u8 proto,
char *data, u16 datalen);
/* Builds a TCP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
@ -586,26 +642,31 @@ u8 *build_ip_raw(const struct in_addr *source, const struct in_addr *victim,
u32 *packetlen);
/* Send a pre-built IPv4 packet */
int send_ip_packet(int sd, u8 *packet, unsigned int packetlen);
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
unsigned int packetlen);
/* Create and send all fragments of the pre-built packet */
/* mtu = MTU - ipv4_headerlen */
int send_frag_ip_packet(int sd, u8 *packet, unsigned int packetlen, unsigned int mtu);
int send_frag_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
unsigned int packetlen, unsigned int mtu);
/* Decoy versions of the raw packet sending functions ... */
int send_tcp_raw_decoys( int sd, const struct in_addr *victim, int ttl,
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
u16 datalen);
int send_udp_raw_decoys( int sd, const struct in_addr *victim, int ttl,
int send_udp_raw_decoys( int sd, struct eth_nfo *eth,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u16 ipid, char *data,
u16 datalen);
/* Calls pcap_open_live and spits out an error (and quits) if the call fails.
So a valid pcap_t will always be returned. */
pcap_t *my_pcap_open_live(char *device, int snaplen, int promisc, int to_ms);
pcap_t *my_pcap_open_live(const char *device, int snaplen, int promisc,
int to_ms);
// Returns whether the packet receive time value obtaned from libpcap
// (and thus by readip_pcap()) should be considered valid. When
// invalid (Windows and Amiga), readip_pcap returns the time you called it.
@ -633,13 +694,7 @@ struct interface_info *getinterfaces(int *howmany);
/* Check whether an IP address appears to be directly connected to an
interface on the computer (e.g. on the same ethernet network rather
than having to route). Returns 1 if yes, -1 if maybe, 0 if not. */
int IPisDirectlyConnected(struct sockaddr_storage *ss, size_t ss_len);
void sethdrinclude(int sd);
int getsourceip(struct in_addr *src, const struct in_addr * const dst);
/* Get the source IP and interface name that a packet
to dst should be sent to. Interface name is dynamically
assigned and thus should be freed */
char *getsourceif(struct in_addr *src, struct in_addr *dst);
/* Fill buf (up to buflen -- truncate if necessary but always
terminate) with a short representation of the packet stats.
@ -663,13 +718,14 @@ char *getFinalPacketStats(char *buf, int buflen);
int setTargetMACIfAvailable(Target *target, struct link_header *linkhdr,
struct ip *ip, int overwrite);
/* Finds MAC address of target->device and sets into target. Caches
the results so that it will be really quick if you have many targets
that send out with the same device, and you pass them roughly in
order (only caches one). Returns -1 if cannot find the MAC address
(often meaning this is localhost, or some other non-ethernet device.
Returns 0 upon success. */
int setTargetSrcMACAddressFromDevName(Target *target);
/* This function ensures that the next hop MAC address for a target is
filled in. This address is the target's own MAC if it is directly
connected, and the next hop mac otherwise. Returns true if the
address is set when the function ends, false if not. This function
firt checks if it is already set, if not it tries the arp cache,
and if that fails it sends an ARP request itself. This should be called
after an ARP scan if many directly connected machines are involved. */
bool setTargetNextHopMAC(Target *target);
int islocalhost(const struct in_addr * const addr);
int unblock_socket(int sd);
@ -690,6 +746,20 @@ int get_link_offset(char *device);
lnkinfo->header will be filled with the appropriate values. */
char *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec,
struct timeval *rcvdtime, struct link_header *linknfo);
/* A trivial functon that maintains a cache of IP to MAC Address
entries. If the command is ARPCACHE_GEt, this func looks for the
IPv4 address in ss and fills in the 'mac' parameter and returns
true if it is found. Otherwise (not found), the function returns
false. If the command is ARPCACHE_SET, the function adds an entry
with the given ip (ss) and mac address. An existing entry for the
IP ss will be overwritten with the new MAC address. true is always
returned for the set command. */
#define ARPCACHE_GET 1
#define ARPCACHE_SET 2
bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac);
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
descriptor pd. If it receives one, fills in sendermac (must pass
in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care)
@ -700,6 +770,15 @@ char *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec,
int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac, struct in_addr *senderIP,
long to_usec, struct timeval *rcvdtime);
/* Issues an ARP request for the MAC of targetss (which will be placed
in targetmac if obtained) from the source IP (srcip) and source mac
(srcmac) given. "The request is ussued using device dev to the
broadcast MAC address. The transmission is attempted up to 3
times. If none of these elicit a response, false will be returned.
If the mac is determined, true is returned. */
bool doArp(const char *dev, u8 *srcmac, struct sockaddr_storage *srcip,
struct sockaddr_storage *targetip, u8 *targetmac);
#ifndef HAVE_INET_ATON
int inet_aton(register const char *, struct in_addr *);
#endif
@ -737,17 +816,10 @@ void broadcast_socket(int sd);
did). */
int recvtime(int sd, char *buf, int len, int seconds, int *timedout);
/* This attempts to calculate the round trip time (rtt) to a host by timing a
connect() to a port which isn't listening. A better approach is to time a
ping (since it is more likely to get through firewalls (note, this isn't
always true nowadays --fyodor). This is now
implemented in isup() for users who are root. */
unsigned long calculate_sleep(struct in_addr target);
/* Sets a pcap filter function -- makes SOCK_RAW reads easier */
#ifndef WINIP_H
typedef int (*PFILTERFN)(const char *packet, unsigned int len); /* 1 to keep */
void set_pcap_filter(Target *target, pcap_t *pd, PFILTERFN filter, char *bpf, ...);
void set_pcap_filter(const char *device, pcap_t *pd, PFILTERFN filter, char *bpf, ...);
#endif
/* Just accept everything ... TODO: Need a better approach than this flt_