Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-02 22:12 MDT
NSE: Loaded 3 scripts for scanning.
Warning: Unable to open interface vmnet8 -- skipping it.
Warning: Unable to open interface vmnet1 -- skipping it.
Initiating ARP Ping Scan at 22:12
Scanning 192.168.1.8 [1 port]
SENT (0.1100s) ARP who-has 192.168.1.8 tell 192.168.1.104
RCVD (0.2080s) ARP reply 192.168.1.8 is-at 00:0F:3D:53:61:76
Completed ARP Ping Scan at 22:12, 0.10s elapsed (1 total hosts)
NSOCK (0.2130s) UDP connection requested to 64.81.45.2:53 (IOD #1) EID 8
NSOCK (0.2130s) Read request from IOD #1 [64.81.45.2:53] (timeout: -1ms) EID 18
Initiating Parallel DNS resolution of 1 host. at 22:12
NSOCK (0.2130s) Write request for 42 bytes to IOD #1 EID 27 [64.81.45.2:53]: .&...........8.1.168.192.in-addr.arpa.....
NSOCK (0.2130s) nsock_loop() started (timeout=500ms). 3 events pending
NSOCK (0.2130s) Callback: CONNECT SUCCESS for EID 8 [64.81.45.2:53]
NSOCK (0.2130s) Callback: WRITE SUCCESS for EID 27 [64.81.45.2:53]
NSOCK (0.2590s) Callback: READ SUCCESS for EID 18 [64.81.45.2:53] (42 bytes): .&...........8.1.168.192.in-addr.arpa.....
NSOCK (0.2590s) Read request from IOD #1 [64.81.45.2:53] (timeout: -1ms) EID 34
Completed Parallel DNS resolution of 1 host. at 22:12, 0.05s elapsed
Initiating SYN Stealth Scan at 22:12
Scanning 192.168.1.8 [1 port]
SENT (0.2610s) TCP 192.168.1.104:58404 > 192.168.1.8:9100 S ttl=58 id=1881 iplen=11264 seq=1674875636 win=3072 <mss 1460>
RCVD (0.2630s) TCP 192.168.1.8:9100 > 192.168.1.104:58404 SA ttl=64 id=7578 iplen=44 seq=1344657160 win=2920 ack=1674875637 <mss 1460>
Discovered open port 9100/tcp on 192.168.1.8
Completed SYN Stealth Scan at 22:12, 0.01s elapsed (1 total ports)
Initiating Service scan at 22:12
Overriding exclude ports option! Some undesirable ports may be version scanned!
Scanning 1 service on 192.168.1.8
NSOCK (0.3660s) TCP connection requested to 192.168.1.8:9100 (IOD #1) EID 8
NSOCK (0.3660s) nsock_loop() started (no timeout). 1 events pending
NSOCK (0.3690s) Callback: CONNECT SUCCESS for EID 8 [192.168.1.8:9100]
Service scan sending probe NULL to 192.168.1.8:9100 (tcp)
NSOCK (0.3690s) Read request from IOD #1 [192.168.1.8:9100] (timeout: 6000ms) EID 18
NSOCK (6.3680s) Callback: READ TIMEOUT for EID 18 [192.168.1.8:9100]
Service scan sending probe hp-pjl to 192.168.1.8:9100 (tcp)
NSOCK (6.3680s) Write request for 34 bytes to IOD #1 EID 27 [192.168.1.8:9100]: .%-12345X@PJL INFO ID...%-12345X..
NSOCK (6.3680s) Read request from IOD #1 [192.168.1.8:9100] (timeout: 5000ms) EID 34
NSOCK (6.3680s) Callback: WRITE SUCCESS for EID 27 [192.168.1.8:9100]
NSOCK (11.3680s) Callback: READ TIMEOUT for EID 34 [192.168.1.8:9100]
NSOCK (11.3680s) TCP connection requested to 192.168.1.8:9100 (IOD #2) EID 40
NSOCK (11.3740s) Callback: CONNECT ERROR [Connection refused (61)] for EID 40 [192.168.1.8:9100]
Completed Service scan at 22:12, 11.01s elapsed (1 service on 1 host)
NSE: Script scanning 192.168.1.8.
NSE: Script Scanning completed.
Host 192.168.1.8 is up (0.086s latency).
Interesting ports on 192.168.1.8:
PORT STATE SERVICE VERSION
9100/tcp open jetdirect?
MAC Address: 00:0F:3D:53:61:76 (D-Link)
Read data files from: /usr/local/share/nmap
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.48 seconds
Raw packets sent: 2 (86B) | Rcvd: 2 (86B)
OS details: D-Link DP-300U, DP-G310, or Hamlet HPS01UU print server
svn co --username guest --password "" svn://svn.insecure.org/nmap
Subversion doesn't remember which revisions have been merged into a branch, so it's important to keep that information in log messages.
Merging to branch from trunk:
Find out the last time a merge happened (use "Merge" in log messages by convention):
~/nmap-soc07$ svn log | grep -i -B 2 Merge | head -n 3 rXXXX | david | 2007-05-18 11:28:26 -0600 (Fri, 18 May 2007) | 1 line Merge raaaa:bbbb from /nmap.
Note the revision number XXXX. Now find out the current revision number:
~/nmap-soc07$ svn update At revision YYYY.
Note the revision number YYYY; this is the same as HEAD but we need the number for the log message.
Subversion has a bug where if the directory name in the remote repository has the same name as a local file ("nmap"), the merge won't work.
~/nmap-soc07$ rm nmap
Do the merge:
~/nmap-soc07$ svn merge -r XXXX:YYYY svn://svn.insecure.org/nmap
Commit:
~/nmap-soc07$ svn commit -m "Merge rXXXX:YYYY from /nmap."
The next time you merge, the beginning of the range will be YYYY.
The main function is in main.cc. It checks if the environment variable NMAP_ARGS is defined, and if so if copies it into the command line and runs nmap_main using the arg_parse method, then returns. It checks if Nmap was started by a special "interactive name" (fake application names like "bash", "netscape", etc.) and if so starts interactive mode. (This happens after the check for NMAP_ARGS, so if NMAP_ARGS is defined the interactive name check is never performed.) Also --interactive enters interactive mode.
If not in interactive mode, nmap_main is called. Interactive mode is entirely contained within main.cc--may be a good candidate for improvement.
nmap_main (within nmap.cc) is the "real" main. It does real argument parsing using getopt_long. The options get stored in a NmapOps object, defined in NmapOps.h. NmapOps::ValidateOptions checks the options to see if they make sense and generates fatal errors if they don't (like if you're not root and ask to do something that requires root). Then there's a bunch more validation in nmap_main.
The order of command-line arguments can matter. -A, for example, sets the OS detection to the default (2nd gen falling back to 1st gen), no matter the previous value. So nmap -O1 -A uses the 1st gen system while nmap -A -O1 uses the 2nd gen.
nmap_main then runs the scan. It uses ultra_scan for most types, but does its own thing for a few.
Nmap uses its own modified versions of libpcap and libdnet. The changes for each are in the NMAP_MODIFICATIONS file in each relevant directory.
libpcap is an interface for low-level packet capturing.
Nmap's version is patched slightly.
libdnet is an interface to low-level networking code. It allows things like transmitting raw ethernet frames and IP packets.
Nmap's version is stripped of unnecessary features and patched slightly.
This appears to be a utility library.
This is a parallel sockets library. It's really well written and designed, even better than Nmap itself. It supplies an event-and-callback interface for socket operations. nsock.h has the scoop.
It's used only in DNS, NSE, and service detection, because it only deals in plain sockets (most of Nmap's other functions use raw sockets). For example, in the DNS code, nsock connects to a bunch of DNS servers simultaneously and registers a callback (read_evt_handler) for when data is read. The callback parses the DNS reply and modifies data structures as needed.
NSE is the Nmap Scripting Engine. Scripts are written in Lua. Run the default scripts by passing the -sC option to nmap.
The default scripts are installed in $(datadir)/nmap. There aren't all that many of them.
Here is an example script that tests for open SMTP relays.
Each script can have port rules and host rules. Port rules are run against each open port, and host rules are run once per host. The results of actions from port rules are printed beneath the port's line in the output and the output of actions from host rules is printed beneath the output table itself. The documentation is inconsistent on how the rules are named. Port rules are called "port rules," "service rules," and "script rules." You choose which kind of rule is run by assigning a function to either the portrule or hostrule variable. It looks like if both are defined, then it becomes a port rule (init_loadfile in nse_init.cc).
Scripts in the categories "safe" and "intrusive" are run by default. Run nmap --script malware to run the scripts in the "malware" category, for example.
The NSE registry is just a global table shared by all the scripts executing for a target group. It's called nmap.registry.
init_rules in nse_init.cc matches categories, files, and directories. Directories are not searched recursively. nse_init.cc also loads scripts into the Lua state with luaL_loadfile.
Nmap installs several databases in $(datadir)/nmap. These are nmap-mac-prefixes, nmap-os-db, nmap-os-fingerprints, nmap-protocols, nmap-rpc, nmap-service-probes, and nmap-services. These are used for detection of various kinds.
There are two OS detection databases, first and second generation. The database file for the first generation is called nmap-os-fingerprints and for the second generation it's nmap-os-db. The second generation was introduced in version 4.20ALPHA2.
Which system is used depends on the argument to the -O argument. -O uses the second generation first, then falls back to the first. -O 1 and -O 2 use the first or second generation, respectively, exclusively.
The service detection database is in nmap-service-probes. There a port name database in nmap-services (like /etc/services).
The file nmap-protocols has a database of TCP/IP protocols. I think this is like if an IP datagram contains a TCP or UDP segment, etc.
The file nmap-mac-prefixes holds a list of MAC prefixes. Nmap can print out the vendor associated with a MAC address using this database. See MACLookup.cc.
It is also used when generating a random MAC address for raw Ethernet frames (--spoof_mac option). You can give a vendor name and MAC address from that vendor is generated.
The file nmap-rpc is the database for the RPC grinder. When RPC ports are found, it runs to find out what programs are behind them. See nmap_rpc.cc.
Packet creation and sending code is in tcpip.cc. See things like build_tcp_raw and send_tcp_raw. These look to be analogous to libdnet's *_pack_* functions. See the functions Sendto and send_ip_packet for sending code.
There's also readip_pcap, which uses libpcap to read an IP packet. This is used in several places in the sniffing part of a sending/sniffing pair as found in the scan engine, the traceroute engine, and the OS detection.
tcpip.cc also contains code for packet tracing (converting to printable string representations and things like that).
Look up IP_HDRINCL and SOCK_RAW for raw sockets. Also raw(7).
Check out safe_zalloc. Also charpool.cc.
There is a Target class defined in Target.cc and Target.h. It represents a host. Most of the scan results (OS scan, hostname, some others) are stored within instances of this class.
portlist.h and portlist.cc define classes representing ports and lists of ports. They also define the data structure (struct serviceDeductions) representing the service running on a port (from version detection). The Port class has a internal array of Port objects which is itself indexed by another array that maps port numbers to indexes in the port list.
The tabular output that is printed to standard output is created by the NmapOutputTable class in NmapOutputTable.cc.
Directly connected hosts (1 hop) are not traced. There's an explicit check for this in traceroute.cc:
if (t->directlyConnected ())
continue;
I don't know why that is. Commenting it out makes it work the way I would expect.
The check for being directly connected is in route_dst in tcpip.c. It just compares the address against the netmask of the interface used to connect to it.
The method Traceroute::sendTTLProbes sends probes to all the targets, the replies from which are received by Traceroute::readTraceResponses. The distance is estimated to be the difference between the TTL of the reply and the TTL rounded up to 32, 64, 128, or 255 (this rounding is done by get_initial_ttl_guess in osscan2.c). The distance is capped at 48 and can't be less than 1.
There's a lot to the scan engine. See scan engine.
The file containing the second-generation OS scanner is osscan2.cc. The main function is os_scan2, which takes simply a vector of Targets. Okay, os_scan2 just breaks the vector into chunks and passes them to os_scan_2.
HostOsScan, despite its name, is really the global state for the scan against a certain group of targets. It has a pcap descriptor, and raw ethernet and IP handles, like UltraScanInfo. It is created with a pointer to a Target, but that is just to get some Ethernet information out; the HostOsScan is not attached to the Target.
OsScanInfo is basically just a list of incomplete hosts, each represented by a HostOsScanInfo. HostOsScanInfo is a container for fingerprints, fingerprint matches, and completion information for a single host. It also has timing and probe information in the form of a HostOsScanStats.
After each pass, HostOsScanInfo objects are removed from the list of imcomplete hosts as they are matched. Unmatched hosts are removed from the incomplete list (the scan is complete, just inconclusive) and moved into a list called unMatchedHosts. The unmatched and incomplete hosts (if any) are fed into the first-generation OS detection at the end.
os_scan_2 creates a HostOsScan object called HOS, which is reinitialized (HostOsScan::reInitScanSystem) for each round. It then sends all the sequence probes, then all the TCP, UDP, and ICMP probes. The methods doSeqTests and doTUITests rend, receive (using pcap, waiting for at least one second), and interpret packets. endRound then makes some calculations based on the responses.
begin_sniffer is analogous to the function of the same name in scan_engine.cc.
The fingerprint Nmap prints out looks scary, but it's not so bad once you format it a little:
SCAN(V=4.21ALPHA5 D=5/17 OT=21 CT=1 CU=34613 PV=N DS=0 G=Y TM=464D097C
P=i686-pc-linux-gnu)
SEQ(SP=CE GCD=1 ISR=D0 TI=Z II=I TS=8)
OPS(O1=M5B4ST11NW4 O2=M5B4ST11NW4 O3=M5B4NNT11NW4 O4=M5B4ST11NW4
O5=M5B4ST11NW4 O6=M5B4ST11)
WIN(W1=16A0 W2=16A0 W3=16A0 W4=16A0 W5=16A0 W6=16A0)
ECN(R=Y DF=Y T=40 W=16D0 O=M5B4NNSNW4 CC=N Q=)
T1(R=Y DF=Y T=40 S=O A=S+ F=AS RD=0 Q=)
T2(R=N)
T3(R=Y DF=Y T=40 W=16A0 S=O A=S+ F=AS O=M5B4ST11NW4 RD=0 Q=)
T4(R=Y DF=Y T=40 W=0 S=A A=Z F=R O= RD=0 Q=)
T5(R=Y DF=Y T=40 W=0 S=Z A=S+ F=AR O= RD=0 Q=)
T6(R=Y DF=Y T=40 W=0 S=A A=Z F=R O= RD=0 Q=)
T7(R=Y DF=Y T=40 W=0 S=Z A=S+ F=AR O= RD=0 Q=)
U1(R=Y DF=N T=40 TOS=C0 IPL=164 UN=0 RIPL=G RID=G RIPCK=G
RUCK=G RUL=G RUD=G)
IE(R=Y DFI=N T=40 TOSI=S CD=S SI=S DLI=S)
The "probes" are the SEQ, OPS, WIN, etc. (but note that these do not correspond one-to-one with individual packets, except for T[1-7] and U1). The "response tests" are inside the parens: SP, GCD, W, etc.
The codes are explained in the "methods" section of the OS detection paper.
Nmap looks in the file nmap-service-probes, which contains a bunch of Probes and match lines to go with them. Each match line has a regular expression which is the expected output of the probe, and then results for things like product, version, and other info. There are things like soft matches and fallbacks, for which read the paper.
Here's a probe for monchat:
match monchat m|\n\n.*Welcome to monchat!\n\.\n| p/monchat/
Put it in the NULL probe section.
Most error handling is done by the functions in nmap_error.cc. error prints an error message. fatal prints an error message and exits. perror and pfatal are similar but they also print out errno and the corresponding message.