added support for PyInstaller on Windows

pull/73/merge
lanjelot 9 years ago
parent 6020420592
commit d830355821

@ -40,6 +40,8 @@ Patator is NOT script-kiddie friendly, please read the README inside patator.py
@lanjelot @lanjelot
# Usage Examples
* FTP : Enumerating users denied login in vsftpd/userlist * FTP : Enumerating users denied login in vsftpd/userlist
``` ```
@ -275,4 +277,29 @@ $ unzip_pass zipfile=challenge1.zip password=FILE0 0=rockyou.dic -x ignore:code!
10:54:31 patator INFO - To resume execution, pass --resume 166,164,165,166,155,158,148,158,155,154 10:54:31 patator INFO - To resume execution, pass --resume 166,164,165,166,155,158,148,158,155,154
``` ```
# PyInstaller
## Bundling on Windows 5.2.3790 x86
install `python-2.7.9.msi` from [Python](https://www.python.org/downloads/windows/)
install `pywin32-219.win32-py2.7.exe` from [PyWin32](http://sourceforge.net/projects/pywin32/files/pywin32/)
install `vcredist_x86.exe` from [Microsoft](http://www.microsoft.com/en-us/download/confirmation.aspx?id=29)
install `Git-1.9.5.exe` from [Git](http://git-scm.com/download/win) (and select "Use Git from Windows Command Prompt" during install)
add `c:\Python27;c:\Python27\Scripts` to your `PATH`
```
pip install pycrypto pyopenssl
pip install impacket
pip install paramiko
pip install IPy
pip install dnspython
cd c:\
git clone https://github.com/lanjelot/patator
git clone https://github.com/pyinstaller/pyinstaller
cd pyinstaller
git checkout a2b0617251ebe70412f6e3573f00a49ce08b7b32 # fixes [this issue](https://groups.google.com/forum/#!topic/pyinstaller/6xD75_w4F-c)
python pyinstaller.py --clean --onefile c:\patator\patator.py
patator\dist\patator.exe -h
```
The resulting stand-alone `patator.exe` executable was confirmed to run successfully on Windows 2003 (5.2.3790), Windows 7 (6.1.7600), Windows 2008 R2 SP1 (6.1.7601) and Windows 2012 R2 (6.3.9600), and is likely to work fine on other Windows versions.

@ -627,7 +627,7 @@ TODO
class Logger: class Logger:
def __init__(self, pipe): def __init__(self, pipe):
self.pipe = pipe self.pipe = pipe
self.name = current_process().name self.name = multiprocessing.current_process().name
# neat but wont work on windows # neat but wont work on windows
# def __getattr__(self, action): # def __getattr__(self, action):
@ -806,7 +806,7 @@ def process_logs(pipe, indicatorsfmt, argv, log_dir):
# imports {{{ # imports {{{
import re import re
import os import os
from sys import exc_info, exit, version_info, maxint import sys
from time import localtime, strftime, sleep, time from time import localtime, strftime, sleep, time
from platform import system from platform import system
from functools import reduce from functools import reduce
@ -822,8 +822,7 @@ import socket
import subprocess import subprocess
import hashlib import hashlib
from collections import defaultdict from collections import defaultdict
from multiprocessing import Process, active_children, current_process, Queue, Pipe import multiprocessing
from multiprocessing.managers import SyncManager
import signal import signal
import ctypes import ctypes
try: try:
@ -846,6 +845,33 @@ except ImportError:
has_ipy = False has_ipy = False
notfound.append('IPy') notfound.append('IPy')
import multiprocessing.forking
class _Popen(multiprocessing.forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
# We have to set original _MEIPASS2 value from sys._MEIPASS
# to get --onefile mode working.
os.putenv('_MEIPASS2', sys._MEIPASS)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
# On some platforms (e.g. AIX) 'os.unsetenv()' is not
# available. In those cases we cannot delete the variable
# but only set it to the empty string. The bootloader
# can handle this case.
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
class Process(multiprocessing.Process):
_Popen = _Popen
# So BaseManager.start() uses this new Process class
multiprocessing.Process = Process
from multiprocessing.managers import SyncManager
# imports }}} # imports }}}
# utils {{{ # utils {{{
@ -854,12 +880,15 @@ def which(program):
return os.path.exists(fpath) and os.access(fpath, os.X_OK) return os.path.exists(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program) fpath, fname = os.path.split(program)
if on_windows() and fname[-4:] != '.exe' :
fname += '.exe'
if fpath: if fpath:
if is_exe(program): if is_exe(program):
return program return program
else: else:
for path in os.environ["PATH"].split(os.pathsep): for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program) exe_file = os.path.join(path, fname)
if is_exe(exe_file): if is_exe(exe_file):
return exe_file return exe_file
@ -882,7 +911,7 @@ def create_dir(top_path):
for root, dirs, files in os.walk(top_path): for root, dirs, files in os.walk(top_path):
if dirs: if dirs:
print("Directory '%s' contains sub-directories, safely aborting..." % root) print("Directory '%s' contains sub-directories, safely aborting..." % root)
exit(0) sys.exit(0)
for f in files: for f in files:
os.unlink(os.path.join(root, f)) os.unlink(os.path.join(root, f))
break break
@ -1057,7 +1086,7 @@ class RangeIter:
if random: if random:
self.generator = random_generator, () self.generator = random_generator, ()
self.size = maxint self.size = sys.maxint
def __iter__(self): def __iter__(self):
fn, args = self.generator fn, args = self.generator
@ -1263,7 +1292,7 @@ Please read the README inside for more examples and usage information.
if not len(args) > 0: if not len(args) > 0:
parser.print_usage() parser.print_usage()
print('ERROR: wrong usage. Please read the README inside for more information.') print('ERROR: wrong usage. Please read the README inside for more information.')
exit(2) sys.exit(2)
return opts, args return opts, args
@ -1300,7 +1329,7 @@ Please read the README inside for more examples and usage information.
self.ns.start_time = 0 self.ns.start_time = 0
self.ns.total_size = 1 self.ns.total_size = 1
pipe = Pipe(duplex=False) pipe = multiprocessing.Pipe(duplex=False)
logsvc = Process(name='LogSvc', target=process_logs, args=(pipe[0], module.Response.indicatorsfmt, argv, build_logdir(opts.log_dir, opts.auto_log))) logsvc = Process(name='LogSvc', target=process_logs, args=(pipe[0], module.Response.indicatorsfmt, argv, build_logdir(opts.log_dir, opts.auto_log)))
logsvc.daemon = True logsvc.daemon = True
@ -1354,7 +1383,7 @@ Please read the README inside for more examples and usage information.
if not has_ipy: if not has_ipy:
print('IPy (https://github.com/haypo/python-ipy) is required for using NET keyword.') print('IPy (https://github.com/haypo/python-ipy) is required for using NET keyword.')
print('Please read the README inside for more information.') print('Please read the README inside for more information.')
exit(3) sys.exit(3)
else: else:
for i, j in self.find_combo_keys(v): for i, j in self.find_combo_keys(v):
@ -1459,14 +1488,14 @@ Please read the README inside for more examples and usage information.
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
except: except:
logging.exception(exc_info()[1]) logging.exception(sys.exc_info()[1])
finally: finally:
self.ns.quit_now = True self.ns.quit_now = True
try: try:
# waiting for reports enqueued by consumers to be flushed # waiting for reports enqueued by consumers to be flushed
while True: while True:
active = active_children() active = multiprocessing.active_children()
self.report_progress() self.report_progress()
if not len(active) > 2: # SyncManager and LogSvc if not len(active) > 2: # SyncManager and LogSvc
break break
@ -1475,7 +1504,7 @@ Please read the README inside for more examples and usage information.
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
if self.ns.total_size >= maxint: if self.ns.total_size >= sys.maxint:
total_size = -1 total_size = -1
else: else:
total_size = self.ns.total_size total_size = self.ns.total_size
@ -1507,7 +1536,7 @@ Please read the README inside for more examples and usage information.
logger.info('To resume execution, pass --resume %s' % ','.join(resume)) logger.info('To resume execution, pass --resume %s' % ','.join(resume))
logger.quit() logger.quit()
while len(active_children()) > 1: while len(multiprocessing.active_children()) > 1:
sleep(.1) sleep(.1)
def push_final(self, resp): pass def push_final(self, resp): pass
@ -1515,11 +1544,11 @@ Please read the README inside for more examples and usage information.
def start_threads(self): def start_threads(self):
task_queues = [Queue() for _ in range(self.num_threads)] task_queues = [multiprocessing.Queue() for _ in range(self.num_threads)]
# consumers # consumers
for num in range(self.num_threads): for num in range(self.num_threads):
report_queue = Queue() report_queue = multiprocessing.Queue()
t = Process(name='Consumer-%d' % num, target=self.consume, args=(task_queues[num], report_queue, logger.pipe)) t = Process(name='Consumer-%d' % num, target=self.consume, args=(task_queues[num], report_queue, logger.pipe))
t.daemon = True t.daemon = True
t.start() t.start()
@ -1584,7 +1613,7 @@ Please read the README inside for more examples and usage information.
if m: if m:
prog, size = m.groups() prog, size = m.groups()
else: else:
prog, size = v, maxint prog, size = v, sys.maxint
logger.debug('prog: %s, size: %s' % (prog, size)) logger.debug('prog: %s, size: %s' % (prog, size))
@ -1744,10 +1773,10 @@ Please read the README inside for more examples and usage information.
resp = module.execute(**payload) resp = module.execute(**payload)
except: except:
mesg = '%s %s' % exc_info()[:2] mesg = '%s %s' % sys.exc_info()[:2]
logger.debug('caught: %s' % mesg) logger.debug('caught: %s' % mesg)
#logging.exception(exc_info()[1]) #logging.exception(sys.exc_info()[1])
resp = self.module.Response('xxx', mesg, timing=time()-start_time) resp = self.module.Response('xxx', mesg, timing=time()-start_time)
@ -1784,7 +1813,7 @@ Please read the README inside for more examples and usage information.
def monitor_progress(self): def monitor_progress(self):
# loop until SyncManager, LogSvc and Producer are the only children left alive # loop until SyncManager, LogSvc and Producer are the only children left alive
while len(active_children()) > 3 and not self.ns.quit_now: while len(multiprocessing.active_children()) > 3 and not self.ns.quit_now:
self.report_progress() self.report_progress()
self.monitor_interaction() self.monitor_interaction()
@ -1853,8 +1882,7 @@ Please read the README inside for more examples and usage information.
command += raw_input() command += raw_input()
else: else:
from sys import stdin i, _, _ = select([sys.stdin], [], [], .1)
i, _, _ = select([stdin], [], [], .1)
if not i: return if not i: return
command = i[0].readline().strip() command = i[0].readline().strip()
@ -1901,7 +1929,7 @@ Please read the README inside for more examples and usage information.
total_count = sum(p.done_count+p.skip_count for p in thread_progress) total_count = sum(p.done_count+p.skip_count for p in thread_progress)
speed_avg = num_threads / (sum(sum(p.seconds) / len(p.seconds) for p in thread_progress) / num_threads) speed_avg = num_threads / (sum(sum(p.seconds) / len(p.seconds) for p in thread_progress) / num_threads)
if total_size >= maxint: if total_size >= sys.maxint:
etc_time = 'inf' etc_time = 'inf'
remain_time = 'inf' remain_time = 'inf'
else: else:
@ -2150,10 +2178,12 @@ class FTP_login(TCP_Cache):
# SSH {{{ # SSH {{{
# logging.NullHandler only available since python 2.7 try:
class NullHandler(logging.Handler): from logging import NullHandler # only available since python 2.7
def emit(self, record): except ImportError:
pass class NullHandler(logging.Handler):
def emit(self, record):
pass
try: try:
import paramiko import paramiko
@ -3560,7 +3590,7 @@ class VNC:
btgt = btgt | (1 << 7-i) btgt = btgt | (1 << 7-i)
newkey.append(btgt) newkey.append(btgt)
if version_info[0] == 2: if sys.version_info[0] == 2:
return ''.join(chr(c) for c in newkey) return ''.join(chr(c) for c in newkey)
else: else:
return bytes(newkey) return bytes(newkey)
@ -4107,7 +4137,7 @@ class IKE_enum:
Response = Response_Base Response = Response_Base
def __init__(self): def __init__(self):
uid = current_process().name[9:] uid = multiprocessing.current_process().name[9:]
self.sport = '51%s' % uid self.sport = '51%s' % uid
def execute(self, host, port='500', transform='5,1,1,2', aggressive='0', groupname='foo', vid=''): def execute(self, host, port='500', transform='5,1,1,2', aggressive='0', groupname='foo', vid=''):
@ -4368,8 +4398,7 @@ dependencies = {
# main {{{ # main {{{
if __name__ == '__main__': if __name__ == '__main__':
from sys import argv multiprocessing.freeze_support()
from os.path import basename
def show_usage(): def show_usage():
print(__banner__) print(__banner__)
@ -4378,20 +4407,20 @@ if __name__ == '__main__':
Available modules: Available modules:
%s''' % '\n'.join(' + %-13s : %s' % (k, v[1].__doc__) for k, v in modules)) %s''' % '\n'.join(' + %-13s : %s' % (k, v[1].__doc__) for k, v in modules))
exit(2) sys.exit(2)
available = dict(modules) available = dict(modules)
name = basename(argv[0]).lower() name = os.path.basename(sys.argv[0]).lower()
if name not in available: if name not in available:
if len(argv) == 1: if len(sys.argv) == 1:
show_usage() show_usage()
name = basename(argv[1]).lower() name = os.path.basename(sys.argv[1]).lower()
if name not in available: if name not in available:
show_usage() show_usage()
argv = argv[1:] argv = sys.argv[1:]
# dependencies # dependencies
abort = False abort = False
@ -4407,7 +4436,7 @@ Available modules:
if abort: if abort:
print('Please read the README inside for more information.') print('Please read the README inside for more information.')
exit(3) sys.exit(3)
# start # start
ctrl, module = available[name] ctrl, module = available[name]

Loading…
Cancel
Save