Turning Hostnames into IP addresses

So, it has been a couple of months since I passed the CompTIA Security+ exam and a little over a month since I wrote a blog post about it. I thought it might be time for a new one. I haven’t been able to turn my experience as a system administrator and certifications with Cisco, F5, and AWS into a role in Cybersecurity or Information Security but that doesn’t mean it won’t happen. I’m trying to keep an open mind but in the meantime, I’ve been trying to learn Python. Truth be told, I am trying to learn more than just Python, such as Malware Analysis and Incident Response but learning Python can help me toward my goals. In this post, I’ll talk about my first program with Python and my experience writing it as well as what I think of the language.

Why Python?

As I try to keep my learning to being more security-centric, I see a lot of scripts on Github and other repositories that are written in Python. From reading (a lot of reading) posts and viewing YouTube videos, it appears that the language and IDE are pretty lightweight and fairly easy to learn. There’s a lot of resources out there as well as some books that can help you along the way. Also, I’ll post a few that I have purchased but in the end, performing a simple Google search will be the best resource in my opinion but I love books so buy some books if you like books. I also want to mention that I used Visual Studio Code as my text editor because it has so many integrations and is really easy to use.

Why Hostnames to IP addresses?

From my experience with troubleshooting or just performing some OSINT (Open Source Intelligence) on domains or hosts on your network, sometimes you get a list that you need to look up and it would just take a long time (not to mention boring) to run a nslookup or ping command on each one separately. You really have better things to do with your time. I also had some requirements based on that experience such as having a program that could be used for list of domains or hosts as well as a single domain or host. I also wanted to be able to write the output to a file with a timestamp that allowed you to run it multiple times in a given day without having to delete or rename the previous file. The most important requirement was to have ASCII art and colors because let’s be honest, that’s what other programmers really want to see. Code is code but if you can have some really nice ASCII art or some nice colored output, you’re on your way to being…what is it again? 1337? 31337? L33t? Something to that effect.

The Program

So there are two scripts that were written to accomplish my goal. The first was a menu-based program, called hostnames-to-ipaddresses.py. This one was my first experience with Python and really wasn’t too bad to write. I had to first learn the syntax for concepts like functions as well as conditional statements like if…then…else. Functions and conditions aren’t written much different than other languages but they still have own syntax. Here is an example of a function:

def single_input():
    single_domain = input("\nPlease enter your domain: ")
    print("\nLooking up", single_domain, "...\n")
    time.sleep(1)

    try:
        ip_address = socket.gethostbyname_ex(single_domain)
        print("The IP for", single_domain, "is", ip_address, "\n")
    except socket.gaierror:
        print("Your domain does not exist.")

As you can see with the code above, the function is set with a colon and inputs can be passed through as usual but the rest of the code is pretty standard and easy to figure out. That is just one example of how Python (at least for me) was easy to understand or at least figure out as I looked at blog posts, videos, and error messages.

With the rest of the program, I was knew that I needed a couple of options, single input and file input. As I mentioned previously, I wanted to use the same program regardless of looking up a single domain/host or a file with a list of domains/hosts. I also make the decision that I don’t need to output to a file if I am looking up a single domain/host. This made the single input function much easier to write than the file version. You can see the above code and see how it’s just asking the user for the domain and printing the output.

Getting the IP address from a Hostname

Let’s talk about the actual module being used for translating a hostname into an IP address, Socket. The Socket module contains a couple of functions that can be used to perform this action. I initially used gethostbyname, but that gave me a false sense of accomplishment. This function is a little misleading unless you read the documentation because it will only return one IP address even if there are multiple IP addresses assigned to that domain name. This is where gethostbyname_ex is the better option for what I was wanting in my output.

ip_address = socket.gethostbyname_ex(single_domain)

Reading and Writing a File

For the next requirement, I needed to be able to build a function to read in and write out to a file. This is a little more complicated than just using a built-in function from an imported module. Reading in a file means that there are more than just one line to input so in addition to figuring out the syntax in Python to read a file but I also needed to be able to loop through the file to produce the expected output. You can read this link but here is what it looks like:

with open(filename, "r") as ins:

As you can probably tell, I’m telling Python to open the file in the variable “filename” and telling it to read it with the “r” argument. So it’s really that simple but there are so many different types of files that can be read such as binary but for my purpose, it could be a simple TXT or CSV file.

Writing to a file isn’t much different as you can see below. I just decided to put the action into a variable that I could call later within the For Loop. It was pretty straight forward and I was even feeling extra generous and put a comment for the strip function. I really did it for myself because I will likely look back on this and without any comments, I’ll probably think I am a little crazy and losing my mind.

outF = open(file_out, "w")
            for line in ins:
                
                try:
                    ip_address = socket.gethostbyname_ex(line.strip()) # strip() will strip any trailing or leading blank spaces
                    print("The IP for", line, "is", ip_address, "\n")
                    outF.write(str(ip_address))
                    outF.write("\n")
                except socket.gaierror:
                    print("Domain does not exist.")

Adding Datetime to a Filename

The ability to add a timestamp to a file name is pretty common. For my purpose, I wanted to be able to run the program multiple times per day without having to delete the file to avoid errors. I accomplished this using two variables. I’m sure there are better ways and likely can be done in a one-liner but for beginners, it might be easier to break the process down in multiple steps and as you become more comfortable, combining lines will make more sense. In the below code, I used the strftime function from the time module to set a timestamp and then added that to the file name within the file_out variable. I’ve used this type of way for adding timestamps in T-SQL scripts so it made sense for me.

date = time.strftime("%Y%m%d-%H%M%S")
file_out = ("hostnames-to-ipaddress-output-" + date + ".txt")

The Real Reason to Write in Python – ASCII Art!

The real reason why we write Python. I’ve always seen this done in scripts and thought it was a colorful way to put your mark on it. For this, I used Pyfiglet which is a nice module for this purpose. It’s really easy to use and there are so many different font types you can use too. I haven’t seen it used a lot but it was a nice add to give the script some aesthetics.

ascii_closing_banner = pyfiglet.figlet_format("Smell Ya Later!\n")

Final Thoughts

The rest of the script is really just an IF…ELSE statement that calls the single or file functions based on which option the user chooses via the menu. The entire script is less than 90 lines with some of those consisting of comments. After spending some time googling error messages or learning the syntax, I can safely say that my experience with Python was rather enjoyable. I’m not sure learning C++ again after such a long time would have been as easy but there are so many resources devoted to Python that it made it easy to find resolution to any errors or questions that I had. I would definitely recommend learning Python. I hope this blog post helps anyone trying to learn Python but at the very least, it will help me remember what I was doing with this code.

Honorable Mention – host2ip.py

I was able to trim the number of lines down with the host2ip.py version that uses arguments rather than menu. I wanted to have a simpler version that can be used to type one line and get the output rather than going through menus. It’s really a preference as both work the same way but I did add color to the output of this version so it’s fancy.

References

Python Crash Course by Eric Matthes

Automate the Boring Stuff with Python by Al Sweigart