From ab2d2c98fabe137b65eac16e01a55fd2a36fd1fc Mon Sep 17 00:00:00 2001 From: kimocoder Date: Mon, 20 Jan 2020 09:59:24 +0100 Subject: [PATCH 1/3] First push for migration to python3 --- __pycache__/pyrit_cli.cpython-37.pyc | Bin 0 -> 49073 bytes cpyrit/__init__.pyc | Bin 0 -> 153 bytes cpyrit/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 145 bytes cpyrit/config.py | 4 +- cpyrit/cpyrit.py | 54 +-- cpyrit/cpyrit.pyc | Bin 0 -> 32463 bytes cpyrit/network.py | 33 +- cpyrit/pckttools.py | 30 +- cpyrit/storage.py | 63 +-- cpyrit/util.py | 28 +- pyrit_cli.py | 54 ++- pyrit_cli.pyc | Bin 0 -> 55937 bytes setup.py | 4 +- test/test_pyrit.py | 42 +- test/test_pyrit.py.bak | 511 +++++++++++++++++++++ 15 files changed, 670 insertions(+), 153 deletions(-) create mode 100644 __pycache__/pyrit_cli.cpython-37.pyc create mode 100644 cpyrit/__init__.pyc create mode 100644 cpyrit/__pycache__/__init__.cpython-37.pyc create mode 100644 cpyrit/cpyrit.pyc mode change 100644 => 100755 pyrit_cli.py create mode 100644 pyrit_cli.pyc create mode 100755 test/test_pyrit.py.bak diff --git a/__pycache__/pyrit_cli.cpython-37.pyc b/__pycache__/pyrit_cli.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4a4864eae8a395e137289414546ec39f7215df27 GIT binary patch literal 49073 zcmeIbdvILWc_-NKZZsNCf*?rI(iJ5>nj%0_c4!%*Btjr5)22We1VyPW8E)WS01Y&{ zfqT12;HKg6NQ$ClWs8%^W)sJo1v8$hog|xiWilR*$LrnkWNWj#nQS(j$@I>{<)l(0 zSIw3yn?F)2*Vg`i-#Pcy03}hQn%b>eO1OPr=iGD8J?Hy=-}5}%)02^b7m; z#bbZM1Mgo7I~VZhyoHS!Gvn1*N&Uu4aXC(u67riYCFM6&O381!l$PI2DI>qxQdWL* zrJVeBmGbi2t$z#px2KeUE@mdoG1IIyDr?py+pgPF#bi4-H&-jKS#xvk{M_7H z-E3C5UznTQXqKz$%HNLJ8B`~mcTb*PuCH0AS1W7vg}Q0kr!QL0YNNh>T53PN&S%Um zR4ZfHOQ6(IwuU>oxEx2Cdl=_0@P^lMN6=g|@p=rMnKV;YY9(!^7gJ`&%)TB+N9N2f zT+5nyvm3uTvtZ@sy38K47e{%s&&uPd-yFbEw>fC;!*9W?n)}URluzZNqeH$VP* z?6r7l#QcOcqR*|HKVhDGJ&v;n%}-hfQSJ%zQz&=H95*OWTf`v({04wqf2dUy!rM%$wFReYR=7 zXuc$8kK^odefE}FGCwb8Pna)TC-9Wp=A8LOw4sRS6meWO=ke5&I68@=P17_jTzw43 zkKuUBTr`((e9Bz5PT|-!E9MH0N73d{JY&QVl1 zm9vJd{nmgrXgzE_Vm)R(Y8|v5vQC++Uw@!9W)5MR{A9aJ2J+nG)hi2}P5j4S4&h1s zIV2TkycL@R72v#@nk~lL*;|%9Uw16*rW~uf7)%&Di~BjtDm6@uxyM)q>x#wQLH|i( z-sN}WMmwIryukU!fBa42PoDfDc3QEOnA6`%HR3CY)ucV!O6??D@w@SOtOe?`+GUT) znIzBD23w#^ICnwLCFHKOb5-ulN!iq0yqvs8e5#nXyYPf|(%Ev_8K+^^n~iq*Hs-U{ zPA^uQ&T=th^X=QIhPBzieb#zAY1K^LY+L0udjJmzFV4=d#J1y&*iMWuZi1}+RN|lz$-Bvy6WfXHWFy&1ycXY1 zG*YePYjHEany~qzse|mY^lHXC+D_GSW_mk?`VwZQmB5v1BeRm-PMg_Qs)8D7d6sCQ zGE8mKn-REPqU&Wci zY690%jY2E`T70MHZVcCYaP19T>y>LGa(^Gr**MoP=g!Nyf%CCe-W-%OKWpy8Fzu~P z;hrHmGcEV*N4asF%gQ-Z&JE+-F`PRf=Qhm|Jo6yV4dUD(Irnur_rUqs#<%gthw;W; z{u_V$CVRQh{8*!ZWng7+m|tn1`QTR)7+eqWo$)?D!XA1Xdw+ys`4D=yyH>#cLo54D zgGa5{&Ty;yZX8d37;lko#TK#uRSaYqphu?O;XHJE=Etq^%6NU;9&e5>7ZYx8xmq1v zF4s(Fxx8vQrDWN1Y~I>VEnC%fH!-@5zlCBP+opSNcG)r(>T7E#U>rZ{95-xhqgk;n z$7tY6eZ5hs*W|*Oaow_v(X0UnNbfy2b;Eeh zs#$iqYD_ohtCa=gYGuKyIhJwj$fdiNS-~+iZTo91TXDWvr(y*vM*ekxqju^l-;MU)$x&++R25* zrFQom+IL+wyI2sCSjy_BwNq%WV;@H$`yrN0EjDWlr91}N+zBrbv&f<(tRFN0X)cn91^$m1sz371kS5QlUt-bj<2kHm(+*H$t+ zSu=AtZe|b07L&s<*1IuwGiK(%f4kh-X$}BmNsl`YfPCHv{=HOh8qRXPSv8I2@-552 zcf^D=F<>!{>ov^zX2Y1@GHUhPV}7}^0iJWi!N43hWLOxV*I)P*k9y?uGuA?VsaA1O znZ7uV3P$IHXUpEWak)}$ShizKEG&S8OxM|7Jn`A<*RNb;3G0KFxa5^s-c>^N0^i

