IP Resolution Using Meterpreter’s Railgun

Thursday, September 15, 2011

Rob Fuller


I saw a post back in June and just recently it came up again:


It looked like a lot of hard work to set that up and I’m really lazy. I didn’t want to have to go through all that every time I got onto a new network.

So, I made a very simple meterpreter post module to just call a Windows API key called ‘gethostbyaddr’ using Railgun.

TL:DR; You can download the post module here: ipresolver.rb

The function ‘gethostbyaddr’ (http://msdn.microsoft.com/en-us/library/ms738521(v=VS.85).aspx) is pretty simple at first glance:

struct hostent* FAR gethostbyaddr(
  __in  const char *addr,
  __in  int len,
  __in  int type

Give it an address, length and type and it gives you a hostname back… easy right?

Defining it, since it isn’t in the Railgun definitions is pretty simple:

client.railgun.add_function('ws2_32', 'gethostbyaddr', 'DWORD', [
    ['PCHAR', 'addr', 'in'],


First hurdle is to get your IP into ‘network byte order’. Rex (Metasploit’s API/Library) to the rescue.


The ‘addr_aton’ method does just that:

nbi = Rex::Socket.addr_aton(‘’)

=> "\xC0\xA8\x01d"

Make the call to the API and done right?

result = client.railgun.ws2_32.gethostbyaddr(nbi.to_s, nbi.size,2)

Wrong, what you get back is a pointer to a mess, well lets get the mess (using a google IP for this example):

struct = client.railgun.memread(result['return'],100)

=> "\xA0\x03\f\x00\x88\x0E\f\x00\x02\x00\x04\x00\x8C\x0E\f\x00\x00\x00\x00\x00\x94\x0E\f\x00\x00\x00\x00\x00J}]cqw-in-f99.1e100.net\x00@\e\f\x00\x06\x00\b\x00\x13\x01\b\x00\xE0v\v\x00xv\v\x00\xE8\x0E\f\x00\xEE\x96\x03\x00\x00\b\x00\x00 \x01\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"

Ya... that…

I tried using the pointer at the 12th byte location and that worked most of the time, but failed bad on others:

ptrptr = struct[12,4].unpack("V*")[0]
hostnameptr = client.railgun.memread(ptrptr,4).unpack("V*")[0]
hostname = client.railgun.memread(hostnameptr+nbi.size,59).split("\0")[0]

(there were a bunch more lines of error correcting but I’ll just wanted to show these as the actual methods used on a successful run)

But on other hosts the 12th byte came back with a pointer to all 0s, so there was no way to jump again (hostnameptr) to the actual hostname.

What I missed while trying to do things the “C” way was that the hostname was always pretexted with the IP address in network byte order… Hold up, I know it begins with something I already know, and ends in the standard “C” string terminator of a null byte. So all of that plus the crazy error correction became:

struct = client.railgun.memread(result['return'],100)
hostname = struct.split(nbi)[1].split("\0")[0]

2 lines… work 100% of the time in my test cases.

That’s it, you can check out the download for the post module above.

I do however have 1 disadvantage over how the guys at SecurityArtWork did things. You can’t thread it.

For whatever reason the API call that I am using uses the exact same memory space for each lookup. I tried putting threading in and what I got was a bunch of systems that resolved to the exact same thing.

If anyone knows a way to fix this I am all ears because right now the module is slow.

Cross-posted from Room362

Possibly Related Articles:
Information Security
Windows Penetration Testing Metasploit API Meterpreter Railgun
Post Rating I Like this!
Matthijs R. Koot Thanks for that contribution! Fortunately I'm a nerd myself, but a few lines of introductory context would have been nice for non-nerd audience.
Al A I agree with Matthijs, not to mention the Background link is in Spanish.
Rob Fuller Matthijs, Al A. The background link is easily translated using Google Chrome's translate feature, or Google Translate.

Not sure home much more introductory is needed past the title. The post takes you through IP reverse resolution using Metasploit's Meterpreter and it's Railgun functionality.
Matthijs R. Koot @Rob Let's agree to disagree.
The views expressed in this post are the opinions of the Infosec Island member that posted this content. Infosec Island is not responsible for the content or messaging of this post.

Unauthorized reproduction of this article (in part or in whole) is prohibited without the express written permission of Infosec Island and the Infosec Island member that posted this content--this includes using our RSS feed for any purpose other than personal use.