Reverse DNS script with Regex in Python - regex

I am currently working on a reverse DNS script intended to open a log file, find the IP address, then resolve the IP to DNS. I have a regex set up to identify the IP address in the file, but when I added socket.gethostbyaddr to my script the script ignores my regex and still lists objects in the file that are not IP addresses. I've never used Python before, but this is what I have right now:
import socket
import re
f = open('ipidk.txt' , 'r')
lines = f.readlines()
raw_data = str(f.readlines())
regex = r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})'
foundip = re.findall( regex, raw_data )
for raw_data in lines:
host = raw_data.strip()
try:
dns = socket.gethostbyaddr(host)
print("%s - %s" % (host, dns))
except socket.error as exc:
pass
f.close()

You're calling f.readlines() twice. The first time reads everything in the file, and puts that in lines. The second time has nothing left to read (it starts reading from the current file position, it doesn't rewind to the beginning), so it returns an empty list, and raw_data will just be "[]", with no IPs.
Just call f.read() once, and assign that to raw_data.
Then you need to loop over the IPs found with the regexp, not lines.
import socket
import re
with open('ipidk.txt' , 'r') as f:
raw_data = f.read()
regex = r'(?:\d{1,3}\.){3}\d{1,3}'
foundip = re.findall( regex, raw_data )
for host in foundip:
try:
dns = socket.gethostbyaddr(host)
print("%s - %s" % (host, dns))
except socket.error as exc:
pass

Related

Return Multiple Serial Numbers from Cisco Devices

