Docopt function argument issues - python

Im not entirely sure how to call my tasklist function with all the required arguments. Im guessing im getting the syntax wrong. Can anyone point out my stupidity please?
CODE
#!/usr/bin/python
"""
Description:
Used for checking users logged into a list of servers.
Usage:
hunter.py (-u <username>) (-p <password>) (-d <domain>) (-s <FILE>)
hunter.py -h | --help
hunter.py --version
Options:
-u --username
-h --help Show this screen.
--version Show version.
-p --password
-d --domain
-s --serverfile=FILE
"""
from docopt import docopt
import subprocess
from subprocess import CalledProcessError
def tasklist(serverlist, domain, username):
for serverl in serverlist():
try:
print "%s Services Listed Below" % serverl
cmd = 'tasklist /V /S %s -u%s\%s /FI "USERNAME eq $s"' % serverl, domain, username, domain
print cmd
subprocess.check_output(cmd)
except CalledProcessError as e:
print(e.returncode)
def getservers(servers):
slist = open(servers).readlines()
return [s.replace('\n', '') for s in slist]
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
print arguments
serverlist = getservers(arguments['--serverfile'])
print serverlist
tasklist(serverlist,(arguments['<domain>'], ['<username>']))
COMMANDLINE EXAMPLE
c:\Python27>hunter.py -u xpuser -p xpuser -d WORKGROUP -s servers.txt
TRACEBACK
{'--domain': True,
'--help': False,
'--password': True,
'--serverfile': 'servers.txt',
'--username': True,
'--version': False,
'<domain>': 'WORKGROUP',
'<password>': 'xpuser',
'<username>': 'xpuser'}
['192.168.1.122', '192.168.1.121']
Traceback (most recent call last):
File "C:\Python27\hunter.py", line 44, in <module>
tasklist(serverlist,(arguments['<domain>'], ['<username>']))
TypeError: tasklist() takes exactly 3 arguments (2 given)

tasklist() function requires 3 arguments, you are passing just two. Replace:
tasklist(serverlist,(arguments['<domain>'], ['<username>']))
with:
tasklist(serverlist, arguments['<domain>'], arguments['<username>'])
Also, you don't need to call serverlist, it's a list, omit the parenthesis:
for serverl in serverlist:
Also, replace:
cmd = 'tasklist /V /S %s -u%s\%s /FI "USERNAME eq $s"' % serverl, domain, username, domain
with:
cmd = 'tasklist /V /S %s -u%s\%s /FI "USERNAME eq %s"' % (serverl, domain, username, domain)
Hope that helps.

Related

3 arguments for 3 tokens but not enough arguments error

If I create a user named Talbot on an ubuntu server, I'm able to manually change ownership of this user's directory by running this command as sudo
chown talbot:talbot -R /home/talbot
I try to do the same thing in the last line of this Fabric python script by doing
sudo("chown %s:%s -R /home/%s" % new_user,new_user, new_user)
However, it keeps giving me this error
sudo("chown %s:%s -R /home/%s" % new_user, new_user,new_user)
TypeError: not enough arguments for format string
Can you explain why this error is happening?
def user_add(new_user, passwd=False):
"""Add new user"""
with settings(hide('running', 'stdout', 'stderr'), warn_only=True):
# if is_host_up(env.host):
if not passwd:
passwd = generate_passwd()
if not sudo("useradd -p $(echo '%s' | openssl passwd -1 -stdin) %s" % (passwd, new_user)).failed:
run('echo "{user} ALL=(ALL:ALL) ALL" >> /etc/sudoers'.format(user=new_user))
if env.host== '107.XX.XX.XXX':
sudo("mkdir /home/%s" % new_user, warn_only=True)
sudo("chown %s:%s -R /home/%s" % new_user,new_user, new_user)
All of your arguments for your format string need to be encased in a single tuple. So instead of
sudo("chown %s:%s -R /home/%s" % new_user,new_user, new_user)
You should use
sudo("chown %s:%s -R /home/%s" % (new_user,new_user, new_user))

Socket function getting error