%H}Pn!C|1vgAIiKsqzz-u1CJLM}Nls2|z%{ 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. -from __future__ import with_statement import os import sys @@ -43,7 +42,7 @@ def read_configfile(filename): for line in f: if line.startswith('#') or '=' not in line: continue - option, value = map(str.strip, line.split('=', 1)) + option, value = list(map(str.strip, line.split('=', 1))) if option in config: config[option] = value else: @@ -68,3 +67,4 @@ def write_configfile(config, filename): if not os.path.exists(configpath): os.makedirs(configpath) write_configfile(cfg, default_configfile) + diff --git a/cpyrit/cpyrit.py b/cpyrit/cpyrit.py index b161006..2105927 100644 --- a/cpyrit/cpyrit.py +++ b/cpyrit/cpyrit.py @@ -28,10 +28,9 @@ CPyrit enumerates the available cores and schedules workunits among them. """ -from __future__ import with_statement from collections import deque -import BaseHTTPServer +import http.server import hashlib import random import socket @@ -39,20 +38,21 @@ import threading import time import uuid -import util +from . import util import warnings -import xmlrpclib -import config -import network -import storage -import _cpyrit_cpu +import xmlrpc.client +from . import config +from . import network +from . import storage +import _cpyrit_cpu +from functools import reduce # prevent call to socket.getfqdn def fast_address_string(self): return '%s' % self.client_address[0] -BaseHTTPServer.BaseHTTPRequestHandler.address_string = fast_address_string +http.server.BaseHTTPRequestHandler.address_string = fast_address_string del fast_address_string @@ -208,7 +208,7 @@ def run(self): except ImportError: pass except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's OpenCL-core ('%s')." % e + print >> sys.stderr, "Failed to load Pyrit's CAL-core ('%s')." % e else: version_check(_cpyrit_opencl) @@ -301,7 +301,7 @@ def __init__(self, core): def run(self): while True: - for _, client in self.core.clients.items(): + for _, client in list(self.core.clients.items()): if time.time() - client.lastseen > 15.0: self.core.rpc_unregister(uuid) time.sleep(3) @@ -342,7 +342,7 @@ def _get_client(self, uuid): client.ping() return client else: - raise xmlrpclib.Fault(403, "Client unknown or timed-out") + raise xmlrpc.client.Fault(403, "Client unknown or timed-out") def rpc_register(self, uuids): with self.client_lock: @@ -373,7 +373,7 @@ def rpc_gather(self, client_uuid, buffersize): else: client.workunits.append((essid, pwlist)) key, buf = storage.PAW2_Buffer.pack(pwlist) - return (essid, xmlrpclib.Binary(buf)) + return (essid, xmlrpc.client.Binary(buf)) def rpc_scatter(self, client_uuid, encoded_buf): client = self._get_client(client_uuid) @@ -387,7 +387,7 @@ def rpc_scatter(self, client_uuid, encoded_buf): if len(buf) != len(pwlist) * 32: raise ValueError("Result has invalid size of %i. Expected %i." % (len(buf), len(pwlist) * 32)) - results = [buf[i * 32:i * 32 + 32] for i in xrange(len(pwlist))] + results = [buf[i * 32:i * 32 + 32] for i in range(len(pwlist))] self.compTime = time.time() - self.startTime self.resCount += len(results) self.callCount += 1 @@ -404,7 +404,7 @@ def rpc_revoke(self, client_uuid): def __iter__(self): with self.client_lock: - return self.clients.values().__iter__() + return list(self.clients.values()).__iter__() class CPyrit(object): @@ -459,14 +459,14 @@ def __init__(self): # CPUs - for i in xrange(util.ncpus): + for i in range(util.ncpus): self.cores.append(CPUCore(queue=self)) # Network if config.cfg['rpc_server'] == 'true': - for port in xrange(17935, 18000): + for port in range(17935, 18000): try: ncore = NetworkCore(queue=self, port=port) except socket.error: @@ -476,7 +476,7 @@ def __init__(self): self.cores.append(ncore) if config.cfg['rpc_announce'] == 'true': cl = config.cfg['rpc_knownclients'].split(' ') - cl = filter(lambda x: len(x) > 0, map(str.strip, cl)) + cl = [x for x in map(str.strip, cl) if len(x) > 0] bcst = config.cfg['rpc_announce_broadcast'] == 'true' self.announcer = network.NetworkAnnouncer(port=port, \ clients=cl, \ @@ -501,7 +501,7 @@ def _check_cores(self): raise SystemError("The core '%s' has died unexpectedly" % core) def _len(self): - return sum((sum((len(pwlist) for pwlist in pwdict.itervalues())) + return sum((sum((len(pwlist) for pwlist in list(pwdict.values()))) for essid, pwdict in self.inqueue)) def __len__(self): @@ -694,7 +694,7 @@ def _scatter(self, essid, passwords, results): for idx, length in slices: self.outqueue[idx] = list(results[ptr:ptr + length]) ptr += length - for idx in sorted(self.outqueue.iterkeys(), reverse=True)[1:]: + for idx in sorted(iter(list(self.outqueue.keys())), reverse=True)[1:]: res = self.outqueue[idx] o_idx = idx + len(res) if o_idx in self.outqueue: @@ -760,16 +760,16 @@ def __exit__(self, exc_type, exc_val, exc_tb): if self.cp is not None: self.cp.shutdown() - def next(self): + def __next__(self): while True: try: - key = self.iterkeys.next() + key = next(self.iterkeys) except StopIteration: if self.yieldNewResults: solvedPMKs = self.cp.dequeue(block=True) if solvedPMKs is not None: solvedEssid, solvedKey, solvedPasswords = self.workunits.pop(0) - solvedResults = zip(solvedPasswords, solvedPMKs) + solvedResults = list(zip(solvedPasswords, solvedPMKs)) self.storage.essids[solvedEssid, solvedKey] = solvedResults return solvedResults assert len(self.workunits) == 0 @@ -789,7 +789,7 @@ def next(self): solvedPMKs = self.cp.dequeue(block=False) if solvedPMKs is not None: solvedEssid, solvedKey, solvedPasswords = self.workunits.pop(0) - solvedResults = zip(solvedPasswords, solvedPMKs) + solvedResults = list(zip(solvedPasswords, solvedPMKs)) self.storage.essids[solvedEssid, solvedKey] = solvedResults return solvedResults @@ -816,7 +816,7 @@ def __enter__(self): def __exit__(self, exc_type, exc_val, exc_tb): self.cp.shutdown() - def next(self): + def __next__(self): pwbuffer = [] for line in self.iterator: pw = line.strip('\r\n')[:63] @@ -828,10 +828,10 @@ def next(self): pwbuffer = [] solvedPMKs = self.cp.dequeue(block=False) if solvedPMKs is not None: - return zip(self.workunits.pop(0), solvedPMKs) + return list(zip(self.workunits.pop(0), solvedPMKs)) if len(pwbuffer) > 0: self.workunits.append(pwbuffer) self.cp.enqueue(self.essid, self.workunits[-1]) for solvedPMKs in self.cp: - return zip(self.workunits.pop(0), solvedPMKs) + return list(zip(self.workunits.pop(0), solvedPMKs)) raise StopIteration diff --git a/cpyrit/cpyrit.pyc b/cpyrit/cpyrit.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f43f9b1af91fb43f1b46f729db4f4e45cc633cb GIT binary patch literal 32463 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 NZ;kwgyEJm?{{jQ!6wUwu literal 0 HcmV?d00001 diff --git a/cpyrit/network.py b/cpyrit/network.py index 6897209..5a79456 100644 --- a/cpyrit/network.py +++ b/cpyrit/network.py @@ -18,16 +18,16 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement + import hashlib import socket import time import threading -import xmlrpclib +import xmlrpc.client -import storage -import util +from . import storage +from . import util class NetworkClient(util.Thread): @@ -37,7 +37,7 @@ class NetworkGatherer(threading.Thread): def __init__(self, client): threading.Thread.__init__(self) self.client = client - self.server = xmlrpclib.ServerProxy("http://%s:%s" % \ + self.server = xmlrpc.client.ServerProxy("http://%s:%s" % \ client.srv_addr) self.shallStop = False self.setDaemon(True) @@ -64,7 +64,7 @@ def shutdown(self): def __init__(self, srv_addr, enqueue_callback, known_uuids): util.Thread.__init__(self) - self.server = xmlrpclib.ServerProxy("http://%s:%s" % srv_addr) + self.server = xmlrpc.client.ServerProxy("http://%s:%s" % srv_addr) self.srv_uuid, self.uuid = self.server.register(";".join(known_uuids)) if not self.uuid: raise KeyError("Loop detected to %s" % self.srv_uuid) @@ -92,7 +92,7 @@ def run(self): buf = ''.join(solvedPMKs) md = hashlib.sha1() md.update(buf) - encoded_buf = xmlrpclib.Binary(md.digest() + buf) + encoded_buf = xmlrpc.client.Binary(md.digest() + buf) self.server.scatter(self.uuid, encoded_buf) self.stat_sent += len(solvedPMKs) self.ping() @@ -118,7 +118,7 @@ class NetworkServer(util.Thread): def __init__(self): util.Thread.__init__(self) - import cpyrit + from . import cpyrit self.cp = cpyrit.CPyrit() self.clients_lock = threading.Lock() self.clients = {} @@ -131,9 +131,9 @@ def __init__(self): def addClient(self, srv_addr): with self.clients_lock: - if any(c.srv_addr == srv_addr for c in self.clients.itervalues()): + if any(c.srv_addr == srv_addr for c in list(self.clients.values())): return - known_uuids = set(c.srv_uuid for c in self.clients.itervalues()) + known_uuids = set(c.srv_uuid for c in list(self.clients.values())) if self.cp.ncore_uuid is not None: known_uuids.add(self.cp.ncore_uuid) try: @@ -144,7 +144,8 @@ def addClient(self, srv_addr): client.start() self.clients[client.uuid] = client - def enqueue(self, uuid, (essid, pwlist)): + def enqueue(self, uuid, xxx_todo_changeme): + (essid, pwlist) = xxx_todo_changeme with self.clients_lock: if uuid not in self.clients: raise KeyError("Client unknown or timed-out") @@ -167,7 +168,7 @@ def run(self): client.scatter(solvedPMKs) self.stat_scattered += len(solvedPMKs) with self.clients_lock: - for client in self.clients.values(): + for client in list(self.clients.values()): if not client.isAlive() or \ time.time() - client.lastseen > 15.0: del self.clients[client.uuid] @@ -177,7 +178,7 @@ def run(self): def __contains__(self, srv_addr): with self.clients_lock: - i = self.clients.itervalues() + i = iter(list(self.clients.values())) return any(c.srv_addr == srv_addr for c in i) def __len__(self): @@ -186,12 +187,12 @@ def __len__(self): def __iter__(self): with self.clients_lock: - return self.clients.values().__iter__() + return list(self.clients.values()).__iter__() def shutdown(self): self.shallStop = True with self.clients_lock: - for client in self.clients.itervalues(): + for client in list(self.clients.values()): client.shutdown() self.join() @@ -282,7 +283,7 @@ def waitForAnnouncement(self, block=True, timeout=None): def __iter__(self): return self - def next(self): + def __next__(self): return self.waitForAnnouncement(block=True) def shutdown(self): diff --git a/cpyrit/pckttools.py b/cpyrit/pckttools.py index 039de23..c0a54fd 100644 --- a/cpyrit/pckttools.py +++ b/cpyrit/pckttools.py @@ -28,15 +28,15 @@ AccessPoint -> Station -> EAPOLAuthentication. """ -from __future__ import with_statement + import binascii import tempfile import threading -import Queue +import queue import warnings -import util +from . import util import _cpyrit_cpu try: @@ -47,7 +47,7 @@ import scapy.layers.dot11 import scapy.packet import scapy.utils -except ImportError, e: +except ImportError as e: raise util.ScapyImportError(e) # Scapy 2.4.0 @@ -192,7 +192,7 @@ def __init__(self, mac): self.stations = {} def __iter__(self): - return self.stations.values().__iter__() + return list(self.stations.values()).__iter__() def __str__(self): return self.mac @@ -212,7 +212,7 @@ def __len__(self): def getCompletedAuthentications(self): """Return list of completed Authentication.""" auths = [] - for station in self.stations.itervalues(): + for station in list(self.stations.values()): auths.extend(station.getAuthentications()) return auths @@ -352,10 +352,10 @@ def addConfirmationFrame(self, pckt_idx, pckt): def _buildAuthentications(self, f1_frames, f2_frames, f3_frames): auths = [] for (version, snonce, keymic_frame, WPAKeyMIC), \ - (f2_idx, f2) in f2_frames.iteritems(): + (f2_idx, f2) in list(f2_frames.items()): # Combinations with Frame3 are of higher value as the AP # acknowledges that the STA used the correct PMK in Frame2 - for anonce, (f3_idx, f3) in f3_frames.iteritems(): + for anonce, (f3_idx, f3) in list(f3_frames.items()): if anonce in f1_frames: # We have F1+F2+F3. Frame2 is only cornered by the # ReplayCounter. Technically we don't benefit @@ -374,7 +374,7 @@ def _buildAuthentications(self, f1_frames, f2_frames, f3_frames): anonce, WPAKeyMIC, keymic_frame, \ 1, spread, (None, f2, f3)) auths.append(auth) - for anonce, (f1_idx, f1) in f1_frames.iteritems(): + for anonce, (f1_idx, f1) in list(f1_frames.items()): # No third frame. Combinations with Frame1 are possible but # can also be triggered by STAs that use an incorrect PMK. spread = abs(f1_idx - f2_idx) @@ -422,7 +422,7 @@ def getAuthentications(self): handshake-packets. Best matches come first. """ auths = [] - for frames in self.eapoldict.itervalues(): + for frames in list(self.eapoldict.values()): auths.extend(self._buildAuthentications(*frames)) return sorted(auths) @@ -610,7 +610,7 @@ def read(self): def __iter__(self): return self - def next(self): + def __next__(self): pckt = self.read() if pckt is not None: return pckt @@ -807,7 +807,7 @@ def parse_packet(self, pckt): def __iter__(self): return [ap for essid, ap in sorted([(ap.essid, ap) \ - for ap in self.air.itervalues()])].__iter__() + for ap in list(self.air.values())])].__iter__() def __getitem__(self, bssid): return self.air[bssid] @@ -834,7 +834,7 @@ def run(self): while not self.shallStop: try: results = self.workqueue.get(block=True, timeout=0.5) - except Queue.Empty: + except queue.Empty: pass else: solution = self.solve(results) @@ -869,7 +869,7 @@ def __init__(self, workqueue, auth): class AuthCracker(object): def __init__(self, authentication, use_aes=False): - self.queue = Queue.Queue(10) + self.queue = queue.Queue(10) self.workers = [] self.solution = None if authentication.version == "HMAC_SHA1_AES" \ @@ -878,7 +878,7 @@ def __init__(self, authentication, use_aes=False): self.cracker = CCMPCrackerThread else: self.cracker = EAPOLCrackerThread - for i in xrange(util.ncpus): + for i in range(util.ncpus): self.workers.append(self.cracker(self.queue, authentication)) def _getSolution(self): diff --git a/cpyrit/storage.py b/cpyrit/storage.py index 3933f62..157a8f2 100644 --- a/cpyrit/storage.py +++ b/cpyrit/storage.py @@ -23,9 +23,6 @@ """ -from __future__ import with_statement - -import BaseHTTPServer import hashlib import itertools import os @@ -34,7 +31,7 @@ import struct import sys import threading -import xmlrpclib +import xmlrpc.client import zlib try: import sqlalchemy as sql @@ -47,15 +44,15 @@ else: UniversalBinary = sql.Binary -import config -import util +from . import config +from . import util import _cpyrit_cpu # prevent call to socket.getfqdn def fast_address_string(self): return '%s' % self.client_address[0] -BaseHTTPServer.BaseHTTPRequestHandler.address_string = fast_address_string +http.server.BaseHTTPRequestHandler.address_string = fast_address_string del fast_address_string @@ -77,7 +74,7 @@ def check_xmlfault(f): def protected_f(*args, **kwds): try: ret = f(*args, **kwds) - except xmlrpclib.Fault, e: + except xmlrpc.client.Fault as e: # rpc does not know Exceptions so they always come as pure # strings. One way would be to hack into the de-marshalling. # These seems easier and less intrusive. @@ -95,7 +92,7 @@ def protected_f(*args, **kwds): else: raise return ret - protected_f.func_name = f.func_name + protected_f.__name__ = f.__name__ protected_f.__doc__ = f.__doc__ return protected_f return check_xmlfault @@ -198,7 +195,7 @@ def __len__(self): return self.numElems def __iter__(self): - return itertools.izip(self.passwords, self.pmks) + return list(zip(self.passwords, self.pmks)) def getpmkbuffer(self): return buffer(self.pmkbuffer) @@ -272,7 +269,7 @@ class PasswordStore(object): Passwords are indexed by keys and are returned as iterables. The iterator cycles over all available keys. """ - h1_list = ["%02.2X" % i for i in xrange(256)] + h1_list = ["%02.2X" % i for i in range(256)] del i def __init__(self): @@ -293,7 +290,7 @@ def flush_buffer(self): For efficiency reasons this function should not be called if the caller wants to add more passwords in the foreseeable future. """ - for pw_h1, pw_bucket in self.pwbuffer.iteritems(): + for pw_h1, pw_bucket in list(self.pwbuffer.items()): self._flush_bucket(pw_h1, pw_bucket) self.pwbuffer[pw_h1] = (set if self.unique_check else list)() @@ -414,13 +411,14 @@ def __init__(self, basepath): else: print >>sys.stderr, "ESSID %s is corrupted." % essid_hash - def __getitem__(self, (essid, key)): + def __getitem__(self, xxx_todo_changeme6): """Receive a iterable of (password,PMK)-tuples stored under the given ESSID and key. Returns a empty iterable if the key is not stored. Raises KeyError if the ESSID is not stored. """ + (essid, key) = xxx_todo_changeme6 try: fname = self.essids[essid][1][key] except IndexError: @@ -433,10 +431,11 @@ def __getitem__(self, (essid, key)): raise StorageError("Invalid ESSID in result-collection") return results - def __setitem__(self, (essid, key), results): + def __setitem__(self, xxx_todo_changeme7, results): """Store a iterable of (password,PMK)-tuples under the given ESSID and key. """ + (essid, key) = xxx_todo_changeme7 if essid not in self.essids: raise KeyError("ESSID not in store.") filename = os.path.join(self.essids[essid][0], key) + '.pyr' @@ -456,10 +455,11 @@ def __contains__(self, essid): """Return True if the given ESSID is currently stored.""" return essid in self.essids - def __delitem__(self, (essid, key)): + def __delitem__(self, xxx_todo_changeme8): """Delete the given ESSID:key resultset or the entire ESSID and all results from the storage. """ + (essid, key) = xxx_todo_changeme8 if essid not in self: raise KeyError("ESSID not in storage") if key is not None: @@ -471,7 +471,7 @@ def __delitem__(self, (essid, key)): else: essid_root, pyrfiles = self.essids[essid] del self.essids[essid] - for fname in pyrfiles.itervalues(): + for fname in list(pyrfiles.values()): os.unlink(fname) os.unlink(os.path.join(essid_root, 'essid')) os.rmdir(essid_root) @@ -534,7 +534,7 @@ def __contains__(self, key): def __iter__(self): """Iterate over all keys that can be used to receive password-sets.""" - return self.pwfiles.keys().__iter__() + return list(self.pwfiles.keys()).__iter__() def __len__(self): """Return the number of keys that can be used to receive @@ -566,7 +566,7 @@ def _flush_bucket(self, pw_h1, bucket): if len(bucket) == 0: return if self.unique_check: - for key, pwpath in self.pwfiles.iteritems(): + for key, pwpath in list(self.pwfiles.items()): if pwpath.endswith(pw_h1): bucket.difference_update(self[key]) if len(bucket) == 0: @@ -583,7 +583,7 @@ def _flush_bucket(self, pw_h1, bucket): class RPCStorage(Storage): def __init__(self, url): - self.cli = xmlrpclib.ServerProxy(url) + self.cli = xmlrpc.client.ServerProxy(url) self.essids = RPCESSIDStore(self.cli) self.passwords = RPCPasswordStore(self.cli) @@ -598,13 +598,14 @@ def __init__(self, cli): self.cli = cli @handle_xmlfault() - def __getitem__(self, (essid, key)): + def __getitem__(self, xxx_todo_changeme3): """Receive a iterable of (password,PMK)-tuples stored under the given ESSID and key. Returns a empty iterable if the key is not stored. Raises KeyError if the ESSID is not stored. """ + (essid, key) = xxx_todo_changeme3 buf = self.cli.essids.getitem(essid, key) if buf: results = PYR2_Buffer(buf.data) @@ -615,10 +616,11 @@ def __getitem__(self, (essid, key)): raise KeyError @handle_xmlfault() - def __setitem__(self, (essid, key), results): + def __setitem__(self, xxx_todo_changeme4, results): """Store a iterable of (password,PMK)-tuples under the given ESSID and key. """ + (essid, key) = xxx_todo_changeme4 b = xmlrpclib.Binary(PYR2_Buffer.pack(essid, results)) self.cli.essids.setitem(essid, key, b) @@ -638,10 +640,11 @@ def __contains__(self, essid): return self.cli.essids.contains(essid) @handle_xmlfault() - def __delitem__(self, (essid, key)): + def __delitem__(self, xxx_todo_changeme5): """Delete the ESSID:key resultset or the entire ESSID and all results from the storage. """ + (essid, key) = xxx_todo_changeme5 if key is None: key = '' self.cli.essids.delitem(essid, key) @@ -682,7 +685,7 @@ def __init__(self, cli): @handle_xmlfault() def __iter__(self): """Iterate over all keys that can be used to receive password-sets.""" - return self.cli.passwords.keys().__iter__() + return list(self.cli.passwords.keys()).__iter__() @handle_xmlfault() def __len__(self): @@ -757,7 +760,7 @@ def passwords_contains(self, key): def passwords_getitem(self, key): newkey, buf = PAW2_Buffer.pack(self.storage.passwords[key]) - return xmlrpclib.Binary(buf) + return xmlrpc.client.Binary(buf) def passwords_delitem(self, key): del self.storage.passwords[key] @@ -789,7 +792,7 @@ def essids_getitem(self, essid, key): return False else: buf = PYR2_Buffer.pack(essid, results) - return xmlrpclib.Binary(buf) + return xmlrpc.client.Binary(buf) def essids_setitem(self, essid, key, buf): results = PYR2_Buffer(buf.data) @@ -996,13 +999,14 @@ def __len__(self): with SessionContext(self.SessionClass) as session: return session.query(ESSID_DBObject).count() - def __getitem__(self, (essid, key)): + def __getitem__(self, xxx_todo_changeme): """Receive a iterable of (password,PMK)-tuples stored under the given ESSID and key. Returns a empty iterable if the key is not stored. Raises KeyError if the ESSID is not stored. """ + (essid, key) = xxx_todo_changeme with SessionContext(self.SessionClass) as session: q = session.query(PYR2_DBObject).join(ESSID_DBObject) result = q.filter(sql.and_(ESSID_DBObject.essid == essid, \ @@ -1013,10 +1017,11 @@ def __getitem__(self, (essid, key)): else: return result - def __setitem__(self, (essid, key), results): + def __setitem__(self, xxx_todo_changeme1, results): """Store a iterable of (password,PMK)-tuples under the given ESSID and key. """ + (essid, key) = xxx_todo_changeme1 with SessionContext(self.SessionClass) as session: q = session.query(ESSID_DBObject) essid_obj = q.filter(ESSID_DBObject.essid == essid).one() @@ -1035,10 +1040,11 @@ def __setitem__(self, (essid, key), results): result_obj.pack(results) session.commit() - def __delitem__(self, (essid, key)): + def __delitem__(self, xxx_todo_changeme2): """Delete the given ESSID:key resultset or the entire ESSID and all results from the storage. """ + (essid, key) = xxx_todo_changeme2 with SessionContext(self.SessionClass) as session: essid_query = session.query(ESSID_DBObject) essid_query = essid_query.filter(ESSID_DBObject.essid == essid) @@ -1156,3 +1162,4 @@ def _flush_bucket(self, pw_h1, bucket): return session.add(PAW2_DBObject(pw_h1, bucket)) session.commit() + diff --git a/cpyrit/util.py b/cpyrit/util.py index 59e14f0..01fc238 100644 --- a/cpyrit/util.py +++ b/cpyrit/util.py @@ -36,16 +36,16 @@ local installations. """ -from __future__ import with_statement + import bisect -import cStringIO +import io import gzip import os -import Queue +import queue import random import socket -import SimpleXMLRPCServer +import xmlrpc.server import sys import struct import time @@ -53,7 +53,7 @@ import _cpyrit_cpu from _cpyrit_cpu import VERSION, grouper -import config +from . import config __version__ = VERSION @@ -343,7 +343,7 @@ def write(self, results): def close(self): self.f.close() - def next(self): + def __next__(self): if self.mode != 'r': raise TypeError("Can't read from write-only file.") self.tail = self.tail + self.f.read(512 * 1024) @@ -372,7 +372,7 @@ def __init__(self, f, maxsize=10 * 1024 ** 2): self.hasstopped = False self.maxsize = maxsize self.excp = None - self.buf = cStringIO.StringIO() + self.buf = io.StringIO() self.cv = threading.Condition() self.start() @@ -460,12 +460,12 @@ def run(self): self.cv.wait() else: data = self.buf.getvalue() - self.buf = cStringIO.StringIO() + self.buf = io.StringIO() self.cv.notifyAll() if data: self.filehndl.write(data) self.filehndl.flush() - except Exception, e: + except Exception as e: # Re-create a 'trans-thread-safe' instance self.excp = type(e)(str(e)) finally: @@ -502,8 +502,7 @@ def __iadd__(self, p): def __purge(self): t = time.time() if t - self.datapoints[0][0] > self.window: - self.datapoints = filter(lambda x: (t - x[0]) < self.window, \ - self.datapoints) + self.datapoints = [x for x in self.datapoints if (t - x[0]) < self.window] def getAvg(self): self.__purge() @@ -539,7 +538,7 @@ def shutdown(self): self.join() -class AsyncXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, Thread): +class AsyncXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer, Thread): """A stoppable XMLRPCServer The main socket is made non-blocking so we can check on @@ -548,8 +547,9 @@ class AsyncXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, Thread): Sub-classes should add (name:function)-entries to self.methods """ - def __init__(self, (iface, port)=('', 17934)): - SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, (iface, port), \ + def __init__(self, xxx_todo_changeme=('', 17934)): + (iface, port) = xxx_todo_changeme + xmlrpc.server.SimpleXMLRPCServer.__init__(self, (iface, port), \ logRequests=False) Thread.__init__(self) self.setDaemon(True) diff --git a/pyrit_cli.py b/pyrit_cli.py old mode 100644 new mode 100755 index 3e587e9..d91be3f --- a/pyrit_cli.py +++ b/pyrit_cli.py @@ -18,7 +18,6 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement import getopt import glob @@ -79,7 +78,7 @@ def initFromArgv(self): raise PyritRuntimeError("The command '%s' requires the " \ "option '%s'. See 'help'." % \ (command, param)) - for arg, value in args.iteritems(): + for arg, value in list(args.items()): if arg in req_params or arg in opt_params: if arg == '-e': options['essid'] = value @@ -164,7 +163,7 @@ def new_f(*args, **kwds): "functions but seems to be " \ "unavailable.") f(*args, **kwds) - new_f.func_name = f.func_name + new_f.__name__ = f.__name__ new_f.__doc__ = f.__doc__ return new_f return check_pkttools @@ -204,10 +203,9 @@ def _fuzzyGetAP(self, parser, bssid=None, essid=None): ap = None if essid is not None: if ap is None: - aps = filter(lambda ap: (ap.essid is None + aps = [ap for ap in parser if (ap.essid is None or ap.essid == essid) - and ap.isCompleted(), - parser) + and ap.isCompleted()] if len(aps) > 0: ap = aps[0] self.tell("Picked AccessPoint %s automatically..." % ap) @@ -342,9 +340,9 @@ def eval_results(self, storage): pwcount, essid_results = storage.getStats() self.tell("\rPasswords available: %i\n" % pwcount) if len(essid_results) > 0: - m = max(len(essid) for essid in essid_results.iterkeys()) - n = max(len(str(c)) for c in essid_results.itervalues()) - for essid, rescnt in sorted(essid_results.iteritems()): + m = max(len(essid) for essid in list(essid_results.keys())) + n = max(len(str(c)) for c in list(essid_results.values())) + for essid, rescnt in sorted(essid_results.items()): self.tell("ESSID '%s'%s : %s%i (%.2f%%)" % (essid, \ ' ' * (m - len(essid)), \ ' ' * (n - len(str(rescnt))), rescnt, \ @@ -572,25 +570,25 @@ def stripLive(self, capturefile, outfile): lambda sta: self._stripLive_newStation(parser, writer, sta) parser.new_keypckt_callback = \ - lambda (sta, idx, pckt): \ - self._stripLive_newKeyPckt(parser, writer, sta, idx, pckt) + lambda sta_idx_pckt: \ + self._stripLive_newKeyPckt(parser, writer, sta_idx_pckt[0], sta_idx_pckt[1], sta_idx_pckt[2]) parser.new_encpckt_callback = \ - lambda (sta, pckt): \ - self._stripLive_newEncPckt(parser, writer, sta, pckt) + lambda sta_pckt: \ + self._stripLive_newEncPckt(parser, writer, sta_pckt[0], sta_pckt[1]) parser.new_auth_callback = \ - lambda (sta, auth): self._stripLive_newAuth(parser, writer, sta, \ - auth) + lambda sta_auth: self._stripLive_newAuth(parser, writer, sta_auth[0], \ + sta_auth[1]) self.tell("Parsing packets from '%s'..." % capturefile) pckt_rdr = cpyrit.pckttools.PcapDevice(use_bpf=True) try: pckt_rdr.open_offline(capturefile) - except IOError, offline_error: + except IOError as offline_error: try: pckt_rdr.open_live(capturefile) - except IOError, live_error: + except IOError as live_error: raise PyritRuntimeError("Failed to open '%s' either as a " \ "file ('%s') or as a device " \ "('%s')" % (capturefile, \ @@ -636,8 +634,8 @@ def export_hashdb(self, storage, outfile, essid=None): con.text_factory = str cur = con.cursor() cur.execute('SELECT * FROM sqlite_master') - tbls = [x[1] for x in cur.fetchall() if x[0] == u'table'] - if u'pmk' not in tbls or u'essid' not in tbls or u'passwd' not in tbls: + tbls = [x[1] for x in cur.fetchall() if x[0] == 'table'] + if 'pmk' not in tbls or 'essid' not in tbls or 'passwd' not in tbls: self.tell("The database '%s' seems to be uninitialized. " % \ outfile) self.tell("Trying to create default table-layout...", end=None) @@ -1207,13 +1205,13 @@ def benchmark(self, timeout=45, calibrate=10): t = time.time() perfcounter = cpyrit.util.PerformanceCounter(timeout + 5) while time.time() - t < timeout: - pws = ["barbarbar%s" % random.random() for i in xrange(bsize)] + pws = ["barbarbar%s" % random.random() for i in range(bsize)] cp.enqueue('foo', pws) r = cp.dequeue(block=False) if r is not None: perfcounter += len(r) self.tell("\rRunning benchmark (%.1f PMKs/s)... %s" % \ - (perfcounter.avg, cycler.next()), end=None) + (perfcounter.avg, next(cycler)), end=None) self.tell('') self.tell("\nComputed %.2f PMKs/s total." % perfcounter.avg) for i, core in enumerate(cp.cores): @@ -1291,10 +1289,10 @@ def selftest(self, timeout=60): t = time.time() err = False while time.time() - t < timeout and not err: - essid = random.choice(cpyrit.util.PMK_TESTVECTORS.keys()) + essid = random.choice(list(cpyrit.util.PMK_TESTVECTORS.keys())) pws = [] - ref = cpyrit.util.PMK_TESTVECTORS[essid].keys() - for i in xrange(random.randrange(10, 1000)): + ref = list(cpyrit.util.PMK_TESTVECTORS[essid].keys()) + for i in range(random.randrange(10, 1000)): pws.append(random.choice(ref)) workunits.append((essid, pws)) cp.enqueue(essid, pws) @@ -1355,7 +1353,7 @@ def verify(self, storage, essid=None): for key, results in storage.essids.iteritems(essid): sample = random.sample(results, int(len(results) * 0.1)) if len(sample) > 0: - pws, pmks = zip(*sample) + pws, pmks = list(zip(*sample)) workunits.append((essid, key, tuple(pmks))) cp.enqueue(essid, pws) solvedPMKs = cp.dequeue(block=False) @@ -1410,14 +1408,14 @@ def checkdb(self, storage, confirm=True): # Check passwords self.tell("Checking workunits...") wu_errors = set() - for key in storage.passwords.iterkeys(): + for key in list(storage.passwords.keys()): try: # explicit call to iter to work around swallowed # exceptions in CPython's bltinmodule.c:map_new() for l in map(len, iter(storage.passwords[key])): if l < 8 or l > 64: raise cpyrit.storage.StorageError("Invalid password") - except cpyrit.storage.StorageError, e: + except cpyrit.storage.StorageError as e: self.tell("Error in workunit %s: %s" % (key, e), \ stream=sys.stderr) wu_errors.add(key) @@ -1452,7 +1450,7 @@ def checkdb(self, storage, confirm=True): if pw not in res_passwords: raise cpyrit.storage.StorageError("Password " \ "not in resultset") - except cpyrit.storage.StorageError, e: + except cpyrit.storage.StorageError as e: self.tell("Error in results %s for ESSID '%s':" \ " %s" % (key, essid, e), stream=sys.stderr) if key not in wu_errors: diff --git a/pyrit_cli.pyc b/pyrit_cli.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f1ab1d2f5ded52d685eb0882d6abcb66b104553 GIT binary patch literal 55937 zcmeIb3vguDdFOY#F)v^S#JnHmP`rGM215-nGo(aHBT^IyfYgXX4Aht*D2fo&=xz*p z2IvO*HaGy6^h1;-+p$Hdw6-I^;`gq0H|6p}u2{A=yJcG|H=`M%tFznvGO+Fj8+jp>O#7e#MG(I;OTh^jlH+I~yj znWY|3C#D8>(V_a^@ZUuH0H>4dt$Mq(+Gy98YU8a|vy}}&fxA!hOZIT6(fLADni}Lh z8Z2^XD|vRdQC_Oe&bIsPVyRhOUF6bpkrdfk@-S!T7Me@7b2sZt%}TRcYn>abB{$p6 z<#X16bIWSRY-O=Nyu4o0gQxfEuEqF^nI4TKdQbERi~|-{VJ!%Ti73cj_GqSs=gRiKWVoP zS``PZghNsFrKtKTOFv}k2QB?@RDC(B&RF_kOFv}kN22Pdqw1`sA4#h?Y*ieMs-KCf zWxI9M9ywx<9E+-RQMF>}$1MG*r5}%~)u>vt^y8L(+|o}()%mD;-O^836?-+&swZ^! z4f=9-R9%Rwb<1#fE`txnJsJvSyC0U9t2B z(?@vfl)bEnqG~IuCU*BByZc^y>Qq#1N7YqJKV|8sE&aVw^_8f4%hKPg^w2`@^)*dA z&Aq|sb33iUr=#jxR9(0Hr*EJCeQEx|sQPMD{X3R_@b>x7ruolA)z_lx>z4n_?eh<% z`5%s|-xgKB-SR)I{MF&8dM>J-x6ycCRQ-;q`ki+7eRlVP_4;g7{cKcy!_v=M`Xf>G zQ5*K5sQS66`dxNw$Zjzd@3&i&{Q0Q*1-mt@TUrPouv^sl-BI;>?AAHms^1gUm{E^K zkJT80$N57`Kgb_C_#yr-sQ%Xy+6Bp;=Gzhr&L>AJ*Md{9%oKls`wJ>Ii?B z#!vHy$uY_wCi@tF_C(cj{;*V@;SVe0S^lsFKgJ)H+$H`nYd+2&ronUkp_7;S!^?l3 zKTPQf{xBD>@P}SbMvuL8UWD>{Ax{<2Q2j*6M)@WE9NJOz8l)2v6+w@6d%`K|4omMwpVJcxn@$c`)%DxYK!w7!g_}^HBjq%11dZFK9!~>MTNGij}smHDq;=#WvykA ztEo50emr_@M?~%$#pq^F)cST^-sp*5D`;vLUNfe5vo~suq&Ir(M&o4kT2URqGlS8|QL$aQ9^n^H5;pm zW}{|F^NXv=g7LhPGTY5|ZLRG^)RygUtx*j{wQA+1lHSqw2U@SHU0Yln=5Ml}LsU3k z=r8Om>@V^w94y$R*hjjWY?I;_81Q-&y_OwJYL8by4tcm848R6w&<~yQ9~4 zM)iW;QFTxB7&#jK_V#xw=>#`qyU}kqZWP-4BJNS-jebohWx6ZNG+>$DNT1%H z-8f)3emT8yFnWSQs)sD~c(Hw#t=xfV<#;hvci3+Icj*I1vXb`LjencoIGWu!W;gz( z(B5y2I-cD)VK*)m!;QP`#>yVypXxm}guVG8+*6p=dxnmljM@jI8;7DBhohs_du{q0 zq34AHV8sWp^%F&%`|EzS$O)GxUf&xv_S>^ZqZ^RE_gIn&WwrB0mBebE!XQn|tP z_p{t>Q9i)*onXE&&9!3YF4ivAFE%f>F0Ni&NbVw~ytp{DP;OL{h4Rf>Vk@m&OPG9N z9WK-smyHY!E%={`|5;5QBg@r=T3l%^Em1&x`c!f{Zq-&+>#bT6x4F|?Zr7U)yD=P3 z)oSr+m3DgAOYpT{OOkrk6XuK<%ykm#w&3fH`TAnbvowwBLQ0fmWO2xEwAy=VPNlru zUTxLvrpR+>nyv7mp$%OPy`Sy$KG9+)ALF2>SCiT-=gAq)H+8grz0usNpUHntZo|Rx zsU#j8Jrh52{`?1r9yx#ELVS7kW;x+lyB-gbeBlG}$D0d{`1xk5+_%tfFDDnzox5Id zFRacD)ADm4pDeE~>ZZf*zN-uMgwd|nV*Xa^NxM~_TW!~>@oEFCZX^Ee#I^X@TBFt~ zFUFIrbBpy#e7Rn!HIiEV%A@b=D@mAW4{)f~<|({Ao3ttax-+wIZftIgxluaAbH?d> z$X5qXs5DV*3gBIrdUY+*T5er`#ZIdAic|5$TEnXVnJD#TnVL+u>$VOm^Vh8@vvhCD$7xV3!I_k1NN8Z%=cM$IZr`J_RQ3F7 zqhdlAt73M!+$z&%Rm5ZIrDmMn@s-!QZk>6hya>S1j1KQ)cD1#*eQu{l3sgMQYA%iN zYCfcbKf@s^?1J0%6b1_Wil++w#a&$QEA+wz`-=nc!{dcr#bbs0_`A=zVq#}Ifpz+rfv3$B1 zt=ugN2b){_lyOoXg%KI{Fh(?HoQ@nkS8rsD8EvRnJ*BXDhrTx z38smmPx0J(+-Tk!&YnwR@WZu)wRSPKc^H2x%$}K)g7)>5YL({oM*UR^3pX!Pz|dT$ zZacdeKg0B`wUT(GQh`8CHq~Bge0pl?(wLs8z0)Vg(jFE-pBLJR$PuNEUYJXTWi_cA?3sFFnV}dwJ#<mAN|)p2ypheY%7z42YfEvv8AJQ^)CQgrUyQFo zN?|0t`IKi;8BdjYWnS1E>_gMQpNAFZ{`2QY#;3a8bxIU3CR*|_j04tjkv}D^8^`^| zktYU~;1o>+bg8`NBvPMtbutlzG zP!DhrQKcwJRn>zX zjg!CIkLb*pm^yrewO)FPlR=H9u_9+Uy5wDN`z@AEQNWk@C8{QZemk45RP2(2hT&O$ zh9r3(hJe&twG;ye1MlZ8$~*|7mFZIiZ^t^ zdZh8vAm68AMmVgakD!=HI%F8mbmQJ=2k-Z0U(`Amfz#W}OcUx5jT(jMMapLCQ0f;M z8XlXnH!@*r+XN+aGzA4(j~^Lc6Y&ec7%pMNB{qn7I*H4T^5XidwR7cm8%mZ9S`q{8 z;-m)5(GznuKwkNka(%Hpw^$ptnvg(1xW-F{vvD-gaA|27GGK~g!%jX`9wocMlAE`x zN$D(CuC~yay3XQG)fF1PM(x(@{Eu;x2-!q{iT%KV{X1+*lvH*}6WA|5uFL0i$_}}H_otP?RP#|~Cg%Wl^it4qjE?V8hD&FINWd3mh% z3PO~vH|7yip|C~O6Gg#QYK6YHU9@VpFI=$cVQB^{U1X5p#gnOsx>UxvqB*OBpI0D5V1oQXv_db3HxHZjxX1MgsnB+*m1>D`aVa&wq6$LO zFBPsE*&dsDENyPut>mvli+NHD^Y?O{v2#fzzo+%aoc5K(TD-X z_7zsXR8WI=X~|2k_I0&JK*u$%>7^<~Ys;k%6RN*-n7E|{h{_Klz(SYah+-NKg!YE6 zeckF|Rqx0T3`0Ap2{2*YauvGQ%@rHH@;+=;Wpa@MrbkK>mnNRQ*!48Swtzmz zA63JLkq$Hn)`@as{Z@H>*i9+owU2ZD!|JUww7`*;;#K@*7;*%W>8FJ&>IPg*}CV9&zto#eP#q==>yv={SU` z5B0)8&wI#s2nEG}hlk^mK$$_Iif64=hka-TxJu%d zM)H?itBo2GsJ|6^X%W^gs4oQl76#8Du4G`(2bSP~^Yi7eL#=!rcsT zf1#pEMe)UzY&id#6H$Gr98~|bk<|1YkO3)ong(DA*`T(s=$!F{#L03|N{8PtPhsUR z!aW2#@`*r(*OO87LgUr6CW`wDQCrvE@H)u<=Cla++Vi4wV>9FSf{_#Vi0SBMXO+V% ze*En#Tlw*bf78=+@)Ix85&lk@{FVHV8V1ZwCeMI$ef@SRgGQ=CJn725UVo+5kR}EV z46t1{s%7X-Ie`e4YC{zjrr85Et*xQWIDM!#K~5qED40>wN}Hkla{L(Xs{9!U zNo}pHWiCZg_Ma=5Xv4(#)n~^?O0m^jn>A&7mNB_T_a+x>G%ij8mG5+g=KE7lo=*?e zPK($h*9q!zm#$QOKoX}|M#fJM)lu+^aCl$Ji^{hi%Bm*9&_1N$VOu&AgCa*Itpg)b zMwr|*;809=@|`e9R~jPKh@G@f)2;IIa;;T*nnV|$gHoH zYj(dU!%ed}8gikADSI_Z0r)po6FXrF1U8nksdS2W&CQUxGokWpBja%CqrPm2=8T9?~h?4to+s5Q}L(P&rQr2)8LJxgD@Eu zC6=^!!=?_jhaeNGM=B2=*Zkrc4r)PQZIE}=OkYgK5tgV27^1_&aC1Pb8(opizYrZ-%U!k`Huws zV8>>!xzFP^_gQYi3|?3%Ba~!S?ukxdla*+2#*l+Iq%TYTX4(of%*uI!A=fJFRV&m~ zmgP5$-%-~-Z`zY-(=Z{Es->B4nhO+J({^;4_8+6^m2VUpU(St*8tBILZ*18>QoTWD zb>G;ayEZfktNIoV0xRXmYGftRZT@KO#_g9eCxir0D>b{A(lEUXBumM)4h zwa~l;agih}UAnaFo$L$cR`pgHwV=B%Cc%hOS#7m2EiSH0W1rl~T30og9o2}GZyGCE ztS{ky)2J*X(9miZlt(A8naNcWL{6#>V_ie=cM5mE~Gv^s*^1+VU_G3RC*%wXu;T=Ati?Lp-ajz-m$wE6e?T z$ysIUZcWJfta>1QVpp3?H8U@Rsp-NtJgP$Dtsk5i6r6X(iq`F@=`&qx(P)>>>E?MI zj1*0AW>wkHm}16yd1aaIiaJ>jJ0gh59F^tLr}UgCl%BJ~uke5blF_m4Qzngm=k1>q zU3!S5XwN}p4NRYyEbb{D#eBKnSos5m`wM5oS!Tw_c=sh9)N+8>85SU1(J593bq>=aUo5NuVl1v*Bz(urM+$J`(DD8AF$`S*Qm>jQ8oL00fLUlhu< zIUZ+eWAMVjN6ygtJ6^XA4YR@xRcgpIBHmRNT%Sod9X<>hNA=*!aGRDgL6yWcJx%kt z!v(iLzqB%Jet9b|YJzDgM}7TFsv~X-Q-UUls(ibUP4 zig{z=lfg9Bh)YJ0>zin!?k}*aU?iVo`M5sUV4CuSIA@ zDfkA=!rXbsW)`d!=2;dR3_C&JW;!P|!+_=S!%9F)Mm2lo66UpHhBx*aT1nSn#(mLY zuTJM#Re|UJjaWTuEIk@~s6mt);9;1AU)Zt+m!^yV!;p zsJS~P^0(=q>~u1<2Vp9%_ZhRQFp=C0jvnJ_TODNQ!p{Nm-_?!G@+9J zg#%2|74rhc=3fn!b36};kz(C1!I-8RdhCE}mi#7L$E z+}|A?Gip0c&QHAPM-f3X7`!i-v@D{Ye29taR#?neDN!<^*Yzhui}jl*UCddfi%^uL zR1sA(ElWpat{X|Kn_<^{jM8FbR31QPypCMol+h7LQ=Y5Wat&E3qmMxZl{1e>U8U3VBehstLNcIb zxFB3#rH74n4W#TfcdHlD!IYVPNu#pbsIROtqzkR)>UCVb+V)N;4&T%Hv_WG>xr{VS*T0MK2I0AD%GCpcd6bsT0{HUoTB{r?ogAl$o6A%gd` z`>JOec6Uswo97-&TQsG*il1D?C|b58pb>rX#Vn746R+=--idzu%BO4h!tc3b$q(W>+nR!ix995za4q7d6( z?0P!%YGX6NpJB_@ep}l@St5(0{E~mgL5e^Z?7=DsXntvCD?rDaKVfF69~7VyVlgje zNC0c!GCwEJL&c*6fT9 z2c4ej6OWjq0EGif5U&J>fHP0Zz9rZq@W%0b7g2BqnUN_51R<#XSrwKbxd62Eh6k{-@F|Czj8QB-Rgs{!XWANq1nc;Xm z*x0NJ#6nuwWaeuRTASsnl?-#wwtgQW?Zek!#V)7O%(!1i%b3#x zGU!pCnbb2LpEj+F&7Y0M^bt4uJEDe(g~Ha($oo=GJ}A!H;nbz?)4Wx_kz~D5aYGp| zu;px8!h^1|S6MQ>-nhzmPzN!3Q_;1X?eb#ji%R=m9kehyzD=$-kvvfP5(hIOlx?eD z%e8pok#OwVw;+P3#~VlWOIot>RfzVAMV~^!A{N~Xv%aTrEEwRLCW}af%4Ct4=ibWX zMi=sO39F8EV=@E_&vh<--_$Ew{J)ZuURc!Rb-K_Kz4-%L^6S-TjlGr71y;4mHe)lF zCD5?`<%nlW63H#7gZ<+1;7deN)DOjAy>r}W`gWE*ix|nomNF~+J6Yk4)3~hOWiG4# zw_H|3qm2wO2X5>aAu7mub(+T{!{``tQLWWsz2nA|sdy8quL5NV@}<)SE!;};)-sN( z>$bdZLnP9Ngzd#1U7GGlHmTsUi3;RbCG0k>3(uoD1dbM!nsfi(@*)owbv9_-l94|( zu!nh>HZp5_A_4zu)@>W0_+_eFgkAU*2CrfCk8N1!`B85KHYc7uH= zM9gxaHi`_5^0S4drI+gD@LXB@8_5ePb@)re3q7VVA)kp8P#@sLF;=P;t9u0sEv)@h zd(w=ZV>7>$LmK`hw8*H}F{q79o6>inWF}3Z0ZlAK$nXjTNh)KbMo^cVXp{e=5kIQW z-I5cP)jMwWTK2J-(^l^u?F?4Wcm!Gp4pED?Ni?x!$8h$~3_zc>yEtK@To)x8R|?$6yyxGVfR4q1D2U2pHJn349@; zHo4tHXS2mDDWJ*r)H%$J*I%tK56OHIb;w4dO2N%B~+ntqkl``dO z2>=NXjgL%Txt!aBdq=3F6+eJhru{HG0Lse`P@e53$XaabU$ZoB@HcdS&x>x3)Pjy< z%NAOuy+;|qFnxrXSim9m&dw)XuG1Y$;c1?d2DHLk>DEF&Oae1vChpp2)4bpKAqd$V zVK*wJdw8g%O(pKWV}QdHz*;_~&v4lGV(wP>{*jikN@f$gT8eurn$Egj&6UaAtBKzi zxR<|RJT!ve(hLt7o^tAEl*tI0&=V5d$SRx<<&mVyX2bQrX3oS()QG70=emAZItO>b zd{bwi;b8RthCPrla|ERj6&DgqziA2(U2l6d9Ig4(`DYr7lhhzUbpkEN35b{Wcgjcb zMB#zr5r~^RG_@*fi6)QwYBcS?? zlIe-TI(8`%20>Z-cSiJ#6phXNp;58Eh@JQ93#HORp4gjFPWOwD3k8&OZwQR=`aZF| z*GvctlylAy7zIE%(_4AUNlz?$N;&(Z*DZK~>V$IkJLM#Dlsmc?R^DHj4xTOKaLS29 z@cKZs#!{jo7DZuf=1}xHaSPCg(`sQp%*~(0HRGQ^V{b?h>PRx)#1Zub^WMnYvv&-XZ19P@xL+9kB6GtBZ6J7DT#g zs5nG8>;vhDpE&12jsrN{NLe$g2p#toENzQOu)zcvh%jw+b!k~dTul(3u+6MnG%R1* z5F+cvGB;Iq-iZ4}P9PQ{?vQ3P(HeboU~1y9#9N4^{eyVV`#u!k z9VrGok;EKrr`N?;Ghj(G6Ubf2SlpPdGqyMHea<+|U2Tk+t?B&h35 z&OOC?{23m|?b*(HY;#9w02;Rajti-DcRaLcK)u&MN6d&U=9J_pn+nfz5~hN=7u!4l z$N50OP#6fN1^?jqJEH512z#S6ZES4jgPRAq&pquYj1Yx^!OCu95kE2Xk$CFr2*YBA zsnG?Dm9+*dbPv^+@Wud3)q(HL*60XJ`C2Pb{tTFn*(>&rc4G zH!7|5W%*daFX!j$l}%&nvudkxQqwjrFdL_Ldx&VHhUo6jQqvG^9-g;aYRog{))q@m znvC31`xuPgf*kok$d6;owRYRii(+qoerPIouQUk-_jN6^9`Z;btLd%tZmkyK6*k&Vo6sz+J@ksDRmG{eW=`(62L$>BcNNN?erLR)3*T zK*d=ISpc9R%gQ5#G|LcKc18u1mjc9?Q^B>iLUdxJC*W0WaCoHfqI8?DUQ(?L0%5mU zGJ?O;jfbf9VAMV&EUmg1QG^yk7aT}8?qW~B_sN{23)6t(?}n})rYlk5#kGGCwU4M+ z3LKmHO%oE#5iUGL7tzM{qv}AX3!pxlLFu)x=t9u%h7_T%eb9=vhf)b*Z-f{U8pH?@3RMkqm9Yk5<#cg+<@XExn_l_B z!gR>VI2Em{Cv4bGWG!a|rUo^2liy$}23)ZT>Zf+=MVKdu*ETp0ZQ!xq9s@ZgZ9 zv<_MTMi^P>@LaSI`JgYQUn0w(9&`X9qU^dELlHurgZ%C|ki;IId1A4=G*>Nu4kSBExC0BD@UHgaNoq88RpgtDG{Aa!)(=61+xO!Q?E}?_<~rbG z{S6ZB%#f(sZj#%(Ir=02Dcb#Oo7!!9!*{dY<7vAO6-A}9{Vog>DOwl3jNwP z0KMkEz`O!qif{37Ws%sumc`|dw^4++9{d3c+oUXiTg}IIbsl$9TSv)J`iHtKaWIQM zgF3Y_B(amI1q}`{K&GqAbwSC(7LvTs~0uf zoS&BmUg^h`+RMRG1qaktcVRAF(@m9&U^LfcJ6HCaOz|>hvDa|e@Cc9gZd|8s>hzyh zIS=X}vDo$j<2n4VGOkusA_Us-j7cGi{E&GEfEotq#y-j+~uHczZn!N%! z0(rq~rH?B=l@r$NUW>80ms|sq4EXiwZ28S09JyUf?DK_A+m*Z8$r5?(`H*M$~`M=fP#OY+gk5PIB2H+ zIK$PsExdDx*0WHZ%j)+JteA;>YW(u}=+*e)_?gm`=i_9BK$*2!;&Xu`jO)7xoVMB; zj5Sm2^3u)D_8Rk_t0qId_p7{$Y-kO_bcgX%B;GpaWum+e$L9QZH4~OX#Eq`uAM!Cz zJ^hn8>KHAJk6ay(uZ}!@c|10QMm%VL0MYTKiL2w!j+f%e(xvA|N}r6M8~7217m;?gIs zjq`r=sP}a><}rVP{>r;5>3Sf%DSM*(?VU+J&}mrLGqvSe&#zaLj_%p;9_jQM3wE(p z^B7WlGS{Uopa0oT%~wm8p4Cjv$BBr?Sc}ZGA( z{A7IP@>q8H;ZTk}(P@)EmtAMsH$FW+F_s8zrxU2VrC~HXO$`Ze*Vgbxm@D4c?D`$H zHp{>1d9_#I`l`nR2=pAHVg6|y!Ky=jjO?a_D#R%}N(qytk!PPDiRCTK_NPX3HKDQ# z=A0Zbfgh?)%+_w+Wag@vM_F+hzaF5is6kuR4T=c(!Tr4rI}GBB8K3QUHX0gbW|DXC4|Kc*Z~JxOs)Aa2cJ z7h$!f*F9NH)cx;uX&un}*G5hIyV^2;uQl@&XwNMsF2a75Ja%K*ByW1-L5oU1$qjpt zuCw}AT;8eRYFmqaAA@5j>F<)yQBt&5q51X|dl6S<)a)-jim=*S*n_CrQ|RB>zoUN_ z|C7%DJ^a7BfA<0I^x6OW>?qMzZU_B5BbWVq@itR_MIdF59U(Y&;iSNw9s3G$O4v1Te)Ho;97Up~MDyl1 z+YJ|~H$RexSuEw7W&ZZ&j*IEe-26G(ew}r>Y3(!@{oK*~``vc7)1*wALwT5;Xx&}W z4avQ!e?L9&yEK4$^0ldH`2MS44k5tTF(%ol$K{A8pMTDc4Y%Y)(QP)Ra5s%hNuFMP#LxoVwJmoGFNB`1%YPD)m-n zbxB+J-24-4A6u0t|Ff_g(0tlbZ!tuybTe~;@)YZeG@#3^CPK&(&}{hnFeJ0q$hXa7 zuzK`Axwge}XBi!1Bh*!TGpCr$@>#ae^-$6)b%k0ZfM7)dlxTduti(Rzpf8x2A zE)Phs-gDR$Z4t^P+DWjqO@t6<-bvTn)Xv?oM_7-iZ%{kX>8RO;vI&!pPR@>$Z%~WS z@|rxhfnlMxbVrh5T}Zo{*v4xl(sbJfGb6X5L;i8O4rY~?eniAYu4Z9@SX^qGya_&i z<<^IVV(ePG@e>-_sP=aps3%Oy>)wo^`D;B<7*Ty3E!&FW5n}~SHq~Z(u(qnqqHJy0 z^yQnee}HmIKgt2qH`uQ8`Y!RN%FK3mf_qTeWauq*Z^bZ`Zim<9{FIGViSl;#VA$Sl z^T#q}t2VkaxHK?WF#HjPU?YlZi(+O0jaqc^o^9BKHB=Sxph!5IzqdR!@-wv z>+s!a-=A_Xn&KPZP+Q7{+Wjptk2tr5R&^3tl4%G*Cyx zrz`rFRlY2fw4CMg_6(+M365-6wX1K*mvZw~S6N}BHPPf+^b7YDpA|5`5V}QJXW20) zDr8U-lZ^M2^33kZ)+*B%bk(-2F~>+XWElo@NN8VCAxaD(4hb_;v31()!c3|zz_=xS z0#S3DE#ej-2LM+Gx@qYy*Oxn!f>18Vl)_BS{D=kDoL2L?KJ{k!h( zt2yx4HA$c0);o&j3}zW}EEm6)O}BW6K>IjM;rWlDd$>|wj)#&I+hlD_%CNjrutlU% zX>;>8SlE4FZ5`!bltJC}`zIQc&eHK6`9WiE8go;}u#qZEVUN?x*UuCqA9w$JEa%g_ zD!BnU%o47cMo}wp1cvqJrQt>@ZdWuYw867g8P*c1T z|ACq25YFT3u*H5Wcs0EBzWWb%l?y${m8v)0Y5SIin%9qo%FeS9_1h!z2(Y;}gOjl1 zRw^jhHOOau6|d(;Jz1z#tt$Vjk442UWw_4*0JsuE8iy&?Ft4E-{mE`$`foUx#sV(^ z3%27Ma;5CZncGcQVc5^MLYSIDfC>aF`ssMD^zT&Q|Ej~6I2anN&I$dAzL}oFpseVS z;X%uhG#6i~Rh8yy3!c1Vcqm+#pSU}FC}UD3ok+uUA3|+$gb2h^U>vkv5&HazK7De~ z6dC(D%I0pW3(kAF>Old~kHx*Wcz`=ncT}X?qVP@-N3E?)`5?UkDupM~*q`Q_E4h0e zH&=X0@nMw_v2hHyR6}&ZE%lO&k-kB{7~l(!8uIfPLQ)4NyQ#QT!!8uVoBf3j@lk;I zm3lcYO^$Za6$c;WtF;vKg=LGkpPoeA6)6tSr~Zd3;>G7L4^hmAok?fZ10-XjTFdhCP4=Z7zxKY!7O!|@%H(f%`|$CP&mzbA{E zK0G{O->3`8?&jsON+iTvtP;}&Px&0PrQ{@1q|B!BETgL+Nu}S`6QYf-JC_323(!hz zEmx}BCsx{OVB#wqH9wx#pBeQ*%;Q1ZC@b0$73CyEL;yaAjdW|Djfa3qwB?+_ zO?fElC27b550PqHSM`MyWIUWWZtjR$UX^+B-x!FF`@JK`tokNX_MtL7QlNP_og0z# zOvtkGYnLulA&dCD(W44z^7IC`{qw2dNEyhsX&Fb=IMG%2)mNMSOr(?ogN{?&z$S&v zu*5IUf{L?noEqA?OqX+hItL-HLr3)`fg4&)I?tABMCp@WoeiHY($D=j$TYxISwVYW#T5vFGTT-O;l_7H;QHh#k01;0>b6#d>Jf`S?>h} zS=2HoWrm6A1Bqfsrxok`bcga8)wnk1Brso|mj4G*Y8Zx`SPZr8kh?8tPlzaQE$({r zn<*JFA~e`ry&~DEOmea}w1MHBw(mQoV|Utm+8HHjc)P}=i!=u2D~#U;ENknmzOV&Z ztky1;s~6{L7i;qu&!5*vc}>^JXNmMlNsB-gRJPe@nm@~&JPyq6)vhnq0B{0x{P!16 zIf6gOdH)ooRdW~xCu(A8dc&*EAnmz?Q^lmbdUeWlp2>qe*f+JXie3}$Yc55b9%oP| z1`S7wBwH&23pdxzuzgvzv#a(VvV@e81{P@|PAayiB7W;5&5n4#FD<8@jL6T^6rQ)r zeD=E8%0J~_1s6~>Aj*3hHSTTS_v3104j_t+!s2$IuY&Bd&2l!WFrIMBs=;Dwq@`ak zGZjegq|_S34qYXq=~Fcr9VTJ`I|)OR3wSRI@6*Y0Xt`O>3_gp~(6CnNCMVw-yRkYJ zAcKyv4|v!beF6M9|L^C2efL{m0`JAWbO1JVOpIs`6-ykE1To4l`HIx0a2`Km4>R2+ zJOpYkZ6xYCv~whqm+xB`{3S(nI;cBIg598JMSDtCLO%2;wo9h&IiK1EycxP!fe@ zrK}J!Av6fDN{95nD7Qx?@{b)>sC;o)#1!~<<*&H*z2=QL^I40@aF3dqMq}7-+tFN! zxN;hwO4O<}%n}|~PZ>?)qf&n22FdY|Zlf54mAec43jzN+VgD$dYI3EgVI|gn(;M2hun{yAk5~Dta&|NY1;1}@t`q?luykj+ z)*yj~j}|)vMItI+#)OdGaOeZt@}|m1*$hQY{rR*Z-BvJT)tRp*IrD|31=XEh z`lWqo(Rj%wU&~BIv!R?3!z&(bLOj@6g@Tld2`&34BD1bwcUvaEm9PSfM47!!9+@BSF6(aIsB1V8aF&Tp zrXO{9mN(<(3sZN3uzp*ME?CWNwuE+$KdESOUM4^dN5^j4s?Q~Vb+aZFIf#{}x3k~R zHr8YjjdGu@m-y)Oz&IWIp}QwI07GA@wKo<%yQ$qMzB~dX$ciHt)UbQM5}NLvm`A}3 zNzO!Ck*JfZR1z&>ZQ6k*&K&N9jH+%KCQ45^TNT>|?V8T4^KF3AcamY-T(jG&>DQqw z?$tyni!+pa^&NJ1IFYH;zOR#C9Ok>$=Za71)A}X@c{0~1IV5;!Ko7+7K61pRnnf97 zDfydsvUYlC2xy;+B6gb3pJ+_`2KChl50+xFQ$DRrenGXEL9iT%65Jxng3QnM{m>CM z0m*{_1jO(r5PI+k-`Ze!Crp-z^?)Otl)6~*&cuycX58Qoo*XndLoSiiG1rph)qorLmcIoG~W%x zws#A}CJ2PQO{_rl1-HWa4a}_|L01{@MgVc(wKpQ{h0XK@oZcZN!kg*}%1MqetJfz-u6^6!sH(L2!zT8HS4_FVa4UEQ3(AYIY zV|V-OF9PWdfE_S2#>IZn7!NTMY=adLpN39Z@TBBdSOU&8;!S8wJ~QW1f*3v{DwM!3 zjXdX!)93FTlfjrAmUWefQ<$nr;Zz=%ZD}hNch8#HRgyS53@?Df6b`&Yc-CD~?h~xr z!e?Ej<*}N_y}m<$)>T>_tYxG2mIy6I>fX|x8PqINV{D1hDyGno9s{GRxS>VVPL&z1 z{OxMnmM_fA1!iA(8#8uSQR(YLv6q>}1#a6IhC83-Zq+_){u{2k%cg}!xvR9y+e6dC z^>Y{`P~>G^99x;?HPyD#9odA<8Yu9#XkLh|+K@RSx&_c)b-I~r1Ay-`dv_NHH0`(x zWSw|-preI$@&&vVYIJDxAS|krCxev^Zlq_C7Lx#SSH#L5<**g-x^o+@nP4ZrHEfn_ z50(jJy$vjrKCZN&gPARcbS5oVsaIgBgR(xMw7p9EKXmrXI!x)XPia4-v+vd6i#iz4 zGF&FuRx-3@MH$*M^X{FXEeBY4QIWwyxAJ;Gt)Eo+Kd-|8x3`b1q^c`Bva;p>2QU=d zo)#VH##Dy_uDTaja;dZQh1vT+P;xHcWmrn#rS_O&OCM_PMpPMOQhlTRlGeKcnb2lz zQgUs8Oj3{GPw0U+JKlgOm{JraAG|z>LI=X7gD6vpwSFr_1n9d`m%9|*2t@sifvEpM ziXMR|Fvt#psPRGoOAew^<=30v%z-6*1;H5m-Cc0)tFpQTcm-rKcm?=D+lsp&+9=93 z__UmZPyGT$j+hGIw;X(;Bj~*VJSYtN1ec_u0zQG5jwm6ZCNLk^%pCa)HBsO(B?$|C z5bX590{>F%0M0P?Kbz7N^G5xp!O5 zWL{%eLFOITDb0)AR}wZM?RNw(-pi8mg&_#C0bWdH@B*V$$IEP@b}M+9{eK8`7;B$n zG(3>*R>~kl9e=JYXLWc7sG|co41WkxW2%&Ga?*OOsK|L+O4^ zX96GZF5>8=*ldm;#{8CCB_%r84L79BA%u&mavXB>;wGm3a3?d+A-6HPmuX+zR%)CK zbO?+Y==ehjfAHx56PPvY&3{^yK@F7PI}?VC`{Pbw7BewW-|S^O)8IZGGo0IduxHVQ z8{*pdeZX3~&2V1mXH9>R6^bYi!hntO!TSHwo-~BwiNSE>P$e`rwbDt~;hLVkX0ZcO zV6poTh9S_`7`OLL0jL%>TkP%4){Vme5C|p0Ahe-BdkSC$ zlp~N)Gy~k8NCr6S@P}LD;F0kH|E5V)p;7|Loc5M=@uoJ^rH05dr`BVc^VWx==m(ZL z-y*WV7@7;Hu=EVo`2FuFhBt%}E^nE0RD*)Z9#U<-Wx`O+{^H91q9ByiI_cX$H6&E? ztA=V$7^>m?Ho71tY^n?La%pbR2tCk~Qsa0_jZhj-GWDgmFo#`i^lt~`Y{^uE*)VIH zd<*j|)Lm_Cd){@K@XdV&p2-D!!Oyv){A~JoP)_N)W*vo8zPO>yroI4}MyAw-am-Z-Ml=yV2{dlLAzMS%?KA$hFgO|*Ln2wLVdUi(GPKyoS zTrrcUIY-*3zVoGN5Go5qcMA^WcL>6sUpM>_42Z&Ejz@5a}Ki46Z?ip!aK+qVKE*mu}*WpJ2eY zl?>fxzR!#0!-w@jm^1u&$6b6|P11yYGy6YS&fsf%G@ZXIdnKavN-Rw^b!sgUot&JHws%Uor3H0D;-?GpeV9?fTUy19(5F z8;0`U1#OaCm^Q51YkJ);lO7$?SAO?lV#8EdOigvWh(xf_U?)^}KpO(Ubu!lNLDi(I z+Z*ia0@C$94i(s++2u0Kw~GddN%Ic?5=C$RWe?a+Y@OYxXcIUp?p&e3W=r2XfWz+E zNR(ZI_>O}WZ{knf7ElBbf;>P{#P_ajbVn zE3e`0#D-3EO+X2A^QA2S1Mm(7P!317m+BVq2S|e=M>xqoxvs6Ixz?#Wj<$HdH#$Z! z3YG8=I+?7^cp1~?FBcFxvPls2BIiB7`9;^Rj@ijH+Z|ObHJr7dPO$`a*mp2 zXrTZOL@`AQ)jv-CV4E>Hk=8QvbC8Megz#P}w&L0vRkX)yei-z-e)J)Deg+$+`72{caHd;Gc~ zM!M!P4;hrTtS9f$Q002U1VJ^J_2k!zx};T>*xeJ7vY!0=Tu(U9o_QxdA@io5e19?5 zlfzk0p6vX~-{|SQ6V9_|-bqi$ zys0PCJsVctU-jUrcNBFZhp9mk%;aBi7~>;yttB?biiKkCVRtA&AowIs`4yt%D#{Z+ z-WZd*AV=pRA)w`2`R34urlU&e~GBbu%m1 zHaLtDNn%b;>FoRrpRPyy9Yyoarg4M0a?AhK|61h#KX9u)`I`(06f%1GwR1ytxi}=E zoLSaWiA4bDFReBjLMd6*ZV$4}(*Ai&S&+V6&!6PbC;t}weDPKqeq=u60+{ic+u-hW zKe;R>upkp3jF6MFS*-E@E?vE931`fHRZ7TOYN=?oZ}i&O$i>o%E_ZXdf~(Bv<%<)8 zF&C~?S=E{GS)mvRCkLFcO>JVjj%v-Eh|NAzdP27~Ow5PUE4t95`cx5bc(OA+kkquJ z1SfLSX%TRt;-5~@*1LAIxtN&acV)e@SnDWuERCJ%lqVYyXVvDC$J!Ocx5hPyn&dX6 zTS}65i6+Ta+H4n8I*MO*+gUoUNPeY$X-jqK94DpoI;`uk#=&D&nAPe3;xc{Grbn&x zs*;!jQQM9!_gGJenrMx*F0>piys2Co9lkGI`a8N%wVL;q+G@8;uai)MRBRt0`s`Hj zKuzi&r-o#i@}k~@J!~k%q;$-9|Bm8A=CHF5OmL!b2Gf%^6&?Z^D7MjIG(-4QnO@tr!L~WoXEhQHv2p#+ zHK0P=QL(PsUeUQ`b1y&Z=P*6)!bm52*zTmB!^m81qYq*Ln|ynvxR`&BH2(!vQ(`eZ z`hsfe{=9N7?i-wgW9&1BYqNzc5hQXP`2M5PPhEDXDI4Z04jijshC!gsdJoqZeFQ`8L#Dv=$5pMzb#^ zs$Y5+ravP|6LalHg~wX6Mcu$x%DM#@l~xY}pDV1ME2<>)TNZNUWiY3Gi*fBad%LC= z9GkglP>WZ4S5Bu$Pkl^0mA)eXrUe7}ASEWben#z^DD1vj z;NSGhPI|$OKQ6AVXdaEt%$ve-%jSG++s*lE)|{^vSH4P6;+3pPdwSZa=@@cD&9pu7 z6w?DUAnMJr9^B&HLrfaj3=7)G6mrV8e%4O%dDiSzJZ-XFX!7^2H4?e@*4tnRV}c6! z!FQR7{t$fme+0PENPGbq&i~ z8}rgJ$|_4viI%CY7_n$GTYOD97<|VxUKjgDC$A+JEn=b}57XATi;RE;+t#>yn6thV z?WENJr%bx6|0#shffL!HEbr$@-_eY2d zW(Qiudc(ee8(wA5zg5ba0g&Jp*U9Ajn9mXe3w)>$BCYBzy{oOpFx@yd9FMu0iG6>x zz;-a}%Q3uibMv7ieaQv2dW1<3rlWY3hkTS*e2c0(4_LdC_{wt=?(1wykPg5yPZ*(= z4)iG9&7yE<^#Es%C>EN0f2VX>86~P4mICd~ULBvh`U26Ruau@rP|~P$za9}^5>hhU zR5AsMDN6)BO82OE19rTNXt}xUXo~Y_P)yBDUqU^Gb3BlvkV^-sSOwb5Z9ytZXH=&O z!%f+uPM3z#6e7;$!Y2rymi~Z@+vm;#cj>J9EAizQNQm|x1i+j$e;OV60Y`R8QBsHj zH@ocK-9R0A+X(dNTa$;m+GVj5-1oVYHo&(F26me&utxbMUxx8_vH2&9Vmh!~ z_iVkQb9vU{mx{mfsKB0#T73S@eR&~?D=+F=pEe-+7KRne%{dqn{eVh0*BV|X+6?Ek zYyZ+iX8leffC}3jO(|wfS$n$Rh2X|a8pL^QX1MS&oXMCn!+!&P0(ui1k0Hm#w*VQ3 z#T<=&Db?L+-7(~A1uzgZjKuFV=B%>p+g)OPSZ3%Wyb*3{9G1Ob#!XSYz)iX5+*FE~ zL(R~{!Byr^1VGJ6aO5QrS?T9Jy5rLlp8r>8>9-FBc zOTFX9{n0yZ+#eNI{s>n7sv>Bb<23J^Mw%V6tC2ROJEIl`GUkwtQ-`1OgqsN|W6Bn7 z@(e5P1(Bik_`>;9Ld_DUQv!u1KaEgmWUPx*luV|=PeWU)wtD(@P8VQyqkLUVk7{uw zg+Q;?WI*Vu*4bdAhFIGj8v>scLiZB{$=pvfrUXBBp7_?pJKLMy)vdQ?fH?J}aTYi9 zA&ZlrvpvACv;8jOEIzi&&7_Wp^}6vqAAE`Uo#(Fq@K^QUuRc|WdN|)RZNPLOoxZIp zAB#sO7`U-}$ai`;jV0U?s(?ISzp4H*;3{XE=fEz56wN;f^bx?ni@S>{fM>napl zO55GS1#oJYVQMMkO{bN4OTkdZR6!!??mLF+*2TVu%~Y07Km<9BS+$Nt4OIWa3ZTF1F4}K+2{xb#ivtdMIb4`(TzZLC?HYB0W*UDPP+!O zQ0wzUS|-*(d)Ox0IP-O#<-<(#Z#P_dZg{X`U@>eVj%87rOPmBSp^21>w0%P6S`+;Lf8cxbyE6}GD*j#kt4X2KC)nd#IFg_WQfDB zG{v_MHl#>!>Tm&oo4mwj)F=2b0C3n}RD|hWb}oC%eT4^r7RP}au2bclS_Aw1*^<1^6cv~xFG6_ zVKKvX+U5U<9*|l{1}XkwvEk_trtZTQjg;#2^aqRllfq$o9B*npYh@uECY->F;&8`U{m@PGnX)v(C=)@ zWVj8Lk8D{?DeOd_O0(MzuW&=HIwT~?GI7r)S(QMKpX$LF<|ZX|{8K%e7Cv$Pb6RUh z901}}WHXAF^5jYrbI3z#rqoM9!60h8o1acku6&_qTBVzrhth-6gP!>JxM2 zKhkQ&BlLPE)9uZIdbx@dZBpKNGt|k4Z{N$^tg&fRY`=QGHEOz{z~tA-uf5iQrp_KP zLeN<2gt4+7CkAP{Zgr|PEKLZxW!rrO3~Z`cE#-@6#*+;E&?P%5D% zd~DM6Wr`|xHk}Iks&8=Q%5YV6*u&`Py~U#dL)7uLr{YhopPQJm5HN|}Em}7Vc4p&j zEn*7jg)F3lMeGHQfFPZ6T2JTeYYNgJ6ey)mOYq5NRdtSVMAw0!>YxIlA}I)SO8cf3 z2ROt4XtHRwF&?)^OA}_uGz*uZ4NOw5TKQgDXKEBnUMjn4#4I*~N^Tt!gvkeJvv=RY zKK3Yk23M7SX)Rlor`@<#lYM0En*4VH&$+~B88h(&LS}}dev_ME(y4V z_w|bK60iW(jJ7qMEcEm|2TezFE2Z|^8;zkUTI)s(#V6h)H&t7sLE)MJ{{R3(%9n`2C)8U8?`#D&j zZF5#hHlor6rRl|3TcKFKjjc(Fz3LjYvGh|a?0?hYhjoxvv-A}m{;m$+ro(sW@W1Qu zf9h~iW$)I(-s0~mZH&u7PQrmJHzW;JEY&SnW?C9rHE%ILulb+)=A_kJX;yBh$Z%^@ zLNTkfp4MbfzI}SLD?eZ~G=8u`yc=YrdpSXVV#ZWAhugNrNe{{7Cywp-Z@=bc?&u- zowwF@Zqa^^E<3B)R`^dT%}B^E>g<3&Q_%$7DT^nJrrTbX>5+RyUn$qDRp7r_4iJ#r!N03TdlxO%Q{}YE@#onIddwZYkJw8zE-NElj z@4&#B-rWOt6Hxdt*C+YirF5=I>pj5lD8G9KiU;}aDjYn;)z01>y}NZhI7YrUDGv=4 z2cG4x%6+f$^+1mYp6CJI@8fD$;RxrO&c>8B@I24-P|lP5M)|!kK!A|lcl^Ka%8BV^ zX_A8xYPnpSKMHXT7jWGv-N&dJUu(KX!>5q!DaPh1wvlbv{}?mxO17YsrdbFX3D~oU zDjY`P4@wV8cxq$*=yv22. + + +"""A test-suite for Pyrit. + + Tests are done by creating a sandbox and executing the cli-functions + normally executed by the user. + + Please notice that the tests backed by the storage-relay open a TCP + socket bound to localhost. +""" + + +from __future__ import with_statement + +import os +import shutil +import random +import unittest +import sys +import tempfile + +import cpyrit.config +import cpyrit.storage +import cpyrit.util +import pyrit_cli + +cpyrit.config.cfg["rpc_server"] = "false" + + +def requires_pckttools(*params): + """Decorate a function to check for cpyrit.cpyrit_pckttools + before execution. + """ + + def check_pkttools(f): + + def new_f(*args, **kwds): + import cpyrit.util + try: + import cpyrit.pckttools + except cpyrit.util.ScapyImportError: + sys.stderr.write("(Skipped: Scapy not installed) ") + else: + f(*args, **kwds) + new_f.func_name = f.func_name + new_f.__doc__ = f.__doc__ + return new_f + return check_pkttools + + +class FilesystemFunctions(object): + + def getStorage(self): + return cpyrit.storage.getStorage('file://' + self.storage_path) + + def corrupt(self, storage): + # Destroy some passwords + keys = list(storage.passwords.iterkeys()) + for i in xrange(13): + key = random.choice(keys) + # This is specific to storage.FSPasswordStore + filename = os.path.join(storage.passwords.pwfiles[key], key) + filename += '.pw' + if i % 3 == 0: + # Delete the workunit without deleting the results. + # Should cause a reference error + del storage.passwords[key] + else: + with open(filename, 'r+b') as f: + # Overwrite either part of the header or part of the file + if i % 2 == 0: + f.seek(4) + f.write('x') + keys.remove(key) + if len(keys) == 0: + break + # Destroy some results + keys = list(storage.essids.iterkeys('test')) + for i in xrange(13): + key = random.choice(keys) + # This is specific to storage.FSEssidStore + filename = os.path.join(storage.essids.essids['test'][0], key) + filename += '.pyr' + with open(filename, 'r+b') as f: + if i % 2 == 0: + f.seek(4) + f.write('x') + keys.remove(key) + if len(keys) == 0: + break + + +class BaseTestCase(unittest.TestCase): + + handshakes = (('wpapsk-linksys.dump.gz', 'linksys', + '00:0b:86:c2:a4:85', '00:13:ce:55:98:ef', 'dictionary'), + ('wpa2psk-linksys.dump.gz', 'linksys', + '00:0b:86:c2:a4:85', '00:13:ce:55:98:ef', 'dictionary'), + ('wpa2psk-2WIRE972.dump.gz', '2WIRE972', + '00:40:10:20:00:03', '00:18:41:9c:a4:a0', 'helium02'), + ('wpa2psk-MOM1.dump.gz', 'MOM1', + '00:21:29:72:a3:19', '00:21:00:ab:55:a9', 'MOM12345'), + ('wpa2psk-Red_Apple.dump.gz', 'Red Apple', + '00:1d:7e:2c:b1:af', '00:0e:35:72:1a:98', 'password'), + ('wpapsk-virgin_broadband.dump.gz', 'virgin broadband', + '00:22:3f:1b:2e:e6', '00:1f:e2:a0:a1:21', 'preinstall')) + + def setUp(self): + self.storage_path = tempfile.mkdtemp() + self.tempfile1 = os.path.join(self.storage_path, 'testfile1') + self.tempfile2 = os.path.join(self.storage_path, 'testfile2') + self.cli = pyrit_cli.Pyrit_CLI() + self.cli.verbose = False + + def tearDown(self): + shutil.rmtree(self.storage_path) + + def _createPasswords(self, filename): + test_passwds = ['test123%i' % i for i in xrange(5000 - 5)] + test_passwds += ['dictionary', 'helium02', 'MOM12345', \ + 'preinstall', 'password'] + random.shuffle(test_passwds) + with cpyrit.util.AsyncFileWriter(filename) as f: + f.write('\n'.join(test_passwds)) + return test_passwds + + def _createDatabase(self, storage): + self.cli.create_essid(storage, 'linksys') + self._createPasswords(self.tempfile1) + self.cli.import_passwords(storage, self.tempfile1) + + def _computeFakeDatabase(self, storage, essid): + self.cli.create_essid(storage, essid) + for key, passwords in storage.passwords.iteritems(): + storage.essids[essid, key] = [(pw, 'x' * 32) for pw in passwords] + + def _computeDatabase(self, storage, essid): + self.cli.create_essid(storage, essid) + l = 0 + with cpyrit.cpyrit.StorageIterator(storage, essid) as dbiter: + for results in dbiter: + l += len(results) + self.assertEqual(l, 5000) + + def _testHandshake(self, filename, essid, ap, sta, passwd, aes=False): + parser = cpyrit.pckttools.PacketParser(filename) + with cpyrit.cpyrit.PassthroughIterator(essid, (passwd,)) as cp: + solution = cp.next() + auths = parser[ap][sta].getAuthentications() + for auth in parser[ap][sta].getAuthentications(): + with cpyrit.pckttools.AuthCracker(auth, aes) as cracker: + cracker.enqueue(solution) + if cracker.solution == passwd: + break + else: + self.fail('Did not detect passphrase in "%s"' % filename) + + +class TestCase(BaseTestCase): + + def testListEssids(self): + storage = self.getStorage() + self._createDatabase(storage) + self.cli.list_essids(storage) + + def testCreateAndDeleteEssid(self): + storage = self.getStorage() + # EssidStore should be empty + self.assertEqual(len(storage.essids), 0) + self.assertFalse('testessid' in storage.essids) + # Add one ESSID + self.cli.create_essid(storage, essid='testessid') + self.assertEqual(len(storage.essids), 1) + self.assertTrue('testessid' in storage.essids) + # Adding it second time should not cause an error + self.cli.create_essid(storage, 'testessid') + self.cli.delete_essid(storage, 'testessid', confirm=False) + # EssidStore should be empty again + self.assertEqual(len(storage.essids), 0) + self.assertTrue('testessid' not in storage.essids) + + def testImportPasswords(self): + storage = self.getStorage() + self.assertEqual(len(storage.passwords), 0) + # valid_passwds should get accepted, short_passwds ignored + valid_passwds = ['test123%i' % i for i in xrange(100000)] + short_passwds = ['x%i' % i for i in xrange(30000)] + test_passwds = valid_passwds + short_passwds + random.shuffle(test_passwds) + with cpyrit.util.AsyncFileWriter(self.tempfile1) as f: + f.write('\n'.join(test_passwds)) + self.cli.import_passwords(storage, self.tempfile1) + new_passwds = set() + for key, pwset in storage.passwords.iteritems(): + new_passwds.update(pwset) + self.assertEqual(new_passwds, set(valid_passwds)) + # There should be no duplicates + random.shuffle(test_passwds) + with cpyrit.util.FileWrapper(self.tempfile1, 'a') as f: + f.write('\n') + f.write('\n'.join(test_passwds)) + self.cli.import_passwords(storage, self.tempfile1) + new_passwds = set() + i = 0 + for key, pwset in storage.passwords.iteritems(): + new_passwds.update(pwset) + i += len(pwset) + self.assertEqual(i, len(valid_passwds)) + self.assertEqual(new_passwds, set(valid_passwds)) + + @requires_pckttools() + def testAttackDB(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeDatabase(storage, 'linksys') + self.cli.attack_db(storage, 'wpapsk-linksys.dump.gz') + + @requires_pckttools() + def testAttackCowpatty(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeDatabase(storage, 'linksys') + self.cli.export_cowpatty(storage, 'linksys', self.tempfile1) + self.cli.attack_cowpatty('wpapsk-linksys.dump.gz', self.tempfile1) + + @requires_pckttools() + def testAttackBatch(self): + storage = self.getStorage() + self._createPasswords(self.tempfile1) + self.cli.import_passwords(storage, self.tempfile1) + self.cli.attack_batch(storage, 'wpapsk-linksys.dump.gz') + + def testPassthrough(self): + storage = self.getStorage() + self._createDatabase(storage) + self.cli.passthrough('linksys', self.tempfile1, self.tempfile2) + fileresults = [] + for results in cpyrit.util.CowpattyFile(self.tempfile2): + fileresults.extend(results) + dbresults = [] + with cpyrit.cpyrit.StorageIterator(storage, 'linksys', \ + yieldNewResults=True) as dbiter: + for results in dbiter: + dbresults.extend(results) + self.assertEqual(sorted(fileresults), sorted(dbresults)) + + def testBatch(self): + storage = self.getStorage() + test_passwds = self._createPasswords(self.tempfile1) + self.cli.import_passwords(storage, self.tempfile1) + self.cli.create_essid(storage, 'test1234') + self.cli.batchprocess(storage) + self.assertEqual(len(storage.passwords), \ + storage.essids.keycount('test1234')) + keys = list(storage.essids.iterkeys('test1234')) + for key in keys: + self.assertTrue(key in storage.passwords) + for key in storage.passwords: + self.assertTrue(key in keys) + passwds = storage.passwords[key] + r = storage.essids['test1234', key] + self.assertTrue(sorted((pw for pw, pmk in r)) == sorted(passwds)) + + def testBatchWithFile(self): + storage = self.getStorage() + test_passwds = self._createPasswords(self.tempfile1) + self.cli.import_passwords(storage, self.tempfile1) + self.cli.create_essid(storage, 'test1234') + self.cli.batchprocess(storage, 'test1234', self.tempfile1) + self.assertEqual(len(storage.passwords), \ + storage.essids.keycount('test1234')) + fileresults = [] + for results in cpyrit.util.CowpattyFile(self.tempfile1): + fileresults.extend(results) + dbresults = [] + with cpyrit.cpyrit.StorageIterator(storage, 'test1234', \ + yieldNewResults=False) as dbiter: + for results in dbiter: + dbresults.extend(results) + self.assertEqual(sorted(fileresults), sorted(dbresults)) + + def testEval(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeFakeDatabase(storage, 'test1') + self._computeFakeDatabase(storage, 'test2') + self.cli.eval_results(storage) + + def testVerify(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeDatabase(storage, 'test') + # Should be OK + self.cli.verify(storage) + keys = list(storage.essids.iterkeys('test')) + for i in xrange(25): + key = random.choice(keys) + results = storage.essids['test', key] + corrupted = tuple((pw, 'x' * 32) for pw, pmk in results) + storage.essids['test', key] = corrupted + # Should fail + self.assertRaises(pyrit_cli.PyritRuntimeError, \ + self.cli.verify, storage) + + def testCheckDB(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeFakeDatabase(storage, 'test') + self.corrupt(storage) + # Should fail but repair + self.assertRaises(pyrit_cli.PyritRuntimeError, \ + self.cli.checkdb, storage, False) + # Should now be OK + self.cli.checkdb(storage, False) + + def testExportPasswords(self): + storage = self.getStorage() + test_passwds = self._createPasswords(self.tempfile1) + self.cli.import_passwords(storage, self.tempfile1) + self.cli.export_passwords(storage, self.tempfile1) + with cpyrit.util.FileWrapper(self.tempfile1) as f: + new_passwds = map(str.strip, f.readlines()) + self.assertEqual(sorted(test_passwds), sorted(new_passwds)) + + def testExportCowpatty(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeDatabase(storage, 'test') + self.cli.export_cowpatty(storage, 'test', self.tempfile1) + fileresults = [] + for results in cpyrit.util.CowpattyFile(self.tempfile1): + fileresults.extend(results) + dbresults = [] + with cpyrit.cpyrit.StorageIterator(storage, 'test', \ + yieldNewResults=False) as dbiter: + for results in dbiter: + dbresults.extend(results) + self.assertEqual(sorted(fileresults), sorted(dbresults)) + + def testExportHashdb(self): + storage = self.getStorage() + self._createDatabase(storage) + self._computeFakeDatabase(storage, 'test') + os.unlink(self.tempfile1) + self.cli.export_hashdb(storage, self.tempfile1) + + +class RPCTestCase(TestCase, FilesystemFunctions): + + def getStorage(self): + return cpyrit.storage.getStorage('http://127.0.0.1:17934') + + def setUp(self): + TestCase.setUp(self) + self.backend = FilesystemFunctions.getStorage(self) + self.server = cpyrit.storage.StorageRelay(self.backend, \ + iface='127.0.0.1') + + def tearDown(self): + self.server.shutdown() + TestCase.tearDown(self) + + def corrupt(self, storage): + # Corrupt backing storage instead... + FilesystemFunctions.corrupt(self, self.backend) + + +class DatabaseTestCase(TestCase): + + def getStorage(self): + return cpyrit.storage.getStorage('sqlite:///:memory:') + + def corrupt(self, storage): + conn = storage.engine.connect() + # Destroy some passwords + keys = list(storage.passwords.iterkeys()) + tbl = cpyrit.storage.passwords_table + for i in xrange(13): + key = random.choice(keys) + sql = tbl.update().where(tbl.c._key == key) + if i % 2 == 0: + buf = 'x' + else: + buf = 'PAW2x' + sql = sql.values(collection_buffer=buf) + conn.execute(sql) + keys.remove(key) + if len(keys) == 0: + break + # Destroy some results + keys = list(storage.essids.iterkeys('test')) + tbl = cpyrit.storage.results_table + for i in xrange(13): + key = random.choice(keys) + if i % 3 == 0: + # Delete workunit + # Should cause a reference-error + sql = tbl.delete().where(tbl.c._key == key) + else: + # Corrupt it + sql = tbl.update().where(tbl.c._key == key) + if i % 2 == 0: + buf = 'x' + else: + buf = 'PYR2xxxxxyyyyyzzz' + sql = sql.values(results_buffer=buf) + conn.execute(sql) + keys.remove(key) + if len(keys) == 0: + break + + +class FilesystemTestCase(TestCase, FilesystemFunctions): + + def testListCores(self): + self.cli.list_cores() + + def testPrintHelp(self): + self.cli.print_help() + + def testSelfTest(self): + self.cli.selftest(timeout=3) + + def testBenchmark(self): + self.cli.benchmark(timeout=3) + + @requires_pckttools() + def testHandshakes(self): + for filename, essid, ap, sta, passwd in self.handshakes: + self._testHandshake(filename, essid, ap, sta, passwd) + + @requires_pckttools() + def testAnalyze(self): + self.cli.analyze(capturefile='wpapsk-linksys.dump.gz') + self.cli.analyze(capturefile='wpa2psk-linksys.dump.gz') + self.cli.analyze(capturefile='wpa2psk-MOM1.dump.gz') + self.cli.analyze(capturefile='wpa2psk-2WIRE972.dump.gz') + self.cli.analyze(capturefile='wpapsk-virgin_broadband.dump.gz') + + @requires_pckttools() + def testStripCapture(self): + self.cli.stripCapture('wpapsk-linksys.dump.gz', self.tempfile1) + parser = self.cli._getParser(self.tempfile1) + self.assertTrue('00:0b:86:c2:a4:85' in parser) + self.assertEqual(parser['00:0b:86:c2:a4:85'].essid, 'linksys') + self.assertTrue('00:13:ce:55:98:ef' in parser['00:0b:86:c2:a4:85']) + self.assertTrue(parser['00:0b:86:c2:a4:85'].isCompleted()) + for filename, essid, ap, sta, passwd in self.handshakes: + self.cli.stripCapture(filename, self.tempfile1) + self._testHandshake(self.tempfile1, essid, ap, sta, passwd) + + @requires_pckttools() + def testStripLive(self): + self.cli.stripLive('wpa2psk-linksys.dump.gz', self.tempfile1) + parser = self.cli._getParser(self.tempfile1) + self.assertTrue('00:0b:86:c2:a4:85' in parser) + self.assertEqual(parser['00:0b:86:c2:a4:85'].essid, 'linksys') + self.assertTrue('00:13:ce:55:98:ef' in parser['00:0b:86:c2:a4:85']) + self.assertTrue(parser['00:0b:86:c2:a4:85'].isCompleted()) + for filename, essid, ap, sta, passwd in self.handshakes: + self.cli.stripLive(filename, self.tempfile1) + self._testHandshake(self.tempfile1, essid, ap, sta, passwd) + + @requires_pckttools() + def testAttackPassthrough(self): + self._createPasswords(self.tempfile1) + self.cli.attack_passthrough(self.tempfile1, 'wpapsk-linksys.dump.gz') + self.cli.attack_passthrough(self.tempfile1, 'wpa2psk-linksys.dump.gz', \ + use_aes=True) + + +def _runTests(case): + loader = unittest.TestLoader() + suite = loader.loadTestsFromTestCase(case) + return unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() + +if __name__ == "__main__": + print "Testing with filesystem-storage..." + if not _runTests(FilesystemTestCase): + sys.exit(1) + + # should have been imported by cpyrit.storage + if 'sqlalchemy' not in sys.modules: + print "SQLAlchemy seems to be unavailable; skipping all tests..." + else: + print "Testing with database-storage..." + if not _runTests(DatabaseTestCase): + sys.exit(1) + + print "Testing with RPC-storage..." + if not _runTests(RPCTestCase): + sys.exit(1) From 8b4de8f9c30f46a61da8fc034546fa5e5c9a8856 Mon Sep 17 00:00:00 2001 From: kimocoder Date: Mon, 20 Jan 2020 10:01:55 +0100 Subject: [PATCH 2/3] A little cleanup --- .gitignore | 2 + __pycache__/pyrit_cli.cpython-37.pyc | Bin 49073 -> 0 bytes cpyrit/__init__.pyc | Bin 153 -> 0 bytes cpyrit/__pycache__/__init__.cpython-37.pyc | Bin 145 -> 0 bytes cpyrit/cpyrit.pyc | Bin 32463 -> 0 bytes pyrit_cli.pyc | Bin 55937 -> 0 bytes test/test_pyrit.py.bak | 511 --------------------- 7 files changed, 2 insertions(+), 511 deletions(-) delete mode 100644 __pycache__/pyrit_cli.cpython-37.pyc delete mode 100644 cpyrit/__init__.pyc delete mode 100644 cpyrit/__pycache__/__init__.cpython-37.pyc delete mode 100644 cpyrit/cpyrit.pyc delete mode 100644 pyrit_cli.pyc delete mode 100755 test/test_pyrit.py.bak diff --git a/.gitignore b/.gitignore index 378eac2..cde270d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build +*.pyc +__pycache__ diff --git a/__pycache__/pyrit_cli.cpython-37.pyc b/__pycache__/pyrit_cli.cpython-37.pyc deleted file mode 100644 index 4a4864eae8a395e137289414546ec39f7215df27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49073 zcmeIbdvILWc_-NKZZsNCf*?rI(iJ5>nj%0_c4!%*Btjr5)22We1VyPW8E)WS01Y&{ zfqT12;HKg6NQ$ClWs8%^W)sJo1v8$hog|xiWilR*$LrnkWNWj#nQS(j$@I>{<)l(0 zSIw3yn?F)2*Vg`i-#Pcy03}hQn%b>eO1OPr=iGD8J?Hy=-}5}%)02^b7m; z#bbZM1Mgo7I~VZhyoHS!Gvn1*N&Uu4aXC(u67riYCFM6&O381!l$PI2DI>qxQdWL* zrJVeBmGbi2t$z#px2KeUE@mdoG1IIyDr?py+pgPF#bi4-H&-jKS#xvk{M_7H z-E3C5UznTQXqKz$%HNLJ8B`~mcTb*PuCH0AS1W7vg}Q0kr!QL0YNNh>T53PN&S%Um zR4ZfHOQ6(IwuU>oxEx2Cdl=_0@P^lMN6=g|@p=rMnKV;YY9(!^7gJ`&%)TB+N9N2f zT+5nyvm3uTvtZ@sy38K47e{%s&&uPd-yFbEw>fC;!*9W?n)}URluzZNqeH$VP* z?6r7l#QcOcqR*|HKVhDGJ&v;n%}-hfQSJ%zQz&=H95*OWTf`v({04wqf2dUy!rM%$wFReYR=7 zXuc$8kK^odefE}FGCwb8Pna)TC-9Wp=A8LOw4sRS6meWO=ke5&I68@=P17_jTzw43 zkKuUBTr`((e9Bz5PT|-!E9MH0N73d{JY&QVl1 zm9vJd{nmgrXgzE_Vm)R(Y8|v5vQC++Uw@!9W)5MR{A9aJ2J+nG)hi2}P5j4S4&h1s zIV2TkycL@R72v#@nk~lL*;|%9Uw16*rW~uf7)%&Di~BjtDm6@uxyM)q>x#wQLH|i( z-sN}WMmwIryukU!fBa42PoDfDc3QEOnA6`%HR3CY)ucV!O6??D@w@SOtOe?`+GUT) znIzBD23w#^ICnwLCFHKOb5-ulN!iq0yqvs8e5#nXyYPf|(%Ev_8K+^^n~iq*Hs-U{ zPA^uQ&T=th^X=QIhPBzieb#zAY1K^LY+L0udjJmzFV4=d#J1y&*iMWuZi1}+RN|lz$-Bvy6WfXHWFy&1ycXY1 zG*YePYjHEany~qzse|mY^lHXC+D_GSW_mk?`VwZQmB5v1BeRm-PMg_Qs)8D7d6sCQ zGE8mKn-REPqU&Wci zY690%jY2E`T70MHZVcCYaP19T>y>LGa(^Gr**MoP=g!Nyf%CCe-W-%OKWpy8Fzu~P z;hrHmGcEV*N4asF%gQ-Z&JE+-F`PRf=Qhm|Jo6yV4dUD(Irnur_rUqs#<%gthw;W; z{u_V$CVRQh{8*!ZWng7+m|tn1`QTR)7+eqWo$)?D!XA1Xdw+ys`4D=yyH>#cLo54D zgGa5{&Ty;yZX8d37;lko#TK#uRSaYqphu?O;XHJE=Etq^%6NU;9&e5>7ZYx8xmq1v zF4s(Fxx8vQrDWN1Y~I>VEnC%fH!-@5zlCBP+opSNcG)r(>T7E#U>rZ{95-xhqgk;n z$7tY6eZ5hs*W|*Oaow_v(X0UnNbfy2b;Eeh zs#$iqYD_ohtCa=gYGuKyIhJwj$fdiNS-~+iZTo91TXDWvr(y*vM*ekxqju^l-;MU)$x&++R25* zrFQom+IL+wyI2sCSjy_BwNq%WV;@H$`yrN0EjDWlr91}N+zBrbv&f<(tRFN0X)cn91^$m1sz371kS5QlUt-bj<2kHm(+*H$t+ zSu=AtZe|b07L&s<*1IuwGiK(%f4kh-X$}BmNsl`YfPCHv{=HOh8qRXPSv8I2@-552 zcf^D=F<>!{>ov^zX2Y1@GHUhPV}7}^0iJWi!N43hWLOxV*I)P*k9y?uGuA?VsaA1O znZ7uV3P$IHXUpEWak)}$ShizKEG&S8OxM|7Jn`A<*RNb;3G0KFxa5^s-c>^N0^i

%H}Pn!C|1vgAIiKsqzz-u1CJLM}Nls2|z%{ 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 NZ;kwgyEJm?{{jQ!6wUwu diff --git a/pyrit_cli.pyc b/pyrit_cli.pyc deleted file mode 100644 index 8f1ab1d2f5ded52d685eb0882d6abcb66b104553..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55937 zcmeIb3vguDdFOY#F)v^S#JnHmP`rGM215-nGo(aHBT^IyfYgXX4Aht*D2fo&=xz*p z2IvO*HaGy6^h1;-+p$Hdw6-I^;`gq0H|6p}u2{A=yJcG|H=`M%tFznvGO+Fj8+jp>O#7e#MG(I;OTh^jlH+I~yj znWY|3C#D8>(V_a^@ZUuH0H>4dt$Mq(+Gy98YU8a|vy}}&fxA!hOZIT6(fLADni}Lh z8Z2^XD|vRdQC_Oe&bIsPVyRhOUF6bpkrdfk@-S!T7Me@7b2sZt%}TRcYn>abB{$p6 z<#X16bIWSRY-O=Nyu4o0gQxfEuEqF^nI4TKdQbERi~|-{VJ!%Ti73cj_GqSs=gRiKWVoP zS``PZghNsFrKtKTOFv}k2QB?@RDC(B&RF_kOFv}kN22Pdqw1`sA4#h?Y*ieMs-KCf zWxI9M9ywx<9E+-RQMF>}$1MG*r5}%~)u>vt^y8L(+|o}()%mD;-O^836?-+&swZ^! z4f=9-R9%Rwb<1#fE`txnJsJvSyC0U9t2B z(?@vfl)bEnqG~IuCU*BByZc^y>Qq#1N7YqJKV|8sE&aVw^_8f4%hKPg^w2`@^)*dA z&Aq|sb33iUr=#jxR9(0Hr*EJCeQEx|sQPMD{X3R_@b>x7ruolA)z_lx>z4n_?eh<% z`5%s|-xgKB-SR)I{MF&8dM>J-x6ycCRQ-;q`ki+7eRlVP_4;g7{cKcy!_v=M`Xf>G zQ5*K5sQS66`dxNw$Zjzd@3&i&{Q0Q*1-mt@TUrPouv^sl-BI;>?AAHms^1gUm{E^K zkJT80$N57`Kgb_C_#yr-sQ%Xy+6Bp;=Gzhr&L>AJ*Md{9%oKls`wJ>Ii?B z#!vHy$uY_wCi@tF_C(cj{;*V@;SVe0S^lsFKgJ)H+$H`nYd+2&ronUkp_7;S!^?l3 zKTPQf{xBD>@P}SbMvuL8UWD>{Ax{<2Q2j*6M)@WE9NJOz8l)2v6+w@6d%`K|4omMwpVJcxn@$c`)%DxYK!w7!g_}^HBjq%11dZFK9!~>MTNGij}smHDq;=#WvykA ztEo50emr_@M?~%$#pq^F)cST^-sp*5D`;vLUNfe5vo~suq&Ir(M&o4kT2URqGlS8|QL$aQ9^n^H5;pm zW}{|F^NXv=g7LhPGTY5|ZLRG^)RygUtx*j{wQA+1lHSqw2U@SHU0Yln=5Ml}LsU3k z=r8Om>@V^w94y$R*hjjWY?I;_81Q-&y_OwJYL8by4tcm848R6w&<~yQ9~4 zM)iW;QFTxB7&#jK_V#xw=>#`qyU}kqZWP-4BJNS-jebohWx6ZNG+>$DNT1%H z-8f)3emT8yFnWSQs)sD~c(Hw#t=xfV<#;hvci3+Icj*I1vXb`LjencoIGWu!W;gz( z(B5y2I-cD)VK*)m!;QP`#>yVypXxm}guVG8+*6p=dxnmljM@jI8;7DBhohs_du{q0 zq34AHV8sWp^%F&%`|EzS$O)GxUf&xv_S>^ZqZ^RE_gIn&WwrB0mBebE!XQn|tP z_p{t>Q9i)*onXE&&9!3YF4ivAFE%f>F0Ni&NbVw~ytp{DP;OL{h4Rf>Vk@m&OPG9N z9WK-smyHY!E%={`|5;5QBg@r=T3l%^Em1&x`c!f{Zq-&+>#bT6x4F|?Zr7U)yD=P3 z)oSr+m3DgAOYpT{OOkrk6XuK<%ykm#w&3fH`TAnbvowwBLQ0fmWO2xEwAy=VPNlru zUTxLvrpR+>nyv7mp$%OPy`Sy$KG9+)ALF2>SCiT-=gAq)H+8grz0usNpUHntZo|Rx zsU#j8Jrh52{`?1r9yx#ELVS7kW;x+lyB-gbeBlG}$D0d{`1xk5+_%tfFDDnzox5Id zFRacD)ADm4pDeE~>ZZf*zN-uMgwd|nV*Xa^NxM~_TW!~>@oEFCZX^Ee#I^X@TBFt~ zFUFIrbBpy#e7Rn!HIiEV%A@b=D@mAW4{)f~<|({Ao3ttax-+wIZftIgxluaAbH?d> z$X5qXs5DV*3gBIrdUY+*T5er`#ZIdAic|5$TEnXVnJD#TnVL+u>$VOm^Vh8@vvhCD$7xV3!I_k1NN8Z%=cM$IZr`J_RQ3F7 zqhdlAt73M!+$z&%Rm5ZIrDmMn@s-!QZk>6hya>S1j1KQ)cD1#*eQu{l3sgMQYA%iN zYCfcbKf@s^?1J0%6b1_Wil++w#a&$QEA+wz`-=nc!{dcr#bbs0_`A=zVq#}Ifpz+rfv3$B1 zt=ugN2b){_lyOoXg%KI{Fh(?HoQ@nkS8rsD8EvRnJ*BXDhrTx z38smmPx0J(+-Tk!&YnwR@WZu)wRSPKc^H2x%$}K)g7)>5YL({oM*UR^3pX!Pz|dT$ zZacdeKg0B`wUT(GQh`8CHq~Bge0pl?(wLs8z0)Vg(jFE-pBLJR$PuNEUYJXTWi_cA?3sFFnV}dwJ#<mAN|)p2ypheY%7z42YfEvv8AJQ^)CQgrUyQFo zN?|0t`IKi;8BdjYWnS1E>_gMQpNAFZ{`2QY#;3a8bxIU3CR*|_j04tjkv}D^8^`^| zktYU~;1o>+bg8`NBvPMtbutlzG zP!DhrQKcwJRn>zX zjg!CIkLb*pm^yrewO)FPlR=H9u_9+Uy5wDN`z@AEQNWk@C8{QZemk45RP2(2hT&O$ zh9r3(hJe&twG;ye1MlZ8$~*|7mFZIiZ^t^ zdZh8vAm68AMmVgakD!=HI%F8mbmQJ=2k-Z0U(`Amfz#W}OcUx5jT(jMMapLCQ0f;M z8XlXnH!@*r+XN+aGzA4(j~^Lc6Y&ec7%pMNB{qn7I*H4T^5XidwR7cm8%mZ9S`q{8 z;-m)5(GznuKwkNka(%Hpw^$ptnvg(1xW-F{vvD-gaA|27GGK~g!%jX`9wocMlAE`x zN$D(CuC~yay3XQG)fF1PM(x(@{Eu;x2-!q{iT%KV{X1+*lvH*}6WA|5uFL0i$_}}H_otP?RP#|~Cg%Wl^it4qjE?V8hD&FINWd3mh% z3PO~vH|7yip|C~O6Gg#QYK6YHU9@VpFI=$cVQB^{U1X5p#gnOsx>UxvqB*OBpI0D5V1oQXv_db3HxHZjxX1MgsnB+*m1>D`aVa&wq6$LO zFBPsE*&dsDENyPut>mvli+NHD^Y?O{v2#fzzo+%aoc5K(TD-X z_7zsXR8WI=X~|2k_I0&JK*u$%>7^<~Ys;k%6RN*-n7E|{h{_Klz(SYah+-NKg!YE6 zeckF|Rqx0T3`0Ap2{2*YauvGQ%@rHH@;+=;Wpa@MrbkK>mnNRQ*!48Swtzmz zA63JLkq$Hn)`@as{Z@H>*i9+owU2ZD!|JUww7`*;;#K@*7;*%W>8FJ&>IPg*}CV9&zto#eP#q==>yv={SU` z5B0)8&wI#s2nEG}hlk^mK$$_Iif64=hka-TxJu%d zM)H?itBo2GsJ|6^X%W^gs4oQl76#8Du4G`(2bSP~^Yi7eL#=!rcsT zf1#pEMe)UzY&id#6H$Gr98~|bk<|1YkO3)ong(DA*`T(s=$!F{#L03|N{8PtPhsUR z!aW2#@`*r(*OO87LgUr6CW`wDQCrvE@H)u<=Cla++Vi4wV>9FSf{_#Vi0SBMXO+V% ze*En#Tlw*bf78=+@)Ix85&lk@{FVHV8V1ZwCeMI$ef@SRgGQ=CJn725UVo+5kR}EV z46t1{s%7X-Ie`e4YC{zjrr85Et*xQWIDM!#K~5qED40>wN}Hkla{L(Xs{9!U zNo}pHWiCZg_Ma=5Xv4(#)n~^?O0m^jn>A&7mNB_T_a+x>G%ij8mG5+g=KE7lo=*?e zPK($h*9q!zm#$QOKoX}|M#fJM)lu+^aCl$Ji^{hi%Bm*9&_1N$VOu&AgCa*Itpg)b zMwr|*;809=@|`e9R~jPKh@G@f)2;IIa;;T*nnV|$gHoH zYj(dU!%ed}8gikADSI_Z0r)po6FXrF1U8nksdS2W&CQUxGokWpBja%CqrPm2=8T9?~h?4to+s5Q}L(P&rQr2)8LJxgD@Eu zC6=^!!=?_jhaeNGM=B2=*Zkrc4r)PQZIE}=OkYgK5tgV27^1_&aC1Pb8(opizYrZ-%U!k`Huws zV8>>!xzFP^_gQYi3|?3%Ba~!S?ukxdla*+2#*l+Iq%TYTX4(of%*uI!A=fJFRV&m~ zmgP5$-%-~-Z`zY-(=Z{Es->B4nhO+J({^;4_8+6^m2VUpU(St*8tBILZ*18>QoTWD zb>G;ayEZfktNIoV0xRXmYGftRZT@KO#_g9eCxir0D>b{A(lEUXBumM)4h zwa~l;agih}UAnaFo$L$cR`pgHwV=B%Cc%hOS#7m2EiSH0W1rl~T30og9o2}GZyGCE ztS{ky)2J*X(9miZlt(A8naNcWL{6#>V_ie=cM5mE~Gv^s*^1+VU_G3RC*%wXu;T=Ati?Lp-ajz-m$wE6e?T z$ysIUZcWJfta>1QVpp3?H8U@Rsp-NtJgP$Dtsk5i6r6X(iq`F@=`&qx(P)>>>E?MI zj1*0AW>wkHm}16yd1aaIiaJ>jJ0gh59F^tLr}UgCl%BJ~uke5blF_m4Qzngm=k1>q zU3!S5XwN}p4NRYyEbb{D#eBKnSos5m`wM5oS!Tw_c=sh9)N+8>85SU1(J593bq>=aUo5NuVl1v*Bz(urM+$J`(DD8AF$`S*Qm>jQ8oL00fLUlhu< zIUZ+eWAMVjN6ygtJ6^XA4YR@xRcgpIBHmRNT%Sod9X<>hNA=*!aGRDgL6yWcJx%kt z!v(iLzqB%Jet9b|YJzDgM}7TFsv~X-Q-UUls(ibUP4 zig{z=lfg9Bh)YJ0>zin!?k}*aU?iVo`M5sUV4CuSIA@ zDfkA=!rXbsW)`d!=2;dR3_C&JW;!P|!+_=S!%9F)Mm2lo66UpHhBx*aT1nSn#(mLY zuTJM#Re|UJjaWTuEIk@~s6mt);9;1AU)Zt+m!^yV!;p zsJS~P^0(=q>~u1<2Vp9%_ZhRQFp=C0jvnJ_TODNQ!p{Nm-_?!G@+9J zg#%2|74rhc=3fn!b36};kz(C1!I-8RdhCE}mi#7L$E z+}|A?Gip0c&QHAPM-f3X7`!i-v@D{Ye29taR#?neDN!<^*Yzhui}jl*UCddfi%^uL zR1sA(ElWpat{X|Kn_<^{jM8FbR31QPypCMol+h7LQ=Y5Wat&E3qmMxZl{1e>U8U3VBehstLNcIb zxFB3#rH74n4W#TfcdHlD!IYVPNu#pbsIROtqzkR)>UCVb+V)N;4&T%Hv_WG>xr{VS*T0MK2I0AD%GCpcd6bsT0{HUoTB{r?ogAl$o6A%gd` z`>JOec6Uswo97-&TQsG*il1D?C|b58pb>rX#Vn746R+=--idzu%BO4h!tc3b$q(W>+nR!ix995za4q7d6( z?0P!%YGX6NpJB_@ep}l@St5(0{E~mgL5e^Z?7=DsXntvCD?rDaKVfF69~7VyVlgje zNC0c!GCwEJL&c*6fT9 z2c4ej6OWjq0EGif5U&J>fHP0Zz9rZq@W%0b7g2BqnUN_51R<#XSrwKbxd62Eh6k{-@F|Czj8QB-Rgs{!XWANq1nc;Xm z*x0NJ#6nuwWaeuRTASsnl?-#wwtgQW?Zek!#V)7O%(!1i%b3#x zGU!pCnbb2LpEj+F&7Y0M^bt4uJEDe(g~Ha($oo=GJ}A!H;nbz?)4Wx_kz~D5aYGp| zu;px8!h^1|S6MQ>-nhzmPzN!3Q_;1X?eb#ji%R=m9kehyzD=$-kvvfP5(hIOlx?eD z%e8pok#OwVw;+P3#~VlWOIot>RfzVAMV~^!A{N~Xv%aTrEEwRLCW}af%4Ct4=ibWX zMi=sO39F8EV=@E_&vh<--_$Ew{J)ZuURc!Rb-K_Kz4-%L^6S-TjlGr71y;4mHe)lF zCD5?`<%nlW63H#7gZ<+1;7deN)DOjAy>r}W`gWE*ix|nomNF~+J6Yk4)3~hOWiG4# zw_H|3qm2wO2X5>aAu7mub(+T{!{``tQLWWsz2nA|sdy8quL5NV@}<)SE!;};)-sN( z>$bdZLnP9Ngzd#1U7GGlHmTsUi3;RbCG0k>3(uoD1dbM!nsfi(@*)owbv9_-l94|( zu!nh>HZp5_A_4zu)@>W0_+_eFgkAU*2CrfCk8N1!`B85KHYc7uH= zM9gxaHi`_5^0S4drI+gD@LXB@8_5ePb@)re3q7VVA)kp8P#@sLF;=P;t9u0sEv)@h zd(w=ZV>7>$LmK`hw8*H}F{q79o6>inWF}3Z0ZlAK$nXjTNh)KbMo^cVXp{e=5kIQW z-I5cP)jMwWTK2J-(^l^u?F?4Wcm!Gp4pED?Ni?x!$8h$~3_zc>yEtK@To)x8R|?$6yyxGVfR4q1D2U2pHJn349@; zHo4tHXS2mDDWJ*r)H%$J*I%tK56OHIb;w4dO2N%B~+ntqkl``dO z2>=NXjgL%Txt!aBdq=3F6+eJhru{HG0Lse`P@e53$XaabU$ZoB@HcdS&x>x3)Pjy< z%NAOuy+;|qFnxrXSim9m&dw)XuG1Y$;c1?d2DHLk>DEF&Oae1vChpp2)4bpKAqd$V zVK*wJdw8g%O(pKWV}QdHz*;_~&v4lGV(wP>{*jikN@f$gT8eurn$Egj&6UaAtBKzi zxR<|RJT!ve(hLt7o^tAEl*tI0&=V5d$SRx<<&mVyX2bQrX3oS()QG70=emAZItO>b zd{bwi;b8RthCPrla|ERj6&DgqziA2(U2l6d9Ig4(`DYr7lhhzUbpkEN35b{Wcgjcb zMB#zr5r~^RG_@*fi6)QwYBcS?? zlIe-TI(8`%20>Z-cSiJ#6phXNp;58Eh@JQ93#HORp4gjFPWOwD3k8&OZwQR=`aZF| z*GvctlylAy7zIE%(_4AUNlz?$N;&(Z*DZK~>V$IkJLM#Dlsmc?R^DHj4xTOKaLS29 z@cKZs#!{jo7DZuf=1}xHaSPCg(`sQp%*~(0HRGQ^V{b?h>PRx)#1Zub^WMnYvv&-XZ19P@xL+9kB6GtBZ6J7DT#g zs5nG8>;vhDpE&12jsrN{NLe$g2p#toENzQOu)zcvh%jw+b!k~dTul(3u+6MnG%R1* z5F+cvGB;Iq-iZ4}P9PQ{?vQ3P(HeboU~1y9#9N4^{eyVV`#u!k z9VrGok;EKrr`N?;Ghj(G6Ubf2SlpPdGqyMHea<+|U2Tk+t?B&h35 z&OOC?{23m|?b*(HY;#9w02;Rajti-DcRaLcK)u&MN6d&U=9J_pn+nfz5~hN=7u!4l z$N50OP#6fN1^?jqJEH512z#S6ZES4jgPRAq&pquYj1Yx^!OCu95kE2Xk$CFr2*YBA zsnG?Dm9+*dbPv^+@Wud3)q(HL*60XJ`C2Pb{tTFn*(>&rc4G zH!7|5W%*daFX!j$l}%&nvudkxQqwjrFdL_Ldx&VHhUo6jQqvG^9-g;aYRog{))q@m znvC31`xuPgf*kok$d6;owRYRii(+qoerPIouQUk-_jN6^9`Z;btLd%tZmkyK6*k&Vo6sz+J@ksDRmG{eW=`(62L$>BcNNN?erLR)3*T zK*d=ISpc9R%gQ5#G|LcKc18u1mjc9?Q^B>iLUdxJC*W0WaCoHfqI8?DUQ(?L0%5mU zGJ?O;jfbf9VAMV&EUmg1QG^yk7aT}8?qW~B_sN{23)6t(?}n})rYlk5#kGGCwU4M+ z3LKmHO%oE#5iUGL7tzM{qv}AX3!pxlLFu)x=t9u%h7_T%eb9=vhf)b*Z-f{U8pH?@3RMkqm9Yk5<#cg+<@XExn_l_B z!gR>VI2Em{Cv4bGWG!a|rUo^2liy$}23)ZT>Zf+=MVKdu*ETp0ZQ!xq9s@ZgZ9 zv<_MTMi^P>@LaSI`JgYQUn0w(9&`X9qU^dELlHurgZ%C|ki;IId1A4=G*>Nu4kSBExC0BD@UHgaNoq88RpgtDG{Aa!)(=61+xO!Q?E}?_<~rbG z{S6ZB%#f(sZj#%(Ir=02Dcb#Oo7!!9!*{dY<7vAO6-A}9{Vog>DOwl3jNwP z0KMkEz`O!qif{37Ws%sumc`|dw^4++9{d3c+oUXiTg}IIbsl$9TSv)J`iHtKaWIQM zgF3Y_B(amI1q}`{K&GqAbwSC(7LvTs~0uf zoS&BmUg^h`+RMRG1qaktcVRAF(@m9&U^LfcJ6HCaOz|>hvDa|e@Cc9gZd|8s>hzyh zIS=X}vDo$j<2n4VGOkusA_Us-j7cGi{E&GEfEotq#y-j+~uHczZn!N%! z0(rq~rH?B=l@r$NUW>80ms|sq4EXiwZ28S09JyUf?DK_A+m*Z8$r5?(`H*M$~`M=fP#OY+gk5PIB2H+ zIK$PsExdDx*0WHZ%j)+JteA;>YW(u}=+*e)_?gm`=i_9BK$*2!;&Xu`jO)7xoVMB; zj5Sm2^3u)D_8Rk_t0qId_p7{$Y-kO_bcgX%B;GpaWum+e$L9QZH4~OX#Eq`uAM!Cz zJ^hn8>KHAJk6ay(uZ}!@c|10QMm%VL0MYTKiL2w!j+f%e(xvA|N}r6M8~7217m;?gIs zjq`r=sP}a><}rVP{>r;5>3Sf%DSM*(?VU+J&}mrLGqvSe&#zaLj_%p;9_jQM3wE(p z^B7WlGS{Uopa0oT%~wm8p4Cjv$BBr?Sc}ZGA( z{A7IP@>q8H;ZTk}(P@)EmtAMsH$FW+F_s8zrxU2VrC~HXO$`Ze*Vgbxm@D4c?D`$H zHp{>1d9_#I`l`nR2=pAHVg6|y!Ky=jjO?a_D#R%}N(qytk!PPDiRCTK_NPX3HKDQ# z=A0Zbfgh?)%+_w+Wag@vM_F+hzaF5is6kuR4T=c(!Tr4rI}GBB8K3QUHX0gbW|DXC4|Kc*Z~JxOs)Aa2cJ z7h$!f*F9NH)cx;uX&un}*G5hIyV^2;uQl@&XwNMsF2a75Ja%K*ByW1-L5oU1$qjpt zuCw}AT;8eRYFmqaAA@5j>F<)yQBt&5q51X|dl6S<)a)-jim=*S*n_CrQ|RB>zoUN_ z|C7%DJ^a7BfA<0I^x6OW>?qMzZU_B5BbWVq@itR_MIdF59U(Y&;iSNw9s3G$O4v1Te)Ho;97Up~MDyl1 z+YJ|~H$RexSuEw7W&ZZ&j*IEe-26G(ew}r>Y3(!@{oK*~``vc7)1*wALwT5;Xx&}W z4avQ!e?L9&yEK4$^0ldH`2MS44k5tTF(%ol$K{A8pMTDc4Y%Y)(QP)Ra5s%hNuFMP#LxoVwJmoGFNB`1%YPD)m-n zbxB+J-24-4A6u0t|Ff_g(0tlbZ!tuybTe~;@)YZeG@#3^CPK&(&}{hnFeJ0q$hXa7 zuzK`Axwge}XBi!1Bh*!TGpCr$@>#ae^-$6)b%k0ZfM7)dlxTduti(Rzpf8x2A zE)Phs-gDR$Z4t^P+DWjqO@t6<-bvTn)Xv?oM_7-iZ%{kX>8RO;vI&!pPR@>$Z%~WS z@|rxhfnlMxbVrh5T}Zo{*v4xl(sbJfGb6X5L;i8O4rY~?eniAYu4Z9@SX^qGya_&i z<<^IVV(ePG@e>-_sP=aps3%Oy>)wo^`D;B<7*Ty3E!&FW5n}~SHq~Z(u(qnqqHJy0 z^yQnee}HmIKgt2qH`uQ8`Y!RN%FK3mf_qTeWauq*Z^bZ`Zim<9{FIGViSl;#VA$Sl z^T#q}t2VkaxHK?WF#HjPU?YlZi(+O0jaqc^o^9BKHB=Sxph!5IzqdR!@-wv z>+s!a-=A_Xn&KPZP+Q7{+Wjptk2tr5R&^3tl4%G*Cyx zrz`rFRlY2fw4CMg_6(+M365-6wX1K*mvZw~S6N}BHPPf+^b7YDpA|5`5V}QJXW20) zDr8U-lZ^M2^33kZ)+*B%bk(-2F~>+XWElo@NN8VCAxaD(4hb_;v31()!c3|zz_=xS z0#S3DE#ej-2LM+Gx@qYy*Oxn!f>18Vl)_BS{D=kDoL2L?KJ{k!h( zt2yx4HA$c0);o&j3}zW}EEm6)O}BW6K>IjM;rWlDd$>|wj)#&I+hlD_%CNjrutlU% zX>;>8SlE4FZ5`!bltJC}`zIQc&eHK6`9WiE8go;}u#qZEVUN?x*UuCqA9w$JEa%g_ zD!BnU%o47cMo}wp1cvqJrQt>@ZdWuYw867g8P*c1T z|ACq25YFT3u*H5Wcs0EBzWWb%l?y${m8v)0Y5SIin%9qo%FeS9_1h!z2(Y;}gOjl1 zRw^jhHOOau6|d(;Jz1z#tt$Vjk442UWw_4*0JsuE8iy&?Ft4E-{mE`$`foUx#sV(^ z3%27Ma;5CZncGcQVc5^MLYSIDfC>aF`ssMD^zT&Q|Ej~6I2anN&I$dAzL}oFpseVS z;X%uhG#6i~Rh8yy3!c1Vcqm+#pSU}FC}UD3ok+uUA3|+$gb2h^U>vkv5&HazK7De~ z6dC(D%I0pW3(kAF>Old~kHx*Wcz`=ncT}X?qVP@-N3E?)`5?UkDupM~*q`Q_E4h0e zH&=X0@nMw_v2hHyR6}&ZE%lO&k-kB{7~l(!8uIfPLQ)4NyQ#QT!!8uVoBf3j@lk;I zm3lcYO^$Za6$c;WtF;vKg=LGkpPoeA6)6tSr~Zd3;>G7L4^hmAok?fZ10-XjTFdhCP4=Z7zxKY!7O!|@%H(f%`|$CP&mzbA{E zK0G{O->3`8?&jsON+iTvtP;}&Px&0PrQ{@1q|B!BETgL+Nu}S`6QYf-JC_323(!hz zEmx}BCsx{OVB#wqH9wx#pBeQ*%;Q1ZC@b0$73CyEL;yaAjdW|Djfa3qwB?+_ zO?fElC27b550PqHSM`MyWIUWWZtjR$UX^+B-x!FF`@JK`tokNX_MtL7QlNP_og0z# zOvtkGYnLulA&dCD(W44z^7IC`{qw2dNEyhsX&Fb=IMG%2)mNMSOr(?ogN{?&z$S&v zu*5IUf{L?noEqA?OqX+hItL-HLr3)`fg4&)I?tABMCp@WoeiHY($D=j$TYxISwVYW#T5vFGTT-O;l_7H;QHh#k01;0>b6#d>Jf`S?>h} zS=2HoWrm6A1Bqfsrxok`bcga8)wnk1Brso|mj4G*Y8Zx`SPZr8kh?8tPlzaQE$({r zn<*JFA~e`ry&~DEOmea}w1MHBw(mQoV|Utm+8HHjc)P}=i!=u2D~#U;ENknmzOV&Z ztky1;s~6{L7i;qu&!5*vc}>^JXNmMlNsB-gRJPe@nm@~&JPyq6)vhnq0B{0x{P!16 zIf6gOdH)ooRdW~xCu(A8dc&*EAnmz?Q^lmbdUeWlp2>qe*f+JXie3}$Yc55b9%oP| z1`S7wBwH&23pdxzuzgvzv#a(VvV@e81{P@|PAayiB7W;5&5n4#FD<8@jL6T^6rQ)r zeD=E8%0J~_1s6~>Aj*3hHSTTS_v3104j_t+!s2$IuY&Bd&2l!WFrIMBs=;Dwq@`ak zGZjegq|_S34qYXq=~Fcr9VTJ`I|)OR3wSRI@6*Y0Xt`O>3_gp~(6CnNCMVw-yRkYJ zAcKyv4|v!beF6M9|L^C2efL{m0`JAWbO1JVOpIs`6-ykE1To4l`HIx0a2`Km4>R2+ zJOpYkZ6xYCv~whqm+xB`{3S(nI;cBIg598JMSDtCLO%2;wo9h&IiK1EycxP!fe@ zrK}J!Av6fDN{95nD7Qx?@{b)>sC;o)#1!~<<*&H*z2=QL^I40@aF3dqMq}7-+tFN! zxN;hwO4O<}%n}|~PZ>?)qf&n22FdY|Zlf54mAec43jzN+VgD$dYI3EgVI|gn(;M2hun{yAk5~Dta&|NY1;1}@t`q?luykj+ z)*yj~j}|)vMItI+#)OdGaOeZt@}|m1*$hQY{rR*Z-BvJT)tRp*IrD|31=XEh z`lWqo(Rj%wU&~BIv!R?3!z&(bLOj@6g@Tld2`&34BD1bwcUvaEm9PSfM47!!9+@BSF6(aIsB1V8aF&Tp zrXO{9mN(<(3sZN3uzp*ME?CWNwuE+$KdESOUM4^dN5^j4s?Q~Vb+aZFIf#{}x3k~R zHr8YjjdGu@m-y)Oz&IWIp}QwI07GA@wKo<%yQ$qMzB~dX$ciHt)UbQM5}NLvm`A}3 zNzO!Ck*JfZR1z&>ZQ6k*&K&N9jH+%KCQ45^TNT>|?V8T4^KF3AcamY-T(jG&>DQqw z?$tyni!+pa^&NJ1IFYH;zOR#C9Ok>$=Za71)A}X@c{0~1IV5;!Ko7+7K61pRnnf97 zDfydsvUYlC2xy;+B6gb3pJ+_`2KChl50+xFQ$DRrenGXEL9iT%65Jxng3QnM{m>CM z0m*{_1jO(r5PI+k-`Ze!Crp-z^?)Otl)6~*&cuycX58Qoo*XndLoSiiG1rph)qorLmcIoG~W%x zws#A}CJ2PQO{_rl1-HWa4a}_|L01{@MgVc(wKpQ{h0XK@oZcZN!kg*}%1MqetJfz-u6^6!sH(L2!zT8HS4_FVa4UEQ3(AYIY zV|V-OF9PWdfE_S2#>IZn7!NTMY=adLpN39Z@TBBdSOU&8;!S8wJ~QW1f*3v{DwM!3 zjXdX!)93FTlfjrAmUWefQ<$nr;Zz=%ZD}hNch8#HRgyS53@?Df6b`&Yc-CD~?h~xr z!e?Ej<*}N_y}m<$)>T>_tYxG2mIy6I>fX|x8PqINV{D1hDyGno9s{GRxS>VVPL&z1 z{OxMnmM_fA1!iA(8#8uSQR(YLv6q>}1#a6IhC83-Zq+_){u{2k%cg}!xvR9y+e6dC z^>Y{`P~>G^99x;?HPyD#9odA<8Yu9#XkLh|+K@RSx&_c)b-I~r1Ay-`dv_NHH0`(x zWSw|-preI$@&&vVYIJDxAS|krCxev^Zlq_C7Lx#SSH#L5<**g-x^o+@nP4ZrHEfn_ z50(jJy$vjrKCZN&gPARcbS5oVsaIgBgR(xMw7p9EKXmrXI!x)XPia4-v+vd6i#iz4 zGF&FuRx-3@MH$*M^X{FXEeBY4QIWwyxAJ;Gt)Eo+Kd-|8x3`b1q^c`Bva;p>2QU=d zo)#VH##Dy_uDTaja;dZQh1vT+P;xHcWmrn#rS_O&OCM_PMpPMOQhlTRlGeKcnb2lz zQgUs8Oj3{GPw0U+JKlgOm{JraAG|z>LI=X7gD6vpwSFr_1n9d`m%9|*2t@sifvEpM ziXMR|Fvt#psPRGoOAew^<=30v%z-6*1;H5m-Cc0)tFpQTcm-rKcm?=D+lsp&+9=93 z__UmZPyGT$j+hGIw;X(;Bj~*VJSYtN1ec_u0zQG5jwm6ZCNLk^%pCa)HBsO(B?$|C z5bX590{>F%0M0P?Kbz7N^G5xp!O5 zWL{%eLFOITDb0)AR}wZM?RNw(-pi8mg&_#C0bWdH@B*V$$IEP@b}M+9{eK8`7;B$n zG(3>*R>~kl9e=JYXLWc7sG|co41WkxW2%&Ga?*OOsK|L+O4^ zX96GZF5>8=*ldm;#{8CCB_%r84L79BA%u&mavXB>;wGm3a3?d+A-6HPmuX+zR%)CK zbO?+Y==ehjfAHx56PPvY&3{^yK@F7PI}?VC`{Pbw7BewW-|S^O)8IZGGo0IduxHVQ z8{*pdeZX3~&2V1mXH9>R6^bYi!hntO!TSHwo-~BwiNSE>P$e`rwbDt~;hLVkX0ZcO zV6poTh9S_`7`OLL0jL%>TkP%4){Vme5C|p0Ahe-BdkSC$ zlp~N)Gy~k8NCr6S@P}LD;F0kH|E5V)p;7|Loc5M=@uoJ^rH05dr`BVc^VWx==m(ZL z-y*WV7@7;Hu=EVo`2FuFhBt%}E^nE0RD*)Z9#U<-Wx`O+{^H91q9ByiI_cX$H6&E? ztA=V$7^>m?Ho71tY^n?La%pbR2tCk~Qsa0_jZhj-GWDgmFo#`i^lt~`Y{^uE*)VIH zd<*j|)Lm_Cd){@K@XdV&p2-D!!Oyv){A~JoP)_N)W*vo8zPO>yroI4}MyAw-am-Z-Ml=yV2{dlLAzMS%?KA$hFgO|*Ln2wLVdUi(GPKyoS zTrrcUIY-*3zVoGN5Go5qcMA^WcL>6sUpM>_42Z&Ejz@5a}Ki46Z?ip!aK+qVKE*mu}*WpJ2eY zl?>fxzR!#0!-w@jm^1u&$6b6|P11yYGy6YS&fsf%G@ZXIdnKavN-Rw^b!sgUot&JHws%Uor3H0D;-?GpeV9?fTUy19(5F z8;0`U1#OaCm^Q51YkJ);lO7$?SAO?lV#8EdOigvWh(xf_U?)^}KpO(Ubu!lNLDi(I z+Z*ia0@C$94i(s++2u0Kw~GddN%Ic?5=C$RWe?a+Y@OYxXcIUp?p&e3W=r2XfWz+E zNR(ZI_>O}WZ{knf7ElBbf;>P{#P_ajbVn zE3e`0#D-3EO+X2A^QA2S1Mm(7P!317m+BVq2S|e=M>xqoxvs6Ixz?#Wj<$HdH#$Z! z3YG8=I+?7^cp1~?FBcFxvPls2BIiB7`9;^Rj@ijH+Z|ObHJr7dPO$`a*mp2 zXrTZOL@`AQ)jv-CV4E>Hk=8QvbC8Megz#P}w&L0vRkX)yei-z-e)J)Deg+$+`72{caHd;Gc~ zM!M!P4;hrTtS9f$Q002U1VJ^J_2k!zx};T>*xeJ7vY!0=Tu(U9o_QxdA@io5e19?5 zlfzk0p6vX~-{|SQ6V9_|-bqi$ zys0PCJsVctU-jUrcNBFZhp9mk%;aBi7~>;yttB?biiKkCVRtA&AowIs`4yt%D#{Z+ z-WZd*AV=pRA)w`2`R34urlU&e~GBbu%m1 zHaLtDNn%b;>FoRrpRPyy9Yyoarg4M0a?AhK|61h#KX9u)`I`(06f%1GwR1ytxi}=E zoLSaWiA4bDFReBjLMd6*ZV$4}(*Ai&S&+V6&!6PbC;t}weDPKqeq=u60+{ic+u-hW zKe;R>upkp3jF6MFS*-E@E?vE931`fHRZ7TOYN=?oZ}i&O$i>o%E_ZXdf~(Bv<%<)8 zF&C~?S=E{GS)mvRCkLFcO>JVjj%v-Eh|NAzdP27~Ow5PUE4t95`cx5bc(OA+kkquJ z1SfLSX%TRt;-5~@*1LAIxtN&acV)e@SnDWuERCJ%lqVYyXVvDC$J!Ocx5hPyn&dX6 zTS}65i6+Ta+H4n8I*MO*+gUoUNPeY$X-jqK94DpoI;`uk#=&D&nAPe3;xc{Grbn&x zs*;!jQQM9!_gGJenrMx*F0>piys2Co9lkGI`a8N%wVL;q+G@8;uai)MRBRt0`s`Hj zKuzi&r-o#i@}k~@J!~k%q;$-9|Bm8A=CHF5OmL!b2Gf%^6&?Z^D7MjIG(-4QnO@tr!L~WoXEhQHv2p#+ zHK0P=QL(PsUeUQ`b1y&Z=P*6)!bm52*zTmB!^m81qYq*Ln|ynvxR`&BH2(!vQ(`eZ z`hsfe{=9N7?i-wgW9&1BYqNzc5hQXP`2M5PPhEDXDI4Z04jijshC!gsdJoqZeFQ`8L#Dv=$5pMzb#^ zs$Y5+ravP|6LalHg~wX6Mcu$x%DM#@l~xY}pDV1ME2<>)TNZNUWiY3Gi*fBad%LC= z9GkglP>WZ4S5Bu$Pkl^0mA)eXrUe7}ASEWben#z^DD1vj z;NSGhPI|$OKQ6AVXdaEt%$ve-%jSG++s*lE)|{^vSH4P6;+3pPdwSZa=@@cD&9pu7 z6w?DUAnMJr9^B&HLrfaj3=7)G6mrV8e%4O%dDiSzJZ-XFX!7^2H4?e@*4tnRV}c6! z!FQR7{t$fme+0PENPGbq&i~ z8}rgJ$|_4viI%CY7_n$GTYOD97<|VxUKjgDC$A+JEn=b}57XATi;RE;+t#>yn6thV z?WENJr%bx6|0#shffL!HEbr$@-_eY2d zW(Qiudc(ee8(wA5zg5ba0g&Jp*U9Ajn9mXe3w)>$BCYBzy{oOpFx@yd9FMu0iG6>x zz;-a}%Q3uibMv7ieaQv2dW1<3rlWY3hkTS*e2c0(4_LdC_{wt=?(1wykPg5yPZ*(= z4)iG9&7yE<^#Es%C>EN0f2VX>86~P4mICd~ULBvh`U26Ruau@rP|~P$za9}^5>hhU zR5AsMDN6)BO82OE19rTNXt}xUXo~Y_P)yBDUqU^Gb3BlvkV^-sSOwb5Z9ytZXH=&O z!%f+uPM3z#6e7;$!Y2rymi~Z@+vm;#cj>J9EAizQNQm|x1i+j$e;OV60Y`R8QBsHj zH@ocK-9R0A+X(dNTa$;m+GVj5-1oVYHo&(F26me&utxbMUxx8_vH2&9Vmh!~ z_iVkQb9vU{mx{mfsKB0#T73S@eR&~?D=+F=pEe-+7KRne%{dqn{eVh0*BV|X+6?Ek zYyZ+iX8leffC}3jO(|wfS$n$Rh2X|a8pL^QX1MS&oXMCn!+!&P0(ui1k0Hm#w*VQ3 z#T<=&Db?L+-7(~A1uzgZjKuFV=B%>p+g)OPSZ3%Wyb*3{9G1Ob#!XSYz)iX5+*FE~ zL(R~{!Byr^1VGJ6aO5QrS?T9Jy5rLlp8r>8>9-FBc zOTFX9{n0yZ+#eNI{s>n7sv>Bb<23J^Mw%V6tC2ROJEIl`GUkwtQ-`1OgqsN|W6Bn7 z@(e5P1(Bik_`>;9Ld_DUQv!u1KaEgmWUPx*luV|=PeWU)wtD(@P8VQyqkLUVk7{uw zg+Q;?WI*Vu*4bdAhFIGj8v>scLiZB{$=pvfrUXBBp7_?pJKLMy)vdQ?fH?J}aTYi9 zA&ZlrvpvACv;8jOEIzi&&7_Wp^}6vqAAE`Uo#(Fq@K^QUuRc|WdN|)RZNPLOoxZIp zAB#sO7`U-}$ai`;jV0U?s(?ISzp4H*;3{XE=fEz56wN;f^bx?ni@S>{fM>napl zO55GS1#oJYVQMMkO{bN4OTkdZR6!!??mLF+*2TVu%~Y07Km<9BS+$Nt4OIWa3ZTF1F4}K+2{xb#ivtdMIb4`(TzZLC?HYB0W*UDPP+!O zQ0wzUS|-*(d)Ox0IP-O#<-<(#Z#P_dZg{X`U@>eVj%87rOPmBSp^21>w0%P6S`+;Lf8cxbyE6}GD*j#kt4X2KC)nd#IFg_WQfDB zG{v_MHl#>!>Tm&oo4mwj)F=2b0C3n}RD|hWb}oC%eT4^r7RP}au2bclS_Aw1*^<1^6cv~xFG6_ zVKKvX+U5U<9*|l{1}XkwvEk_trtZTQjg;#2^aqRllfq$o9B*npYh@uECY->F;&8`U{m@PGnX)v(C=)@ zWVj8Lk8D{?DeOd_O0(MzuW&=HIwT~?GI7r)S(QMKpX$LF<|ZX|{8K%e7Cv$Pb6RUh z901}}WHXAF^5jYrbI3z#rqoM9!60h8o1acku6&_qTBVzrhth-6gP!>JxM2 zKhkQ&BlLPE)9uZIdbx@dZBpKNGt|k4Z{N$^tg&fRY`=QGHEOz{z~tA-uf5iQrp_KP zLeN<2gt4+7CkAP{Zgr|PEKLZxW!rrO3~Z`cE#-@6#*+;E&?P%5D% zd~DM6Wr`|xHk}Iks&8=Q%5YV6*u&`Py~U#dL)7uLr{YhopPQJm5HN|}Em}7Vc4p&j zEn*7jg)F3lMeGHQfFPZ6T2JTeYYNgJ6ey)mOYq5NRdtSVMAw0!>YxIlA}I)SO8cf3 z2ROt4XtHRwF&?)^OA}_uGz*uZ4NOw5TKQgDXKEBnUMjn4#4I*~N^Tt!gvkeJvv=RY zKK3Yk23M7SX)Rlor`@<#lYM0En*4VH&$+~B88h(&LS}}dev_ME(y4V z_w|bK60iW(jJ7qMEcEm|2TezFE2Z|^8;zkUTI)s(#V6h)H&t7sLE)MJ{{R3(%9n`2C)8U8?`#D&j zZF5#hHlor6rRl|3TcKFKjjc(Fz3LjYvGh|a?0?hYhjoxvv-A}m{;m$+ro(sW@W1Qu zf9h~iW$)I(-s0~mZH&u7PQrmJHzW;JEY&SnW?C9rHE%ILulb+)=A_kJX;yBh$Z%^@ zLNTkfp4MbfzI}SLD?eZ~G=8u`yc=YrdpSXVV#ZWAhugNrNe{{7Cywp-Z@=bc?&u- zowwF@Zqa^^E<3B)R`^dT%}B^E>g<3&Q_%$7DT^nJrrTbX>5+RyUn$qDRp7r_4iJ#r!N03TdlxO%Q{}YE@#onIddwZYkJw8zE-NElj z@4&#B-rWOt6Hxdt*C+YirF5=I>pj5lD8G9KiU;}aDjYn;)z01>y}NZhI7YrUDGv=4 z2cG4x%6+f$^+1mYp6CJI@8fD$;RxrO&c>8B@I24-P|lP5M)|!kK!A|lcl^Ka%8BV^ zX_A8xYPnpSKMHXT7jWGv-N&dJUu(KX!>5q!DaPh1wvlbv{}?mxO17YsrdbFX3D~oU zDjY`P4@wV8cxq$*=yv22. - - -"""A test-suite for Pyrit. - - Tests are done by creating a sandbox and executing the cli-functions - normally executed by the user. - - Please notice that the tests backed by the storage-relay open a TCP - socket bound to localhost. -""" - - -from __future__ import with_statement - -import os -import shutil -import random -import unittest -import sys -import tempfile - -import cpyrit.config -import cpyrit.storage -import cpyrit.util -import pyrit_cli - -cpyrit.config.cfg["rpc_server"] = "false" - - -def requires_pckttools(*params): - """Decorate a function to check for cpyrit.cpyrit_pckttools - before execution. - """ - - def check_pkttools(f): - - def new_f(*args, **kwds): - import cpyrit.util - try: - import cpyrit.pckttools - except cpyrit.util.ScapyImportError: - sys.stderr.write("(Skipped: Scapy not installed) ") - else: - f(*args, **kwds) - new_f.func_name = f.func_name - new_f.__doc__ = f.__doc__ - return new_f - return check_pkttools - - -class FilesystemFunctions(object): - - def getStorage(self): - return cpyrit.storage.getStorage('file://' + self.storage_path) - - def corrupt(self, storage): - # Destroy some passwords - keys = list(storage.passwords.iterkeys()) - for i in xrange(13): - key = random.choice(keys) - # This is specific to storage.FSPasswordStore - filename = os.path.join(storage.passwords.pwfiles[key], key) - filename += '.pw' - if i % 3 == 0: - # Delete the workunit without deleting the results. - # Should cause a reference error - del storage.passwords[key] - else: - with open(filename, 'r+b') as f: - # Overwrite either part of the header or part of the file - if i % 2 == 0: - f.seek(4) - f.write('x') - keys.remove(key) - if len(keys) == 0: - break - # Destroy some results - keys = list(storage.essids.iterkeys('test')) - for i in xrange(13): - key = random.choice(keys) - # This is specific to storage.FSEssidStore - filename = os.path.join(storage.essids.essids['test'][0], key) - filename += '.pyr' - with open(filename, 'r+b') as f: - if i % 2 == 0: - f.seek(4) - f.write('x') - keys.remove(key) - if len(keys) == 0: - break - - -class BaseTestCase(unittest.TestCase): - - handshakes = (('wpapsk-linksys.dump.gz', 'linksys', - '00:0b:86:c2:a4:85', '00:13:ce:55:98:ef', 'dictionary'), - ('wpa2psk-linksys.dump.gz', 'linksys', - '00:0b:86:c2:a4:85', '00:13:ce:55:98:ef', 'dictionary'), - ('wpa2psk-2WIRE972.dump.gz', '2WIRE972', - '00:40:10:20:00:03', '00:18:41:9c:a4:a0', 'helium02'), - ('wpa2psk-MOM1.dump.gz', 'MOM1', - '00:21:29:72:a3:19', '00:21:00:ab:55:a9', 'MOM12345'), - ('wpa2psk-Red_Apple.dump.gz', 'Red Apple', - '00:1d:7e:2c:b1:af', '00:0e:35:72:1a:98', 'password'), - ('wpapsk-virgin_broadband.dump.gz', 'virgin broadband', - '00:22:3f:1b:2e:e6', '00:1f:e2:a0:a1:21', 'preinstall')) - - def setUp(self): - self.storage_path = tempfile.mkdtemp() - self.tempfile1 = os.path.join(self.storage_path, 'testfile1') - self.tempfile2 = os.path.join(self.storage_path, 'testfile2') - self.cli = pyrit_cli.Pyrit_CLI() - self.cli.verbose = False - - def tearDown(self): - shutil.rmtree(self.storage_path) - - def _createPasswords(self, filename): - test_passwds = ['test123%i' % i for i in xrange(5000 - 5)] - test_passwds += ['dictionary', 'helium02', 'MOM12345', \ - 'preinstall', 'password'] - random.shuffle(test_passwds) - with cpyrit.util.AsyncFileWriter(filename) as f: - f.write('\n'.join(test_passwds)) - return test_passwds - - def _createDatabase(self, storage): - self.cli.create_essid(storage, 'linksys') - self._createPasswords(self.tempfile1) - self.cli.import_passwords(storage, self.tempfile1) - - def _computeFakeDatabase(self, storage, essid): - self.cli.create_essid(storage, essid) - for key, passwords in storage.passwords.iteritems(): - storage.essids[essid, key] = [(pw, 'x' * 32) for pw in passwords] - - def _computeDatabase(self, storage, essid): - self.cli.create_essid(storage, essid) - l = 0 - with cpyrit.cpyrit.StorageIterator(storage, essid) as dbiter: - for results in dbiter: - l += len(results) - self.assertEqual(l, 5000) - - def _testHandshake(self, filename, essid, ap, sta, passwd, aes=False): - parser = cpyrit.pckttools.PacketParser(filename) - with cpyrit.cpyrit.PassthroughIterator(essid, (passwd,)) as cp: - solution = cp.next() - auths = parser[ap][sta].getAuthentications() - for auth in parser[ap][sta].getAuthentications(): - with cpyrit.pckttools.AuthCracker(auth, aes) as cracker: - cracker.enqueue(solution) - if cracker.solution == passwd: - break - else: - self.fail('Did not detect passphrase in "%s"' % filename) - - -class TestCase(BaseTestCase): - - def testListEssids(self): - storage = self.getStorage() - self._createDatabase(storage) - self.cli.list_essids(storage) - - def testCreateAndDeleteEssid(self): - storage = self.getStorage() - # EssidStore should be empty - self.assertEqual(len(storage.essids), 0) - self.assertFalse('testessid' in storage.essids) - # Add one ESSID - self.cli.create_essid(storage, essid='testessid') - self.assertEqual(len(storage.essids), 1) - self.assertTrue('testessid' in storage.essids) - # Adding it second time should not cause an error - self.cli.create_essid(storage, 'testessid') - self.cli.delete_essid(storage, 'testessid', confirm=False) - # EssidStore should be empty again - self.assertEqual(len(storage.essids), 0) - self.assertTrue('testessid' not in storage.essids) - - def testImportPasswords(self): - storage = self.getStorage() - self.assertEqual(len(storage.passwords), 0) - # valid_passwds should get accepted, short_passwds ignored - valid_passwds = ['test123%i' % i for i in xrange(100000)] - short_passwds = ['x%i' % i for i in xrange(30000)] - test_passwds = valid_passwds + short_passwds - random.shuffle(test_passwds) - with cpyrit.util.AsyncFileWriter(self.tempfile1) as f: - f.write('\n'.join(test_passwds)) - self.cli.import_passwords(storage, self.tempfile1) - new_passwds = set() - for key, pwset in storage.passwords.iteritems(): - new_passwds.update(pwset) - self.assertEqual(new_passwds, set(valid_passwds)) - # There should be no duplicates - random.shuffle(test_passwds) - with cpyrit.util.FileWrapper(self.tempfile1, 'a') as f: - f.write('\n') - f.write('\n'.join(test_passwds)) - self.cli.import_passwords(storage, self.tempfile1) - new_passwds = set() - i = 0 - for key, pwset in storage.passwords.iteritems(): - new_passwds.update(pwset) - i += len(pwset) - self.assertEqual(i, len(valid_passwds)) - self.assertEqual(new_passwds, set(valid_passwds)) - - @requires_pckttools() - def testAttackDB(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeDatabase(storage, 'linksys') - self.cli.attack_db(storage, 'wpapsk-linksys.dump.gz') - - @requires_pckttools() - def testAttackCowpatty(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeDatabase(storage, 'linksys') - self.cli.export_cowpatty(storage, 'linksys', self.tempfile1) - self.cli.attack_cowpatty('wpapsk-linksys.dump.gz', self.tempfile1) - - @requires_pckttools() - def testAttackBatch(self): - storage = self.getStorage() - self._createPasswords(self.tempfile1) - self.cli.import_passwords(storage, self.tempfile1) - self.cli.attack_batch(storage, 'wpapsk-linksys.dump.gz') - - def testPassthrough(self): - storage = self.getStorage() - self._createDatabase(storage) - self.cli.passthrough('linksys', self.tempfile1, self.tempfile2) - fileresults = [] - for results in cpyrit.util.CowpattyFile(self.tempfile2): - fileresults.extend(results) - dbresults = [] - with cpyrit.cpyrit.StorageIterator(storage, 'linksys', \ - yieldNewResults=True) as dbiter: - for results in dbiter: - dbresults.extend(results) - self.assertEqual(sorted(fileresults), sorted(dbresults)) - - def testBatch(self): - storage = self.getStorage() - test_passwds = self._createPasswords(self.tempfile1) - self.cli.import_passwords(storage, self.tempfile1) - self.cli.create_essid(storage, 'test1234') - self.cli.batchprocess(storage) - self.assertEqual(len(storage.passwords), \ - storage.essids.keycount('test1234')) - keys = list(storage.essids.iterkeys('test1234')) - for key in keys: - self.assertTrue(key in storage.passwords) - for key in storage.passwords: - self.assertTrue(key in keys) - passwds = storage.passwords[key] - r = storage.essids['test1234', key] - self.assertTrue(sorted((pw for pw, pmk in r)) == sorted(passwds)) - - def testBatchWithFile(self): - storage = self.getStorage() - test_passwds = self._createPasswords(self.tempfile1) - self.cli.import_passwords(storage, self.tempfile1) - self.cli.create_essid(storage, 'test1234') - self.cli.batchprocess(storage, 'test1234', self.tempfile1) - self.assertEqual(len(storage.passwords), \ - storage.essids.keycount('test1234')) - fileresults = [] - for results in cpyrit.util.CowpattyFile(self.tempfile1): - fileresults.extend(results) - dbresults = [] - with cpyrit.cpyrit.StorageIterator(storage, 'test1234', \ - yieldNewResults=False) as dbiter: - for results in dbiter: - dbresults.extend(results) - self.assertEqual(sorted(fileresults), sorted(dbresults)) - - def testEval(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeFakeDatabase(storage, 'test1') - self._computeFakeDatabase(storage, 'test2') - self.cli.eval_results(storage) - - def testVerify(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeDatabase(storage, 'test') - # Should be OK - self.cli.verify(storage) - keys = list(storage.essids.iterkeys('test')) - for i in xrange(25): - key = random.choice(keys) - results = storage.essids['test', key] - corrupted = tuple((pw, 'x' * 32) for pw, pmk in results) - storage.essids['test', key] = corrupted - # Should fail - self.assertRaises(pyrit_cli.PyritRuntimeError, \ - self.cli.verify, storage) - - def testCheckDB(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeFakeDatabase(storage, 'test') - self.corrupt(storage) - # Should fail but repair - self.assertRaises(pyrit_cli.PyritRuntimeError, \ - self.cli.checkdb, storage, False) - # Should now be OK - self.cli.checkdb(storage, False) - - def testExportPasswords(self): - storage = self.getStorage() - test_passwds = self._createPasswords(self.tempfile1) - self.cli.import_passwords(storage, self.tempfile1) - self.cli.export_passwords(storage, self.tempfile1) - with cpyrit.util.FileWrapper(self.tempfile1) as f: - new_passwds = map(str.strip, f.readlines()) - self.assertEqual(sorted(test_passwds), sorted(new_passwds)) - - def testExportCowpatty(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeDatabase(storage, 'test') - self.cli.export_cowpatty(storage, 'test', self.tempfile1) - fileresults = [] - for results in cpyrit.util.CowpattyFile(self.tempfile1): - fileresults.extend(results) - dbresults = [] - with cpyrit.cpyrit.StorageIterator(storage, 'test', \ - yieldNewResults=False) as dbiter: - for results in dbiter: - dbresults.extend(results) - self.assertEqual(sorted(fileresults), sorted(dbresults)) - - def testExportHashdb(self): - storage = self.getStorage() - self._createDatabase(storage) - self._computeFakeDatabase(storage, 'test') - os.unlink(self.tempfile1) - self.cli.export_hashdb(storage, self.tempfile1) - - -class RPCTestCase(TestCase, FilesystemFunctions): - - def getStorage(self): - return cpyrit.storage.getStorage('http://127.0.0.1:17934') - - def setUp(self): - TestCase.setUp(self) - self.backend = FilesystemFunctions.getStorage(self) - self.server = cpyrit.storage.StorageRelay(self.backend, \ - iface='127.0.0.1') - - def tearDown(self): - self.server.shutdown() - TestCase.tearDown(self) - - def corrupt(self, storage): - # Corrupt backing storage instead... - FilesystemFunctions.corrupt(self, self.backend) - - -class DatabaseTestCase(TestCase): - - def getStorage(self): - return cpyrit.storage.getStorage('sqlite:///:memory:') - - def corrupt(self, storage): - conn = storage.engine.connect() - # Destroy some passwords - keys = list(storage.passwords.iterkeys()) - tbl = cpyrit.storage.passwords_table - for i in xrange(13): - key = random.choice(keys) - sql = tbl.update().where(tbl.c._key == key) - if i % 2 == 0: - buf = 'x' - else: - buf = 'PAW2x' - sql = sql.values(collection_buffer=buf) - conn.execute(sql) - keys.remove(key) - if len(keys) == 0: - break - # Destroy some results - keys = list(storage.essids.iterkeys('test')) - tbl = cpyrit.storage.results_table - for i in xrange(13): - key = random.choice(keys) - if i % 3 == 0: - # Delete workunit - # Should cause a reference-error - sql = tbl.delete().where(tbl.c._key == key) - else: - # Corrupt it - sql = tbl.update().where(tbl.c._key == key) - if i % 2 == 0: - buf = 'x' - else: - buf = 'PYR2xxxxxyyyyyzzz' - sql = sql.values(results_buffer=buf) - conn.execute(sql) - keys.remove(key) - if len(keys) == 0: - break - - -class FilesystemTestCase(TestCase, FilesystemFunctions): - - def testListCores(self): - self.cli.list_cores() - - def testPrintHelp(self): - self.cli.print_help() - - def testSelfTest(self): - self.cli.selftest(timeout=3) - - def testBenchmark(self): - self.cli.benchmark(timeout=3) - - @requires_pckttools() - def testHandshakes(self): - for filename, essid, ap, sta, passwd in self.handshakes: - self._testHandshake(filename, essid, ap, sta, passwd) - - @requires_pckttools() - def testAnalyze(self): - self.cli.analyze(capturefile='wpapsk-linksys.dump.gz') - self.cli.analyze(capturefile='wpa2psk-linksys.dump.gz') - self.cli.analyze(capturefile='wpa2psk-MOM1.dump.gz') - self.cli.analyze(capturefile='wpa2psk-2WIRE972.dump.gz') - self.cli.analyze(capturefile='wpapsk-virgin_broadband.dump.gz') - - @requires_pckttools() - def testStripCapture(self): - self.cli.stripCapture('wpapsk-linksys.dump.gz', self.tempfile1) - parser = self.cli._getParser(self.tempfile1) - self.assertTrue('00:0b:86:c2:a4:85' in parser) - self.assertEqual(parser['00:0b:86:c2:a4:85'].essid, 'linksys') - self.assertTrue('00:13:ce:55:98:ef' in parser['00:0b:86:c2:a4:85']) - self.assertTrue(parser['00:0b:86:c2:a4:85'].isCompleted()) - for filename, essid, ap, sta, passwd in self.handshakes: - self.cli.stripCapture(filename, self.tempfile1) - self._testHandshake(self.tempfile1, essid, ap, sta, passwd) - - @requires_pckttools() - def testStripLive(self): - self.cli.stripLive('wpa2psk-linksys.dump.gz', self.tempfile1) - parser = self.cli._getParser(self.tempfile1) - self.assertTrue('00:0b:86:c2:a4:85' in parser) - self.assertEqual(parser['00:0b:86:c2:a4:85'].essid, 'linksys') - self.assertTrue('00:13:ce:55:98:ef' in parser['00:0b:86:c2:a4:85']) - self.assertTrue(parser['00:0b:86:c2:a4:85'].isCompleted()) - for filename, essid, ap, sta, passwd in self.handshakes: - self.cli.stripLive(filename, self.tempfile1) - self._testHandshake(self.tempfile1, essid, ap, sta, passwd) - - @requires_pckttools() - def testAttackPassthrough(self): - self._createPasswords(self.tempfile1) - self.cli.attack_passthrough(self.tempfile1, 'wpapsk-linksys.dump.gz') - self.cli.attack_passthrough(self.tempfile1, 'wpa2psk-linksys.dump.gz', \ - use_aes=True) - - -def _runTests(case): - loader = unittest.TestLoader() - suite = loader.loadTestsFromTestCase(case) - return unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() - -if __name__ == "__main__": - print "Testing with filesystem-storage..." - if not _runTests(FilesystemTestCase): - sys.exit(1) - - # should have been imported by cpyrit.storage - if 'sqlalchemy' not in sys.modules: - print "SQLAlchemy seems to be unavailable; skipping all tests..." - else: - print "Testing with database-storage..." - if not _runTests(DatabaseTestCase): - sys.exit(1) - - print "Testing with RPC-storage..." - if not _runTests(RPCTestCase): - sys.exit(1) From f5854d80ad585247b1efc2661f61a7029d0cfcad Mon Sep 17 00:00:00 2001 From: kimocoder Date: Mon, 20 Jan 2020 10:18:36 +0100 Subject: [PATCH 3/3] Final python3 migration push. Needs testing. --- cpyrit/config.py | 4 ++-- cpyrit/cpyrit.py | 12 ++++++------ cpyrit/storage.py | 2 +- modules/cpyrit_calpp/setup.py | 12 ++++++------ modules/cpyrit_cuda/setup.py | 27 ++++++++++++++------------- modules/cpyrit_opencl/setup.py | 18 ++++++++++-------- pyrit | 4 ++-- 7 files changed, 41 insertions(+), 38 deletions(-) mode change 100755 => 100644 modules/cpyrit_opencl/setup.py diff --git a/cpyrit/config.py b/cpyrit/config.py index 4cfe584..d0020ed 100644 --- a/cpyrit/config.py +++ b/cpyrit/config.py @@ -46,8 +46,8 @@ def read_configfile(filename): if option in config: config[option] = value else: - print >> sys.stderr, "WARNING: Unknown option '%s' " \ - "in configfile '%s'" % (option, filename) + print("WARNING: Unknown option '%s' " \ + "in configfile '%s'" % (option, filename), file=sys.stderr) return config diff --git a/cpyrit/cpyrit.py b/cpyrit/cpyrit.py index 2105927..0590ca6 100644 --- a/cpyrit/cpyrit.py +++ b/cpyrit/cpyrit.py @@ -207,8 +207,8 @@ def run(self): import _cpyrit_opencl except ImportError: pass -except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's CAL-core ('%s')." % e +except Exception as e: + print("Failed to load Pyrit's CAL-core ('%s')." % e, file=sys.stderr) else: version_check(_cpyrit_opencl) @@ -230,8 +230,8 @@ def __init__(self, queue, platform_idx, dev_idx): import _cpyrit_cuda except ImportError: pass -except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's CUDA-core ('%s')." % e +except Exception as e: + print("Failed to load Pyrit's CUDA-core ('%s')." % e, file=sys.stderr) else: version_check(_cpyrit_cuda) @@ -252,8 +252,8 @@ def __init__(self, queue, dev_idx): import _cpyrit_calpp except ImportError: pass -except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's CAL-core ('%s')." % e +except Exception as e: + print("Failed to load Pyrit's CAL-core ('%s')." % e, file=sys.stderr) else: version_check(_cpyrit_calpp) diff --git a/cpyrit/storage.py b/cpyrit/storage.py index 157a8f2..40e5793 100644 --- a/cpyrit/storage.py +++ b/cpyrit/storage.py @@ -409,7 +409,7 @@ def __init__(self, basepath): self.essids[essid][1][pyrfile[:len(pyrfile) - 4]] = \ os.path.join(essidpath, pyrfile) else: - print >>sys.stderr, "ESSID %s is corrupted." % essid_hash + print("ESSID %s is corrupted." % essid_hash, file=sys.stderr) def __getitem__(self, xxx_todo_changeme6): """Receive a iterable of (password,PMK)-tuples stored under diff --git a/modules/cpyrit_calpp/setup.py b/modules/cpyrit_calpp/setup.py index 6dd21d5..8031d88 100755 --- a/modules/cpyrit_calpp/setup.py +++ b/modules/cpyrit_calpp/setup.py @@ -26,7 +26,7 @@ import subprocess import sys -VERSION = '0.5.0' +VERSION = '0.5.2' CALPP_INC_DIRS = [] @@ -34,14 +34,14 @@ try: CALPP_INC_DIR = os.environ['ATISTREAMSDKROOT'] except KeyError: - print >>sys.stderr, "unavailable enviroment variable ATISTREAMSDKROOT" + print("unavailable enviroment variable ATISTREAMSDKROOT", file=sys.stderr) raise else: if os.path.exists(CALPP_INC_DIR): CALPP_INC_DIRS.append(os.path.join(CALPP_INC_DIR, 'include')) else: - print >>sys.stderr, "The headers required to build CAL++ kernel" \ - "were not found. Trying to continue anyway..." + print("The headers required to build CAL++ kernel" \ + "were not found. Trying to continue anyway...", file=sys.stderr) EXTRA_COMPILE_ARGS = ['-Wall', '-fno-strict-aliasing', \ @@ -50,7 +50,7 @@ class GPUBuilder(build_ext): def run(self): - print "Building modules..." + print("Building modules...") build_ext.run(self) @@ -66,7 +66,7 @@ def _unlink(self, node): pass def run(self): - print "Removing temporary files and pre-built GPU-kernels..." + print("Removing temporary files and pre-built GPU-kernels...") clean.run(self) diff --git a/modules/cpyrit_cuda/setup.py b/modules/cpyrit_cuda/setup.py index a05fc85..7a2a010 100755 --- a/modules/cpyrit_cuda/setup.py +++ b/modules/cpyrit_cuda/setup.py @@ -37,8 +37,8 @@ NVCC = os.path.join(path, 'bin', 'nvcc') break else: - print >>sys.stderr, "The CUDA compiler and headers required to build " \ - "kernel were not found. Trying to continue anyway..." + print("The CUDA compiler and headers required to build " \ + "kernel were not found. Trying to continue anyway...", file=sys.stderr) EXTRA_COMPILE_ARGS = ['-Wall', '-fno-strict-aliasing', @@ -53,8 +53,8 @@ def _call(self, comm): if p.returncode == 0: return stdo else: - print >>sys.stderr, "%s\nFailed to execute command '%s'" % \ - (stde, comm) + print("%s\nFailed to execute command '%s'" % \ + (stde, comm), file=sys.stderr) return None def _makedirs(self, pathname): @@ -65,7 +65,7 @@ def _makedirs(self, pathname): def run(self): if '_cpyrit_cudakernel.ptx.h' in os.listdir('./'): - print "Skipping rebuild of Nvidia CUDA kernel ..." + print("Skipping rebuild of Nvidia CUDA kernel ...") else: nvcc_o = self._call(NVCC + ' -V') if nvcc_o is not None: @@ -73,7 +73,7 @@ def run(self): else: raise SystemError("Nvidia's CUDA-compiler 'nvcc' can't be " \ "found.") - print "Compiling CUDA module using nvcc %s..." % nvcc_version + print("Compiling CUDA module using nvcc %s..." % nvcc_version) # We need to hardcode arch at least for MacOS 10.6 / CUDA 3.1 bits, linkage = platform.architecture() @@ -82,12 +82,12 @@ def run(self): elif bits == '64bit': bit_flag = ' -m64' else: - print >>sys.stderr, "Can't detect platform, using 32bit" + print("Can't detect platform, using 32bit", file=sys.stderr) bit_flag = ' -m32' nvcc_cmd = NVCC + bit_flag + ' -ccbin clang -Xcompiler "-fPIC" --ptx ./_cpyrit_cudakernel.cu' - print "Executing '%s'" % nvcc_cmd + print("Executing '%s'" % nvcc_cmd) subprocess.check_call(nvcc_cmd, shell=True) with open("_cpyrit_cudakernel.ptx", "rb") as fid: @@ -97,7 +97,7 @@ def run(self): fid.write("unsigned char __cudakernel_packedmodule[] = {") fid.write(','.join(ptx_inc)) fid.write("};\nsize_t cudakernel_modulesize = %i;\n" % len(ptx)) - print "Building modules..." + print("Building modules...") build_ext.run(self) @@ -113,15 +113,16 @@ def _unlink(self, node): pass def run(self): - print "Removing temporary files and pre-built GPU-kernels..." + print("Removing temporary files and pre-built GPU-kernels...") try: for f in ('_cpyrit_cudakernel.linkinfo', \ '_cpyrit_cudakernel.ptx', \ '_cpyrit_cudakernel.ptx.h'): self._unlink(f) - except Exception, (errno, sterrno): - print >>sys.stderr, "Exception while cleaning temporary " \ - "files ('%s')" % sterrno + except Exception as xxx_todo_changeme: + (errno, sterrno) = xxx_todo_changeme.args + print("Exception while cleaning temporary " \ + "files ('%s')" % sterrno, file=sys.stderr) clean.run(self) diff --git a/modules/cpyrit_opencl/setup.py b/modules/cpyrit_opencl/setup.py old mode 100755 new mode 100644 index 4f0bcd3..3c81073 --- a/modules/cpyrit_opencl/setup.py +++ b/modules/cpyrit_opencl/setup.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement + from distutils.core import setup, Extension from distutils.command.build_ext import build_ext from distutils.command.clean import clean @@ -57,8 +57,8 @@ OPENCL_INC_DIRS.append(path) break else: - print >>sys.stderr, "The headers required to build the OpenCL-kernel " \ - "were not found. Trying to continue anyway..." + print("The headers required to build the OpenCL-kernel " \ + "were not found. Trying to continue anyway...", file=sys.stderr) EXTRA_COMPILE_ARGS = ['-Wall', '-fno-strict-aliasing', \ @@ -77,7 +77,7 @@ def run(self): f.write("unsigned char oclkernel_packedprogram[] = {") f.write(",".join(("0x%02X" % ord(c) for c in oclkernel_inc))) f.write("};\nsize_t oclkernel_size = %i;\n" % len(oclkernel_code)) - print "Building modules..." + print("Building modules...") build_ext.run(self) @@ -92,13 +92,14 @@ def _unlink(self, node): pass def run(self): - print "Removing temporary files and pre-built GPU-kernels..." + print("Removing temporary files and pre-built GPU-kernels...") try: for f in ('_cpyrit_oclkernel.cl.h',): self._unlink(f) - except Exception, (errno, sterrno): - print >>sys.stderr, "Exception while cleaning temporary " \ - "files ('%s')" % sterrno + except Exception as xxx_todo_changeme: + (errno, sterrno) = xxx_todo_changeme.args + print("Exception while cleaning temporary " \ + "files ('%s')" % sterrno, file=sys.stderr) clean.run(self) @@ -144,3 +145,4 @@ def run(self): if __name__ == "__main__": setup(**setup_args) + diff --git a/pyrit b/pyrit index a5316a1..12ccca3 100755 --- a/pyrit +++ b/pyrit @@ -5,6 +5,6 @@ if __name__ == "__main__": try: pyrit_cli.Pyrit_CLI().initFromArgv() except (KeyboardInterrupt, SystemExit): - print >>sys.stderr, "\nInterrupted..." - except pyrit_cli.PyritRuntimeError, e: + print("\nInterrupted...", file=sys.stderr) + except pyrit_cli.PyritRuntimeError as e: sys.exit(e)