I am parsing the show version command for a series of information. Maybe there is any easier way, but I am trying to return all the serial numbers for devices in a stack. Currently I am only getting back the active switches serial number. Also I need to search through multiple areas for the serial number. Both Processor Board ID and System Serial Number.
I have tested the following Regex strings on https://regex101.com,
.*?^System\sSerial\sNumber\s
^System Serial Number\s([^,]+)
But in my code they do not seem to be working. When I print my variable it is showing empty for all iterations through the For loop.
#!/usr/bin/python
from getpass import getpass
import netmiko
import re
def make_connection (ip, username, password):
return netmiko.ConnectHandler(device_type='cisco_ios', ip=ip,
username=username, password=password)
def get_ip (input):
return(re.findall(r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', input))
def get_ips (file_name):
#with does all the cleanup and prework of file open for you
with open(file_name, 'r') as in_file:
for line in in_file:
#this is probably supposed to be lineips = get_ip(line)
#line = get_ip(line)
lineips = get_ip(line)
for ip in lineips:
ips.append(ip)
def to_doc_a(file_name, varable):
f=open(file_name, 'a')
f.write(str(varable))
f.write('\n')
f.close()
def to_doc_w(file_name, varable):
f=open(file_name, 'w', newline="\n")
f.write(str(varable))
f.close()
#This will be a list of the devices we want to SSH to
ips = []
#Pull the IPs.txt is a list of the IPs we want to connect to
#This function pulls those IPs out of the txt file and puts them into a
#list
get_ips('IPs.txt')
#list where informations will be stored
#devices = []
#Results string storage
strresults = ""
#Prompt user for account info
username = input("Username: ")
password = getpass()
file_name = "results.csv"
#Clearing all the old info out of the results.csv file
to_doc_w(file_name, "")
#Make a for loop to hit all the devices, for this we will be looking at
#the IOS it’s running
for ip in ips:
#Connect to a device
net_connect = make_connection(ip, username, password)
#Run a command and set that to output
output = net_connect.send_command('show version')
#finding hostname in output using regular expressions
regex_hostname = re.compile(r'(\S+)\suptime')
hostname = regex_hostname.findall(output)
#finding uptime in output using regular expressions
regex_uptime = re.compile(r'\S+\suptime\sis\s(.+)')
uptime = regex_uptime.findall(output)
#finding version in output using regular expressions
regex_version = re.compile(r'Cisco\sIOS\sSoftware.+Version\s([^,]+)')
version = regex_version.findall(output)
#finding serial in output using regular expressions
regex_serial = re.compile(r'Processor\sboard\sID\s(\S+)')
serial = regex_serial.findall(output)
#finding serial in output using regular expressions
regex_serial2 = re.compile(r'^System Serial Number\s([^,]+)')
serial2 = regex_serial2.findall(output)
print(serial2)
#finding ios image in output using regular expressions
#regex_ios = re.compile(r'System\s\image\s\file\sis\s"([^ "]+)')
#ios = regex_ios.findall(output)
#finding model in output using regular expressions
regex_model = re.compile(r'[Cc]isco\s(\S+).*memory.')
model = regex_model.findall(output)
#append results to table [hostname,uptime,version,serial,ios,model]
#devices.append([hostname[0], uptime[0], version[0], serial[0],
#model[0]])
results = (ip, hostname, version, serial, serial2, model)
#Store results for later, reduce calls to append file, greatly i
#ncrease performance
strresults = strresults + str(results) + "\n"
#Next we will append the output to the results file
#to_doc_a(file_name, results)
to_doc_w(file_name, strresults)
No matter what Cisco device I would like this to pull the serial number and if there are multiple devices in a stack return all the serial numbers for devices in the stack. Also it should return IP, hostname, Version of Code and Model.
For the System Serial Number, your pattern ^System Serial Number\s([^,]+) uses an anchor to assert the start of the string, starts with uppercase Serial Number and is missing a colon : after number.
You could update your pattern where (\S+) captures in a group matching 1+ times a non whitespace char. In your pattern you use [^,]+ to match not a comma, but that would also match a space or newline.
System serial number:\s(\S+)
Regex demo | Python demo

How to add a string to a file with the execution of a regular expression?

import re
import logging
x = input("enter number of bad car")
if re.match('/^[A-ZА-Я]{1}[0-9]{3}[A-ZА-Я]{2}([0-9]{0,3})?$/', x):
logging.debug("found match" + x)
with open("some.txt" , 'w') as f:
f.write(x + '\n')
else:
logging.debug("does not match")
However, nothing is written in the file some.txt
I got a logging file which wrote away 'does not match' with the following changes:
import re
import logging
logging.basicConfig(filename = ( "loggingfile.log"), level = logging.DEBUG, format = '%(message)s')
x = input("enter number of bad car")
if re.match('/^[A-ZА-Я]{1}[0-9]{3}[A-ZА-Я]{2}([0-9]{0,3})?$/', x):
logging.debug("found match" + x)
with open("some.txt" , 'w') as f:
needed = str(x + '\n')
logging.info(needed)
else:
logging.info("does not match")
So, I added:
logging.basicConfig, which set some basic configuration stuff
for your logging file (name, path, format...)
I created needed up front, which has all the needed data in it, and then wrote it away to the logging file using logging.info()
I think that that is all that I changed, hope I helped out!
I got output like this from 'logging.log' with input (the random number) 56184615:
does not match
Your regex cannot match. `/^' means a slash, followed by the start of the string. Try to remove the two slashes in the regex.

how to exclude Hosts from IP range from scanning inside nmap python script

would appreciate your advice how to exclude hosts from scanning inside the nm.scan().I have the following script which works perfectly when i enter the range : for example 10.0.0.0/24
import sys
import os
import subprocess
import csv
import nmap # import nmap.py module
try:
nm = nmap.PortScanner() # instantiate nmap.PortScanner object
except nmap.PortScannerError:
print('Nmap not found', sys.exc_info()[0])
sys.exit(0)
except:
print("Unexpected error:", sys.exc_info()[0])
sys.exit(0)
file = raw_input('\nEnter the name of the file where the scan will be saved/add .csv/: ')
ip_range = raw_input('\nEnter the IP range you want to scan/in the following foramt:x.x.x.x/mask: ')
nmap_arguments= raw_input('\nEnter the nmap arguments : ')
nm.scan(hosts=ip_range, arguments= nmap_arguments)
nm.command_line() # get command line used for the scan
nm.scaninfo() # get nmap scan informations {'tcp': {'services': '22-443', 'method'nect'}}
nm.all_hosts() # get all hosts that were scanned
if (len(sys.argv) > 1 and sys.argv[1]):
save_csv_data(nm.csv(), path=sys.argv[1])
else:
save_csv_data(nm.csv())
print "Completed!"
but For example if i want to scan the range but exclude 2 hosts , when i enter :nm.scan(hosts='10.0.0.0/24 --exclude 10.0.0.1, 10.0.0.2, arguments= nmap_arguments) - it excludes only 10.0.0.1 but still scanning 10.0.0.2.So bottom line is how to enter the IP part inside the nmap()
I got it.Needed to put the arguments first:
nm.scan(arguments='-sT --open --exclude X.X.X.X,X.X.X.X',hosts='X.X.X.0/24')

Print 3000 first characters from the file online using sockets

So I am doing this ungraded assignment from an online course (so please do not hesitate to post solutions to this nemesis of mine).
Assignment open the file from the webpage using import socket,prompt the user for the url, print 3000 first characters including header, but count all of the characters in the file.
So first I have done this:
import socket
import re
url = raw_input('Enter - ')
try:
hostname = re.findall('http://(.+?)/', url)
hostname = hostname[0]
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect((hostname, 80))
mysock.send('GET ' + url + ' HTTP/1.0\n\n')
count = 0
text = str()
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
count += len(data)
if count <= 3000:
print data
mysock.close()
except:
print 'Please enter a valid URL'
print count
But every time I adjust the buffer in the mysock.recv() the output changes and I get random spaces inside the text.
Then I've done this which eliminated the funky random splits in lines but the output still differs depending on the buffer inside.
import socket
import re
url = raw_input('Enter - ')
try:
hostname = re.findall('http://(.+?)/', url)
hostname = hostname[0]
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect((hostname, 80))
mysock.send('GET ' + url + ' HTTP/1.0\n\n')
count = 0
text = str()
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
count += len(data)
if count <= 3000:
data.rstrip()
text = text + data
mysock.close()
except:
print 'Please enter a valid URL'
print text
print count
So I've been at it for several hours now and still can't get the exact same output regardless of the size of the buffer without funky line splitting spaces in there.
the file that I use: http://www.py4inf.com/code/romeo-full.txt
I'm studying on same book and i'm on same exercise. Question is 3 years old but don't give af, maybe is helpful for someone.
On first you can't print data in that way. You need something like this:
while True:
data = mysock.recv(512)
if len(data) < 1:
break
print(data.decode(),end='')
Also, it's perfectly normal that you haven't same results if you change the buffer 512 because count variable depends on it. Anyway the author asked just to stop after showing 3000 chars.
My full code (will works only with HTTP, HTTPS not handled):
import socket
import sys
import validators
import urllib.parse
url = input('Insert url to fetch: ')
# Test valid url
try:
valid = validators.url(url)
if valid != True:
raise ValueError
except ValueError:
print('url incorrect')
sys.exit()
# Test socket connection
try:
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('\nSocket successfully created')
except socket.error as err:
print('Socket creation failed with error %s' %(err))
# Extract hostname of url
parsed_url = urllib.parse.urlparse(url)
print('Resolving ->', parsed_url.netloc)
# Test if we can resolve the host
try:
host_ip = socket.gethostbyname(parsed_url.netloc)
except socket.gaierror:
print('Unable to resolve', parsed_url.netloc)
sys.exit()
# Connect to host
mysock.connect((parsed_url.netloc, 80))
# Crafting our command to send
cmd = ('GET ' + url + ' HTTP/1.0\r\n\r\n').encode()
# Sending our command
mysock.send(cmd)
count = 0
# Receive data
while True:
data = mysock.recv(500)
count += len(data)
if len(data) < 1:
break
if count > 3000:
break
print(data.decode(),end='')
mysock.close()
Could be the solution, maybe

Python regex - matching regex in Cisco ASA config

I have the following config from a Cisco ASA:
access-list OUTSIDE extended permit tcp any object O-10.1.2.230 eq 9091
access-list OUTSIDE extended permit tcp any object O-10.1.2.241 eq pptp
I want the result to look like this in a list or CSV format:
rule number, permit/deny, protocol, source IP, source port, des ip, des port.
1, permit, tcp, any, any, 10.1.2.230, 9091
2, permit, tcp, any, any, 10.1.2.241, pptp
for line in open("file.txt"):
if "access-list" in line:
print line.split()
print type(line)
Thanks!
Please check if this is useful.
import csv
import sys
#Open both files and get handles.
config_file = open("out.txt" ,'r')
csv_file = open("result.csv",'w')
#
try:
writer = csv.writer(csv_file)
#Write titles in csv file
csv_head_list = ['rule number', 'permit/deny', 'protocol', 'source IP', 'source port', 'des ip', 'des port']
writer.writerow( csv_head_list )
rule_num = 0
#Read file line by line
for line in config_file.readlines():
line=line.strip()
#Check "access-list" in line
if "access-list" in line:
tmp_list = line.split()
rule_num = rule_num + 1
permit_deny = str(tmp_list[3])
protocol = str(tmp_list[4])
src_ip = src_port = str(tmp_list[5])
des_ip = str(tmp_list[7]).replace("O-",'')
des_port = str(tmp_list[9])
#Write data in csv file
csv_data_list =[rule_num, permit_deny, protocol, src_ip, src_port, des_ip, des_port]
writer.writerow( csv_data_list)
csv_data_list = []
except Exception, e:
print str(e)
finally:
config_file.close()
csv_file.close()