Im trying to do a socket.gethostbyname from a list of subdomains concatenated with an argument value but am getting an error. Im not sure if the loop isnt working correctly and the first try is just not a valid subdomain+domain. or if it just isnt working at all?
ERROR
Traceback (most recent call last):
File "./attack2.py", line 40, in <module>
print subcheck(returned_list, arguments['--domain'])
File "./attack2.py", line 31, in subcheck
socket.gethostbyname(sub + domain)
socket.gaierror: [Errno -2] Name or service not known
CODE
#!/usr/bin/python
"""
Description:
Basic Domain bruteforcer
Usage:
attack2.py (-f <file>) (-d <domain>) [-t 10] [-v]
attack2.py -h | --help
Arguments:
-f --file File to read potential Sub-domains from. (Required)
-d --domain Domain to bruteforce. (Required)
Options:
-h --help Show this screen.
-p --proxy Proxy address and port. [default: http://127.0.0.1:8080] (Optional)
-t --thread Thread count. (Optional)
-v --verbose Turn debug on. (Optional)
"""
import socket
from docopt import docopt
def fread(dwords):
flist = open(dwords).readlines()
return [s.replace('\n', '.') for s in flist]
def subcheck(subdomain, domain):
for sub in subdomain:
socket.gethostbyname(sub + domain)
return output
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
print arguments
print fread(arguments['--file'])
returned_list = fread(arguments['--file'])
print subcheck(returned_list, arguments['--domain'])
NEW def subcheck code
def subcheck(subdomain, domain):
for sub in subdomain:
try:
#print "%s %d" % (sub+domain,len(sub+domain))
print socket.gethostbyname(sub + domain)
except:
print "Some error"
NEW OUTPUT
173.194.34.150
173.194.34.137
Some error
Some error
None
domain.google.com and stuff.google.com are invalid domains. Getting rid of those will fix the problem.
None is returned because you aren't returning anything in your subcheck function. So when you invoke it like this:
print subcheck(returned_list, arguments['--domain'])
it will be forced to return, and print None. Remove the print in front of it and you won't see None.
"[Errno -2] Name or service not known" sounds to me like your program cannot reach a DNS server. Can you resolve the names in some other way? e.g. using `dig'. I think if socket.gethostbyname cannot resolve the name, it returns a different error; when I try it, I get: "No address associated with hostname".

Using Python subprocess and string formating

I am attempting to call a windows command with relevant arguments using python's subprocess . The command is executing and the arguments and their values look to be correct, however It only seems to be working correctly when using the "local mode" -l.
I'm getting an invalid argument/option error when using the remote mode. Could any point out where im going wrong?
Could anyone point out how to format the subprocess.check_ouput() arguments correctly to include the variables given at commandline when executing the script? As you can see ive tryd using string formating, both old and new to try get it working as I cant workout how to add the last domain variable inbetween the filter (/FI) argument value without string formatting.
expected commandline to execute
tasklist /V /S 192.168.1.122 /U 'DOMAIN'\'USERNAME' /P 'PASSWORD' /FI "USERNAME eq 'DOMAIN'\*"
with this commandline example of the script:
hunter.py -d DOMAIN -u USERNAME -p PASSWORD -s servers.txt
This is the error:
ERROR: Invalid argument/option - '/S 192.168.1.122'.
Type "TASKLIST /?" for usage.
Clearly the argument is correct "visually" correct anyway, here is the usage for the tasklist:
Description:
This tool displays a list of currently running processes on
either a local or remote machine.
Parameter List:
/S system Specifies the remote system to connect to.
/U [domain\]user Specifies the user context under which
the command should execute.
/P [password] Specifies the password for the given
user context. Prompts for input if omitted.
/M [module] Lists all tasks currently using the given
exe/dll name. If the module name is not
specified all loaded modules are displayed.
/SVC Displays services hosted in each process.
/APPS Displays Store Apps and their accociated processes.
/V Displays verbose task information.
/FI filter Displays a set of tasks that match a
given criteria specified by the filter.
/FO format Specifies the output format.
Valid values: "TABLE", "LIST", "CSV".
/NH Specifies that the "Column Header" should
not be displayed in the output.
Valid only for "TABLE" and "CSV" formats.
/? Displays this help message.
This is the python code i have so far;
#!/usr/bin/python
"""
Description:
Used for checking users logged into a list of servers.
Usage:
hunter.py [-u <username>] [-p <password>] [-s <FILE>] (-d <domain>)
hunter.py (-d <domain>) (-l)
hunter.py -h | --help
hunter.py --version
Options:
-l --local
-u --username
-h --help Show this screen.
--version Show version.
-p --password
-d --domain
-s --serverfile=FILE
"""
from docopt import docopt
import subprocess
from subprocess import CalledProcessError
def tldomain(serverlist, domain, username, password):
nlist = serverlist
for serverl in nlist:
try:
print subprocess.check_output(["tasklist", "/V", "/S " + serverl, "/U" + domain, "\\" + username, "/P" + password, "/FI", "'USERNAME eq %s\\\*'"]) % domain
except CalledProcessError as e:
print(e.returncode)
def tllocal(domain):
try:
cmd = 'tasklist /V /FI "USERNAME eq {0}\\*"' .format(domain)
subprocess.call(cmd)
except OSError as e:
print e
def getservers(servers):
slist = open(servers).readlines()
return [s.replace('\n', '') for s in slist]
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
print arguments
if (arguments['--local']) == False:
serverlist = getservers(arguments['--serverfile'])
tldomain(serverlist, arguments['<domain>'], arguments['<username>'], arguments['<password>'])
else:
tllocal(arguments['<domain>'])
Pass in your arguments as separate elements in the list and apply the string formatting to the last element, no the output of the subprocess.check_output() call:
print subprocess.check_output(
["tasklist", "/V", "/S", serverl, "/U", domain + "\\" + username,
"/P", password, "/FI", "USERNAME eq %s\\*" % domain])
Note that I also removed the ' quoting from the last argument, leave that to the subprocess module.
This also assumes that domain is always a non-empty string; if that's not the case, use:
if domain:
domain += '\\'
print subprocess.check_output(
["tasklist", "/V", "/S", serverl, "/U", domain + username,
"/P", password, "/FI", "USERNAME eq %s*" % domain])
e.g. only use the \ backslash when domain is actually specified.

Python usage not printing

im creating my first python "app" and im having problems with the args or lack of. If i execute the script with no arguments id expect a message stating usage, but instead im getting the following error
ERROR
unknown#ubuntu:~$ ./attack.py
Traceback (most recent call last):
File "./attack.py", line 60, in <module>
main(sys.argv[1:])
File "./attack.py", line 57, in main
print fread(FWORD)
File "./attack.py", line 19, in fread
flist = open(FWORD).readlines()
TypeError: coercing to Unicode: need string or buffer, NoneType found
CODE
#!/usr/bin/python
import sys, getopt, socket, fileinput, traceback
from Queue import Queue
from threading import Thread
def usage():
print "-h --help: help\n"
print "-f --file: File to read potential Sub-domains from.\n"
print "-p --PROXY: PROXY address and port. e.g http://192.168.1.64:8080\n"
print "-d --DOMAIN: DOMAIN to bruteforce.\n"
print "-t --thread: Thread count.\n"
print "-e: Turn debug on.\n"
sys.exit()
def fread(FWORD, *args):
flist = open(FWORD).readlines()
return flist
#def addcheck(fcontent):
def main(argv):
PROXY = None
DOMAIN = None
FWORD= None
try:
opts, argv =getopt.getopt(argv, "h:f:p:d:t:e",["help", "file=", "PROXY=", "DOMAIN=", "thread="])
except getopt.GetoptError as err:
print str(err)
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-f", "--file"):
FWORD = arg
elif opt in ("-p", "--PROXY"):
PROXY = arg
elif opt in ("-d", "--DOMAIN"):
DOMAIN = arg
elif opt in ("-t", "--thread"):
thread = arg
elif opt in '-e':
global _debug
_debug = 1
else:
usage()
sys.exit()
print fread(FWORD)
if __name__ == "__main__":
main(sys.argv[1:])
Ok thanks all for the comments and pointers. ZMO im going to go with docopt it looks clean and simple (simple just like me). Im not entire sure what i need to do to my old code so am uploading what i think i need to do. Can anyone tell me if this is the right direction?
What do i do with def main() now? and
#!/usr/bin/python
import sys, getopt, socket, fileinput, traceback
from Queue import Queue
from threading import Thread
def fread(FWORD, *args):
flist = open(FWORD).readlines()
return flist
def main(argv):
"""
Usage:
your_script.py [-f <file>] [-p <proxy>] [-d <domain>] [-t] [-v]
your_script.py -h | --help
Options:
-h --help Show this screen.
-f --file File to read potential Sub-domains from.
-p --proxy Proxy address and port. [default: http://127.0.0.1:8080]
-d --domain Domain to bruteforce.
-t --thread Thread count.
-v --verbose Turn debug on.
"""
# […] your code (NOT SURE WHAT CODE YOU MEAN?
if __name__ == "__main__":
from docopt import docopt
arguments = docopt(__doc__, version='0.1a')
print fread(FWORD)
geptopt is deprecated in modern python, you should use argparse instead. I personally prefer the 3rd party docopt
It's useless to give the sys.argv array as argument to main() because you import the sys module globally in your module context (and there are many other things you'd use from sys aside from argv). Your code would only make sense if you were doing the import in the if __name__ == "__main__", but then that would be not good python practice. A better thing to do is to actually parse the arguments and then give the returned NamedTuple as an argument to main().
Argparse example
# […] your code
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='Your script.')
parser.add_argument('--file', '-f', metavar='FILE', dest='file', type=file,
help='File to read potential Sub-domains from.')
parser.add_argument('--proxy', '-p', dest='proxy', action='store',
help='Proxy address and port.', default='http://127.0.0.1:8080')
parser.add_argument('--domain', '-d', dest='domain', action='store',
help='Domain to bruteforce.')
parser.add_argument('--thread', '-t', dest='thread', action='store_true',
help='Thread count.')
parser.add_argument('--verbose', '-v', dest='verbose', action='store_true',
help='Turn debug on.')
args = parser.parse_args()
main(args)
docopt example
Your script presentation.
"""
Usage:
your_script.py [-f <file>] [-p <proxy>] [-d <domain>] [-t] [-v]
your_script.py -h | --help
Options:
-h --help Show this screen.
-f --file File to read potential Sub-domains from.
-p --proxy Proxy address and port. [default: http://127.0.0.1:8080]
-d --domain Domain to bruteforce.
-t --thread Thread count.
-v --verbose Turn debug on.
"""
# […] your code
if __name__ == "__main__":
from docopt import docopt
arguments = docopt(__doc__, version='Naval Fate 2.0')
main(arguments) # here using the parameter makes sense ;-)

OptionParser - supporting any option at the end of the command line

I'm writing a small program that's supposed to execute a command on a remote server (let's say a reasonably dumb wrapper around ssh [hostname] [command]).
I want to execute it as such:
./floep [command]
However, I need to pass certain command lines from time to time:
./floep -v [command]
so I decided to use optparse.OptionParser for this. Problem is, I sometimes the command also has argument, which works fine if I do:
./floep -v "uname -a"
But I also want it to work when I use:
./floep -v uname -a
The idea is, as soon as I come across the first non-option argument, everything after that should be part of my command.
This, however, gives me:
Usage: floep [options]
floep: error: no such option: -a
Does OptionParser support this syntax? If so: how?
If not: what's the best way to fix this?
Try using disable_interspersed_args()
#!/usr/bin/env python
from optparse import OptionParser
parser = OptionParser()
parser.disable_interspersed_args()
parser.add_option("-v", action="store_true", dest="verbose")
(options, args) = parser.parse_args()
print "Options: %s args: %s" % (options, args)
When run:
$ ./options.py foo -v bar
Options: {'verbose': None} args: ['foo', '-v', 'bar']
$ ./options.py -v foo bar
Options: {'verbose': True} args: ['foo', 'bar']
$ ./options.py foo -a bar
Options: {'verbose': None} args: ['foo', '-a', 'bar']
OptionParser instances can actually be manipulated during the parsing operation for complex cases. In this case, however, I believe the scenario you describe is supported out-of-the-box (which would be good news if true! how often does that happen??). See this section in the docs: Querying and manipulating your option parser.
To quote the link above:
disable_interspersed_args()
Set parsing to stop on the first non-option. Use this if you have a
command processor which runs another command which has options of its
own and you want to make sure these options don’t get confused. For example,
each command might have a different set of options.
from optparse import OptionParser
import subprocess
import os
import sys
parser = OptionParser()
parser.add_option("-q", "--quiet",
action="store_true", dest="quiet", default=False,
help="don't print output")
parser.add_option("-s", "--signal",
action="store_true", dest="signal", default=False,
help="signal end of program and return code")
parser.disable_interspersed_args()
(options, command) = parser.parse_args()
if not command:
parser.print_help()
sys.exit(1)
if options.quiet:
ret = subprocess.call(command, stdout=open(os.devnull, 'w'),
stderr=subprocess.STDOUT)
else:
ret = subprocess.call(command)
if options.signal:
print "END OF PROGRAM!!! Code: %d" % ret
You can use a bash script like this:
#!/bin/bash
while [ "-" == "${1:0:1}" ] ; do
if [ "-v" == "${1}" ] ; then
# do something
echo "-v"
elif [ "-s" == "${1}" ] ; then
# do something
echo "-s"
fi
shift
done
${#}
The ${#} gives you the rest of the command line that was not consumed by the shift calls.
To use ssh you simply change the line from
${#}
to
ssh ${user}#${host} ${#}
test.sh echo bla
bla
test.sh -v echo bla
-v
bla
test.sh -v -s echo bla
-v
-s
bla

Categories