From 70335cafe2087b5e29832f92f07cf7d82490efa9 Mon Sep 17 00:00:00 2001 From: lanjelot Date: Wed, 1 Mar 2017 14:15:38 +1100 Subject: [PATCH 01/21] Fixes #23 --- patator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patator.py b/patator.py index 6d84330..3655de9 100755 --- a/patator.py +++ b/patator.py @@ -1848,7 +1848,10 @@ def shutdown(): enable_alarm(self.timeout) resp = module.execute(**payload) + disable_alarm() except: + disable_alarm() + mesg = '%s %s' % sys.exc_info()[:2] logger.debug('caught: %s' % mesg) @@ -1862,9 +1865,6 @@ def shutdown(): sleep(try_count * .1) continue - finally: - disable_alarm() - else: actions = {'fail': None} From 116040eb8b7a5af460a9e3d11c8d4c1468011c70 Mon Sep 17 00:00:00 2001 From: lanjelot Date: Wed, 1 Mar 2017 14:33:48 +1100 Subject: [PATCH 02/21] Fixes #39 --- patator.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/patator.py b/patator.py index 3655de9..42326da 100755 --- a/patator.py +++ b/patator.py @@ -879,6 +879,7 @@ def process_logs(pipe, indicatorsfmt, argv, log_dir): import multiprocessing import signal import ctypes +import glob from xml.sax.saxutils import escape as xmlescape, quoteattr as xmlquoteattr try: # python3+ @@ -932,6 +933,9 @@ class Process(multiprocessing.Process): # imports }}} # utils {{{ +def expand_path(s): + return os.path.expandvars(os.path.expanduser(s)) + def strfutctime(): return strftime("%Y-%m-%d %H:%M:%S", gmtime()) @@ -1418,7 +1422,7 @@ def __init__(self, module, argv): else: if v.startswith('@'): - p = os.path.expanduser(v[1:]) + p = expand_path(v[1:]) v = open(p).read() kargs.append((k, v)) @@ -1644,17 +1648,16 @@ def abort(msg): size = 0 files = [] - for fname in v.split(','): - fpath = os.path.expanduser(fname) - - if not os.path.isfile(fpath): - return abort("No such file '%s'" % fpath) + for name in v.split(','): + for fpath in sorted(glob.iglob(expand_path(name))): + if not os.path.isfile(fpath): + return abort("No such file '%s'" % fpath) - with open(fpath) as f: - for _ in f: - size += 1 + with open(fpath) as f: + for _ in f: + size += 1 - files.append(FileIter(fpath)) + files.append(FileIter(fpath)) iterable = chain(*files) From 8fdf6ac3ca48b0bdb205b0eefbf500166d3417d9 Mon Sep 17 00:00:00 2001 From: lanjelot Date: Wed, 1 Mar 2017 15:16:40 +1100 Subject: [PATCH 03/21] Fixes #18 (hopefully :) --- patator.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/patator.py b/patator.py index 42326da..f8e622c 100755 --- a/patator.py +++ b/patator.py @@ -631,18 +631,12 @@ # logging {{{ class Logger: - def __init__(self, pipe): - self.pipe = pipe + def __init__(self, queue): + self.queue = queue self.name = multiprocessing.current_process().name -# neat but wont work on windows -# def __getattr__(self, action): -# def send(*args): -# self.pipe.send((self.name, action, args)) -# return send - def send(self, action, *args): - self.pipe.send((self.name, action, args)) + self.queue.put((self.name, action, args)) def quit(self): self.send('quit') @@ -729,7 +723,7 @@ def filter(self, record): else: return 1 -def process_logs(pipe, indicatorsfmt, argv, log_dir): +def process_logs(queue, indicatorsfmt, argv, log_dir): ignore_ctrlc() @@ -814,7 +808,7 @@ def process_logs(pipe, indicatorsfmt, argv, log_dir): while True: - pname, action, args = pipe.recv() + pname, action, args = queue.get() if action == 'quit': if log_dir: @@ -1397,14 +1391,14 @@ def __init__(self, module, argv): self.ns.start_time = 0 self.ns.total_size = 1 - pipe = multiprocessing.Pipe(duplex=False) + log_queue = multiprocessing.Queue() - 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=(log_queue, module.Response.indicatorsfmt, argv, build_logdir(opts.log_dir, opts.auto_log))) logsvc.daemon = True logsvc.start() global logger - logger = Logger(pipe[1]) + logger = Logger(log_queue) if opts.debug: logger.setLevel(logging.DEBUG) @@ -1617,23 +1611,23 @@ def start_threads(self): # consumers for num in range(self.num_threads): report_queue = multiprocessing.Queue(maxsize=1000) - 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.queue)) t.daemon = True t.start() self.thread_report.append(report_queue) self.thread_progress.append(Progress()) # producer - t = Process(name='Producer', target=self.produce, args=(task_queues, logger.pipe)) + t = Process(name='Producer', target=self.produce, args=(task_queues, logger.queue)) t.daemon = True t.start() - def produce(self, task_queues, pipe): + def produce(self, task_queues, log_queue): ignore_ctrlc() global logger - logger = Logger(pipe) + logger = Logger(log_queue) iterables = [] total_size = 1 @@ -1766,13 +1760,13 @@ def abort(msg): logger.debug('producer exits') - def consume(self, task_queue, report_queue, pipe): + def consume(self, task_queue, report_queue, log_queue): ignore_ctrlc() handle_alarm() global logger - logger = Logger(pipe) + logger = Logger(log_queue) module = self.module() From 025dc572b047d8d7f3f815795f08493703876d8d Mon Sep 17 00:00:00 2001 From: lanjelot Date: Thu, 23 Mar 2017 10:13:44 +1100 Subject: [PATCH 04/21] Fixes #36 --- patator.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/patator.py b/patator.py index f8e622c..a7c072d 100755 --- a/patator.py +++ b/patator.py @@ -126,7 +126,9 @@ -------------------------------------------------------------------------------------------------- paramiko | SSH | http://www.lag.net/paramiko/ | 1.7.7.1 | -------------------------------------------------------------------------------------------------- -pycurl | HTTP | http://pycurl.sourceforge.net/ | 7.19.0 | +pycurl | HTTP | http://pycurl.sourceforge.net/ | 7.19.3 | +-------------------------------------------------------------------------------------------------- +libcurl | HTTP | https://curl.haxx.se/ | 7.21.0 | -------------------------------------------------------------------------------------------------- ajpy | AJP | https://github.com/hypn0s/AJPy/ | 0.0.1 | -------------------------------------------------------------------------------------------------- @@ -3364,9 +3366,12 @@ def execute(self, host, port='5432', user=None, password=None, database='postgre # HTTP {{{ try: import pycurl + if not hasattr(pycurl, 'PRIMARY_PORT'): + notfound.append('libcurl') except ImportError: notfound.append('pycurl') + class Response_HTTP(Response_Base): indicatorsfmt = [('code', -4), ('size:clen', -13), ('time', 6)] @@ -4640,7 +4645,8 @@ def execute(self, data, data2='', delay='1'): dependencies = { 'paramiko': [('ssh_login',), 'http://www.lag.net/paramiko/', '1.7.7.1'], - 'pycurl': [('http_fuzz',), 'http://pycurl.sourceforge.net/', '7.19.0'], + 'pycurl': [('http_fuzz',), 'http://pycurl.sourceforge.net/', '7.19.3'], + 'libcurl': [('http_fuzz',), 'https://curl.haxx.se/', '7.21.0'], 'ajpy': [('ajp_fuzz',), 'https://github.com/hypn0s/AJPy/', '0.0.1'], 'openldap': [('ldap_login',), 'http://www.openldap.org/', '2.4.24'], 'impacket': [('smb_login','smb_lookupsid','mssql_login'), 'https://github.com/CoreSecurity/impacket', '0.9.12'], From 7dee459c8b2807af6e8b3b171186be4272002b56 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Mon, 24 Apr 2017 15:36:51 +0100 Subject: [PATCH 05/21] Cleaned up the README --- README.md | 88 +++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 6dd107d..66367a7 100644 --- a/README.md +++ b/README.md @@ -3,42 +3,42 @@ Patator was written out of frustration from using Hydra, Medusa, Ncrack, Metaspl Currently it supports the following modules: ``` -* ftp_login : Brute-force FTP -* ssh_login : Brute-force SSH -* telnet_login : Brute-force Telnet -* smtp_login : Brute-force SMTP -* smtp_vrfy : Enumerate valid users using the SMTP VRFY command -* smtp_rcpt : Enumerate valid users using the SMTP RCPT TO command -* finger_lookup : Enumerate valid users using Finger -* http_fuzz : Brute-force HTTP/HTTPS -* ajp_fuzz : Brute-force AJP -* pop_login : Brute-force POP -* pop_passd : Brute-force poppassd (not POP3) -* imap_login : Brute-force IMAP -* ldap_login : Brute-force LDAP -* smb_login : Brute-force SMB -* smb_lookupsid : Brute-force SMB SID-lookup -* rlogin_login : Brute-force rlogin -* vmauthd_login : Brute-force VMware Authentication Daemon -* mssql_login : Brute-force MSSQL -* oracle_login : Brute-force Oracle -* mysql_login : Brute-force MySQL -* mysql_query : Brute-force MySQL queries -* rdp_login : Brute-force RDP (NLA) -* pgsql_login : Brute-force PostgreSQL -* vnc_login : Brute-force VNC -* dns_forward : Brute-force DNS -* dns_reverse : Brute-force DNS (reverse lookup subnets) -* ike_enum : Enumerate IKE transforms -* snmp_login : Brute-force SNMPv1/2 and SNMPv3 -* unzip_pass : Brute-force the password of encrypted ZIP files -* keystore_pass : Brute-force the password of Java keystore files -* umbraco_crack : Crack Umbraco HMAC-SHA1 password hashes +* `ftp_login` : Brute-force FTP +* `ssh_login` : Brute-force SSH +* `telnet_login` : Brute-force Telnet +* `smtp_login` : Brute-force SMTP +* `smtp_vrfy` : Enumerate valid users using the SMTP VRFY command +* `smtp_rcpt` : Enumerate valid users using the SMTP RCPT TO command +* `finger_lookup` : Enumerate valid users using Finger +* `http_fuzz` : Brute-force HTTP/HTTPS +* `ajp_fuzz` : Brute-force AJP +* `pop_login` : Brute-force POP +* `pop_passd` : Brute-force poppassd (not POP3) +* `imap_login` : Brute-force IMAP +* `ldap_login` : Brute-force LDAP +* `smb_login` : Brute-force SMB +* `smb_lookupsid` : Brute-force SMB SID-lookup +* `rlogin_login` : Brute-force rlogin +* `vmauthd_login` : Brute-force VMware Authentication Daemon +* `mssql_login` : Brute-force MSSQL +* `oracle_login` : Brute-force Oracle +* `mysql_login` : Brute-force MySQL +* `mysql_query` : Brute-force MySQL queries +* `rdp_login` : Brute-force RDP (NLA) +* `pgsql_login` : Brute-force PostgreSQL +* `vnc_login` : Brute-force VNC +* `dns_forward` : Brute-force DNS +* `dns_reverse` : Brute-force DNS (reverse lookup subnets) +* `ike_enum` : Enumerate IKE transforms +* `snmp_login` : Brute-force SNMPv1/2 and SNMPv3 +* `unzip_pass` : Brute-force the password of encrypted ZIP files +* `keystore_pass` : Brute-force the password of Java keystore files +* `umbraco_crack` : Crack Umbraco HMAC-SHA1 password hashes ``` The name "Patator" comes from https://www.youtube.com/watch?v=kU2yPJJdpag -Patator is NOT script-kiddie friendly, please read the README inside patator.py before reporting. +Patator is NOT script-kiddie friendly, please read the README inside `patator.py` before reporting. @lanjelot @@ -60,7 +60,7 @@ $ ftp_login host=10.0.0.1 user=FILE0 0=logins.txt password=asdf -x ignore:mesg=' ... ``` -Tested against vsftpd-3.0.2-9 on CentOS 7.0-1406 +Tested against `vsftpd-3.0.2-9` on `CentOS 7.0-1406` * SSH : Time-based user enumeration @@ -142,7 +142,7 @@ Tested against phpMyAdmin 4.2.7.1. ``` $ snmp_login host=10.0.0.1 version=3 user=FILE0 0=logins.txt -x ignore:mesg=unknownUserName 17:51:06 patator INFO - Starting Patator v0.5 -17:51:06 patator INFO - +17:51:06 patator INFO - 17:51:06 patator INFO - code size | candidate | num | mesg 17:51:06 patator INFO - ---------------------------------------------------------------------- 17:51:11 patator INFO - 0-0 11 | robert | 55 | wrongDigest @@ -156,7 +156,7 @@ $ snmp_login host=10.0.0.1 version=3 user=FILE0 0=logins.txt -x ignore:mesg=unkn ``` $ snmp_login host=10.0.0.1 version=3 user=robert auth_key=FILE0 0=passwords_8+.txt -x ignore:mesg=wrongDigest 17:52:15 patator INFO - Starting Patator v0.5 -17:52:15 patator INFO - +17:52:15 patator INFO - 17:52:15 patator INFO - code size | candidate | num | mesg 17:52:15 patator INFO - ---------------------------------------------------------------------- 17:52:16 patator INFO - 0-0 69 | password123 | 16 | Linux thug 2.6.36-gentoo #5 SMP Fri Aug 12 14:49:51 CEST 2011 i686 @@ -168,7 +168,7 @@ $ snmp_login host=10.0.0.1 version=3 user=robert auth_key=FILE0 0=passwords_8+.t ``` $ dns_forward name=FILE0.hsc.fr 0=names.txt -x ignore:code=3 03:18:46 patator INFO - Starting Patator v0.5 (http://code.google.com/p/patator/) at 2012-06-29 03:18 PMT -03:18:46 patator INFO - +03:18:46 patator INFO - 03:18:46 patator INFO - code size | candidate | num | mesg 03:18:46 patator INFO - ---------------------------------------------------------------------- 03:18:46 patator INFO - 0 41 | www | 4 | NOERROR [www.hsc.fr. IN A 217.174.211.25] @@ -222,7 +222,7 @@ Also notice that test.hsc.fr. is the start of a new zone because we got NOERROR ``` $ dns_reverse host=NET0 0=216.239.32.0-216.239.47.255,8.8.8.0/24 -x ignore:code=3 -x ignore:fgrep!=google.com -x ignore:fgrep=216-239- 03:24:22 patator INFO - Starting Patator v0.5 (http://code.google.com/p/patator/) at 2012-06-29 03:24 PMT -03:24:22 patator INFO - +03:24:22 patator INFO - 03:24:22 patator INFO - code size | candidate | num | mesg 03:24:22 patator INFO - ---------------------------------------------------------------------- 03:24:22 patator INFO - 0 46 | 216.239.32.10 | 11 | NOERROR [216.239.32.10 IN PTR ns1.google.com.] @@ -268,9 +268,9 @@ Networks ----------------------------------------- * ZIP : Crack a password-protected ZIP file (older pkzip encryption used not to be supported in JtR) ``` -$ unzip_pass zipfile=challenge1.zip password=FILE0 0=rockyou.dic -x ignore:code!=0 +$ unzip_pass zipfile=challenge1.zip password=FILE0 0=rockyou.dic -x ignore:code!=0 10:54:29 patator INFO - Starting Patator v0.5 (http://code.google.com/p/patator/) at 2012-06-29 10:54:29 PMT -10:54:29 patator INFO - +10:54:29 patator INFO - 10:54:29 patator INFO - code size | candidate | num | mesg 10:54:29 patator INFO - ---------------------------------------------------------------------- 10:54:30 patator INFO - 0 82 | love | 387 | 0 [82] No errors detected in compressed data of challenge1.zip. @@ -282,11 +282,11 @@ $ unzip_pass zipfile=challenge1.zip password=FILE0 0=rockyou.dic -x ignore:code! ## 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`. +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 From cbf7be1d129afb8d24da4639a7c31362907fcf90 Mon Sep 17 00:00:00 2001 From: lanjelot Date: Fri, 2 Jun 2017 08:35:08 +1000 Subject: [PATCH 06/21] Fix xml output --- README.md | 62 +++++++++++++++++++++++++++--------------------------- patator.py | 8 ++++--- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 66367a7..ff36a6c 100644 --- a/README.md +++ b/README.md @@ -3,37 +3,37 @@ Patator was written out of frustration from using Hydra, Medusa, Ncrack, Metaspl Currently it supports the following modules: ``` -* `ftp_login` : Brute-force FTP -* `ssh_login` : Brute-force SSH -* `telnet_login` : Brute-force Telnet -* `smtp_login` : Brute-force SMTP -* `smtp_vrfy` : Enumerate valid users using the SMTP VRFY command -* `smtp_rcpt` : Enumerate valid users using the SMTP RCPT TO command -* `finger_lookup` : Enumerate valid users using Finger -* `http_fuzz` : Brute-force HTTP/HTTPS -* `ajp_fuzz` : Brute-force AJP -* `pop_login` : Brute-force POP -* `pop_passd` : Brute-force poppassd (not POP3) -* `imap_login` : Brute-force IMAP -* `ldap_login` : Brute-force LDAP -* `smb_login` : Brute-force SMB -* `smb_lookupsid` : Brute-force SMB SID-lookup -* `rlogin_login` : Brute-force rlogin -* `vmauthd_login` : Brute-force VMware Authentication Daemon -* `mssql_login` : Brute-force MSSQL -* `oracle_login` : Brute-force Oracle -* `mysql_login` : Brute-force MySQL -* `mysql_query` : Brute-force MySQL queries -* `rdp_login` : Brute-force RDP (NLA) -* `pgsql_login` : Brute-force PostgreSQL -* `vnc_login` : Brute-force VNC -* `dns_forward` : Brute-force DNS -* `dns_reverse` : Brute-force DNS (reverse lookup subnets) -* `ike_enum` : Enumerate IKE transforms -* `snmp_login` : Brute-force SNMPv1/2 and SNMPv3 -* `unzip_pass` : Brute-force the password of encrypted ZIP files -* `keystore_pass` : Brute-force the password of Java keystore files -* `umbraco_crack` : Crack Umbraco HMAC-SHA1 password hashes +* ftp_login : Brute-force FTP +* ssh_login : Brute-force SSH +* telnet_login : Brute-force Telnet +* smtp_login : Brute-force SMTP +* smtp_vrfy : Enumerate valid users using the SMTP VRFY command +* smtp_rcpt : Enumerate valid users using the SMTP RCPT TO command +* finger_lookup : Enumerate valid users using Finger +* http_fuzz : Brute-force HTTP/HTTPS +* ajp_fuzz : Brute-force AJP +* pop_login : Brute-force POP +* pop_passd : Brute-force poppassd (not POP3) +* imap_login : Brute-force IMAP +* ldap_login : Brute-force LDAP +* smb_login : Brute-force SMB +* smb_lookupsid : Brute-force SMB SID-lookup +* rlogin_login : Brute-force rlogin +* vmauthd_login : Brute-force VMware Authentication Daemon +* mssql_login : Brute-force MSSQL +* oracle_login : Brute-force Oracle +* mysql_login : Brute-force MySQL +* mysql_query : Brute-force MySQL queries +* rdp_login : Brute-force RDP (NLA) +* pgsql_login : Brute-force PostgreSQL +* vnc_login : Brute-force VNC +* dns_forward : Brute-force DNS +* dns_reverse : Brute-force DNS (reverse lookup subnets) +* ike_enum : Enumerate IKE transforms +* snmp_login : Brute-force SNMPv1/2 and SNMPv3 +* unzip_pass : Brute-force the password of encrypted ZIP files +* keystore_pass : Brute-force the password of Java keystore files +* umbraco_crack : Crack Umbraco HMAC-SHA1 password hashes ``` The name "Patator" comes from https://www.youtube.com/watch?v=kU2yPJJdpag diff --git a/patator.py b/patator.py index a7c072d..e793a87 100755 --- a/patator.py +++ b/patator.py @@ -789,9 +789,11 @@ def process_logs(queue, indicatorsfmt, argv, log_dir): f.write('\n') else: # remove "..." - with open(results_xml, 'r+') as f: - f.seek(f.read().find('')) - f.truncate(f.tell()) + with open(results_xml, 'r+b') as f: + offset = f.read().find('') + if offset != -1: + f.seek(offset) + f.truncate(f.tell()) handler_log = logging.FileHandler(runtime_log) handler_csv = logging.FileHandler(results_csv) From aa232dd7e6f59b4cb95777f5da196b6a0e46c7e7 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 8 Jun 2017 19:48:02 +0200 Subject: [PATCH 07/21] SOCKS support and "resolve" option in http_fuzz This commit brings the SOCKS support to the http_fuzz module and the "resolve" parameter that prevent many dns resolution if you already know it (more stylish than overriding the "Host" header :]) --- patator.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/patator.py b/patator.py index e793a87..7cec304 100755 --- a/patator.py +++ b/patator.py @@ -3440,7 +3440,9 @@ class HTTP_fuzz(TCP_Cache): ('follow', 'follow any Location redirect [0|1]'), ('max_follow', 'redirection limit [5]'), ('accept_cookie', 'save received cookies to issue them in future requests [0|1]'), - ('http_proxy', 'HTTP proxy to use (host:port)'), + ('proxy', 'Proxy to use (host:port)'), + ('proxy_type', 'Proxy type [http|socks4|socks4a|socks5] (default: http)'), + ('resolve', 'DNS resolution if known (HOST:IP)'), ('ssl_cert', 'client SSL certificate file (cert+key in PEM format)'), ('timeout_tcp', 'seconds to wait for a TCP handshake [10]'), ('timeout', 'seconds to wait for a HTTP response [20]'), @@ -3454,6 +3456,14 @@ class HTTP_fuzz(TCP_Cache): Response = Response_HTTP + proxytype_mapping = { + "http": pycurl.PROXYTYPE_HTTP, + "socks4": pycurl.PROXYTYPE_SOCKS4, + "socks4a": pycurl.PROXYTYPE_SOCKS4A, + "socks5": pycurl.PROXYTYPE_SOCKS5, + "socks5_with_hostname": pycurl.PROXYTYPE_SOCKS5_HOSTNAME, + } + def connect(self, host, port, scheme): fp = pycurl.Curl() fp.setopt(pycurl.SSL_VERIFYPEER, 0) @@ -3466,7 +3476,7 @@ def connect(self, host, port, scheme): def execute(self, url=None, host=None, port='', scheme='http', path='/', params='', query='', fragment='', body='', header='', method='GET', auto_urlencode='1', user_pass='', auth_type='basic', - follow='0', max_follow='5', accept_cookie='0', http_proxy='', ssl_cert='', timeout_tcp='10', timeout='20', persistent='1', + follow='0', max_follow='5', accept_cookie='0', proxy='', proxy_type='http', resolve='', ssl_cert='', timeout_tcp='10', timeout='20', persistent='1', before_urls='', before_header='', before_egrep='', after_urls='', max_mem='-1'): if url: @@ -3475,13 +3485,29 @@ def execute(self, url=None, host=None, port='', scheme='http', path='/', params= host, port = host.split(':') del url + if resolve: + resolve_host, resolve_ip = resolve.split(":") + if port: + resolve_port = port + else: + resolve_port = 80 + + resolve = "%s:%s:%s" % (resolve_host, resolve_port, resolve_ip) + + if proxy_type in HTTP_fuzz.proxytype_mapping: + proxy_type = HTTP_fuzz.proxytype_mapping[proxy_type] + else: + raise ValueError("invalid proxy type.") + fp, _ = self.bind(host, port, scheme) fp.setopt(pycurl.FOLLOWLOCATION, int(follow)) fp.setopt(pycurl.MAXREDIRS, int(max_follow)) fp.setopt(pycurl.CONNECTTIMEOUT, int(timeout_tcp)) fp.setopt(pycurl.TIMEOUT, int(timeout)) - fp.setopt(pycurl.PROXY, http_proxy) + fp.setopt(pycurl.PROXY, proxy) + fp.setopt(pycurl.PROXYTYPE, proxy_type) + fp.setopt(pycurl.RESOLVE, [resolve]) def noop(buf): pass fp.setopt(pycurl.WRITEFUNCTION, noop) From 5af1f397c22bc83703e050e770c30ebe3b44f925 Mon Sep 17 00:00:00 2001 From: lanjelot Date: Fri, 9 Jun 2017 15:11:26 +1000 Subject: [PATCH 08/21] Polishing #64 --- patator.py | 72 +++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/patator.py b/patator.py index 7cec304..88b3428 100755 --- a/patator.py +++ b/patator.py @@ -1049,13 +1049,13 @@ class RangeIter: def __init__(self, typ, rng, random=None): if typ not in ['hex', 'int', 'float', 'letters', 'lower', 'lowercase', 'upper', 'uppercase']: - raise ValueError("Incorrect range type '%s'" % typ) + raise ValueError('Incorrect range type %r' % typ) if typ in ('hex', 'int', 'float'): m = re.match('(-?[^-]+)-(-?[^-]+)$', rng) # 5-50 or -5-50 or 5--50 or -5--50 if not m: - raise ValueError("Unsupported range '%s'" % rng) + raise ValueError('Unsupported range %r' % rng) mn = m.group(1) mx = m.group(2) @@ -1504,7 +1504,7 @@ def update_actions(self, arg): name, opts = action, None if name not in self.available_actions: - raise ValueError('Unsupported action: %s' % name) + raise ValueError('Unsupported action %r' % name) if name not in ns_actions: ns_actions[name] = [] @@ -1698,7 +1698,7 @@ def abort(msg): iterable, size = chain(it), int(size) else: - return abort("Incorrect keyword '%s'" % t) + return abort('Incorrect keyword %r' % t) total_size *= size iterables.append(iterable) @@ -2335,7 +2335,7 @@ def execute(self, host, port='22', user=None, password=None, auth_type='password fp.auth_password(user, password, fallback=True) else: - raise ValueError("Incorrect auth_type '%s'" % auth_type) + raise ValueError('Incorrect auth_type %r' % auth_type) logger.debug('No error') code, mesg = '0', banner @@ -2390,7 +2390,7 @@ def execute(self, host, port='23', inputs=None, prompt_re='\w+:', timeout='20', if self.prompt_count == 0: _, _, raw = fp.expect([prompt_re], timeout=timeout) - logger.debug('raw banner: %s' % repr(raw)) + logger.debug('raw banner: %r' % raw) trace += raw self.prompt_count += 1 @@ -2403,7 +2403,7 @@ def execute(self, host, port='23', inputs=None, prompt_re='\w+:', timeout='20', trace += cmd _, _, raw = fp.expect([prompt_re], timeout=timeout) - logger.debug('raw %d: %s' % (self.prompt_count, repr(raw))) + logger.debug('raw %d: %r' % (self.prompt_count, raw)) trace += raw self.prompt_count += 1 @@ -2604,7 +2604,7 @@ def execute(self, host, port='79', user='', timeout='5'): s.close() - logger.debug('recv: %s' % repr(data)) + logger.debug('recv: %r' % data) data = data.strip() mesg = repr(data) @@ -3070,7 +3070,7 @@ def getresp(self): code, _ = self.parse(resp) if not code.isdigit(): - raise Exception('Unexpected response: %s' % resp) + raise Exception('Unexpected response: %r' % resp) if code[0] not in ('1', '2', '3'): raise LineReceiver_Error(resp) @@ -3309,7 +3309,7 @@ def execute(self, host, port='1521', user='', password='', sid='', service_name= elif service_name: dsn = cx_Oracle.makedsn(host=host, port=port, service_name=service_name) else: - raise ValueError("Options sid and service_name cannot be both empty") + raise ValueError('Options sid and service_name cannot be both empty') try: with Timing() as timing: @@ -3440,9 +3440,9 @@ class HTTP_fuzz(TCP_Cache): ('follow', 'follow any Location redirect [0|1]'), ('max_follow', 'redirection limit [5]'), ('accept_cookie', 'save received cookies to issue them in future requests [0|1]'), - ('proxy', 'Proxy to use (host:port)'), - ('proxy_type', 'Proxy type [http|socks4|socks4a|socks5] (default: http)'), - ('resolve', 'DNS resolution if known (HOST:IP)'), + ('proxy', 'proxy to use (host:port)'), + ('proxy_type', 'proxy type [http|socks4|socks4a|socks5] (default: http)'), + ('resolve', 'hostname to IP address resolution to use (hostname:IP)'), ('ssl_cert', 'client SSL certificate file (cert+key in PEM format)'), ('timeout_tcp', 'seconds to wait for a TCP handshake [10]'), ('timeout', 'seconds to wait for a HTTP response [20]'), @@ -3457,11 +3457,11 @@ class HTTP_fuzz(TCP_Cache): Response = Response_HTTP proxytype_mapping = { - "http": pycurl.PROXYTYPE_HTTP, - "socks4": pycurl.PROXYTYPE_SOCKS4, - "socks4a": pycurl.PROXYTYPE_SOCKS4A, - "socks5": pycurl.PROXYTYPE_SOCKS5, - "socks5_with_hostname": pycurl.PROXYTYPE_SOCKS5_HOSTNAME, + 'http': pycurl.PROXYTYPE_HTTP, + 'socks4': pycurl.PROXYTYPE_SOCKS4, + 'socks4a': pycurl.PROXYTYPE_SOCKS4A, + 'socks5': pycurl.PROXYTYPE_SOCKS5, + 'socks5_with_hostname': pycurl.PROXYTYPE_SOCKS5_HOSTNAME, } def connect(self, host, port, scheme): @@ -3486,18 +3486,18 @@ def execute(self, url=None, host=None, port='', scheme='http', path='/', params= del url if resolve: - resolve_host, resolve_ip = resolve.split(":") - if port: - resolve_port = port - else: - resolve_port = 80 + resolve_host, resolve_ip = resolve.split(':', 1) + if port: + resolve_port = port + else: + resolve_port = 80 - resolve = "%s:%s:%s" % (resolve_host, resolve_port, resolve_ip) + resolve = '%s:%s:%s' % (resolve_host, resolve_port, resolve_ip) if proxy_type in HTTP_fuzz.proxytype_mapping: - proxy_type = HTTP_fuzz.proxytype_mapping[proxy_type] + proxy_type = HTTP_fuzz.proxytype_mapping[proxy_type] else: - raise ValueError("invalid proxy type.") + raise ValueError('Invalid proxy_type %r' % proxy_type) fp, _ = self.bind(host, port, scheme) @@ -3538,7 +3538,7 @@ def debug_func(t, s): elif auth_type == 'ntlm': fp.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_NTLM) else: - raise ValueError("Incorrect auth_type '%s'" % auth_type) + raise ValueError('Incorrect auth_type %r' % auth_type) if ssl_cert: fp.setopt(pycurl.SSLCERT, ssl_cert) @@ -3795,7 +3795,7 @@ def connect(self, host, port, timeout): self.fp = socket.create_connection((host, port), timeout=timeout) resp = self.fp.recv(99) # banner - logger.debug('banner: %s' % repr(resp)) + logger.debug('banner: %r' % resp) self.version = resp[:11].decode('ascii') if len(resp) > 12: @@ -3822,7 +3822,7 @@ def login(self, password): sleep(0.5) resp = self.fp.recv(99) - logger.debug('Security types supported: %s' % repr(resp)) + logger.debug('Security types supported: %r' % resp) if major == '4' or (major == '3' and int(minor) >= 7): code = ord(resp[0:1]) @@ -3842,20 +3842,20 @@ def login(self, password): if len(resp) != 16: raise VNC_Error('Unexpected challenge size (No authentication required? Unsupported authentication type?)') - logger.debug('challenge: %s' % repr(resp)) + logger.debug('challenge: %r' % resp) pw = password.ljust(8, '\x00')[:8] # make sure it is 8 chars long, zero padded key = self.gen_key(pw) - logger.debug('key: %s' % repr(key)) + logger.debug('key: %r' % key) des = DES.new(key, DES.MODE_ECB) enc = des.encrypt(resp) - logger.debug('enc: %s' % repr(enc)) + logger.debug('enc: %r' % enc) self.fp.sendall(enc) resp = self.fp.recv(99) - logger.debug('resp: %s' % repr(resp)) + logger.debug('resp: %r' % resp) code = ord(resp[3:4]) mesg = resp[8:].decode('ascii', 'ignore') @@ -3867,7 +3867,7 @@ def login(self, password): return code, mesg or 'OK' else: - raise VNC_Error('Unknown response: %s (code: %s)' % (repr(resp), code)) + raise VNC_Error('Unknown response: %r (code: %s)' % (resp, code)) def gen_key(self, key): @@ -4316,7 +4316,7 @@ def execute(self, host, port=None, version='2', community='public', user='myuser return self.Response('1', 'SNMPv3 requires passphrases to be at least 8 characters long') else: - raise ValueError("Incorrect SNMP version '%s'" % version) + raise ValueError('Incorrect SNMP version %r' % version) with Timing() as timing: errorIndication, errorStatus, errorIndex, varBinds = cmdgen.CommandGenerator().getCmd( @@ -4446,7 +4446,7 @@ def execute(self, host, port='500', transform='5,1,1,2', aggressive='0', groupna code = p.returncode trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err) - logger.debug('trace: %s' % repr(trace)) + logger.debug('trace: %r' % trace) has_sa = 'SA=(' in out if has_sa: From 02783fb3d02baa471eda96dfd04a76c40c55f119 Mon Sep 17 00:00:00 2001 From: lanjelot Date: Fri, 16 Jun 2017 18:07:08 +1000 Subject: [PATCH 09/21] Add raw_request option to http_fuzz #61 --- patator.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/patator.py b/patator.py index 88b3428..c8d1b7e 100755 --- a/patator.py +++ b/patator.py @@ -1421,7 +1421,8 @@ def __init__(self, module, argv): else: if v.startswith('@'): p = expand_path(v[1:]) - v = open(p).read() + with open(p) as f: + v = f.read() kargs.append((k, v)) iter_vals = [v for k, v in sorted(wlists.items())] @@ -3373,7 +3374,6 @@ def execute(self, host, port='5432', user=None, password=None, database='postgre except ImportError: notfound.append('pycurl') - class Response_HTTP(Response_Base): indicatorsfmt = [('code', -4), ('size:clen', -13), ('time', 6)] @@ -3410,6 +3410,54 @@ def str_target(self): ('clen', 'match Content-Length header (N or N-M or N- or -N)'), ) +from BaseHTTPServer import BaseHTTPRequestHandler +class HTTPRequestParser(BaseHTTPRequestHandler): + def __init__(self, fd): + self.rfile = fd + self.error = None + self.body = None + self.raw_requestline = self.rfile.readline() + self.parse_request() + + if self.command == 'POST': + self.body = self.rfile.read(-1).rstrip('\r\n') + if 'Content-Length' in self.headers: + del self.headers['Content-Length'] + + def send_error(self, code, message): + self.error = message + +class Controller_HTTP(Controller): + + def expand_key(self, arg): + key, val = arg.split('=', 1) + if key == 'raw_request': + + with open(val) as fd: + r = HTTPRequestParser(fd) + + if r.error: + raise ValueError('Failed to parse file %r as a raw HTTP request' % val, r.error) + + opts = {} + + if r.path.startswith('http'): + opts['url'] = r.path + else: + _, _, opts['path'], opts['params'], opts['query'], opts['fragment'] = urlparse(r.path) + opts['host'] = r.headers['Host'] + + opts['header'] = str(r.headers) + opts['method'] = r.command + opts['body'] = r.body + + for key, val in opts.iteritems(): + if val: + yield (key, val) + + else: + yield (key, val) + class HTTP_fuzz(TCP_Cache): '''Brute-force HTTP''' @@ -3428,12 +3476,13 @@ class HTTP_fuzz(TCP_Cache): ('url', 'target url (scheme://host[:port]/path?query)'), #('host', 'target host'), #('port', 'target port'), - #('scheme', 'scheme [http | https]'), #('path', 'web path [/]'), #('query', 'query string'), ('body', 'body data'), ('header', 'use custom headers'), - ('method', 'method to use [GET | POST | HEAD | ...]'), + ('method', 'method to use [GET|POST|HEAD|...]'), + ('raw_request', 'load request from file'), + ('scheme', 'scheme [http|https]'), ('auto_urlencode', 'automatically perform URL-encoding [1|0]'), ('user_pass', 'username and password for HTTP authentication (user:pass)'), ('auth_type', 'type of HTTP authentication [basic | digest | ntlm]'), @@ -3441,7 +3490,7 @@ class HTTP_fuzz(TCP_Cache): ('max_follow', 'redirection limit [5]'), ('accept_cookie', 'save received cookies to issue them in future requests [0|1]'), ('proxy', 'proxy to use (host:port)'), - ('proxy_type', 'proxy type [http|socks4|socks4a|socks5] (default: http)'), + ('proxy_type', 'proxy type [http|socks4|socks4a|socks5]'), ('resolve', 'hostname to IP address resolution to use (hostname:IP)'), ('ssl_cert', 'client SSL certificate file (cert+key in PEM format)'), ('timeout_tcp', 'seconds to wait for a TCP handshake [10]'), @@ -3481,9 +3530,11 @@ def execute(self, url=None, host=None, port='', scheme='http', path='/', params= if url: scheme, host, path, params, query, fragment = urlparse(url) + del url + + if host: if ':' in host: host, port = host.split(':') - del url if resolve: resolve_host, resolve_ip = resolve.split(':', 1) @@ -4640,7 +4691,7 @@ def execute(self, data, data2='', delay='1'): ('smtp_vrfy', (Controller, SMTP_vrfy)), ('smtp_rcpt', (Controller, SMTP_rcpt)), ('finger_lookup', (Controller_Finger, Finger_lookup)), - ('http_fuzz', (Controller, HTTP_fuzz)), + ('http_fuzz', (Controller_HTTP, HTTP_fuzz)), ('ajp_fuzz', (Controller, AJP_fuzz)), ('pop_login', (Controller, POP_login)), ('pop_passd', (Controller, POP_passd)), From 5c224380c5f788169a7043d626a2f6310910fd1f Mon Sep 17 00:00:00 2001 From: lanjelot Date: Mon, 21 Aug 2017 16:36:11 +1000 Subject: [PATCH 10/21] Add more Windows info --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ff36a6c..13701ec 100644 --- a/README.md +++ b/README.md @@ -305,3 +305,5 @@ 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. + +Refer to [#50](https://github.com/lanjelot/patator/issues/50) for more info. From b4fb10ae6bc43a8ab3de76c596ad09c7fd2a1c8f Mon Sep 17 00:00:00 2001 From: lanjelot Date: Tue, 29 Aug 2017 12:00:49 +1000 Subject: [PATCH 11/21] New sqlcipher_pass module --- README.md | 63 ++++++++++++++--------------- patator.py | 114 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 110 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 13701ec..cabfb48 100644 --- a/README.md +++ b/README.md @@ -3,37 +3,38 @@ Patator was written out of frustration from using Hydra, Medusa, Ncrack, Metaspl Currently it supports the following modules: ``` -* ftp_login : Brute-force FTP -* ssh_login : Brute-force SSH -* telnet_login : Brute-force Telnet -* smtp_login : Brute-force SMTP -* smtp_vrfy : Enumerate valid users using the SMTP VRFY command -* smtp_rcpt : Enumerate valid users using the SMTP RCPT TO command -* finger_lookup : Enumerate valid users using Finger -* http_fuzz : Brute-force HTTP/HTTPS -* ajp_fuzz : Brute-force AJP -* pop_login : Brute-force POP -* pop_passd : Brute-force poppassd (not POP3) -* imap_login : Brute-force IMAP -* ldap_login : Brute-force LDAP -* smb_login : Brute-force SMB -* smb_lookupsid : Brute-force SMB SID-lookup -* rlogin_login : Brute-force rlogin -* vmauthd_login : Brute-force VMware Authentication Daemon -* mssql_login : Brute-force MSSQL -* oracle_login : Brute-force Oracle -* mysql_login : Brute-force MySQL -* mysql_query : Brute-force MySQL queries -* rdp_login : Brute-force RDP (NLA) -* pgsql_login : Brute-force PostgreSQL -* vnc_login : Brute-force VNC -* dns_forward : Brute-force DNS -* dns_reverse : Brute-force DNS (reverse lookup subnets) -* ike_enum : Enumerate IKE transforms -* snmp_login : Brute-force SNMPv1/2 and SNMPv3 -* unzip_pass : Brute-force the password of encrypted ZIP files -* keystore_pass : Brute-force the password of Java keystore files -* umbraco_crack : Crack Umbraco HMAC-SHA1 password hashes +* ftp_login : Brute-force FTP +* ssh_login : Brute-force SSH +* telnet_login : Brute-force Telnet +* smtp_login : Brute-force SMTP +* smtp_vrfy : Enumerate valid users using the SMTP VRFY command +* smtp_rcpt : Enumerate valid users using the SMTP RCPT TO command +* finger_lookup : Enumerate valid users using Finger +* http_fuzz : Brute-force HTTP/HTTPS +* ajp_fuzz : Brute-force AJP +* pop_login : Brute-force POP +* pop_passd : Brute-force poppassd (not POP3) +* imap_login : Brute-force IMAP +* ldap_login : Brute-force LDAP +* smb_login : Brute-force SMB +* smb_lookupsid : Brute-force SMB SID-lookup +* rlogin_login : Brute-force rlogin +* vmauthd_login : Brute-force VMware Authentication Daemon +* mssql_login : Brute-force MSSQL +* oracle_login : Brute-force Oracle +* mysql_login : Brute-force MySQL +* mysql_query : Brute-force MySQL queries +* rdp_login : Brute-force RDP (NLA) +* pgsql_login : Brute-force PostgreSQL +* vnc_login : Brute-force VNC +* dns_forward : Brute-force DNS +* dns_reverse : Brute-force DNS (reverse lookup subnets) +* ike_enum : Enumerate IKE transforms +* snmp_login : Brute-force SNMPv1/2 and SNMPv3 +* unzip_pass : Brute-force the password of encrypted ZIP files +* keystore_pass : Brute-force the password of Java keystore files +* sqlcipher_pass : Brute-force the password of SQLCipher-encrypted databases +* umbraco_crack : Crack Umbraco HMAC-SHA1 password hashes ``` The name "Patator" comes from https://www.youtube.com/watch?v=kU2yPJJdpag diff --git a/patator.py b/patator.py index c8d1b7e..b8ab401 100755 --- a/patator.py +++ b/patator.py @@ -31,42 +31,43 @@ Patator is a multi-purpose brute-forcer, with a modular design and a flexible usage. Currently it supports the following modules: - + ftp_login : Brute-force FTP - + ssh_login : Brute-force SSH - + telnet_login : Brute-force Telnet - + smtp_login : Brute-force SMTP - + smtp_vrfy : Enumerate valid users using SMTP VRFY - + smtp_rcpt : Enumerate valid users using SMTP RCPT TO - + finger_lookup : Enumerate valid users using Finger - + http_fuzz : Brute-force HTTP - + ajp_fuzz : Brute-force AJP - + pop_login : Brute-force POP3 - + pop_passd : Brute-force poppassd (http://netwinsite.com/poppassd/) - + imap_login : Brute-force IMAP4 - + ldap_login : Brute-force LDAP - + smb_login : Brute-force SMB - + smb_lookupsid : Brute-force SMB SID-lookup - + rlogin_login : Brute-force rlogin - + vmauthd_login : Brute-force VMware Authentication Daemon - + mssql_login : Brute-force MSSQL - + oracle_login : Brute-force Oracle - + mysql_login : Brute-force MySQL - + mysql_query : Brute-force MySQL queries - * rdp_login : Brute-force RDP (NLA) - + pgsql_login : Brute-force PostgreSQL - + vnc_login : Brute-force VNC - - + dns_forward : Forward DNS lookup - + dns_reverse : Reverse DNS lookup - + snmp_login : Brute-force SNMP v1/2/3 - + ike_enum : Enumerate IKE transforms - - + unzip_pass : Brute-force the password of encrypted ZIP files - + keystore_pass : Brute-force the password of Java keystore files - + umbraco_crack : Crack Umbraco HMAC-SHA1 password hashes - - + tcp_fuzz : Fuzz TCP services - + dummy_test : Testing module + + ftp_login : Brute-force FTP + + ssh_login : Brute-force SSH + + telnet_login : Brute-force Telnet + + smtp_login : Brute-force SMTP + + smtp_vrfy : Enumerate valid users using SMTP VRFY + + smtp_rcpt : Enumerate valid users using SMTP RCPT TO + + finger_lookup : Enumerate valid users using Finger + + http_fuzz : Brute-force HTTP + + ajp_fuzz : Brute-force AJP + + pop_login : Brute-force POP3 + + pop_passd : Brute-force poppassd (http://netwinsite.com/poppassd/) + + imap_login : Brute-force IMAP4 + + ldap_login : Brute-force LDAP + + smb_login : Brute-force SMB + + smb_lookupsid : Brute-force SMB SID-lookup + + rlogin_login : Brute-force rlogin + + vmauthd_login : Brute-force VMware Authentication Daemon + + mssql_login : Brute-force MSSQL + + oracle_login : Brute-force Oracle + + mysql_login : Brute-force MySQL + + mysql_query : Brute-force MySQL queries + * rdp_login : Brute-force RDP (NLA) + + pgsql_login : Brute-force PostgreSQL + + vnc_login : Brute-force VNC + + + dns_forward : Forward DNS lookup + + dns_reverse : Reverse DNS lookup + + snmp_login : Brute-force SNMP v1/2/3 + + ike_enum : Enumerate IKE transforms + + + unzip_pass : Brute-force the password of encrypted ZIP files + + keystore_pass : Brute-force the password of Java keystore files + + sqlcipher_pass : Brute-force the password of SQLCipher-encrypted databases + + umbraco_crack : Crack Umbraco HMAC-SHA1 password hashes + + + tcp_fuzz : Fuzz TCP services + + dummy_test : Testing module Future modules to be implemented: - rdp_login w/no NLA @@ -160,6 +161,8 @@ -------------------------------------------------------------------------------------------------- Java | keystore files | http://www.oracle.com/technetwork/java/javase/ | 6 | -------------------------------------------------------------------------------------------------- +pysqlcipher | SQLCipher | https://github.com/leapcode/pysqlcipher/ | 2.6.10 | +-------------------------------------------------------------------------------------------------- python | | http://www.python.org/ | 2.7 | -------------------------------------------------------------------------------------------------- @@ -4590,6 +4593,43 @@ def execute(self, keystore, password, storetype='jks'): # }}} +# SQLCipher {{{ +try: + from pysqlcipher import dbapi2 as sqlcipher +except ImportError: + notfound.append('pysqlcipher') + +class SQLCipher_pass: + '''Brute-force the password of SQLCipher-encrypted databases''' + + usage_hints = [ + """%prog database=path/to/db.sqlite password=FILE0 0=passwords.txt -x ignore:fgrep='file is encrypted'""", + ] + + available_options = ( + ('database', 'database files to test'), + ('password', 'passwords to test'), + ) + available_actions = () + + Response = Response_Base + + def execute(self, database, password): + with sqlcipher.connect(database) as db: + c = db.cursor() + c.execute('PRAGMA key=%r' % password) + + try: + c.execute('PRAGMA integrity_check') + code, mesg = '0', 'OK' + + except sqlcipher.DatabaseError as e: + code, mesg = '1', str(e) + + return self.Response(code, mesg) + +# }}} + # Umbraco {{{ import hmac class Umbraco_crack: @@ -4716,6 +4756,7 @@ def execute(self, data, data2='', delay='1'): ('unzip_pass', (Controller, Unzip_pass)), ('keystore_pass', (Controller, Keystore_pass)), + ('sqlcipher_pass', (Controller, SQLCipher_pass)), ('umbraco_crack', (Controller, Umbraco_crack)), ('tcp_fuzz', (Controller, TCP_fuzz)), @@ -4740,6 +4781,7 @@ def execute(self, data, data2='', delay='1'): 'ike-scan': [('ike_enum',), 'http://www.nta-monitor.com/tools-resources/security-tools/ike-scan', '1.9'], 'unzip': [('unzip_pass',), 'http://www.info-zip.org/', '6.0'], 'java': [('keystore_pass',), 'http://www.oracle.com/technetwork/java/javase/', '6'], + 'pysqlcipher': [('sqlcipher_pass',), 'https://github.com/leapcode/pysqlcipher/', '2.6.10'], 'ftp-tls': [('ftp_login',), 'TLS support unavailable before python 2.7'], } # }}} From b2384baaa0ff9e13cf303f3490941158a1b98824 Mon Sep 17 00:00:00 2001 From: bastien Date: Tue, 29 Aug 2017 11:28:08 +0200 Subject: [PATCH 12/21] Update README.md missing dep --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cabfb48..aa9c960 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,7 @@ pip install impacket pip install paramiko pip install IPy pip install dnspython +pip install pysnmp cd c:\ git clone https://github.com/lanjelot/patator From a903eeb191bd01e24077f5696451b47155576a0b Mon Sep 17 00:00:00 2001 From: lanjelot Date: Mon, 4 Dec 2017 20:48:12 +1000 Subject: [PATCH 13/21] Add LICENSE --- LICENSE | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. From f82ccd307b394d56645a24fba74f9d4c8e78e7ad Mon Sep 17 00:00:00 2001 From: lanjelot Date: Sun, 10 Dec 2017 17:19:03 +1000 Subject: [PATCH 14/21] Fixes #80 --- patator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patator.py b/patator.py index b8ab401..2fd089d 100755 --- a/patator.py +++ b/patator.py @@ -773,7 +773,7 @@ def process_logs(queue, indicatorsfmt, argv, log_dir): while i < len(argv): arg = argv[i] if arg[0] == '-': - if arg in ('-d', '--debug'): + if arg in ('-d', '--debug', '--allow-ignore-failures'): f.write('