Oct 2013

So you think you can hide from me?

At some point in computing history, someone decided that we should use packet payloads to establish who someone is on UDP. See, TCPIP already does this, sorta, but UDP (generally) just horks one way messages and hopes for the best (kind of like me at staff meetings). Then, one fine day, someone decided UDP should be more industrial strength and less a message horker which is funny ... because UDP was designed to be a message horker and nothing more really. We all learned this the hard way when using UDP to transport NFS... yes you all know what I am talking about and how much fun that can devolve into.

So why do this? Well one reason which could make some sense is to make sure a server doesn't accept messages it doesn't need to; but that could still be done without having to use initial payload modification. Indeed the problem that arises is a service on a port will not even react to any query unless a particular payload is introduced in the first or at least initial packets.

So how do we deal with it? We probe it! Hopefully it hurts a little too.

And then there is Nmap

The problem with the payload issue is simple, system admins cannot do relatively fast network based inventories of what the bloody hell is running on the local wire. Even more fun, conceptually, someone could hide a service on the network. No fear, there is a way to deal with the issue!

The Nmap utility comes with a payload mechanism to look for so called hidden services. The way it works is pretty cool, I would know, I helped redesign it. In the old days (a few years ago) the payloads were binary blobs defined in a source file and built directly into the Nmap executable. At first, this was fine, there weren't that many - perhaps twenty or so that wrapped up to 240 bytes of space or so each. Not really a big deal. Well, it seemed that over time this could become somewhat cumbersome. So we decided to set it up so payloads could be loaded from a file instead. Loading the payloads from file at run time has a few advantages:

  • Executable is smaller
  • Payloads are only loaded if requested (smaller runtime)
  • Easier to test new payloads
  • Easier to add new payloads once tested
  • Mad Scientists can create their own servers and payloads for testing

I never really thought of the last one until I wrote this, but it makes sense. A programmer can use Nmap as a testing vehicle for their own software..... how cool is that?

The Super Cool: Using C++ Maps

This text is not going to go into the mechanics of the STD::Map class in C++ other than a high level this is how it works kind of thing; a later text very well may do a technical example though because frankly it is one of the cooler C++ capabilities out there (and I am not a fan of C++... so that means something!)

If you are familar with anonymous hashes in Perl (another text for this site in the making right there) then this isn't new. Basically we load up a keyed array. There is a key value, in this case proto server-port, the payload data, then a source port defintion at the end. Also, payload data can have line breaks in it. Neat eh? Check out the definition for RPC:

udp 111
  "\x72\xFE\x1D\x13\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA0"
  "\x00\x01\x97\x7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  "\x00\x00\x00\x00\x00\x00\x00\x00"

Or a much more involved example, Amanda backup:

udp 10080
  "Amanda 2.6 REQ HANDLE 000-00000000 SEQ 0\n"
  "SERVICE noop\n"

The short short version is these values are loaded up, then searched using Boolean operations across the map structure. Here is some code that does it:

/* Get a payload appropriate for the given UDP port. For certain selected ports
   a payload is returned, and for others a zero-length payload is returned. The
   length is returned through the length pointer. */
const char *udp_port2payload(u16 dport, size_t *length) {
  static const char *payload_null = "";
  std::map<struct proto_dport, struct payload>::iterator it;
  proto_dport pp(IPPROTO_UDP, dport);

  it = payloads.find(pp);
  if (it != payloads.end()) {
    *length = it->second.data.size();
    return it->second.data.data();
  } else {
    *length = 0;
    return payload_null;
  }
}

Very nice. Waay easier than making a linked list or even using ones own multidimensional array in C where the search routines would have to be written.