Nmap Development mailing list archives

Re: Scans failing on Win32 - failures differ depending on args len (maybe)


From: David Fifield <david () bamsoftware com>
Date: Wed, 12 Oct 2011 00:16:15 -0700

On Sat, Oct 08, 2011 at 07:38:22PM +0100, jah wrote:
Hello,

The failures I reported stem from the call to GetAdaptersAddresses
from _refresh_tables in libdnet-stripped/src/intf-win32.c

With the args: -F -v -d -n 195.166.128.231, GetAdaptersAddresses
returns ERROR_INVALID_PARAMETER the very first time _refresh_tables
is called:

nmap.exe!_refresh_tables(intf_handle * intf)  Line 216    C
nmap.exe!intf_loop(intf_handle * intf, int (const intf_entry *, void *)* callback, void * arg)  Line 373 + 0x9 bytes  
  C
nmap.exe!getinterfaces_dnet(int * howmany, char * errstr, unsigned int errstrlen)  Line 1312 + 0x12 bytes    C++
nmap.exe!getinterfaces(int * howmany, char * errstr, unsigned int errstrlen)  Line 1335 + 0x12 bytes    C++
nmap.exe!sysroutes_dnet_find_interfaces(dnet_collector_route_nfo * dcrn)  Line 1490 + 0xd bytes    C++
nmap.exe!getsysroutes_dnet(int * howmany, char * errstr, unsigned int errstrlen)  Line 1596 + 0x9 bytes    C++
nmap.exe!getsysroutes(int * howmany, char * errstr, unsigned int errstrlen)  Line 1625 + 0x11 bytes    C++
nmap.exe!route_dst_generic(const sockaddr_storage * dst, route_nfo * rnfo, const char * device, const 
sockaddr_storage * spoofss)  Line 3233 + 0x15 bytes    C++
nmap.exe!route_dst(const sockaddr_storage * dst, route_nfo * rnfo, const char * device, const sockaddr_storage * 
spoofss)  Line 3329 + 0x15 bytes    C++
nmap.exe!nmap_route_dst(const sockaddr_storage * dst, route_nfo * rnfo)  Line 2031 + 0x17 bytes    C++
nmap.exe!nexthost(HostGroupState * hs, const addrset * exclude_group, scan_lists * ports, int pingtype)  Line 359 + 
0x13 bytes    C++
nmap.exe!nmap_main(int argc, char * * argv)  Line 1778 + 0x1e bytes    C++
nmap.exe!main(int argc, char * * argv)  Line 195 + 0xd bytes    C++
nmap.exe!__tmainCRTStartup()  Line 278 + 0x19 bytes    C
nmap.exe!mainCRTStartup()  Line 189    C
kernel32.dll!_BaseProcessStart@4()  + 0x23 bytes   

With the args -F -v -v -d -n 195.166.128.231, GetAdaptersAddresses
returns NO_ERROR the first time _refresh_tables is called and
ERROR_INVALID_PARAMETER the second time _refresh_tables is called:

nmap.exe!_refresh_tables(intf_handle * intf)  Line 216    C
nmap.exe!intf_get_pcap_devname(const char * intf_name, char * pcapdev, int pcapdevlen)  Line 417 + 0x9 bytes    C
nmap.exe!eth_get_pcap_devname(const char * intf_name, char * pcapdev, int pcapdevlen)  Line 117 + 0x11 bytes    C
nmap.exe!eth_open(const char * device)  Line 39 + 0x15 bytes    C
nmap.exe!eth_open_cached(const char * device)  Line 942 + 0x9 bytes    C++
nmap.exe!UltraScanInfo::Init(std::vector<Target *,std::allocator<Target *> > & Targets, scan_lists * pts, stype 
scantp)  Line 1653 + 0x17 bytes    C++
nmap.exe!UltraScanInfo::UltraScanInfo(std::vector<Target *,std::allocator<Target *> > & Targets, scan_lists * pts, 
stype scantype)  Line 607 + 0xa3 bytes    C++
nmap.exe!ultra_scan(std::vector<Target *,std::allocator<Target *> > & Targets, scan_lists * ports, stype scantype, 
timeout_info * to)  Line 5718 + 0x3a bytes    C++
nmap.exe!massping(Target * * hostbatch, int num_hosts, scan_lists * ports)  Line 257 + 0x14 bytes    C++
nmap.exe!nexthost(HostGroupState * hs, const addrset * exclude_group, scan_lists * ports, int pingtype)  Line 465 + 
0x16 bytes    C++
nmap.exe!nmap_main(int argc, char * * argv)  Line 1778 + 0x1e bytes    C++
nmap.exe!main(int argc, char * * argv)  Line 195 + 0xd bytes    C++
nmap.exe!__tmainCRTStartup()  Line 278 + 0x19 bytes    C
nmap.exe!mainCRTStartup()  Line 189    C
kernel32.dll!_BaseProcessStart@4()  + 0x23 bytes

GetAdaptersAddresses is called in a loop, first with a 2 byte buffer
allocation for the adapter addresses and then again, if it returned
ERROR_BUFFER_OVERFLOW, with a larger allocation having the length as
updated by GetAdaptersAddresses.

In each of the two aforementioned cases GetAdaptersAddresses returns
ERROR_INVALID_PARAMETER during the first go round the loop.  In the
latter of the cases, during the first call to _refresh_tables, it
takes two loops to allocate the (assumed) correct buffer size - I've
observed that 2940 bytes is allocated.

According to the msdn docs for GetAdaptersAddresses [1], this method
of determining the buffer size is "Strongly discouraged" (it doesn't
say exactly why, but it does say that the function "requires a
significant amount of network resources and time to complete since all
of the low-level network interface tables must be traversed"). Instead
the docs suggest pre-allocating a 15KB buffer which, "on typical
computers", "dramatically reduces the chances that the
GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW, which
would require calling GetAdaptersAddresses function multiple times".

I read this same documentation and wasn't convinced. Even if you start
with a large buffer, you still have to call in a loop in case it's not
big enough. (I don't find "dramatically reduces" reassuring.) Starting
with a small buffer size ensures that the buffer growing code is
exercised and tested.

David Fifield
_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://seclists.org/nmap-dev/


Current thread: