I am trying to write a simple Python SMTP enumeration script, which reads usernames from a text file (filename supplied as the second argument - sys.argv[2]), and checks them against an SMTP server (hostname or ip supplied as the first argument - sys.argv[1]. I found something that is kind of close, and tweaked it a bit, like so:
#!/usr/bin/python
import socket
import sys
users = sys.argv[2]
for line in users:
line = line.strip()
if line!='':
users.append(line)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], 25))
fn = s.makefile('rwb')
fn.readline()
fn.write('HELO testing.com \r\n')
fn.flush()
fn.readline()
for user in users:
fn.write('VRFY %s\r\n' % user)
fn.flush()
print '%s: %s' % (user, fn.readline().strip())
fn.write('QUIT\r\n')
fn.flush()
s.close()
However, when I run the script (for example):
./smtp-vrfy.py 192.168.1.9 users.txt
It results in an error:
File "./smtp-vrfy.py", line 10, in
users.append(line)
AttributeError: 'str' object has no attribute 'append'
What am I doing wrong? How can I fix it? Perhaps there is an easier way to accomplish what I'm trying to do?
users is a file name, but you're not reading it. Instead, see what happens:
>>> users = "users.txt"
>>> for line in users:
... print(line)
...
u
s
e
r
s
.
t
x
t
You probably want:
with open(users) as f:
for line in f:
# ...
Even better:
filename = sys.argv[2]
with open(filename) as f:
users = [line.strip() for line in f.readlines() if line]
Related
I have to create a program called 'user_generator' that takes a login as an argument and stores this login in the end of an external file called 'logins.db'.
My problem is : when I use the function 'writelines' into 'logins.db', this file returns only the last input data. This is what I've done :
import sys
new_logins = sys.argv[0]
logins = sys.argv[1:]
count = len(logins)
f=open('logins.db','w')
logins=map(lambda x:x+'\n', logins)
f.writelines(logins)
logins = []
with open('logins.db', 'r') as filehandle:
for line in filehandle:
current_login = line[:-1]
logins.append(current_login)
Some people told me to use SQL functions, but I really don't that it's really needed in this case. What do you think ?
Edit : As expected, thanks to you it worked and I could learn more about Python. However, I don't understand the utility of the first line "new_logins = sys.argv[0]", because it worked without it. Can you tell me if it is important for something ? Thanks by advance.
The problem is that you never closed the file before you opened it again to read it.
You need to use the close() function on the file before you reopen it:
import sys
new_logins = sys.argv[0]
logins = sys.argv[1:]
count = len(logins)
f=open('logins.db','w')
logins=map(lambda x:x+'\n', logins)
f.writelines(logins)
f.close()
logins = []
with open('logins.db', 'r') as filehandle:
for line in filehandle:
current_login = line[:-1]
logins.append(current_login)
or just use with block like you used for reading:
import sys
new_logins = sys.argv[0]
logins = sys.argv[1:]
count = len(logins)
logins=map(lambda x:x+'\n', logins)
with open('logins.db', 'w') as f:
f.writelines(logins)
logins = []
with open('logins.db', 'r') as filehandle:
for line in filehandle:
current_login = line[:-1]
logins.append(current_login)
Trying to feed a text file list through socket.gethostbyaddr and I seem to be stuck on a data type issue.
when try to loop through the list I'm getting no output except an Exception error on my last test line
This is just a small script to resolve ip to name if one exists. To test my opened file is just:
1.1.1.1
2.2.2.2
10.1.1.1
with my local hosts having an entry for the first two lines to a "test1"or "test2" name
just running socket.gethostbyaddr('1.1.1.1') returns "test1" as the host so I know that part is correct for testing
import subprocess
import socket
tstout = open('testout.txt','w+')
with open("testip.txt", "r") as ins:
for l in ins:
line = str(l)
try:
tstout.write (socket.gethostbyaddr(line))
except Exception as e:
print (e)
tstout.close()
subprocess.Popen([r'c:\Windows\notepad.exe',r'c:\scripts\testout.txt'])
Was expecting the output file to have the resolve results written to it, any pointers where I messed this up is appreciated
Simplified to:
import socket
tstout = open('testout.txt','w+')
with open("testip.txt", "r") as ins:
for l in ins:
l = str(l)
# print(l)
tstout.write (socket.gethostbyaddr(l))
I am currently trying to get ip address from text. But the code I tried is only getting the last line from the file. I am using the following code
import paramiko
import time
import getpass
import sys
import socket
import re
user = raw_input("Enter you username: ")
password = getpass.getpass()
inp = open(r'ipaddressrouter.txt', 'r')
for line in inp:
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=line,username=user,password=password)
print "Successful Connection to " + line + '\n'
stdin, stdout, stderr = ssh_client.exec_command('sh ip int b \n')
output = stdout.read()
out = open('out.txt', 'a')
out.write(line + '\n')
out.write(output + '\n')
out.write('\n')
except (socket.error, paramiko.AuthenticationException):
status = 'fail'
ssh_client.close
help would be appreciated
Update:
When I removed except
I got the following error
File "C:\Users\abc\Desktop\Python Test Scripts\newstest2.py", line 20, in
ssh_client.connect(hostname=host,username=user,password=password)
File "C:\Python27\lib\site-packages\paramiko\client.py", line 329, in connect to_try = list(self._families_and_addresses(hostname, port))
File "C:\Python27\lib\site-packages\paramiko\client.py", line 200, in _families_and_addresses hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM)socket.gaierror: [Errno 11004] getaddrinfo failed
Can some one help me out ?
for line in inp:
will store the next line of inp in line including the terminating new line character '\n'. When you pass this unmodified to ssh_client.connect(), then the host name will include '\n'. The reason that you get a successful connection with the last line of your input file is very likely that the last line is not terminated by '\n'.
One way to remove the '\n' is:
line = line.strip()
To put it all together, including my comments to your question regarding the recommended use of with:
import socket
import paramiko
# get user/password as in the question code (not repeated here)
# ....
status = 'OK'
with open(r'ipaddressrouter.txt', 'r') as inp:
for line in inp:
line = line.strip()
with paramiko.SSHClient() as ssh_client:
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh_client.connect(hostname=line, username=user, password=password)
print("Successful Connection to " + line)
stdin, stdout, stderr = ssh_client.exec_command('target command here')
output = stdout.read()
with open('out.txt', 'a') as out:
out.write(line + '\n')
out.write(str(output, encoding='utf-8') + '\n')
out.write('\n')
except (socket.error, paramiko.AuthenticationException) as e:
print("Failed connection to " + line)
status = 'fail'
Note:
I modified your example to work with Python3. Some of my changes are probably not necessary for Python2. If you are not forced to use Python2, I would always recommend to use Python3 for new projects. See End of support for python 2.7?
import re
lis_of_ip = ['10.1.1.1','10.1.1']
for ip in lis_of_ip:
if(re.match('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.|$)){4}', ip)):
print(ip,'true')
else:
print(ip,'false')
I want to delete some specific lines in a file. The below code doesn't seem to work. There are no errors thrown but this code won't delete the lines that are meant to be deleted.
#!/usr/bin/python
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')
args = p.parse_args()
kkk_list = args.input # ['1.1.1.1:443:myname', '2.2.2.2:443:yourname']
def getStringInFormat(ip, port, name):
formattedText = "HOST Address:{ip}:PORT:{port}\n"\
" server tcp\n"\
" server {ip}:{port} name {name}\n\n".format(ip=ip,
port=port,
name=name)
return formattedText
with open("file.txt", "r+") as f:
fileContent = f.read()
# below two lines delete old content of file
f.seek(0)
f.truncate()
for kkk in kkk_list:
ip, port, name = re.split(":|,", kkk)
stringNeedsToBeDeleted = getStringInFormat(ip, port, name)
fileContent = fileContent.replace(stringNeedsToBeDeleted, "")
f.write(fileContent)
The content of the file from which I'm trying to delete looks like following. Please note the space before 2nd and 3rd lines
------------do not delete this line------
HOST Address:1.1.1.1:PORT:443\n"\
server tcp\n"\
server 1.1.1.1:443 name myname1
--------------- do not delete this line either
If the script is successful the file should look like below where there is only one new line in between.
------------do not delete this line------
------------do not delete this line either ----
Any insights?
You are doing everything correct in your file editing loop, which means that if you aren't actually replacing anything its because the string you are looking for doesn't exist. Indeed, when you tell us that you are looking for this string:
------------do not delete this line------
HOST Address:1.1.1.1:PORT:443\n"\
server tcp\n"\
server 1.1.1.1:443 name myname1
--------------- do not delete this line either
It doesn't appear to match up with the string you are trying to match it with:
formattedText = "HOST Address:{ip}:PORT:{port}\n"\
" server tcp\n"\
" server {ip}:{port} name {name}\n\n"
Keep in mind in order to replace this string with your current code, the strings have to exactly match, in this case I don't see the \n between "HOST Addess..." and " server tcp\n"\ or the \ lines. But I suspect those were just formatting errors on your part.
If you really want to get to the root of this problem I suggest you find a string you know for certain you are trying to delete and test your code with that to make sure the strings are the same. Here is an example. If you want to find:
HOST Address:1.1.1.1:PORT:443
server tcp
server 1.1.1.1:443 name myname1
Then compare with your search string via:
test_string = # the string I posted above, you should probably
# grab this from a file for consistency.
kkk = '1.1.1.1:443:myname'
ip, port, name = re.split(":|,", kkk)
assert ip == '1.1.1.1'
assert port == '443'
assert name == 'myname'
stringNeedsToBeDeleted = getStringInFormat(ip, port, name)
assert stringNeedsToBeDeleted == test_string, "Error, strings are not equal!"
This should give you a clue into what the actual problem is. myname1, which I grabbed directly from your example, doesn't match up with your match string.
You're opening the file in read mode 'r+'. You need to open it in write mode 'w' to write to it. Or just don't specify a mode.
You can copy the contents of your file to a list, write over the old file, mutate your list, and then write the list to the file.
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name",nargs='*')
args = p.parse_args()
kkk_list = args.input # ['1.1.1.1:443:myname', '2.2.2.2:443:yourname']
def getStringInFormat(ip, port, name):
formattedText = "HOST Address:{ip}:PORT:{port}\n"\
" server tcp\n"\
" server {ip}:{port} name {name}\n\n".format(ip=ip,
port=port,
name=name)
return formattedText
with open("file.txt", "r+") as f:
for kkk in kkk_list:
ip, port, name = re.split(":|,", kkk)
stringNeedsToBeDeleted = getStringInFormat(ip, port, name)
fileContent = fileContent.replace(stringNeedsToBeDeleted, "")
f.write(fileContent) #now, your file contains all the host addressed and IPs
f = open("file.txt").readlines()
contents = [i.strip('\n').split() for i in f]
new_file = open('file.txt', 'w')
new_file.write('')
new_file.write(''.join(contents[0]))
new_file.write('\n\n\n')
new_file.write(contents[''.join(len(contents)-1])))
new_file.close()
This is my script which is supposed to parse a list of domains (each seperated by returns) in a .txt file, separate them into individual domain names, send a request to a whois site with the domain name, check the response to see if it is available, and if it is, write it to a new file. so i get a list of only available names.
The problem? It's pretty simple i just dont know the language well enough, I dont know how to get the domain name in a string format so that the request to the whois site is like this :
http://whois.domaintools.com/google.com
Apparently the %s thing is not working.
Code:
#!/usr/bin/python
import urllib2, urllib
print "Domain Name Availability Scanner."
print "Enter the Location of the txt file containing your list of domains:"
path = raw_input("-->")
wordfile = open(path, "r")
words = wordfile.read().split("n")
words = map(lambda x: x.rstrip(), words)
wordfile.close()
for word in words:
req = urllib2.Request("http://whois.domaintools.com/%s") % (word)
source = urllib2.urlopen(req).read()
if "This domain name is not registered" in source:
f = open("success.txt", "a")
f.write("%s\n") % (word)
f.close()
break
error in terminal:
python domain.py
Domain Name Availability Scanner.
Enter the Location of the txt file containing your list of domains:
-->a.txt
Traceback (most recent call last):
File "domain.py", line 13, in <module>
req = urllib2.Request("http://whois.domaintools.com/%s") % (word)
TypeError: unsupported operand type(s) for %: 'instance' and 'str'
Fix the parentheses:
req = urllib2.Request("http://whois.domaintools.com/%s" % (word))
As well as:
f.write("%s\n" % word)
:)
You need to use:
req = urllib2.Request("http://whois.domaintools.com/%s" % word)
# ...
f.write("%s\n" % word)
Use:
f.write("%s\n" % word)
Check out this link, it should explain how this formatting works: http://docs.python.org/release/2.5.2/lib/typesseq-strings.html