From 52ccbd2973549c8db8cb53f9e468393d0fa5f8c5 Mon Sep 17 00:00:00 2001 From: Michael Skelton Date: Thu, 18 Oct 2018 22:30:42 +1000 Subject: [PATCH] Remove Redundant Setup files --- Reconnoitre.egg-info/PKG-INFO | 121 ------ Reconnoitre.egg-info/SOURCES.txt | 23 -- Reconnoitre.egg-info/dependency_links.txt | 1 - Reconnoitre.egg-info/entry_points.txt | 3 - Reconnoitre.egg-info/top_level.txt | 1 - .../Reconnoitre/__init__.py | 0 .../Reconnoitre/lib/__init__.py | 0 .../Reconnoitre/lib/config.json | 354 ------------------ .../Reconnoitre/lib/core/__init__.py | 0 .../Reconnoitre/lib/core/__version__.py | 6 - .../Reconnoitre/lib/core/input.py | 118 ------ .../Reconnoitre/lib/file_helper.py | 120 ------ .../Reconnoitre/lib/find_dns.py | 43 --- .../Reconnoitre/lib/hostname_scan.py | 48 --- .../Reconnoitre/lib/ping_sweeper.py | 45 --- .../Reconnoitre/lib/service_scan.py | 102 ----- .../Reconnoitre/lib/snmp_walk.py | 73 ---- .../Reconnoitre/lib/virtual_host_scanner.py | 74 ---- .../Reconnoitre/reconnoitre.py | 110 ------ .../wordlists/virtual-host-scanning.txt | 34 -- build/lib.linux-x86_64-2.7/lib/__init__.py | 0 .../lib.linux-x86_64-2.7/lib/core/__init__.py | 0 .../lib/core/__version__.py | 6 - build/lib.linux-x86_64-2.7/lib/core/input.py | 118 ------ build/lib.linux-x86_64-2.7/lib/file_helper.py | 120 ------ build/lib.linux-x86_64-2.7/lib/find_dns.py | 43 --- .../lib.linux-x86_64-2.7/lib/hostname_scan.py | 48 --- .../lib.linux-x86_64-2.7/lib/ping_sweeper.py | 45 --- .../lib.linux-x86_64-2.7/lib/service_scan.py | 102 ----- build/lib.linux-x86_64-2.7/lib/snmp_walk.py | 73 ---- .../lib/virtual_host_scanner.py | 74 ---- dist/Reconnoitre-1.0-py2.7.egg | Bin 51612 -> 0 bytes 32 files changed, 1905 deletions(-) delete mode 100644 Reconnoitre.egg-info/PKG-INFO delete mode 100644 Reconnoitre.egg-info/SOURCES.txt delete mode 100644 Reconnoitre.egg-info/dependency_links.txt delete mode 100644 Reconnoitre.egg-info/entry_points.txt delete mode 100644 Reconnoitre.egg-info/top_level.txt delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/__init__.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/__init__.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/config.json delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__init__.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__version__.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/input.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/file_helper.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/find_dns.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/hostname_scan.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/ping_sweeper.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/service_scan.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/snmp_walk.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/lib/virtual_host_scanner.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/reconnoitre.py delete mode 100644 build/lib.linux-x86_64-2.7/Reconnoitre/wordlists/virtual-host-scanning.txt delete mode 100644 build/lib.linux-x86_64-2.7/lib/__init__.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/core/__init__.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/core/__version__.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/core/input.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/file_helper.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/find_dns.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/hostname_scan.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/ping_sweeper.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/service_scan.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/snmp_walk.py delete mode 100644 build/lib.linux-x86_64-2.7/lib/virtual_host_scanner.py delete mode 100644 dist/Reconnoitre-1.0-py2.7.egg diff --git a/Reconnoitre.egg-info/PKG-INFO b/Reconnoitre.egg-info/PKG-INFO deleted file mode 100644 index f690d19..0000000 --- a/Reconnoitre.egg-info/PKG-INFO +++ /dev/null @@ -1,121 +0,0 @@ -Metadata-Version: 1.0 -Name: Reconnoitre -Version: 1.0 -Summary: A reconnaissance tool made for the OSCP labs to automate information gathering, and service enumeration whilst creating a directory structure to store results,findings and exploits used for each host, recommended commands to execute and directory structures for storing loot and flags. -Home-page: https://github.com/codingo/Reconnoitre -Author: codingo -Author-email: codingo@protonmail.com -License: GPLv3 -Description-Content-Type: UNKNOWN -Description: ![Reconnnoitre](https://github.com/codingo/Reconnoitre/blob/master/assets/tank-152362_640.png) - A reconnaissance tool made for the OSCP labs to automate information gathering and service enumeration whilst creating a directory structure to store results, findings and exploits used for each host, recommended commands to execute and directory structures for storing loot and flags. - - Contributions are more than welcome! - - [![Python 3.2|3.6](https://img.shields.io/badge/python-3.2|3.6-green.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPL3-_red.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) [![Build Status](https://travis-ci.org/codingo/Reconnoitre.svg?branch=master)](https://travis-ci.org/codingo/Reconnoitre) [![Twitter](https://img.shields.io/badge/twitter-@codingo__-blue.svg)](https://twitter.com/codingo_) - - # Credit - - This tool is based heavily upon the work made public in Mike Czumak's (T_v3rn1x) OSCP review ([link](https://www.securitysift.com/offsec-pwb-oscp/)) along with considerable influence and code taken from Re4son's mix-recon ([link](https://whitedome.com.au/re4son/category/re4son/oscpnotes/)). Virtual host scanning is originally adapted from teknogeek's work which is heavily influenced by jobertabma's virtual host discovery script ([link](https://github.com/jobertabma/virtual-host-discovery)). Further Virtual Host scanning code has been adapted from a project by Tim Kent and I, available here ([link](https://github.com/codingo/VHostScan)). - - # Usage - - This tool can be used and copied for personal use freely however attribution and credit should be offered to Mike Czumak who originally started the process of automating this work. - - | Argument | Description | - | ------------- |:-------------| - | -h, --help | Display help message and exit | - | -t TARGET_HOSTS | Set either a target range of addresses or a single host to target. May also be a file containing hosts. | - | -o OUTPUT_DIRECTORY | Set the target directory where results should be written. | - | -w WORDLIST | Optionally specify your own wordlist to use for pre-compiled commands, or executed attacks. | - | --pingsweep | Write a new target.txt file in the OUTPUT_DIRECTORY by performing a ping sweep and discovering live hosts. | - | --dns, --dnssweep | Find DNS servers from the list of target(s). | - | --snmp | Find hosts responding to SNMP requests from the list of target(s). | - | --services | Perform a service scan over the target(s) and write recommendations for further commands to execute. | - | --hostnames | Attempt to discover target hostnames and write to hostnames.txt. | - | --virtualhosts | Attempt to discover virtual hosts using the specified wordlist. This can be expended via discovered hostnames. | - | --ignore-http-codes | Comma separated list of http codes to ignore with virtual host scans. | - | --ignore-content-length | Ignore content lengths of specificed amount. This may become useful when a server returns a static page on every virtual host guess. | - | --quiet | Supress banner and headers and limit feedback to grepable results. | - | --quick | Move to the next target after performing a quick scan and writing first-round recommendations. | - | --no-udp | Disable UDP service scanning, which is ON by default. | - - ## Usage Examples - _Note that these are some examples to give you insight into potential use cases for this tool. Command lines can be added or removed based on what you wish to accomplish with your scan._ - - ### Scan a single host, create a file structure and discover services - ``` - python ./reconnoitre.py -t 192.168.1.5 -o /root/Documents/labs/ --services - ``` - - An example output would look like: - - ``` - root@kali:~/Documents/tools/reconnoitre/reconnoitre# python ./reconnoitre.py -t 192.168.1.5 --services -o /root/Documents/labs/ - __ - |"""\-= RECONNOITRE - (____) An OSCP scanner - - [#] Performing service scans - [*] Loaded single target: 192.168.1.5 - [+] Creating directory structure for 192.168.1.5 - [>] Creating scans directory at: /root/Documents/labs/192.168.1.5/scans - [>] Creating exploit directory at: /root/Documents/labs/192.168.1.5/exploit - [>] Creating loot directory at: /root/Documents/labs/192.168.1.5/loot - [>] Creating proof file at: /root/Documents/labs/192.168.1.5/proof.txt - [+] Starting quick nmap scan for 192.168.1.5 - [+] Writing findings for 192.168.1.5 - [>] Found HTTP service on 192.168.1.5:80 - [>] Found MS SMB service on 192.168.1.5:445 - [>] Found RDP service on 192.168.1.5:3389 - [*] TCP quick scan completed for 192.168.1.5 - [+] Starting detailed TCP/UDP nmap scans for 192.168.1.5 - [+] Writing findings for 192.168.1.5 - [>] Found MS SMB service on 192.168.1.5:445 - [>] Found RDP service on 192.168.1.5:3389 - [>] Found HTTP service on 192.168.1.5:80 - [*] TCP/UDP Nmap scans completed for 192.168.1.5 - ``` - Which would also write the following recommendations file in the scans folder for each target: - ``` - [*] Found HTTP service on 192.168.1.50:80 - [>] Use nikto & dirb / dirbuster for service enumeration, e.g - [=] nikto -h 192.168.1.50 -p 80 > /root/Documents/labs/192.168.1.50/scans/192.168.1.50_nikto.txt - [=] dirb http://192.168.1.50:80/ -o /root/Documents/labs/192.168.1.50/scans/192.168.1.50_dirb.txt -r -S -x ./dirb-extensions/php.ext - [=] java -jar /usr/share/dirbuster/DirBuster-1.0-RC1.jar -H -l /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -r /root/Documents/labs/192.168.1.50/scans/192.168.1.50_dirbuster.txt -u http://192.168.1.50:80/ - [=] gobuster -w /usr/share/seclists/Discovery/Web_Content/common.txt -u http://192.168.1.50:80/ -s '200,204,301,302,307,403,500' -e > /root/Documents/labs/192.168.1.50/scans/192.168.1.50_gobuster_common.txt -t 50 - [=] gobuster -w /usr/share/seclists/Discovery/Web_Content/cgis.txt -u http://192.168.1.50:80/ -s '200,204,301,307,403,500' -e > /root/Documents/labs/192.168.1.50/scans/192.168.1.50_gobuster_cgis.txt -t 50 - [>] Use curl to retreive web headers and find host information, e.g - [=] curl -i 192.168.1.50 - [=] curl -i 192.168.1.50/robots.txt -s | html2text - [*] Found MS SMB service on 192.168.1.5:445 - [>] Use nmap scripts or enum4linux for further enumeration, e.g - [=] nmap -sV -Pn -vv -p445 --script="smb-* -oN '/root/Documents/labs/192.168.1.5/nmap/192.168.1.5_smb.nmap' -oX '/root/Documents/labs/192.168.1.5/scans/192.168.1.5_smb_nmap_scan_import.xml' 192.168.1.5 - [=] enum4linux 192.168.1.5 - [*] Found RDP service on 192.168.1.5:3389 - [>] Use ncrackpassword cracking, e.g - [=] ncrack -vv --user administrator -P /root/rockyou.txt rdp://192.168.1.5 - ``` - ### Discover live hosts and hostnames within a range - ``` - python ./reconnoitre.py -t 192.168.1.1-252 -o /root/Documents/testing/ --pingsweep --hostnames - ``` - - ### Discover live hosts within a range and then do a quick probe for services - ``` - python ./reconnoitre.py -t 192.168.1.1-252 -o /root/Documents/testing/ --pingsweep --services --quick - ``` - This will scan all services within a target range to create a file structure of live hosts as well as write recommendations for other commands to be executed based on the services discovered on these machines. Removing --quick will do a further probe but will greatly lengthen execution times. - - ### Discover live hosts within a range and then do probe all ports (UDP and TCP) for services - ``` - python ./reconnoitre.py -t 192.168.1.1-252 -o /root/Documents/testing/ --pingsweep --services - ``` - - # Requirements - - This bare requirement for host and service scanning for this tool is to have both `nbtscan` and `nmap` installed. If you are not using host scanning and only wish to perform a ping sweep and service scan you can get away with only installing `nmap`. The outputted _findings.txt_ will often recommend additional tools which you may not have available in your distribution if not using Kali Linux. All requirements and recommendations are native to Kali Linux which is the recommended (although not required) distribution for using this tool. - - In addition to these requirements outputs will often refer to Wordlists that you may need to find. If you are undertaking OSCP these can be found in the "List of Recommended Tools" thread by g0tmilk. If not then you can find the majority of these online or already within a Kali Linux installation. - -Platform: UNKNOWN diff --git a/Reconnoitre.egg-info/SOURCES.txt b/Reconnoitre.egg-info/SOURCES.txt deleted file mode 100644 index 8261f66..0000000 --- a/Reconnoitre.egg-info/SOURCES.txt +++ /dev/null @@ -1,23 +0,0 @@ -MANIFEST.in -README.md -setup.py -Reconnoitre/__init__.py -Reconnoitre/reconnoitre.py -Reconnoitre.egg-info/PKG-INFO -Reconnoitre.egg-info/SOURCES.txt -Reconnoitre.egg-info/dependency_links.txt -Reconnoitre.egg-info/entry_points.txt -Reconnoitre.egg-info/top_level.txt -Reconnoitre/lib/__init__.py -Reconnoitre/lib/config.json -Reconnoitre/lib/file_helper.py -Reconnoitre/lib/find_dns.py -Reconnoitre/lib/hostname_scan.py -Reconnoitre/lib/ping_sweeper.py -Reconnoitre/lib/service_scan.py -Reconnoitre/lib/snmp_walk.py -Reconnoitre/lib/virtual_host_scanner.py -Reconnoitre/lib/core/__init__.py -Reconnoitre/lib/core/__version__.py -Reconnoitre/lib/core/input.py -Reconnoitre/wordlists/virtual-host-scanning.txt \ No newline at end of file diff --git a/Reconnoitre.egg-info/dependency_links.txt b/Reconnoitre.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/Reconnoitre.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Reconnoitre.egg-info/entry_points.txt b/Reconnoitre.egg-info/entry_points.txt deleted file mode 100644 index 259fb97..0000000 --- a/Reconnoitre.egg-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -reconnoitre = Reconnoitre.reconnoitre:main - diff --git a/Reconnoitre.egg-info/top_level.txt b/Reconnoitre.egg-info/top_level.txt deleted file mode 100644 index a7da783..0000000 --- a/Reconnoitre.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -Reconnoitre diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/__init__.py b/build/lib.linux-x86_64-2.7/Reconnoitre/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/__init__.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/config.json b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/config.json deleted file mode 100644 index 020cce6..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/config.json +++ /dev/null @@ -1,354 +0,0 @@ -{ - "services": { - "http/s": { - "description": "Found HTTP/S service on $ip:$port", - "nmap-service-names": [ - "http", - "ssl/http", - "https", - "ssl/http-alt" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "nikto -h $ip -p $port -output $outputdir/$ip_$port_nikto.txt", - "curl -i $ip:$port", - "w3m -dump $ip/robots.txt | tee $outputdir/$ip_$port_robots.txt", - "VHostScan -t $ip -oN $outputdir/$ip_$port_vhosts.txt" - ] - } - ] - }, - "http": { - "description": "Found HTTP service on $ip:$port", - "nmap-service-names": [ - "http" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "dirb http://$ip:$port/ -o $outputdir/$ip_$port_dirb.txt", - "dirbuster -H -u http://$ip:$port/ -l /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -t 20 -s / -v -r $outputdir/$ip_$port_dirbuster_medium.txt", - "gobuster -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://$ip:$port/ -s '200,204,301,302,307,403,500' -e | tee '$outputdir/$ip_$port_gobuster_common.txt'", - "gobuster -w /usr/share/seclists/Discovery/Web-Content/CGIs.txt -u http://$ip:$port/ -s '200,204,301,307,403,500' -e | tee '$outputdir/$ip_$port_gobuster_cgis.txt'" - ] - } - ] - }, - "https": { - "description": "Found HTTPS service on $ip:$port", - "nmap-service-names": [ - "https", - "ssl/http", - "ssl/http-alt" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "dirb https://$ip:$port/ -o $outputdir/$ip_$port_dirb.txt", - "dirbuster -H -u https://$ip:$port/ -l /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -t 20 -s / -v -r $outputdir/$ip_$port_dirbuster_medium.txt", - "gobuster -w /usr/share/seclists/Discovery/Web-Content/common.txt -u https://$ip:$port/ -s '200,204,301,302,307,403,500' -e | tee '$outputdir/$ip_$port_gobuster_common.txt'", - "gobuster -w /usr/share/seclists/Discovery/Web-Content/CGIs.txt -u https://$ip:$port/ -s '200,204,301,307,403,500' -e | tee '$outputdir/$ip_$port_gobuster_cgis.txt'" - ] - } - ] - }, - "ftp": { - "description": "Found FTP service on $ip:$port", - "nmap-service-names": [ - "ftp" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "nmap -sV -Pn -vv -p$port --script=ftp-anon,ftp-bounce,ftp-libopie,ftp-proftpd-backdoor,ftp-syst,ftp-vsftpd-backdoor,ftp-vuln-cve2010-4221 -oA '$outputdir/$ip_$port_ftp' $ip", - "hydra -L USER_LIST -P PASS_LIST -f -o $outputdir/$ip_$port_ftphydra.txt -u $ip -s $port ftp" - ] - } - ] - }, - "mysql": { - "description": "Found MySql service on $ip:$port", - "nmap-service-names": [ - "mysql" - ], - "output": [ - { - "description": "Check out the server for web applications with sqli vulnerabilities", - "commands": [ - "searchsploit mysql" - ] - } - ] - }, - "dns": { - "description": "Found DNS service on $ip:$port", - "nmap-service-names": [ - "dns" - ], - "output": [ - { - "description": "Check out the server for zone transfers", - "commands": [ - "dnsrecon -t axfr -d $ip" - ] - } - ] - }, - "microsoftsql": { - "description": "Found MS SQL service on $ip:$port", - "nmap-service-names": [ - "ms-sql", - "ms-sql-s" - ], - "output": [ - { - "description": "Check out the server for web applications with sqli vulnerabilities", - "commands": [ - "searchsploit mssql" - ] - }, - { - "description": "Use nmap scripts for further enumeration, e.g", - "commands": [ - "nmap -vv -sV -Pn -p $port --script=ms-sql-info,ms-sql-config,ms-sql-dump-hashes --script-args=mssql.instance-port=$port,smsql.username-sa,mssql.password-sa -oA $outputdir/$ip_$port_mssql_nmap_scan $ip" - ] - } - ] - }, - - "telnet": { - "description": "Found telnet service on $ip:$port", - "nmap-service-names": [ - "telnet" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "ncat -nv $ip $port" - ] - } - ] - }, - "smb": { - "description": "Found MS SMB service on $ip:$port", - "nmap-service-names": [ - "microsoft-ds" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "nmap -sV -Pn -vv -p 139,$port --script=smb-vuln* --script-args=unsafe=1 -oA '$outputdir/$ip_$port_smb.nmap' $ip", - "enum4linux -a $ip | tee $outputdir/$ip_$port_enum4linux.txt", - "nmap -sV -Pn -vv -p $port --script=smb-enum-users -oA '$outputdir/$ip_$port_smb_smb-enum-users.nmap' $ip" - ] - } - ] - }, - "remotedesktop": { - "description": "Found RDP service on $ip:$port", - "nmap-service-names": [ - "msrdp", - "ms-wbt-server" - ], - "output": [ - { - "description": "Bruteforcing", - "commands": [ - "ncrack -vv --user administrator -P PASS_LIST rdp://$ip", - "crowbar -b rdp -u -s $ip/32 -U USER_LIST -C PASS_LIST", - "for username in $(cat USER_LIST); do for password in $(cat PASS_LIST) do; rdesktop -u $username -p $password $ip; done; done;" - ] - } - ] - }, - "smtp": { - "description": "Found SMTP service on $ip:$port", - "nmap-service-names": [ - "smtp" - ], - "output": [ - { - "description": "Find users", - "commands": [ - "smtp-user-enum -M VRFY -U /usr/share/seclists/Usernames/top_shortlist.txt -t $ip -p $port" - ] - } - ] - }, - "snmp": { - "description": "Found SNMP service on $ip:$port", - "nmap-service-names": [ - "snmp" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "nmap -sV -Pn -vv -p$port --script=snmp-netstat,snmp-processes -oA '$outputdir/$ip_$port_snmp' $ip", - "onesixtyone $ip > $outputdir/$ip_$port_snmp_onesixtyone.txt", - "snmpwalk -c public -v1 $ip > $outputdir/$ip_$port_snmpwalk.txt" - ] - } - ] - }, - "ssh": { - "description": "Found SSH service on $ip:$port", - "nmap-service-names": [ - "ssh" - ], - "output": [ - { - "description": "Bruteforcing", - "commands": [ - "medusa -u root -P /usr/share/wordlists/rockyou.txt -e ns -h $ip - $port -M ssh", - "hydra -f -V -t 1 -l root -P /usr/share/wordlists/rockyou.txt -s $port $ip ssh", - "ncrack -vv -p $port --user root -P PASS_LIST $ip" - ] - }, - { - "description": "Use nmap to automate banner grabbing and key fingerprints, e.g.", - "commands": [ - "nmap $ip -p $port -sV --script=ssh-hostkey -oA '$outputdir/$ip_$port_ssh-hostkey'" - ] - } - ] - }, - "msrpc": { - "description": "Found MSRPC service on $ip:$port", - "nmap-service-names": [ - "msrpc", - "rpcbind" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "rpcclient -U \"\" $ip" - ] - }, - { - "description": "Bruteforce", - "commands": [ - "rpcclient -U \"\" $ip" - ] - } - ] - }, - "netbios-ssn": { - "description": "Found NetBIOS service on $ip:$port", - "nmap-service-names": [ - "netbios-ssn" - ], - "output": [ - { - "description": "Enumeration", - "commands": [ - "nmblookup -A $ip", - "smbclient //MOUNT/share -I $ip N", - "smbclient -L //$ip", - "enum4linux -a $ip", - "rpcclient -U \"\" $ip" - ] - } - ] - }, - "CUPS": { - "description": "Found CUPS service on $ip:$port", - "nmap-service-names": [ - "ipp" - ], - "output": [ - { - "description": "Find public exploits", - "commands": [ - "searchsploit cups" - ] - } - ] - }, - "java-rmi": { - "description": "Found CUPS service on $ip:$port", - "nmap-service-names": [ - "java-rmi" - ], - "output": [ - { - "description": "Find public exploits", - "commands": [ - "searchsploit java rmi" - ] - } - ] - }, - "vnc": { - "description": "Found VNC service on $ip:$port", - "nmap-service-names": [ - "vnc", - "vnc-http" - ], - "output": [ - { - "description": "Find public exploits", - "commands": [ - "searchsploit vnc" - ] - }, - { - "description": "Bruteforcing", - "commands": [ - "crowbar -b vnckey -s $ip/32 -p IP -k PASS_FILE" - ] - } - ] - }, - "oracle": { - "description": "Found Oracle service on $ip:$port", - "nmap-service-names": [ - "oracle-tns" - ], - "output": [ - { - "description": "Find public exploits", - "commands": [ - "searchsploit Oracle TNS" - ] - } - ] - }, - "kerberos": { - "description": "Found Kerberos service on $ip:$port", - "nmap-service-names": [ - "kerberos-sec" - ], - "output": [ - { - "description": "Find public exploits", - "commands": [ - "searchsploit kerberos" - ] - } - ] - }, - "ldap": { - "description": "Found LDAP service on $ip:$port", - "nmap-service-names": [ - "ldap" - ], - "output": [ - { - "description": "Find public exploits", - "commands": [ - "searchsploit ldap" - ] - } - ] - } - } -} \ No newline at end of file diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__init__.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__version__.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__version__.py deleted file mode 100644 index 19d8875..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/__version__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -# |"""\-= RECONNOITRE -# (____) An OSCP scanner by @codingo_ -# https://github.com/codingo/VHostScan - -__version__ = '1.0' diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/input.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/input.py deleted file mode 100644 index ce2a754..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/core/input.py +++ /dev/null @@ -1,118 +0,0 @@ -from argparse import ArgumentParser -import os.path - - -class CliHelper(object): - @staticmethod - def readable_file(parser, arg): - if not os.path.exists(arg): - parser.error("The file %s does not exist!" % arg) - else: - return open(arg, 'r') # return an open file handle - - -class CliArgumentParser(object): - def __init__(self): - self._parser = self.setup_parser() - - def parse(self, argv): - return self._parser.parse_args(argv) - - @staticmethod - def setup_parser(): - parser = ArgumentParser() - - parser.add_argument("-t", - dest="target_hosts", - required=True, - help="Set a target range of addresses to target. Ex 10.11.1.1-255") - - parser.add_argument("-o", - dest="output_directory", - required=True, - help="Set the output directory. Ex /root/Documents/labs/") - - parser.add_argument("-w", - dest="wordlist", - required=False, - help="Set the wordlist to use for generated commands. Ex /usr/share/wordlist.txt", - default=False) - - parser.add_argument("-p", - dest="port", - required=False, - help="Set the port to use. Leave blank to use discovered ports. " - "Useful to force virtual host scanning on non-standard webserver ports.", - default=80) - - parser.add_argument("--pingsweep", - dest="ping_sweep", - action="store_true", - help="Write a new target.txt by performing a ping sweep and discovering live hosts.", - default=False) - - parser.add_argument("--dns", "--dnssweep", - dest="find_dns_servers", - action="store_true", - help="Find DNS servers from a list of targets.", - default=False) - - parser.add_argument("--services", - dest="perform_service_scan", - action="store_true", - help="Perform service scan over targets.", - default=False) - - parser.add_argument("--hostnames", - dest="hostname_scan", - action="store_true", - help="Attempt to discover target hostnames and write to 0-name.txt and hostnames.txt.", - default=False) - - parser.add_argument("--snmp", - dest="perform_snmp_walk", - action="store_true", - help="Perform service scan over targets.", - default=False) - - parser.add_argument("--quick", - dest="quick", - action="store_true", - required=False, - help="Move to the next target after performing a quick scan and writing " - "first-round recommendations.", - default=False) - - parser.add_argument("--virtualhosts", - dest="virtualhosts", - action="store_true", - required=False, - help="Attempt to discover virtual hosts using the specified wordlist.", - default=False) - - parser.add_argument('--ignore-http-codes', - dest='ignore_http_codes', - type=str, - help='Comma separated list of http codes to ignore with virtual host scans.', - default='404') - - parser.add_argument('--ignore-content-length', - dest='ignore_content_length', - type=int, - help='Ignore content lengths of specificed amount. ' - 'This may become useful when a server returns a static page on ' - 'every virtual host guess.', - default=0) - - parser.add_argument("--quiet", - dest="quiet", - action="store_true", - help="Supress banner and headers to limit to comma dilimeted results only.", - default=False) - - parser.add_argument("--no-udp", - dest="no_udp_service_scan", - action="store_true", - help="Disable UDP services scan over targets.", - default=False) - return parser diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/file_helper.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/file_helper.py deleted file mode 100644 index 7991cbd..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/file_helper.py +++ /dev/null @@ -1,120 +0,0 @@ -import os -import json - - -def check_directory(output_directory): - try: - os.stat(output_directory) - except Exception: - os.mkdir(output_directory) - print("[!] %s didn't exist and has been created." % output_directory) - - -def load_targets(target_hosts, output_directory, quiet): - if (os.path.isdir(target_hosts) or os.path.isfile(target_hosts)): - return target_hosts - elif "-" in target_hosts: - expand_targets(target_hosts, output_directory) - return output_directory + "/targets.txt" - else: - return output_directory + "/targets.txt" - - -def expand_targets(target_hosts, output_directory): - parts = target_hosts.split(".") - target_list = [] - for part in parts: - if "-" in part: - iprange = part.split("-") - for i in range(int(iprange[0]), int(iprange[1])): - target_list.append(parts[0] + "." + parts[1] + "." + parts[2] + "." + str(i)) - with open(output_directory + "/targets.txt", "w") as targets: - for target in target_list: - targets.write("%s\n" % target) - - -def create_dir_structure(ip_address, output_directory): - print("[+] Creating directory structure for " + ip_address) - - hostdir = output_directory + "/" + ip_address - try: - os.stat(hostdir) - except Exception: - os.mkdir(hostdir) - - nmapdir = hostdir + "/scans" - print(" [>] Creating scans directory at: %s" % nmapdir) - try: - os.stat(nmapdir) - except Exception: - os.mkdir(nmapdir) - - exploitdir = hostdir + "/exploit" - print(" [>] Creating exploit directory at: %s" % exploitdir) - try: - os.stat(exploitdir) - except Exception: - os.mkdir(exploitdir) - - lootdir = hostdir + "/loot" - print(" [>] Creating loot directory at: %s" % lootdir) - try: - os.stat(lootdir) - except Exception: - os.mkdir(lootdir) - - prooffile = hostdir + "/proof.txt" - print(" [>] Creating proof file at: %s" % prooffile) - open(prooffile, 'a').close() - - -def write_recommendations(results, ip_address, outputdir): - recommendations_file = outputdir + "/" + ip_address + "_findings.txt" - serv_dict = {} - lines = results.split("\n") - for line in lines: - ports = [] - line = line.strip() - if ("tcp" in line) and ("open" in line) and not ("Discovered" in line): - while " " in line: - line = line.replace(" ", " ") - service = line.split(" ")[2] - port = line.split(" ")[0] - - if service in serv_dict: - ports = serv_dict[service] - - ports.append(port) - serv_dict[service] = ports - - print("[+] Writing findings for %s" % (ip_address)) - - __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) - with open(os.path.join(__location__, "config.json"), "r") as config: - c = config.read() - j = json.loads(c.replace("$ip", "%(ip)s").replace("$port", "%(port)s").replace("$outputdir", "%(outputdir)s")) - - f = open(recommendations_file, 'w') - for serv in serv_dict: - ports = serv_dict[serv] - - for service in j["services"]: - if (serv in j["services"][service]["nmap-service-names"]) or (service in serv): - for port in ports: - port = port.split("/")[0] - - description = "[*] " + j["services"][service]["description"] - print(description % {"ip": ip_address, "port": port}) - f.write((description + "\n") % {"ip": ip_address, "port": port}) - - for entry in j["services"][service]["output"]: - f.write(" [*] " + entry["description"] + "\n") - - for cmd in entry["commands"]: - f.write( - (" [=] " + cmd + "\n") % {"ip": ip_address, "port": port, "outputdir": outputdir}) - - f.write("\n") - - f.write("\n\n[*] Always remember to manually go over the portscan report and carefully read between the lines ;)") - f.close() diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/find_dns.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/find_dns.py deleted file mode 100644 index 38fb816..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/find_dns.py +++ /dev/null @@ -1,43 +0,0 @@ -import subprocess - -from file_helper import check_directory -from file_helper import load_targets - - -def find_dns(target_hosts, output_directory, quiet): - check_directory(output_directory) - results = 0 - hostcount = 0 - dnscount = 0 - - output_file = open(output_directory + "/DNS-Detailed.txt", 'w') - output_targets = open(output_directory + "/DNS-targets.txt", 'w') - - targets = load_targets(target_hosts, output_directory, quiet) - target_file = open(targets, 'r') - - print("[*] Loaded targets from: %s" % targets) - print("[+] Enumerating TCP port 53 over targets to find dns servers") - - for ip_address in target_file: - hostcount += 1 - ip_address = ip_address.strip() - ip_address = ip_address.rstrip() - - print(" [>] Testing %s for DNS" % ip_address) - DNSSCAN = "nmap -n -sV -Pn -vv -p53 %s" % (ip_address) - results = subprocess.check_output(DNSSCAN, shell=True).decode("utf-8") - lines = results.split("\n") - - for line in lines: - line = line.strip() - line = line.rstrip() - if ("53/tcp" in line) and ("open" in line) and ("Discovered" not in line): - print(" [=] Found DNS service running on: %s" % (ip_address)) - output_file.write("[*] Found DNS service running on: %s\n" % (ip_address)) - output_file.write(" [>] %s\n" % (line)) - output_targets.write("%s" % (ip_address)) - dnscount += 1 - print("[*] Found %s DNS servers within %s hosts" % (str(dnscount), str(hostcount))) - output_file.close() - output_targets.close() diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/hostname_scan.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/hostname_scan.py deleted file mode 100644 index cee97bf..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/hostname_scan.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -import subprocess - -from file_helper import check_directory - - -def hostname_scan(target_hosts, output_directory, quiet): - check_directory(output_directory) - output_file = output_directory + "/hostnames.txt" - f = open(output_file, 'w') - print("[+] Writing hostnames to: %s" % output_file) - - hostnames = 0 - SWEEP = '' - - if (os.path.isfile(target_hosts)): - SWEEP = "nbtscan -q -f %s" % (target_hosts) - else: - SWEEP = "nbtscan -q %s" % (target_hosts) - - results = subprocess.check_output(SWEEP, shell=True).decode("utf-8") - lines = results.split("\n") - - for line in lines: - line = line.strip() - line = line.rstrip() - - # Final line is blank which causes list index issues if we don't - # continue past it. - if " " not in line: - continue - - while " " in line: - line = line.replace(" ", " ") - - ip_address = line.split(" ")[0] - host = line.split(" ")[1] - - if (hostnames > 0): - f.write('\n') - - print(" [>] Discovered hostname: %s (%s)" % (host, ip_address)) - f.write("%s - %s" % (host, ip_address)) - hostnames += 1 - - print("[*] Found %s hostnames." % (hostnames)) - print("[*] Created hostname list %s" % (output_file)) - f.close() diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/ping_sweeper.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/ping_sweeper.py deleted file mode 100644 index 3bea501..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/ping_sweeper.py +++ /dev/null @@ -1,45 +0,0 @@ -import subprocess - -from file_helper import check_directory - - -def ping_sweeper(target_hosts, output_directory, quiet): - check_directory(output_directory) - output_file = output_directory + "/targets.txt" - - print("[+] Performing ping sweep over %s" % target_hosts) - - lines = call_nmap_sweep(target_hosts) - live_hosts = parse_nmap_output_for_live_hosts(lines) - write_live_hosts_list_to_file(output_file, live_hosts) - - for ip_address in live_hosts: - print(" [>] Discovered host: %s" % (ip_address)) - - print("[*] Found %s live hosts" % (len(live_hosts))) - print("[*] Created target list %s" % (output_file)) - - -def call_nmap_sweep(target_hosts): - SWEEP = "nmap -n -sP %s" % (target_hosts) - - results = subprocess.check_output(SWEEP, shell=True) - lines = str(results).encode("utf-8").split("\n") - return lines - - -def parse_nmap_output_for_live_hosts(lines): - def get_ip_from_nmap_line(line): - return line.split()[4] - - live_hosts = [get_ip_from_nmap_line(line) - for line in lines - if "Nmap scan report for" in line] - - return live_hosts - - -def write_live_hosts_list_to_file(output_file, live_hosts): - print("[+] Writing discovered targets to: %s" % output_file) - with open(output_file, 'w') as f: - f.write("\n".join(live_hosts)) diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/service_scan.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/service_scan.py deleted file mode 100644 index 83702ad..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/service_scan.py +++ /dev/null @@ -1,102 +0,0 @@ -import multiprocessing -import socket -import subprocess - -from file_helper import check_directory -from file_helper import create_dir_structure -from file_helper import load_targets -from file_helper import write_recommendations - - -def nmap_scan(ip_address, output_directory, dns_server, quick, no_udp_service_scan): - ip_address = ip_address.strip() - - print("[+] Starting quick nmap scan for %s" % (ip_address)) - QUICKSCAN = "nmap -sC -sV %s -oA '%s/%s.quick'" % (ip_address, output_directory, ip_address) - quickresults = subprocess.check_output(QUICKSCAN, shell=True).decode("utf-8") - - write_recommendations(quickresults, ip_address, output_directory) - print("[*] TCP quick scans completed for %s" % ip_address) - - if (quick): - return - - if dns_server: - print("[+] Starting detailed TCP%s nmap scans for %s using DNS Server %s" % ( - ("" if no_udp_service_scan is True else "/UDP"), ip_address, dns_server)) - print("[+] Using DNS server %s" % (dns_server)) - TCPSCAN = "nmap -vv -Pn -sS -A -sC -p- -T 3 -script-args=unsafe=1 " \ - "--dns-servers %s -oN '%s/%s.nmap' -oX '%s/%s_nmap_scan_import.xml' %s" % ( - dns_server, output_directory, ip_address, output_directory, ip_address, ip_address) - UDPSCAN = "nmap -vv -Pn -A -sC -sU -T 4 --top-ports 200 --max-retries 0 " \ - "--dns-servers %s -oN '%s/%sU.nmap' -oX '%s/%sU_nmap_scan_import.xml' %s" % ( - dns_server, output_directory, ip_address, output_directory, ip_address, ip_address) - else: - print("[+] Starting detailed TCP%s nmap scans for %s" % ( - ("" if no_udp_service_scan is True else "/UDP"), ip_address)) - TCPSCAN = "nmap -vv -Pn -sS -A -sC -p- -T 3 " \ - "-script-args=unsafe=1 -n %s -oN '%s/%s.nmap' -oX '%s/%s_nmap_scan_import.xml' %s" % ( - dns_server, output_directory, ip_address, output_directory, ip_address, ip_address) - UDPSCAN = "nmap -sC -sV -sU %s -oA '%s/%s-udp'" % (ip_address, output_directory, ip_address) - - udpresults = "" if no_udp_service_scan is True else subprocess.check_output(UDPSCAN, shell=True).decode("utf-8") - tcpresults = subprocess.check_output(TCPSCAN, shell=True).decode("utf-8") - - write_recommendations(tcpresults + udpresults, ip_address, output_directory) - print("[*] TCP%s scans completed for %s" % (("" if no_udp_service_scan is True else "/UDP"), ip_address)) - - -def valid_ip(address): - try: - socket.inet_aton(address) - return True - except socket.error: - return False - - -def target_file(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan): - targets = load_targets(target_hosts, output_directory, quiet) - target_file = open(targets, 'r') - try: - target_file = open(targets, 'r') - print("[*] Loaded targets from: %s" % targets) - except Exception: - print("[!] Unable to load: %s" % targets) - - for ip_address in target_file: - ip_address = ip_address.strip() - create_dir_structure(ip_address, output_directory) - - host_directory = output_directory + "/" + ip_address - nmap_directory = host_directory + "/scans" - - jobs = [] - p = multiprocessing.Process(target=nmap_scan, - args=(ip_address, nmap_directory, dns_server, quick, no_udp_service_scan)) - jobs.append(p) - p.start() - target_file.close() - - -def target_ip(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan): - print("[*] Loaded single target: %s" % target_hosts) - target_hosts = target_hosts.strip() - create_dir_structure(target_hosts, output_directory) - - host_directory = output_directory + "/" + target_hosts - nmap_directory = host_directory + "/scans" - - jobs = [] - p = multiprocessing.Process(target=nmap_scan, - args=(target_hosts, nmap_directory, dns_server, quick, no_udp_service_scan)) - jobs.append(p) - p.start() - - -def service_scan(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan): - check_directory(output_directory) - - if (valid_ip(target_hosts)): - target_ip(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan) - else: - target_file(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan) diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/snmp_walk.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/snmp_walk.py deleted file mode 100644 index e514352..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/snmp_walk.py +++ /dev/null @@ -1,73 +0,0 @@ -import multiprocessing -import socket -import subprocess - -from file_helper import check_directory, load_targets - - -def valid_ip(address): - try: - socket.inet_aton(address) - return True - except socket.error: - return False - - -def target_file(target_hosts, output_directory, quiet): - targets = load_targets(target_hosts, output_directory, quiet) - target_file = open(targets, 'r') - try: - target_file = open(targets, 'r') - print("[*] Loaded targets from: %s" % targets) - except Exception: - print("[!] Unable to load: %s" % targets) - - for ip_address in target_file: - ip_address = ip_address.strip() - - snmp_directory = output_directory + '/' + ip_address + '/scans/snmp/' - check_directory(snmp_directory) - - jobs = [] - p = multiprocessing.Process(target=snmp_scans, args=(ip_address, snmp_directory)) - jobs.append(p) - p.start() - target_file.close() - - -def target_ip(target_hosts, output_directory, quiet): - print("[*] Loaded single target: %s" % target_hosts) - target_hosts = target_hosts.strip() - - snmp_directory = output_directory + '/' + target_hosts + '/scans/snmp/' - check_directory(snmp_directory) - - jobs = [] - p = multiprocessing.Process(target=snmp_scans, args=(target_hosts, snmp_directory)) - jobs.append(p) - p.start() - - -def snmp_walk(target_hosts, output_directory, quiet): - check_directory(output_directory) - - if (valid_ip(target_hosts)): - target_ip(target_hosts, output_directory, quiet) - else: - target_file(target_hosts, output_directory, quiet) - - -def snmp_scans(ip_address, output_directory): - print("[+] Performing SNMP scans for %s to %s" % (ip_address, output_directory)) - print(" [>] Performing snmpwalk on public tree for: %s - Checking for System Processes" % (ip_address)) - SCAN = "snmpwalk -c public -v1 %s 1.3.6.1.2.1.25.1.6.0 > '%s%s-systemprocesses.txt'" % ( - ip_address, output_directory, ip_address) - - try: - subprocess.check_output(SCAN, stderr=subprocess.STDOUT, shell=True).decode("utf-8").decode('utf-8') - except Exception as e: - print("[+] No Response from %s" % ip_address) - except subprocess.CalledProcessError as cpe: - print("[+] Subprocess failure during scan of %s" % ip_address) - - print("[+] Completed SNMP scans for %s" % (ip_address)) diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/virtual_host_scanner.py b/build/lib.linux-x86_64-2.7/Reconnoitre/lib/virtual_host_scanner.py deleted file mode 100644 index d18d22f..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/lib/virtual_host_scanner.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/python - -import os -import requests - - -class VirtualHostScanner(object): - """Virtual host scanning class for Reconnoitre - - Virtual host scanner has the following properties: - - Attributes: - wordlist: location to a wordlist file to use with scans - target: the target for scanning - port: the port to scan. Defaults to 80 - ignore_http_codes: commad seperated list of http codes to ignore - ignore_content_length: integer value of content length to ignore - output: folder to write output file to - - """ - - def __init__(self, target, output, port=80, ignore_http_codes='404', ignore_content_length=0, - wordlist="./wordlist/virtual-host-scanning.txt"): - self.target = target - self.output = output + '/' + target + '_virtualhosts.txt' - self.port = port - self.ignore_http_codes = list(map(int, ignore_http_codes.replace(' ', '').split(','))) - self.ignore_content_length = ignore_content_length - self.wordlist = wordlist - - def scan(self): - print("[+] Starting virtual host scan for %s using port %s and wordlist %s" % ( - self.target, str(self.port), self.wordlist)) - print("[>] Ignoring HTTP codes: %s" % (self.ignore_http_codes)) - if (self.ignore_content_length > 0): - print("[>] Ignoring Content length: %s" % (self.ignore_content_length)) - - if not os.path.exists(self.wordlist): - print("[!] Wordlist %s doesn't exist, exiting virtual host scanner." % self.wordlist) - return - - virtual_host_list = open(self.wordlist).read().splitlines() - results = '' - - for virtual_host in virtual_host_list: - hostname = virtual_host.replace('%s', self.target) - - headers = { - 'Host': hostname if self.port == 80 else '{}:{}'.format(hostname, self.port), - 'Accept': '*/*' - } - - dest_url = '{}://{}:{}/'.format('https' if int(self.port) == 443 else 'http', self.target, self.port) - - try: - res = requests.get(dest_url, headers=headers, verify=False) - except requests.exceptions.RequestException: - continue - - if res.status_code in self.ignore_http_codes: - continue - - if self.ignore_content_length > 0 and self.ignore_content_length == int(res.headers.get('content-length')): - continue - - output = 'Found: {} (code: {}, length: {})'.format(hostname, res.status_code, - res.headers.get('content-length')) - results += output + '\n' - - print(output) - for key, val in res.headers.items(): - output = ' {}: {}'.format(key, val) - results += output + '\n' - print(output) diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/reconnoitre.py b/build/lib.linux-x86_64-2.7/Reconnoitre/reconnoitre.py deleted file mode 100644 index ccab11a..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/reconnoitre.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/python - - -import sys - -from lib.core.input import CliArgumentParser -from lib.find_dns import find_dns -from lib.hostname_scan import hostname_scan -from lib.ping_sweeper import ping_sweeper -from lib.service_scan import service_scan -from lib.snmp_walk import snmp_walk -from lib.virtual_host_scanner import VirtualHostScanner - - -def print_banner(): - print(" __") - print("|\"\"\"\-= RECONNOITRE") - print("(____) An OSCP scanner by @codingo_\n") - - -def util_checks(util=None): - if util is None: - print("[!] Error hit in chktool: None encountered for util.") - sys.exit(1) - - pyvers = sys.version_info - - if (pyvers[0] >= 3) and (pyvers[1] >= 3): # python3.3+ - import shutil - if shutil.which(util) is None: - if util is "nmap": - print( - " [!] nmap was not found on your system. Exiting since we wont be able to scan anything. " - "Please install nmap and try again.") - sys.exit(1) - else: - print(" [-] %s was not found in your system. Scan types using this will fail." % util) - return "Not Found" - else: - return "Found" - else: # less-than python 3.3 - from distutils import spawn - if spawn.find_executable(util) is None: - if util is "nmap": - print( - " [!] nmap was not found on your system. Exiting since we wont be able to scan anything. " - "Please install nmap and try again.") - sys.exit(1) - else: - print(" [-] %s was not found in your system. Scan types using this will fail." % util) - return "Not Found" - else: - return "Found" - - -def main(): - parser = CliArgumentParser() - arguments = parser.parse(sys.argv[1:]) - - if arguments.output_directory.endswith('/' or '\\'): - arguments.output_directory = arguments.output_directory[:-1] - if arguments.target_hosts.endswith('/' or '\\'): - arguments.target_hosts = arguments.target_hosts[:-1] - - if arguments.quiet is not True: - print_banner() - print("[+] Testing for required utilities on your system.") - - utils = ['nmap', 'snmpwalk', 'nbtscan'] # list of utils to check on local system. - for util in utils: - util_checks(util) - - if arguments.ping_sweep is True: - print("[#] Performing ping sweep") - ping_sweeper(arguments.target_hosts, arguments.output_directory, arguments.quiet) - - if arguments.hostname_scan is True: - print("[#] Identifying hostnames") - hostname_scan(arguments.target_hosts, arguments.output_directory, arguments.quiet) - - if arguments.find_dns_servers is True: - print("[#] Identifying DNS Servers") - find_dns(arguments.target_hosts, arguments.output_directory, arguments.quiet) - - if arguments.perform_service_scan is True: - print("[#] Performing service scans") - if arguments.find_dns_servers is True: - service_scan(arguments.target_hosts, arguments.output_directory, arguments.find_dns_servers, - arguments.quiet, arguments.quick, arguments.no_udp_service_scan) - else: - service_scan(arguments.target_hosts, arguments.output_directory, '', arguments.quiet, arguments.quick, - arguments.no_udp_service_scan) - - if arguments.perform_snmp_walk is True: - print("[#] Performing SNMP walks") - snmp_walk(arguments.target_hosts, arguments.output_directory, arguments.quiet) - - if arguments.virtualhosts is True: - print("[#] Performing Virtual host scans") - if arguments.wordlist is False: - print("[!] No wordlist was provided, skipping virtual host scanning.") - else: - scanner = VirtualHostScanner(arguments.target_hosts, arguments.output_directory, arguments.port, - arguments.ignore_http_codes, arguments.ignore_content_length, - arguments.wordlist) - scanner.scan() - - -if __name__ == "__main__": - main() diff --git a/build/lib.linux-x86_64-2.7/Reconnoitre/wordlists/virtual-host-scanning.txt b/build/lib.linux-x86_64-2.7/Reconnoitre/wordlists/virtual-host-scanning.txt deleted file mode 100644 index 80c09a6..0000000 --- a/build/lib.linux-x86_64-2.7/Reconnoitre/wordlists/virtual-host-scanning.txt +++ /dev/null @@ -1,34 +0,0 @@ -www.%s -dev.%s -local -localhost -status.%s -status -staging.%s -staging -development -development.%s -uat -uat.%s -%s -beta -beta.%s -secure -secure.%s -mobile -mobile.%s -127.0.0.1 -m.%s -m -admin -admin.%s -old -old.%s -v1.%s -v1 -v2.%s -v2 -v3.%s -v3 -alpha -alpha.%s \ No newline at end of file diff --git a/build/lib.linux-x86_64-2.7/lib/__init__.py b/build/lib.linux-x86_64-2.7/lib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib.linux-x86_64-2.7/lib/core/__init__.py b/build/lib.linux-x86_64-2.7/lib/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib.linux-x86_64-2.7/lib/core/__version__.py b/build/lib.linux-x86_64-2.7/lib/core/__version__.py deleted file mode 100644 index 19d8875..0000000 --- a/build/lib.linux-x86_64-2.7/lib/core/__version__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -# |"""\-= RECONNOITRE -# (____) An OSCP scanner by @codingo_ -# https://github.com/codingo/VHostScan - -__version__ = '1.0' diff --git a/build/lib.linux-x86_64-2.7/lib/core/input.py b/build/lib.linux-x86_64-2.7/lib/core/input.py deleted file mode 100644 index ce2a754..0000000 --- a/build/lib.linux-x86_64-2.7/lib/core/input.py +++ /dev/null @@ -1,118 +0,0 @@ -from argparse import ArgumentParser -import os.path - - -class CliHelper(object): - @staticmethod - def readable_file(parser, arg): - if not os.path.exists(arg): - parser.error("The file %s does not exist!" % arg) - else: - return open(arg, 'r') # return an open file handle - - -class CliArgumentParser(object): - def __init__(self): - self._parser = self.setup_parser() - - def parse(self, argv): - return self._parser.parse_args(argv) - - @staticmethod - def setup_parser(): - parser = ArgumentParser() - - parser.add_argument("-t", - dest="target_hosts", - required=True, - help="Set a target range of addresses to target. Ex 10.11.1.1-255") - - parser.add_argument("-o", - dest="output_directory", - required=True, - help="Set the output directory. Ex /root/Documents/labs/") - - parser.add_argument("-w", - dest="wordlist", - required=False, - help="Set the wordlist to use for generated commands. Ex /usr/share/wordlist.txt", - default=False) - - parser.add_argument("-p", - dest="port", - required=False, - help="Set the port to use. Leave blank to use discovered ports. " - "Useful to force virtual host scanning on non-standard webserver ports.", - default=80) - - parser.add_argument("--pingsweep", - dest="ping_sweep", - action="store_true", - help="Write a new target.txt by performing a ping sweep and discovering live hosts.", - default=False) - - parser.add_argument("--dns", "--dnssweep", - dest="find_dns_servers", - action="store_true", - help="Find DNS servers from a list of targets.", - default=False) - - parser.add_argument("--services", - dest="perform_service_scan", - action="store_true", - help="Perform service scan over targets.", - default=False) - - parser.add_argument("--hostnames", - dest="hostname_scan", - action="store_true", - help="Attempt to discover target hostnames and write to 0-name.txt and hostnames.txt.", - default=False) - - parser.add_argument("--snmp", - dest="perform_snmp_walk", - action="store_true", - help="Perform service scan over targets.", - default=False) - - parser.add_argument("--quick", - dest="quick", - action="store_true", - required=False, - help="Move to the next target after performing a quick scan and writing " - "first-round recommendations.", - default=False) - - parser.add_argument("--virtualhosts", - dest="virtualhosts", - action="store_true", - required=False, - help="Attempt to discover virtual hosts using the specified wordlist.", - default=False) - - parser.add_argument('--ignore-http-codes', - dest='ignore_http_codes', - type=str, - help='Comma separated list of http codes to ignore with virtual host scans.', - default='404') - - parser.add_argument('--ignore-content-length', - dest='ignore_content_length', - type=int, - help='Ignore content lengths of specificed amount. ' - 'This may become useful when a server returns a static page on ' - 'every virtual host guess.', - default=0) - - parser.add_argument("--quiet", - dest="quiet", - action="store_true", - help="Supress banner and headers to limit to comma dilimeted results only.", - default=False) - - parser.add_argument("--no-udp", - dest="no_udp_service_scan", - action="store_true", - help="Disable UDP services scan over targets.", - default=False) - return parser diff --git a/build/lib.linux-x86_64-2.7/lib/file_helper.py b/build/lib.linux-x86_64-2.7/lib/file_helper.py deleted file mode 100644 index 7991cbd..0000000 --- a/build/lib.linux-x86_64-2.7/lib/file_helper.py +++ /dev/null @@ -1,120 +0,0 @@ -import os -import json - - -def check_directory(output_directory): - try: - os.stat(output_directory) - except Exception: - os.mkdir(output_directory) - print("[!] %s didn't exist and has been created." % output_directory) - - -def load_targets(target_hosts, output_directory, quiet): - if (os.path.isdir(target_hosts) or os.path.isfile(target_hosts)): - return target_hosts - elif "-" in target_hosts: - expand_targets(target_hosts, output_directory) - return output_directory + "/targets.txt" - else: - return output_directory + "/targets.txt" - - -def expand_targets(target_hosts, output_directory): - parts = target_hosts.split(".") - target_list = [] - for part in parts: - if "-" in part: - iprange = part.split("-") - for i in range(int(iprange[0]), int(iprange[1])): - target_list.append(parts[0] + "." + parts[1] + "." + parts[2] + "." + str(i)) - with open(output_directory + "/targets.txt", "w") as targets: - for target in target_list: - targets.write("%s\n" % target) - - -def create_dir_structure(ip_address, output_directory): - print("[+] Creating directory structure for " + ip_address) - - hostdir = output_directory + "/" + ip_address - try: - os.stat(hostdir) - except Exception: - os.mkdir(hostdir) - - nmapdir = hostdir + "/scans" - print(" [>] Creating scans directory at: %s" % nmapdir) - try: - os.stat(nmapdir) - except Exception: - os.mkdir(nmapdir) - - exploitdir = hostdir + "/exploit" - print(" [>] Creating exploit directory at: %s" % exploitdir) - try: - os.stat(exploitdir) - except Exception: - os.mkdir(exploitdir) - - lootdir = hostdir + "/loot" - print(" [>] Creating loot directory at: %s" % lootdir) - try: - os.stat(lootdir) - except Exception: - os.mkdir(lootdir) - - prooffile = hostdir + "/proof.txt" - print(" [>] Creating proof file at: %s" % prooffile) - open(prooffile, 'a').close() - - -def write_recommendations(results, ip_address, outputdir): - recommendations_file = outputdir + "/" + ip_address + "_findings.txt" - serv_dict = {} - lines = results.split("\n") - for line in lines: - ports = [] - line = line.strip() - if ("tcp" in line) and ("open" in line) and not ("Discovered" in line): - while " " in line: - line = line.replace(" ", " ") - service = line.split(" ")[2] - port = line.split(" ")[0] - - if service in serv_dict: - ports = serv_dict[service] - - ports.append(port) - serv_dict[service] = ports - - print("[+] Writing findings for %s" % (ip_address)) - - __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) - with open(os.path.join(__location__, "config.json"), "r") as config: - c = config.read() - j = json.loads(c.replace("$ip", "%(ip)s").replace("$port", "%(port)s").replace("$outputdir", "%(outputdir)s")) - - f = open(recommendations_file, 'w') - for serv in serv_dict: - ports = serv_dict[serv] - - for service in j["services"]: - if (serv in j["services"][service]["nmap-service-names"]) or (service in serv): - for port in ports: - port = port.split("/")[0] - - description = "[*] " + j["services"][service]["description"] - print(description % {"ip": ip_address, "port": port}) - f.write((description + "\n") % {"ip": ip_address, "port": port}) - - for entry in j["services"][service]["output"]: - f.write(" [*] " + entry["description"] + "\n") - - for cmd in entry["commands"]: - f.write( - (" [=] " + cmd + "\n") % {"ip": ip_address, "port": port, "outputdir": outputdir}) - - f.write("\n") - - f.write("\n\n[*] Always remember to manually go over the portscan report and carefully read between the lines ;)") - f.close() diff --git a/build/lib.linux-x86_64-2.7/lib/find_dns.py b/build/lib.linux-x86_64-2.7/lib/find_dns.py deleted file mode 100644 index 38fb816..0000000 --- a/build/lib.linux-x86_64-2.7/lib/find_dns.py +++ /dev/null @@ -1,43 +0,0 @@ -import subprocess - -from file_helper import check_directory -from file_helper import load_targets - - -def find_dns(target_hosts, output_directory, quiet): - check_directory(output_directory) - results = 0 - hostcount = 0 - dnscount = 0 - - output_file = open(output_directory + "/DNS-Detailed.txt", 'w') - output_targets = open(output_directory + "/DNS-targets.txt", 'w') - - targets = load_targets(target_hosts, output_directory, quiet) - target_file = open(targets, 'r') - - print("[*] Loaded targets from: %s" % targets) - print("[+] Enumerating TCP port 53 over targets to find dns servers") - - for ip_address in target_file: - hostcount += 1 - ip_address = ip_address.strip() - ip_address = ip_address.rstrip() - - print(" [>] Testing %s for DNS" % ip_address) - DNSSCAN = "nmap -n -sV -Pn -vv -p53 %s" % (ip_address) - results = subprocess.check_output(DNSSCAN, shell=True).decode("utf-8") - lines = results.split("\n") - - for line in lines: - line = line.strip() - line = line.rstrip() - if ("53/tcp" in line) and ("open" in line) and ("Discovered" not in line): - print(" [=] Found DNS service running on: %s" % (ip_address)) - output_file.write("[*] Found DNS service running on: %s\n" % (ip_address)) - output_file.write(" [>] %s\n" % (line)) - output_targets.write("%s" % (ip_address)) - dnscount += 1 - print("[*] Found %s DNS servers within %s hosts" % (str(dnscount), str(hostcount))) - output_file.close() - output_targets.close() diff --git a/build/lib.linux-x86_64-2.7/lib/hostname_scan.py b/build/lib.linux-x86_64-2.7/lib/hostname_scan.py deleted file mode 100644 index cee97bf..0000000 --- a/build/lib.linux-x86_64-2.7/lib/hostname_scan.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -import subprocess - -from file_helper import check_directory - - -def hostname_scan(target_hosts, output_directory, quiet): - check_directory(output_directory) - output_file = output_directory + "/hostnames.txt" - f = open(output_file, 'w') - print("[+] Writing hostnames to: %s" % output_file) - - hostnames = 0 - SWEEP = '' - - if (os.path.isfile(target_hosts)): - SWEEP = "nbtscan -q -f %s" % (target_hosts) - else: - SWEEP = "nbtscan -q %s" % (target_hosts) - - results = subprocess.check_output(SWEEP, shell=True).decode("utf-8") - lines = results.split("\n") - - for line in lines: - line = line.strip() - line = line.rstrip() - - # Final line is blank which causes list index issues if we don't - # continue past it. - if " " not in line: - continue - - while " " in line: - line = line.replace(" ", " ") - - ip_address = line.split(" ")[0] - host = line.split(" ")[1] - - if (hostnames > 0): - f.write('\n') - - print(" [>] Discovered hostname: %s (%s)" % (host, ip_address)) - f.write("%s - %s" % (host, ip_address)) - hostnames += 1 - - print("[*] Found %s hostnames." % (hostnames)) - print("[*] Created hostname list %s" % (output_file)) - f.close() diff --git a/build/lib.linux-x86_64-2.7/lib/ping_sweeper.py b/build/lib.linux-x86_64-2.7/lib/ping_sweeper.py deleted file mode 100644 index 3bea501..0000000 --- a/build/lib.linux-x86_64-2.7/lib/ping_sweeper.py +++ /dev/null @@ -1,45 +0,0 @@ -import subprocess - -from file_helper import check_directory - - -def ping_sweeper(target_hosts, output_directory, quiet): - check_directory(output_directory) - output_file = output_directory + "/targets.txt" - - print("[+] Performing ping sweep over %s" % target_hosts) - - lines = call_nmap_sweep(target_hosts) - live_hosts = parse_nmap_output_for_live_hosts(lines) - write_live_hosts_list_to_file(output_file, live_hosts) - - for ip_address in live_hosts: - print(" [>] Discovered host: %s" % (ip_address)) - - print("[*] Found %s live hosts" % (len(live_hosts))) - print("[*] Created target list %s" % (output_file)) - - -def call_nmap_sweep(target_hosts): - SWEEP = "nmap -n -sP %s" % (target_hosts) - - results = subprocess.check_output(SWEEP, shell=True) - lines = str(results).encode("utf-8").split("\n") - return lines - - -def parse_nmap_output_for_live_hosts(lines): - def get_ip_from_nmap_line(line): - return line.split()[4] - - live_hosts = [get_ip_from_nmap_line(line) - for line in lines - if "Nmap scan report for" in line] - - return live_hosts - - -def write_live_hosts_list_to_file(output_file, live_hosts): - print("[+] Writing discovered targets to: %s" % output_file) - with open(output_file, 'w') as f: - f.write("\n".join(live_hosts)) diff --git a/build/lib.linux-x86_64-2.7/lib/service_scan.py b/build/lib.linux-x86_64-2.7/lib/service_scan.py deleted file mode 100644 index 83702ad..0000000 --- a/build/lib.linux-x86_64-2.7/lib/service_scan.py +++ /dev/null @@ -1,102 +0,0 @@ -import multiprocessing -import socket -import subprocess - -from file_helper import check_directory -from file_helper import create_dir_structure -from file_helper import load_targets -from file_helper import write_recommendations - - -def nmap_scan(ip_address, output_directory, dns_server, quick, no_udp_service_scan): - ip_address = ip_address.strip() - - print("[+] Starting quick nmap scan for %s" % (ip_address)) - QUICKSCAN = "nmap -sC -sV %s -oA '%s/%s.quick'" % (ip_address, output_directory, ip_address) - quickresults = subprocess.check_output(QUICKSCAN, shell=True).decode("utf-8") - - write_recommendations(quickresults, ip_address, output_directory) - print("[*] TCP quick scans completed for %s" % ip_address) - - if (quick): - return - - if dns_server: - print("[+] Starting detailed TCP%s nmap scans for %s using DNS Server %s" % ( - ("" if no_udp_service_scan is True else "/UDP"), ip_address, dns_server)) - print("[+] Using DNS server %s" % (dns_server)) - TCPSCAN = "nmap -vv -Pn -sS -A -sC -p- -T 3 -script-args=unsafe=1 " \ - "--dns-servers %s -oN '%s/%s.nmap' -oX '%s/%s_nmap_scan_import.xml' %s" % ( - dns_server, output_directory, ip_address, output_directory, ip_address, ip_address) - UDPSCAN = "nmap -vv -Pn -A -sC -sU -T 4 --top-ports 200 --max-retries 0 " \ - "--dns-servers %s -oN '%s/%sU.nmap' -oX '%s/%sU_nmap_scan_import.xml' %s" % ( - dns_server, output_directory, ip_address, output_directory, ip_address, ip_address) - else: - print("[+] Starting detailed TCP%s nmap scans for %s" % ( - ("" if no_udp_service_scan is True else "/UDP"), ip_address)) - TCPSCAN = "nmap -vv -Pn -sS -A -sC -p- -T 3 " \ - "-script-args=unsafe=1 -n %s -oN '%s/%s.nmap' -oX '%s/%s_nmap_scan_import.xml' %s" % ( - dns_server, output_directory, ip_address, output_directory, ip_address, ip_address) - UDPSCAN = "nmap -sC -sV -sU %s -oA '%s/%s-udp'" % (ip_address, output_directory, ip_address) - - udpresults = "" if no_udp_service_scan is True else subprocess.check_output(UDPSCAN, shell=True).decode("utf-8") - tcpresults = subprocess.check_output(TCPSCAN, shell=True).decode("utf-8") - - write_recommendations(tcpresults + udpresults, ip_address, output_directory) - print("[*] TCP%s scans completed for %s" % (("" if no_udp_service_scan is True else "/UDP"), ip_address)) - - -def valid_ip(address): - try: - socket.inet_aton(address) - return True - except socket.error: - return False - - -def target_file(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan): - targets = load_targets(target_hosts, output_directory, quiet) - target_file = open(targets, 'r') - try: - target_file = open(targets, 'r') - print("[*] Loaded targets from: %s" % targets) - except Exception: - print("[!] Unable to load: %s" % targets) - - for ip_address in target_file: - ip_address = ip_address.strip() - create_dir_structure(ip_address, output_directory) - - host_directory = output_directory + "/" + ip_address - nmap_directory = host_directory + "/scans" - - jobs = [] - p = multiprocessing.Process(target=nmap_scan, - args=(ip_address, nmap_directory, dns_server, quick, no_udp_service_scan)) - jobs.append(p) - p.start() - target_file.close() - - -def target_ip(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan): - print("[*] Loaded single target: %s" % target_hosts) - target_hosts = target_hosts.strip() - create_dir_structure(target_hosts, output_directory) - - host_directory = output_directory + "/" + target_hosts - nmap_directory = host_directory + "/scans" - - jobs = [] - p = multiprocessing.Process(target=nmap_scan, - args=(target_hosts, nmap_directory, dns_server, quick, no_udp_service_scan)) - jobs.append(p) - p.start() - - -def service_scan(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan): - check_directory(output_directory) - - if (valid_ip(target_hosts)): - target_ip(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan) - else: - target_file(target_hosts, output_directory, dns_server, quiet, quick, no_udp_service_scan) diff --git a/build/lib.linux-x86_64-2.7/lib/snmp_walk.py b/build/lib.linux-x86_64-2.7/lib/snmp_walk.py deleted file mode 100644 index e514352..0000000 --- a/build/lib.linux-x86_64-2.7/lib/snmp_walk.py +++ /dev/null @@ -1,73 +0,0 @@ -import multiprocessing -import socket -import subprocess - -from file_helper import check_directory, load_targets - - -def valid_ip(address): - try: - socket.inet_aton(address) - return True - except socket.error: - return False - - -def target_file(target_hosts, output_directory, quiet): - targets = load_targets(target_hosts, output_directory, quiet) - target_file = open(targets, 'r') - try: - target_file = open(targets, 'r') - print("[*] Loaded targets from: %s" % targets) - except Exception: - print("[!] Unable to load: %s" % targets) - - for ip_address in target_file: - ip_address = ip_address.strip() - - snmp_directory = output_directory + '/' + ip_address + '/scans/snmp/' - check_directory(snmp_directory) - - jobs = [] - p = multiprocessing.Process(target=snmp_scans, args=(ip_address, snmp_directory)) - jobs.append(p) - p.start() - target_file.close() - - -def target_ip(target_hosts, output_directory, quiet): - print("[*] Loaded single target: %s" % target_hosts) - target_hosts = target_hosts.strip() - - snmp_directory = output_directory + '/' + target_hosts + '/scans/snmp/' - check_directory(snmp_directory) - - jobs = [] - p = multiprocessing.Process(target=snmp_scans, args=(target_hosts, snmp_directory)) - jobs.append(p) - p.start() - - -def snmp_walk(target_hosts, output_directory, quiet): - check_directory(output_directory) - - if (valid_ip(target_hosts)): - target_ip(target_hosts, output_directory, quiet) - else: - target_file(target_hosts, output_directory, quiet) - - -def snmp_scans(ip_address, output_directory): - print("[+] Performing SNMP scans for %s to %s" % (ip_address, output_directory)) - print(" [>] Performing snmpwalk on public tree for: %s - Checking for System Processes" % (ip_address)) - SCAN = "snmpwalk -c public -v1 %s 1.3.6.1.2.1.25.1.6.0 > '%s%s-systemprocesses.txt'" % ( - ip_address, output_directory, ip_address) - - try: - subprocess.check_output(SCAN, stderr=subprocess.STDOUT, shell=True).decode("utf-8").decode('utf-8') - except Exception as e: - print("[+] No Response from %s" % ip_address) - except subprocess.CalledProcessError as cpe: - print("[+] Subprocess failure during scan of %s" % ip_address) - - print("[+] Completed SNMP scans for %s" % (ip_address)) diff --git a/build/lib.linux-x86_64-2.7/lib/virtual_host_scanner.py b/build/lib.linux-x86_64-2.7/lib/virtual_host_scanner.py deleted file mode 100644 index d18d22f..0000000 --- a/build/lib.linux-x86_64-2.7/lib/virtual_host_scanner.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/python - -import os -import requests - - -class VirtualHostScanner(object): - """Virtual host scanning class for Reconnoitre - - Virtual host scanner has the following properties: - - Attributes: - wordlist: location to a wordlist file to use with scans - target: the target for scanning - port: the port to scan. Defaults to 80 - ignore_http_codes: commad seperated list of http codes to ignore - ignore_content_length: integer value of content length to ignore - output: folder to write output file to - - """ - - def __init__(self, target, output, port=80, ignore_http_codes='404', ignore_content_length=0, - wordlist="./wordlist/virtual-host-scanning.txt"): - self.target = target - self.output = output + '/' + target + '_virtualhosts.txt' - self.port = port - self.ignore_http_codes = list(map(int, ignore_http_codes.replace(' ', '').split(','))) - self.ignore_content_length = ignore_content_length - self.wordlist = wordlist - - def scan(self): - print("[+] Starting virtual host scan for %s using port %s and wordlist %s" % ( - self.target, str(self.port), self.wordlist)) - print("[>] Ignoring HTTP codes: %s" % (self.ignore_http_codes)) - if (self.ignore_content_length > 0): - print("[>] Ignoring Content length: %s" % (self.ignore_content_length)) - - if not os.path.exists(self.wordlist): - print("[!] Wordlist %s doesn't exist, exiting virtual host scanner." % self.wordlist) - return - - virtual_host_list = open(self.wordlist).read().splitlines() - results = '' - - for virtual_host in virtual_host_list: - hostname = virtual_host.replace('%s', self.target) - - headers = { - 'Host': hostname if self.port == 80 else '{}:{}'.format(hostname, self.port), - 'Accept': '*/*' - } - - dest_url = '{}://{}:{}/'.format('https' if int(self.port) == 443 else 'http', self.target, self.port) - - try: - res = requests.get(dest_url, headers=headers, verify=False) - except requests.exceptions.RequestException: - continue - - if res.status_code in self.ignore_http_codes: - continue - - if self.ignore_content_length > 0 and self.ignore_content_length == int(res.headers.get('content-length')): - continue - - output = 'Found: {} (code: {}, length: {})'.format(hostname, res.status_code, - res.headers.get('content-length')) - results += output + '\n' - - print(output) - for key, val in res.headers.items(): - output = ' {}: {}'.format(key, val) - results += output + '\n' - print(output) diff --git a/dist/Reconnoitre-1.0-py2.7.egg b/dist/Reconnoitre-1.0-py2.7.egg deleted file mode 100644 index 32c55e3c06a174e0ce1981e2b7d2a38da83cb674..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51612 zcma&O1CV9ivMyS-ZQJg$ZQHhO+qSygW!tuG+tuZ&Tl>6-d;YWUe)qi)X034D603iNc6%iAom5>#cqnDTZe|`*U zdf9ETBYpSe1#SSXxYH+Qi+ODUY;D-iZ-H%aBXmsRdWJ}8H4bVLH4&MRhwbvdPr*=X z+#4-CdaeS5JQ17>W$bV-G8=eI(!y^?&5KvXuIjG(IZrz|3|0>cQx_N04*j0K5J)-c z?Bp@5QJ1i4WeNQgp|5%oeZ-AsT_I(v)JF$4l16i21bl;0Q#sv+Doy1Mug0H9inE-e zNZJwoCmmB^nlv7%VqD}bl}0fGbAqhc-z$Y-+7L3kiq0;h&V;p2C1P?6Nbo=Ik6tt5fucYfP2`*B?*(%G+g1AHawpAEq8lVD%P!QKh%Fbj`1;8&F{DYa-m(m+VxX~K zaGji|l>O1xX#YU5J4P3T(3#OyL|Vd#hTIyMIg+j3_58`6$;E1B#+ibbY;s$00#u7^ zLxFC7AWX7c=D`7m(~7J=!XHFfwC40>K=M3GX&UJ`A_X z23y9Et=lB;Nj*6=&Iu0t*v7Vw1(^pO;~}`(3abghMS}F61*iy-g+)G1uL5bWdhSd{ zjGW10ybqbcw1d+D40E3u00D|Snd2SS5g=!PvS^j#5SEiDpY}_9l#^nc_yF)0w1DmP zf(w}PI&KrSIWQScI_DS4{DCE)Nl2(sUm8Itg8r>CJ;E{(Zvl=X0d=4~^EMLt zfhDp_$%3_^j=iIfz0+gx2^lqoGPPkvl)_z{s(CJ15B(pg@1W}jhrfZGifbR zP%u2v2lqa-g7wX!K*`Txk8P`)VV=pm%J_vd-x|{>YtIEdrW2oz1EMb{zaD8@vsfWe zH(dByD)#h=>`%l6_fXpx#KZ_5+dx`V`%8ald9ft{FzfA**W z?eO?lQ@6uxYIDZSHF=YU?heY&rBVaH*7pTYuA|6pqO!SLE5$isN0zHxmqi3_gRJ!c zJ&!><`mc94J=3PqatzcTGvb|6S;P%Yt7etA?BQ7nh2i#dkqc^Gr4$J9!F$WgwmUk| zc?ii2(t4;GCqx7q((_BhA)F}W8#ThIx9`fI_aDC%*&{kd@vF8h938w`(rpf#?RNxA zmx2750D*V!wU{~+WsNk0mdK04*<`EH*kM0Xt$(RIWDHR+v3U_LRSZo9> z=7JZ%h8XDQas>+$Y=r=?00HTICglw&tis;1h34?O(t9zak`mt|RVUSbdQd5m1XsE2 z%M12$b6krc61lQhiqg&|9vn0r7YJdiGr{`nk>1t4=aB%p(21F2B^3h<$ih#`h72Yr z`BH357EH>o=Fd)?wAfG2P0PaR|M=?BA7f`^owFfyl4k5diWL{O2#i;Fx9L=CbvdD8 zIm-`s*bq-vENT}RpR(h3)zLUvDwmgO zwX$E!K&1sM>=4D_b`$n#fAbn;PwyQ%Mo(4X7A5-_Tmgh^FoM+-??C)&f?sLbz^t=Y zSnrRSj#xmL9RO>#Z|)Y~#u1=&wgRb8>xm zF!Bwh%LMj%yZ`aA@9h56?$O2^*rWTKhZXm5zi@N5m-kiu1XZ%2DqbDy@4z$un%30Z zP$zn;I*+AQgZAf2+^S-mqTK=u0IuhP=;phT6+Pr!VQ;{mC~;G`h|ZXr#GAl?P{f;! z*4VuBUI2^3jB23#FW?s?dmltb%{Yx_Cn(^`!GvsJ`ILwLg41T?UYQlx_BX&Oo{=Z$ zy_>8(d&sigw<=gM`nRm-Y}nP^%M+UpIQW*@cFwi&v)$bxc-$J?z?+tOaKgOWZuE82 zfMM%8|9TuNEdpeNVRM?+Eh;^`{_h5k?&H=@NQvi%;_K(Ex|sZxWM$lQ#e;*30h9!S ziANxrCe_mBitqJZOl91Oz5KBJ7#f9ZFVrhL`$@NWmy~RQ%n#_{hjfugr9Fm;DdZKi z{0`}0i7bS9&)2yH$ay$9G?Yt`yia#K@n_sb7rdBoWAe$gOL1))*|nxnGu{)Lmq{r!m6B*_s1*6dRc6kFqZwz^ z%aG6Ab9ef|;y!FNkm zq#cOJ{#AlSlQ5VZNf51=6`JpdFj z2tyFNvBo-Qi(&2VFVC8-FP|(mjE!Qyzo?VwHT)C>OSSEd5T-G<6du}!1{-@ZfBBan zXx?H-xm#zwSMbXlWT`sZB>8@Pj;zIYFb!(skgfH`CvP}*Q=n2+n4$>t zx^Bjy8`+jPnxBPq>u!s!zeq5*-{vJrKZga+y?`C=(i8^J;pl5>u3$+0qjz?p#4~6x z%P(KNaBGL{$n|*4)V#+c$A<=tyVfsPvQpY1zk>{8JI0jYOVnHIoIs)VrC#EWzNV~L zx)%DdBn-Q&ZT{d`H%88~v>Q78 z$j;kG-_NfNYc??ZSx& z)1_o92~|nkP`t|sOi%()%l+JQ0jjv#OzB|MFmWN}$$mBCpqaZ9Robb%M?DA{1E)c} zf{d}BRhc!~C$~%Euv#1FqHoXNpv)wM|0ihrvfHXmCC~5`-)fXVdyf6FZa!2!$TXtv zPfD*!7=gL|G7s=U@J_(KYIiCvvB{pN5&@hCbq^VwniR$ z))ux_PXF4h10aC^DJ>+V<4pS_#rv}`|0!)^>+I;EXK!a=>-=AmQL@uB)YCH(G4!%@ z<1`eMu}4&rpioCgW~nH}RI5}Vgzlc=OsZ`W86Mi&|MrZ3YKZ#JXV}^~(|TIi(>fWL zn*1M{L1O|#!~NX-!({=`{wd{bXRl{%;%Z|3FN2^ZWu|8)CT3_TC6E4T+fALK%#RSj zkK_E;2mR+;(ZtBk*4EC#+0levPtU^E!dXv`&fWv~-_%{8m~85w;| zPNXP%5OHPzLSY1~0)|Iv_zOb;3)O;&56S_Pgo&bL0YntdPiCWh79~&aBXwm@cFsd> zK|wdTGb4X4K01HqFCKn$c79AI7Ak+fyi9gZCce0L1&$-Z<%?!*ek9LlD|5x)4G|pt zL&2~gyJBQyq%=VQ00a;K0I>c|LC62L@yE0)H7UCTHiYhXwMkBO^RLa9a(VKSA(`W1dZZ?m#e(h>V#qs0`+1mpI2JKXF-x<0LA(cK!59!YrC zmBuwI$Q#NQ(8v0oT}`T5;)CPxDaYOM7N!NOJ#vHSU1QDK>l*p6E36Niqv0a+$(2Xn ztYVeXDSfHT$YAxxTtv&AYkiMUnQi&)u@*i7CDJjz!k1*aO2 z*G&cbAySdknm+j+x^^6_a&Po^iMm6Tp)J@VYVLy2+JD zJpe@yHwa)5SjpKYX?bb(1gwe)(bBCT4L%H0B!^>hTVYhlXjixcS(y^(dH|%M{|uk- z1wYv$Mk{%(I@sv%yPhghj0J1|(S;nD&_L^<*?R!F4n-I(BicqAWb8#fB=tPm@u|2> zIg5f6m(f8-@xzZ|a23FC)v+D=P2VE0&bM7nyg<0nUj!r)O=5tL5f3$iON04jY6 z9D*$%e#$y~Trz1Ic|h-BrOmY~IIiR<-JC-d9N?1h2#iSxuMn7m7-5Su|J*;0Zcs-( zb3YnQ$&^N7X~ges%U>qTQlSSs1!)8D3yU*KCuB!K$&NvL{Jwu6$a5^ zRn+&cfhi^Zx7xH{jpIFDn@HFnu&ZPAzh%?X4~`200!6&3%Qy%lI@pclunYLNuU-dQt}gdP7}B^D;Ag2$pTVtt3!xvkcgAAh*BsNzy-clkqh0M zNbiFYPr#7Bq$filAgoj7(Ic%|YV3&q*&B!}p!|g(h+HgoViCK7L40y%&bni}!V>4# zdeUESo|MNg(+0T{EDUMqKbJGj(sA`<>8T?Ghgo09 zj{PvI3LhzC2bgs}r{G}0az0${boSRJcFmv) ze7&?)K_AZWnF#_+A(b_^|JX*I$nk>F32SmkY2&l&HF^~juf!-ktmG$c4jUO)kN^t+fc<}sNJdqvQ+C)Y2zfewgR++-HWn87y;jhQFXlw@ln{VGDf1}h zw#I4%ZLoiuo`-zz-mXk{Hb_zvmDn8*A^{?hf5Ckq-j>?$4n_!pGBSV9`Gmyr&**u!q<+XKQZQ6dqXWd9k47dNH3NXv3_KOA_Er zU9WzRNRVh&5vnhD-UVGZ#^L0Sj$Zmw_bj=&h~DByqUO1stWI`t$Zid9`u#Ryaxu7c zu)6UypfJoCbtsjxx(L65&>2*(NhZcio{{Bzj&qA^TT@V)kQ@%6TOR$9N=Oxal5uit z@I9VF4PWC!BK*EQ%tO+p{F8mt%MVuvOO|@A{N3)^+iLBm0uNehz7*3G8z*yQ_4w#Sl4Bw#mDH*k zIY)!29Y?R+ZIN4{IUyWgafxr3NnouIaOCJ{chR3HmgjPQ$(e5l0f)QfLa~>^F#Zii z!uPPw(>!c0R8$KCPIuW+t3qfEGPc)arlR8el`41>Tyd30@g;u@#MuRxb0vo2io0d9 z%K`C+AvYihiT#~)wL&K7+X?1lhCF~T6Kur<>?CbtH_Z$8ENB9IUo}xU0)vV=8SQg# zR8-+5z+6NVs{CD{qDtDBfK7p-iAr1HP(?&mwV3FZ)QrLyS&-6t(1FC8r%nh(3-O}hF-BM@ z=4pUoVVAgChO8g|MY1NnY17{dd!N-wu#2-GcV2K+f+j{Bb}hj2Hd^ph2EWFVqCwOB z!->#;?F@~#>|XER^%qUWrKXEGfUQXYJ;ocOa4sYkaM@Qw`FB$ zLECDlzCG()u&1W0&c<{b*2&g%YAb-AMtNNskZ$B3dhkbfm;k&`Y&Ib34m8Lj-BQhP zgaqdB%|b$W9Yg29caqypQUjA#HdKM03kxyNe1M*_B;*u2a#IdF&-i-c;zN^t+hXin7dQMlpm*3dGYzsB!}2Za5g*N$2;mPoo!kuLZx2ta+*V>u~2w z@Yakb?pz;loQDlv&hWGtKy~b}V+mhhpzOtUJAqP6o44n$Jh;_(m{IR!w_w#^7j{U& zN(^oO1Cn)x0GMqg(;~y})#5L)$-5GCOXm z%$Sv7*L|qF#B_nEH;R^d_5reVuqxw1-;A2(0RO%YWIkAoXUp*@LOq$MZ1=x19P?ST zkiD~{V?+F?f8dT|ao=X@YNAO!P6)1OnHO8Bq=+d<4$&q)LAUGjVTnd|vmExtA!>B- zo<4@)T<5^Wn=&+e8`7Ixd!0BLeR8yW*q9b{tq$M#%O%2d$K5>cmFmQ}=gS@&$dZij zR2%OBdpSMQUF_N9(DY?H@CyIm!1b?G`Uk82H%0h&;Ig(b{J+tJ#oAmk`ycVRpM~?Y z{>d)>P4vI00&CB{urm`d3Ik9bFaml5Km-a{s6K3bcpjKITnt4s0Fp#;1_$Mv1ZBn$ zsV7HD`?tXbLF~{}fx> zD`hc9xhny6q=4u@dC3oSc?A>o&Tlj4=XaYFr%|{va{XNw6WV@L-^X( zbAW&{#vL4WV1ltq0JNB==|lPzl>{@OiQ!pbG@V$Mn2cL<;kT3ES$9cMr_3SK3?D0U z?(Wu^b`tB%+XJu~uPmJ|b~J4D5^a=?Nr}4gz&QP)>=`%|c?VJYE7l$9)!y5~!}gg_ z3!XbLjmGzr=~&Q4{dJte*)TC7eiSk$o3EiIqcTv_iWu0-LpII?7105xDM7}MM)+QM zC_)qAq0PO$Bg0JrNpUZ|K&9lt9fLEWr_8>cl1&w7RNM|j9L98pU$O6&>GN+!?cHZ@ zCr&!4*10O}=&T|VB7gyE^8`c*7a;;4q>+pv^tB@?EAb0BO7YVCvGT-bbzGaW&rF1W znX=FJpJPT$LX+{|gZoBzA4eh{$5E_tIhqL#v8^6JE5Bp3XZ!UwTnn0GR4dsE$!Z*f za^;E&fkqkQiz1BxT!}(x#bWdSCPVY-pTc*jm*b6!A(4 zB9ot<+Jc9J7;^#=U9T+O;!dW~S@{e&6_=VEkvu7G!DT$Y1V?6ka=DBF#-YR{SH+C| zR!$kukzBoWhw(*KJ-pLw|45Pte`8huMXE&x*S>-2Yiy5ki=ko5kj5>_=+x?CJj`Yk?KM;ttj?ZlnIVqsW#sSci?UA z+|hm2N(-hbS&aE?hr2L87REbIV_3j22;}^*lf;i^D-BORp&@QpcQ3*eusu{iKh`!2%k#Uwk&6I#L&ly1V_U zi`{zTEmZO4?&r9*M;7t#aCUD;3M&li#ECo+E+em2mB2BUfQ-Ov1dpJ@C2{-gi&6W-el>05e6&W8k!bTE@j;G_4Z(-)E zBSVq(_-FS$4b9=N$ElcY{`sl1hz7wQLb#Rb9j1XCQ6G!4#r9*dUFS44*QGvi`}<(R zDli8wVQwH_ia!Ft=i#L!@++!>qomN1c?7W4kcaiAe&f0raO zEVgi$6A{mA7fgS79Cv${ZM`!dnZ-7;S!?i(iKMv%u@OU3+ zA=LWZn5ITi`T4TgA+kA3`JU^h5NFyUO^n2*kD$JF=~7f}=!##b)skk4D0UTpKcuk+ z#yH{~){Ag*vb(MJm1Dc)_|@K?x(Kb#)|Jr|tXeztvVJwh==^(JbyLj?k%NEU$PJ0fHZv-(XM@)~3;FVXMgN~EK(I;R>Bvtt z?GqjV0PjEGxT%G;iJrNMwY`bsPem<7Z6oo348iAF4S`CD*o1pq1}`U5xj4~V2(Ob4 zH7b6p5(aAbN!sSBrxZJ$ADt^!*LbcpYe7b@mfK~Wz3@shRIf($&yuA|ROs#RUA+oT ztiBw!n-JcP>&tn;HXTIwY!7(8+c{SwTqmbWvG8AXoMK=1^yN$9H;b7>VM*bQZE0JVEmhTGGlJ}!A#Tpgsv0gb z#xp;hQu{^BOoX6z*BRY5#iN3qt`g0K5?d3hFeWAr>kzN4QO1S{MQJYu@+cFG4CYbn zaM``dKONimQ228pJ`rqeHnV;wgrG84e^+4@zJEi6+Hjg?lhPBX{c5%%#d!?{qc5x+ zBK9Nf=+d($I4q04yB9^eLJ>zPa-qL~Q33~am0!Mj#Bme+jfBcm);kyl)e-mZD03f@ z_xxICiu0@TBDey22I`SPJ3d7&fb3KT%~t|?IYTftU_zvwcuwC!6}#c32C{25k)L#M zX%LzRDoVqUaKb^|(+Zt9hvGEov#2(<-%*dJpg&#=RCop_5!i51rLsDv_SZDK>g_`A zM*vw7XZ+!${>?u=i+o+(e^-r6G5 znlR{?aAB9T!E3vxA!y-{n zs!=G#;=XS@+ovl+T0bR7?06L{6dgxlSS#aY^~b28WO@48!K&VZlA9T;6(xi%WO8oL zZ7ZMEK!FbZY%Xe%q`-G_>P1a|IA_EN?!DvSPs1P9zs`GnEWFx8dzaG4kE{`=kC8W# z9A1zH0Q5i~oNAL$f!F3;&wh=bo%!On2@AXEVi-|5T91*g2MVO$Bv z>uV=IE`8f4@g)duEJr4eDOFyjDf9jD50!M6`=3B8i@OnfXs;#3J@83#-*RY-=`N6a z<+>yas=RI$m1%HGTjCuAxJav|(E+fV0hDM(WH2jr*}cPFTEPI#9MT9j%^pg@yumpMYBvvO~dIQZrbXFJysTi-P{QFsFx1dWQP9$UK1y6PN(uxMlau7g>-49N0B?c(d>3t zL%MsL+PurcW$tPdT~i3=4%i^Y^VT?cJD3VPiIOxEzK~ziy_jL_8Ek)P{ylJMCHsK> z?-2N}nL%-`kk&PD0Dyp>h64WoX9zT^Qj@VG9zm?a^Nm1x>O%YN-jEwpOmie`h=3h6 zXvHN<XNT3Y@Ljy5r?nwgcHcD8UMGZwDmt~cxRo!-|c4$ZtMo@}#PalYbM9`wW z@5#!X+;~q2Zo$#Tx}~$UwN#_Kg!0v({6274BgSju2gis1V8nYO`XHwu{CK3T`dCbK zHCxlRK&XRIz~4?GnBXiCjC58HVPei>r@E^7!uQ4Xh#KWC`QaUy;yXTdgr!lKTSz%a zEmFbkE-Z2}8-+!BlcWgsJH%UgqI0Tr1}xHd2-|CWuo-@eu0;&~XB_I_Tpk`z<5zm{ zaQilY$4Rb(T%i8$o5b!K|IM!`?hQdkHnjS>+$I$?-kg`d+0eUQ!?;g$PU+0mI-Q}z zI^0;Bw0EGL;V~0r-K1gey<=k>(RP{dBz(SWUf&wj?3||c0DO2b2lJ$S z)DZHj1qP`069E>O#LvBA9Rr_l?pr-=jS(!R`Gpt-8U2p|xk}oQ>3{#D?BXAFeu? z%c_{Fi09B;9(2EuP&c~?qCJ1tj3IrdL#b2KbHkN>{q;GX6KV#VHiUGHn1SBy0;4)b z6t9P;H2p?8-7QrS6|)*TcHVsd3%$|LH#yr?0UiO~4*TO-%(+VbB>dUMf}jJNOw_$9 z3k7aZd>~UUrVioX?=LQ7cU}*Vo5YcZNVP2a6nr~Iz`oF`9GP`W;toF)_-Do$HgA6b^{onBGn_9AM!aq|4^2 zh1{|oxxYFttEV>5YlEv_!79D~g3@P#=NnWQ-QH_hLNfA@d6XTw;cf@)WfQFa9>X2{ zLBS?~RmcjNR$c0XlpgKE2!I6UB82zYMR=$=zQu0L8$2Z>nmz7Yo5Mw7C9ItJI{~cY z;bJrNZUo6z#f(EL%t}^9<(pn({uqoe%7b6E4ZIh)=|0H)(A{u83)N|z-dLFTm3h|F z{)0T8#gQL$*EpD&22it)O0k!h=vm=>>d=0Xp?__(Ob+)k(U}rt z5Ka8uQ!S>WBL9Zw-~$$@$M!B1j09xHK_#ViKh60zXpZ-;W}t5HL|Q0{I8sS~Oj%gH z*PuR^No(Mdr^G}IX(N2C<(192f-Tqu7 zaP@3f<4`x_x4aT&U|zRk(sw@>_{cXAd#z{6B6HsPFf8`YJ~x+E@fnpO{-|dZUPI~^ z8;>ctY+89spn(1D73A&L;SsEtonZqxi`H*tHK(dt(Rvu`@Zpj9C)`QzIMa*QNpKb& z@(ffoT`kB{A8IZ8N3T-m$ZXk?l=_d;oeJhR$-5fnx8LIV8YH0HGAh70R8odTu#wEP*D3=paS@G*Ok6jV7kS%L)Xqy|X1n*o>6iKKX^xTFI1DZZALN1^0LLUl6`Q+4Ir%)Q zH0f{iGTKpzHy=8u1)H{ew@1P_l@qE}V*s<|{KtmV{tgyfq{pByiQX|PR}H^Qk-1_o zv<~|!s~KRm=_$%cGr{B=%pIw~1x8aQHOsHYI`o(JK4;U--c~u+EGu!qKM(bj`{Jw2 zSrOcP=5~_{qNHxf*il8vBOYFiX*TTi=yG2nXga)rIAlp3I(yf)k>Q3F)k-Q!KD-6j zY*#Wg`$S^ahi9QlGwk~n_`O!&5M9qj=(2}Mb3qR=Gz4D*HV%Tf3;l|*6wm^aQNrvJ zG-l`1hVLD1Ci9Phf2zm*-X(Td?lxcR{jj1OWgDvv286HNpR%D~ z6|3tnNdpijjH$mC$$|sj&VBC7ZHP`Ja*0V-J2xaf$Hhf7dN?`PxeHqln`1V`F~C~i zmC@64>tjU>p3osQj9dB|1%PWWhuD*T#e!IqIc$D&cSSm>hWnv01?Egly@ZbS*_J%^w`En{KO+YJcx*upetRZaLrAphbpfiY2U6bV7 zmFXO636fnKxI=@Ndq~O|^EG1d)4>`{?VXx;*!-dsV&N@D0ca9|&vpa*okftHqC}*C zyJSKMvs`;Hcc*F(n^bVl>@Ul-fhDFi7d9V6o9+O*irt*CYz4ad7N6km>owYAtoe<9 zHXQf6Z;*(PT58i8w9I+gyfj4NM4vHMY8mO;tVQuY9(ShkYi2#K})qk{51eI$q>BC5E*L~$%^wZ!{3TNBHMGn zctBvTt{FOCPMzjw4!oSE1<(-cIySJ=)G8^)1i7`CH!34}@}RL|v&1 zVSS}IJ}oa!Oju526iCji>9E9CrCJJNlUOfP;{(lOI7wvZe;e^dWIr6FWE>VZW8`QB zeJ=6+&(w4wZH+wtXS^xm#|i&amHi)1XjG*zrFStx7 za}HuL+i#mBWB^h>2fzj*a9n+)%WXN1K?<6;DpQjQV9p;3nUnz6!b3v3d6(hBCtU7Of!5b?>g!W zC@^*7eyi5d(lPx9jti(@OMsAlc~A?ni6U+*yN{Z5qXWc29afuzXF(3Ew{zuz5GI`X zD0s9JK%2i-01FTruLDiGg#swKIb4%Zq^B*9`eJJJc+MZV>7eYSL%hwmTJ?i`R(TaT zbN`Bjwuk$aih&8Whs;rId-e}xG?~!^OW1CK;Z8`UNr+1kZOS^!c!{XBo(A)PKm905 z&HRMbzg-zcn%PhTKo5DP6B-6gv5$KMwnf|Z4CVql8%QYaiw7-pCRm>VyJO9P_)?3FJFvN6==sR`d z8XYQt4AgMk+-_H6VO)~7`V0Kroj17_ZLI~X{%&q^aK2)9v}IGrec4hq!P|3tu_yBx zn3n<<$h}X)jjxrYPuv9ueHKuE$dn| zFo!g;o!@9lZnm&u=k;B56WFJMI1m=Aj@X@D^-s1i!ADyh{JN6=!Z0g?m(a+AY?N-G zAmVWte7a73ztanl+0b4RCety~-uYbdq;bpudKTQqaI+w~*BxG7vjq*vv9a~J`JKz-T$6p z%AGMx33&tE;kS%#ZlPrR>;e4mll?DvIU#YLA^Cw9bWi{Qg8x7|&F!3=Z4GQp^qh%kk+1eYAtKj}pJ^l#F|du9 z*@oboh-Or7lim3npu{QpTxOiV6eQg*K-%}|0R41cCg|rxgkhKS!I$y5`;q4D$RU;6 z+|ootG<2G!U*9o?9Z_%{e8iydCn@k4vo^h$mLq&O95=9I`Hic%HzkWX6 z-cEd*Xv87F9%fPvXlp@2EjARQ2;DnbR{W(?hF7(#wG3T7sT>uMc;R@bVr8OHB-e@O zX=*>`nl;N1^COM7YuEm+!$nhx(OyX}&9PG5S$5 zgA4~Z znL>XM=rQ_Br*5*!oxfc7+3?~Op2lk)GvZ1W)$bfS_dSjMaSc%e7^!h$H~5e1VI(9z zpd!X$&mIqh^EK{mVV-o<&YRb#wmH>{<;$kzr;~&Gi`#$2+ z0HuR7kb-NUTS@6u-`zFB9V2IdLsRx%(v6ldFZX)8_Q^EMlL$fVegJ`4yNoSH#(y+I z>~SeYNh`OFPcJ~F?+kVVEi5~-3)mcTPEryDM~pbrY+YH2ju@p_@sO36w+3wPCQ5I| zkVa)UPs@YoocW%RZ4Fv=$kw|hYDkNjjbHD=B;4FpeP$f))rigYnlGL?G)6`+cp=$n zO+g3KT!KY7N3-D-D?D?b%Z}P;?O?ai-al<1r;wyJ0g-R%OmqpZFxGd*C=|Ww`#E?z zzg$vyR@-EEDTt0O!EExKTW@$Z%Q_UfwH=_zd4E%QW}ucIhEuDPV%=Y1vi4i06bfq< zt-{^d>I2`dA^PJD{6@>v^ zXk$bh)AjVb8y(??JOgaS?Yjn9lrWEz)|Aq0<96sb?Ej49_1$pVP(P8J{^y+ir}Ck_ zg{_&MlbgxUJo>*{C^^b~wi^sET^H04z#_%0cXV7Zfa?>>xM2X;vqESXxiY`jaU_xs zP2b-Y5_KlVessJ9{ZxFo=JqnZzH2gavXxw}Fz7X=IamOXdp)EHiNw?Y7J zOOLS!7THo>PW@@8SF3JZsho@6k;P*@=emw3VXO?LKzT}D?{Wmy8mL__e$=IWTBfD+ z>{A@uB=Plvlo>CV-i^GuxNOibSJ6~u3K7>?ersGja*4~sspo+kb3ge=b-_4JtQucZ zv9Ubg&0hhND4I3ppX=)8^+KV8ENui0*n&CrkRcX+bh&-GmxQM*H9Crap{NiSX;u-; zPXD1__ji#B7ACNz+`yF9IU3Q^VR~#XE$scBcB&PEL7iH?<4X874mPo%AWkYHNT;Ni z6p$OKx>sTFeWS*ezfQgDAvKPqPn4Lx*U}< z!VgkeU0TGe8E2TpEPM0uc6A!};$&8gc&$*PpRMRn5sE__TrzhxbA36UdiY*D|7`krXHlIRIXLn1-9)5^^lKVV_Eg%)9dFchKaVMO z-v7hrKAYecKTA0&| zPsm0Zd--CD>WZet*Pe0*H9n~}<g#!AkB!R|E1jDGZcNKk zWR!s$cmaA(88Tg_rla)0P_YvV%n+*E%YDJdp$k7U7xN*Uxx}@VYql>lTx?7Znrp&w zL;m1CT?}Q=epg)|@=5ohk^n+>Hx9U1dDI@8guO2N8`?&P_`NgEhq|&ye=LF24)$8L zP~G!*CZvPB4@aK;Ao;t^Hrx_ya1u?_{ZLW#p)b^`nrtO=Q$tx|;8- z&U*5s*fhi|F;$^OCZ-@bQS%N^IHInxeHocxMN%1?vv=k;+IE{#lVF`hcx z^WL4tXfg@I7$=|3WSVPGdNY+w(x8Um3C`V9%eEeFZ#*79Him{Z0v3ma6A{T}nEFR+ zf4D^m3@>@#_(Zn#hs!)$5AE9}+lyM;XnY%-V1!yz#GUT~kVk!WDPX`SSR}^l zjAPYJx*q)utCrh9rTUGGAiH_-b|g7i?Q-rS^nst;t8OEkf`EfLSu{?yRGHWKoQt!_ z(~vaPoYXdm%ry6OPeqIQNaG(e6x7Vv-M02^~|8ral>Abh(q#T=Q?6*xc)l7-YfO`oE%c@Pu@T$ydIJp48Z6eTq{>Cdekc;jW zbG)tf>#RfTt6>5r1plu$W<~TLjWQpGb*pOrmeT2)NL! z^dM{n+TDkvKZQd$VhSKaIO%|mh}$4z=UtRYf^vpO`HIZuqwB|Y=~m43=l8$8!cxSP znfUy3)}?;_qT)Y6hLee-tA)}3&i$vCv8TdqK+~|AWr{Q6JM$&$-WH9$OGM5Q${(&gN18 z2ImgEN#Np_FP&z=JIjP%Xw-pK5!l89kj2uCmP;2eBDDI_2oPR;yHR3ek(3VZEOJ;n zfqf>uVU#x`f`bjQjn0dulOoqXIxv6rc zw{R-I0EpkCkrOo$$T_09JZEUmC59Ev^z{zCUtF_jdOMWdW$QO@q;~rd(ienId@rsl z;6{W;OC26ED;tJqOo(|Mg#E@qe0e$h-swxo1Zk#(o`KNoQKa0plAhie0VnkI2R<=zG_{4kWJ* zE>JK$kb|EOW1s@Iwu|ZVeQ#;>s z#C8&oM{Tr<5}i{8w|UXT$CiC@Aq%?)--FhLZI({s3=d-x)Ttpo?-1O}9a3HA;}$vq zY$LX$rnH3l7N(zR&!^|Iv+H_wouJp|=W~&AF6~+0Y8g8D;ExC7BM<*eO2X5&v|WHN zxgJ6zc)V{5^Xo|l8mc;r+)Ht&rB{p)w$qxwg@#4Uz2u3^BTfr>T8RCI@fyh>UhI(5 zPkY~xQ!{x(^;}K*NvhE@-=W#PC6HV$I?kD3rCOoP{xIJz@{l9yDjN-6IMTw$izsAo zBYU6j7S>n%|K4W)-XBoR8JCBDh5;`=y8{1efAFU{<1v4Jdat`DQDz4g@q>U*&IO;LtnnYGt(9)_7uKG zq|PjtK^C-ZES#GxE>hw0N>4vV$ZJceE}ePgZ!G(wP?d@>b9hGgm=fGk+h9PQRz}o5{F87cT z4LKaTbj*(Wl&M+1mbWqEz~ekDb2+N#(puB77FT=1GE9wJs*1CiZk`LTs?zkOC!etr zkGJmVSjAY5_NK-IR4}n6$XR~};QQdyPYqm;!vNGNAL=}yZ3XbQz{TUHHHe=7T z;~c!nzh%KeI8&u%@RXXyt8JkvL$Bf7P=?rEH9lixeNdG(@rMp}jmonWD~6t>*G5Hc zsB?9Rs$bj|Lyh*m`10$L0}}tTOC+>QFMfsVXs6#`#mc6_H)U0-5F^qsAgW`_9Z9yi z0Rd>&);B#IQcs6c^r=Dr)LM)<+?r+kCt5BsaR*$lBo`;kh?njMIo@mMJ+BEZ&qT~G zwX5|Hp2DXeXdd@_eg^2j%=_r@NeSb)M20-KV~&$u1UNHzb8Mkai#W)tLX%Y`-eWi- zaO5dx!YzqnUbrs4z)JB-z2uDWrQYP9t$`wOg5KKl+cxX6_uCGsbzBm_-(uaUQ{SWG zPhaQB?`tVW$sBWTUq3yp7hTt`@ag|5Xn!*Zq20T87UG|iB7R5Ix#V{7-FCC*+Z7u-Hrpl>46#1B9`O}BR^bTk zNT>DooVvf@X0VYavy6w99*dmhBE=+;52%M^MuS0CsogTgSQJezTZ+Xu%pZB{JJg4V z2Vkt7=AfWXsmkPsT;;Iy-Z(j^qR~pWm5~P>aY_m18S)&3g2NL)Np*=T2i6`L)px@3 zt?OJ+Hq4J5sU(W0!Sd??6Q=|QQ{L_g0;&@IuH09fDfs(V6%!n&2f8wLl(O?G=6ow zxmtqyBJ7?Ll=BaCXEm=X&-Xp703#!v_pWMdgY zThQPpRW!d^IKfHR!J=vmzmQuKQFsv5;x0qxT>0Jj7_bl(mY(EP2(4FtAu$+;%_~VG zo8;8TpNAplSvu+4;DgwXCRf9idp`=bMHy3TxR;qwg}*RHd${oO$XRSy!K$?J`9AJw z)OBBd{Wu<9nI{T|ZwdwlHNCf7P~Y>l9;ArV0am8Jb%3sx7I9iadHfx z7f~s(XiMq2WVGy|%+zNh1irnQx3KIlv@Ys8{}@7jkwV)${GU#0Z$A z&8p!bWK6Up_jPP=j$XhEJWtQ()`% zt%fmOhG`snOe1z4_y~xUg>4*|?5pAg30cNuD(3-@95L>s*OIeMf)SX!!^}cBB)^=p zq(#3Y(4EDz68)627o27US0pRF_QtYML5&F{dxMZy=qzNU&lsW9_+f+H8|w@zo8l6q zC>eOKCcl00Hyrn3(c(=KUv-#!z9}wr4HqSDqyfRY9LNx8n#>L7`9wX2su4x@DPj`p zX8vxk&Ja5k+!C9%&^pqoB^0yQ#=h!};&-Di9k{+N>)n=Uw*zgb%sYTly>X6m0TEcm zJ}LH}z!k;~j%@i02_*9dnvh8$94d1Mo77ZU{%)u98v!ihR1wlHRyDbvv|93MzUZ3{ zuThsWCT<(TxE33)LBT8c4f%$q^HtlNa}iq4VQEL*GJ$#f)X|{V=`RC@@sWtq=kNze zWSr_2kq1&~6AxH`@T^8mOh2{a=-OFL$Pv7RNF7>rA7agGfH@~N6}wzGU+H@~P;pGH zgR6m+S&1LEayk6GQHkGiUYBK4Xn=dqvvEBG1uHqUkX_*OS~%8iVnH1mT2;@-{Nm)) z!^pMU#3VNh2?`9H?%%O!LTxCRO*7=G$NYl8=qRc$=(yU**o0xOkVKj%HHB!=<~bN6 z!$7NGp+}aUHoGWdKv^34dp<@s%-)|PhuCcT(Z}(;ubs^dW(VMRJ>1cH*mJ+$alvo* zgSs=bDnpxQhj)Kf;Qunqg=LvyJnXiY9vwaBsuR}SX9chgA`7)bIX#wa+|>Sjv;Pq4 zn;(%=JEa3VfP$P;z+dg$^2B2En6v4%4-8@i%8^ARa*G<4TLwapy6&-bby~6uz?EOU z&okOYxW5qXx=(_*Z_9QrI%brjjzm~pgbMfr%AIYmwRVh^UL-anV_zUnnDPzuKX-iR zJ08Xb{z4H1OCN0N`)#o(k78SQoBG^JZ|HcLWfu43Rs zv@}4W_(e%cviT${ST8FCXE&TKI^Ix{J z553UU{O})J_jykmPu?M4`2=?N)de8xm{&l5hAXuij2dkQ&V^cnx>7Mz56Gbg+YMem zX~DihQM+7KR*``P%=Bq;_RCESF3mexK0Ln0-t19C0w-4ZVnn}iWsnW(Z(il4;$TKj zP_x6l8OFucXq%|48VRxtC0tos$LHQN0er-f3uyC?0BG174Nidtb;vsK)f=b<6k^vt z8bH;z-<-Q`%(KEI4J*Ec6a=SFi4y_N!s`z>fZ|<(GE@#YBoBB1RY6ZUgLiVJoy=5$ zVbtwojr!r6F98;^mMh*c%B6W^MGP7{BUEVu$DT0=uI->-Z5K&~4ojoAIP^fFBFKF%=BKDZRc6=&HVlis@}7&lSC(P+1sCILRkun_IC-$-%aS z^U7V!&D;$xEa^;DaNrnRLM5j%V#&erq+$dt5X7-a1d9MBZC|8e5lk4t8$b|wof=u} zvZM&fGSN#*bw+MFMGyVHRCg4@SRg9R_|&dFh+faOP7_a_F3IF{Brrs0|J#EpF}8V`H|y~>2lolBNDtrK`FXO(_^e2S>G??F!WKP2kwZHBm7?ko2pIc z8?5%oTIi2WRwBd3<@_t*5@Hw%vH%)K^N4$Jf1VOlWpiGTdZ7yB#H)ayw1&Db?AA#? zREXRKTbey!EOOd3y_EDg<$T%X5h&EIAh?1fxCC5#D{a}59UAtJ*GvPB&msW z&peuUgi}0omgo`=M049Bb!e0s5>-h#qC^wC0bJAGYhsxt4O|qEFP0fh6%9c2u%WHA zejyZnwq8S=N5XjZUP-soP8Sc7YjTPLL0o9wj_wb!_1tp!iUqsnJZTk0og$7de^2A& zH=RDnOTZwJV}}aya@!3UT`x34!_lF=#e=pO+9BG9891MzQubz8briW8i)YYW?b!Sd zI}|OXLjO~|^#;3gq|k520#qFPkV4J4SF=ON(1x)hX?*kRlJU}KvUl{J^x z-hB0g(`>3di(|g2f4O_my417lZe8w_o;{{m_R5_QznQV|(XO>>Nlq&9JevDHPH(cm zACs9nicST?YMG8%yS0*S)SFrFoFum=L0$9F)NjkkHYOIL$mtryAf0^In8Y5X7=N8c zwoOH5H?#;+NrHFFzBe+;LBH)3rIT^HP3ggF76z{U)z7o#5MlrO1EQ2Zr^**t+-F#J zm}GsBbIA9!9ewR4Oj?nb!lf`*~WXAr=yF;&t!2r#rwH8+g59COE=r*YzkHm3*lkg;8<*IV_v&aS2acr7gV)3Uv;w79NvT5 zY?dZalgboaexMX<+o1ceIJU!(*$ZITnUH+L<9f_yyHZTjqNL46guZn8K>&l(2I_`z zqPX%BkAPK(ZJ34Py7AoYG&AAuarL^zHAQaA8qBF(eLZ|{M@KoSLuf?d zbU$9*0F-PvyR2_w=pv1}c zWEe$Z8wz)RXI_GQz=M9VfZobYIRY0YL}dY0)JU{jI!MCuO1c~8IaAg%-Eqd2y_F_g zo^ZPexOw+9Duuq$#jn@*q~kEO!<~JC* zCyihUlrbd$G~%a$W4_&|u&Al|$TD*AEfS4#OdBTRjEqzwLw_j7mI>?6ZmzndYPCwu zCk=iWMlZZhIORC__1F+nS|3GnE;g`dvPt?Cw=2kG2bM7SGh72RUS%?Kdg{8qOs>O*Nne(zsz*umvc0Y_&H{qdcvCowP>>(?eGgiC1q=aUdl^`>t+r%__5uB{g5Yx5HB4e?C zGHGS;;ZpmegtIi`h#yZhIIpWB*LU+LpoE5J(W$`}qGN5uGS+c@f|(AfL1ov;{c`jh zi_nvCAMu?vwF4qjVF((X(X=Y)LP1kIv7^n57*1W0%DuinAe47 z7==jV8yon*(hZTrX-v_=T(@1_dDd^sr}`h5KqS1)P3lbW+mt*I#BQ_CUa|fAu}Jbs z&k#$z`(M_~@H-pzUlOH}Sa_70iH@Smi94sbF0{_TGc(M6_j-YEH#Yie8||vMzpn&^ zgQ|9!(WGrUo3%}S&=>B$4{e>PscLg{3kY$}>vC0PElygMV9ws9do=rQ-)~!HSI65P z)Rx+<)JD>pEo+)1ye>LEN%NH6xrJJB!+!lxjBV4SGsOV~RtZVM4E|BC=48V+d-t7z z?DY@FnBT!T2pILz!OyK($LAdJ*;f8Pbie;k<_P0vwSU&=75mam-pFUIf+ZBJ0kBq( zwH%@aU}Ffz;j=p^5u^KVyNJv!g7^k3Fy#PNc9c$Dgiuzuis=VW@2^gbFVw)MLfP0KC93Zs5?quPB1l$;&C*p1c z%y@|0N#3zR9CJ^1U8fH0R?a1;<{w_|_?hQXKHh`hV#;jaoKj7Z(qbiMi1AFO_N`** z*asAKGPbh#2gMRZ;7JtZU_=%w7P-8EmLJwq z_@y?{>+#qmkLJtA}^-`FF=xa(g|K@SXBcIBO)X*Qqs$mb}yDJw~xUlk+5E%V&#sgJSxUN zix)!Wh7Y8CA|)22q5a2MXhN|fkY+%#vkDiSUf+gkFu1-{y##Eigl0%S0&ioiKX+p> zKp%gPf@DS284sGw9>%spZL+=@Axn`JdVqm#WSQDk2=kuP=D;EG-C>2}X=*@wGGx-g z{k~z(cEP67x%niI&j$2CFq`JXoR{=7Ggs+ z$$Z>q$Vg|1)q$f*bfe+|JxA5I*JvZdAsZ!vtXKeok4E?_b|K5rp7OxNV4^cw2KW4g zPgQ`6R5{I(*`w!sHPV|)sRa&XV0k=fP%h~5+VU@XBb7X?v*o_bG4CNEEY$v1Ci!kC z94&+o!4UMBAa=-2%YsIyJONa;F3KybI!2-1Qp?S$tlY&+Ltxh3X`yga?$q-{NE8E= z(8NpwvwUuG&@O&cgLdaFvTH*NR<9shvxJraxw5P6TP$9t2=^SUJ;R-i} zP|h82M+j#-!dWUd{|)H;Q1`G0@#j{j%w%UuExcuA*s52QHIkFk;g0WIUuN$RooC%-OovF!XTOZz=2|NEs#mDO$H~oM zpLxh7uk^WS;0C>ZPaNhQ-5JV|tsa`EBOt4!!Zvxj z_N(LL_qIEt;=$P%6=0L9x#PhaCE&I1ZL9G9ok+1(LLrOuM?b>7GUyCtcN{t$GUJaF z8_QqB~?)=_~^DoaCEY0YR?+D*3M4Xm_iRe^296(O*1 zTPW(o!K`23T)fQ@=gg}To<3{2F%{_#%^h*L3is{Da7)oWBn1{Bb37Fn9jsr}Eo=4L z{C{l&ug7iD>tr7OVA|quhWe;)uKl!wYV%L>DlT_(ZPRC-|6$`l0KimD$@J&&;RdODxm+*ES2$R0WoiH zGd(j&?=C$-Q%LYRkpJQrd4~y{{#3ZS_@w#G^K-P}pAYfp^XI6gZ%?XZsIg zQu#-Q16#-)}aKKs_&7j0eFYkQ4>y7UeA{8yF=r5&8B;DGDWl z3Kb{eR+;H`;dVbjij$KQ6@^Jk3M#Vt?tYP3nn^10F5%YcK40o?kmn{!IxxVqy=`xQ zQYk8u`Sx~iAJrOl3HBalsr?UW_us2_+5AI$0G|{258z)Y$y(+W0-{JKQRa0TOXyY8hY{7>G6+ z0k;qeDBUUM6(60s&k?tl2Y6&=73G;h?LhxoE9OYApXBHTE4)>~(<&i`5Em0OK0heq3>m71eu z1PUffxeR-hY;C_=o&JT5N8*~8TEWwfe9+u7TNmf{3b}}xMJ#jptzOKa_-a6?eBKjR z@1c{k>x%4QVO4`?*>vt+EZ{<+zW9rTj3emP`;$8BM%2q<<+-@VcR^~8Z$54oIOw{<(oI{;sgw>K>+r7JD3ewNneIV=Xo<5;}-~CqkT;#GOHSg4gYIS)4WVVTB;7KTo|e2Q0|+<^3DBqUL`U_ms0VDs82{An3` zZfwU5MIPcztPGx5sJJP_S7_l}6EgD|z4_Jr*No9O_NpKRI)t1ehi(ghX(VgHqy#Hq zEk$Nk%4RrKDCGgP6%Zs$Y#C9b_x)*-IZN?}pJ403BlM&`3F8rl&+|kp;tF z`>QG?b4nf%`YP)_QX6_ntLO*G86NZy0Mup=w%ksCsfu=>yPQ2eGdrt{S+!Lndr>le z$%&#omc#lc){?;#fGg*yLIx4K3?ViWp8NNM&BmBQ|l)rK4$1bS1fU zRU!3F2K=G&j00#5!`&E0mjlqcxRPJD-5u+|iDCbHZGXc#c)?!Nw$Ld`2*G(J)rD%>bh`b6`V=&+`XJU7hMR(^vx}CJ%r1zN76N~K@GB2s>>B@nua3VbT#>|jQ~we~EZom!8 zx>Ue{bJhnW5?LKg2|9m@Iq50cU2FtifEoj@$`CQOpQP@5*phq-5eMqD=wezmG5e14 znr>_P+f}SFzH^QB2I2KAj>POi&WNVCr=}_C(M@E@9U&HhMNRHu7X{X<1E`CGzHncC zYmny8q3aeTlV%>*z1-}=T30$8IetEvSU0gvm^NgV`LeSyC~!^dl5e_6kI9G;osu(& zyqrwUD2U909AnWI?H%nPhH_y|GB`uuF|iTJU%4QXw~dv%(`=4~ZwZZ`uWCFn_+sEj zU8g~QZ=eqtOm=8Ou~jMFIWy=Ccpd^wCOxR9h_$4Fi?)f*2^;`J9o2L3*1^c3A|4E^XrumBO8tvlQ1QFV4eye& zRD>PGuxYnZI|*FD<~}i>ZU>jL@pNPveM;3OtA(`CnBVms@DvUS3>H)q(yHj3aGnQlB^OvQ+@D$kU<4VHpyH$)(K1CkRz^hsDODo$LNp;kS>SS z4 zuXOk-pe>%y4)MZ>oNF*laH0&Q-FeX=oJSXM0)apcqE#Jai*(YsPP80Lw}%#ByCUEQ z7u2HVR!(c|(u|8*AGbU&=AtmO5JDV;>lWLwJ=;D}M6e10hw23nroC_-?!_=m#GCYK zR+EU3Rfim1$mIXL68G|UDQ@go57>T~)^6?6-nTbT|1P*0281&-WAgf7X1LLBxtrXj zlu&MK7JXKenZ}iQPNul++C2_=ot-8_;;!ed&8!L)uWq|bz=Vk}McX(g*>B8@C$6P& zNzkgf5=*q2bXXO;;k48gj3eT)*VVa%uVjz2rvIfzL80x(6*<#-a#ya%i|7xm3?XY* zQjw&*oxAqrARa;9xk%D&)%3~2U}Lzp7~<+=JjcS_p(Ps*sittIe)0zRcVrk;vn4XN zP~@?y>;Vw&c&7Vo=q;g-NN{x&Zc`RZnqbvXy2)Z6sM>Aw2}y~{ltd=4I>)W;WBWt^ zTjK*nho;eSJaD>ifeINE8g$>}M&*!E^Q(2s#6*CQ`4zN+2_WCGs)moAF@n8)jHA$n z_{OF%aFmYnx_HPL&S8n9h85b5?c;L{H6VneGrNHzWovgr0)ZytFR7jQEF`eM+DnJ| zJ|DsQfG2>@j5|oR)28a!`dd+fng|(!tV&^rpa>_aQzSW`AOS|r8924~03ZY>Qg|4e zLjrWt`wET%#r%|K@PwMNj1ug&ggk=Ao9{E^T}l*9d@GQ)EyF0A>Tor4jO%|0geAzY zs$(F)BOiBA4DCTS_)-S_^W85(qT8J|EK=NVY_Wt%4H(o^--fz_r)k5gEFWfr_;|t9 zx(?Zpr;A0z@}$`L+q!(QPw*(gg{A~mR&rC=B$gl#InTn4*po>6{JagQM<4g}`UIA4 zBsGye5BCY}xyUKucY)bnB4rDq+Io9#qiuKikWh3i6D1lBFvoceAlT}wH3?0=*ar`M zVY+(!otfNd5|h$0Pl>QeW*bF;6|o$#RbAH9yiNYDXu_X5t1r&iWfP(u4LW%pEA_00 zlr5%PVQN5dWoWx{QQR;_NoDl~I7-;TGJyg{5{7VW-1gZ&-G1Vvuasm*Eg9}LK^nTd z59)$HcQm+bAI+|?Ps*Ba*PUr;eDJF2A?%*?O`^KEOx!V_NHxWdDgw2Rk~LHN4XUrt zqgJzz#@?dEJc`J)yl2~v-^L6Zfccv1zv^SNo;E1ge)%w0$$b|SxsAC6#^?B{$qSsP8ZPrZsxQ7><9U6_sd2}!wnL^h&=X)w<;1w<%~kA1rCu@^`4~yq9vcF zm)37;ZRkZrt9(K?o#k#a=}JdBNNkA)sjw?j{_d#g`1FJy%yLlXFm;cF>0!}!oRjJ) zgjd&faw&ugFOA(^lsCrm)?Kj5h$7|;eHA52-+)=Z`Si*C%*iZ$IQY{y`5gRzonk+i zYJfiho`1d~;4vMq#N_j1L7&g3ne*q5|HYZ<&)(-U;Q#uJ`ac?WOz8b=9^0Q~7R z^hd=E>0cxITQ2)sF8f<9`&%yi|FB$E-xcXF{n;FJc{B%D}%?Vao^^>)PdQI?c9` z3o_WhlU!NnJ!XpL*yLkiL$7Jfu2Vth%Dov_47wZCkN$$jC6oQRT4Qvx3OCv^=@VeL zf6xHARK!SYD>q_Tq)ncYy7_gW-@SqT`Fj6i|52-dO_Lf*UaQm)#d$W!0)ymrP`Yz~ z>zBt)Z(BpSs4OhnAB-}PCVeCRK#kdP1I7&xc{r7Y;47YxGtu;f*$DZG8~yAgtTr>GxjN5c zx-Og}70grQ@r`;kpzhgq97_b*VTRE(Mz$LjnpStd;Q#V7^;s(tc4~N~NMPL!? zp5sD8BTshz721W%yS-N;sFqZr+;oA_`$zT3~+c?skH zD3r0&TM^%3DfE!%G!{(!WOr#U-%^xsJG20iNDk!+XjaWNsWn-agR!>rV1STrOSX^-lJXf9jB)6Ijr!&Gq z&z9n?aNO+nN2_73ZS;9);1wY;Yt5G>6Qx za)@~mCIrAzxTGtehZeE!Xq;X`@D1kl>J8ETDUf*fPo(=4ORZF7xp75;JPY6jaWW16@{KqIWPGTpWHS|8Vg|IDve2 z%c%N)7-c|m`sL$(0WVB!c7Ff8=ovnD_%v7DUCjOz8J+B_=mpzZK%6C-qtDnA7T?Zs)L0gK-klO%vGmLW+Yj#@PU1@dS*I+HtVKv1h)b=UZa6QmFy zUT(1QJ!cmP>m@=3Zev#=&9f8}&P^F<6K^Ez61@m{&vqhl!!lypgphmNa%S627W=*- zBoZZ@H2E>g7A^DYxhGYOgZlAd>TrCWIUBNv@7z{e zX`~d~Z=y`*A4Hk?Cs8K(PofMUaeTAJ-i`hK-$WT)e$PLNGJ5L+%24DPj=e~{*p*+1 zo|lsJ0tZTSz)xam2ygb}hDIu(CL_1mh?Bz9!E z|BEQ=jQu3aIIVPo$Wr%y6J?CefMk?rowc~Plr+AC?Katyqo^}lrgVg@n(HdqR)f3p zh~Vi}r(KnJH)HZRQ{|jrc+4Y4*;R$R&#lX8FDNVVxgI@QOrGvMbMxZu7)8QWs?NnN zdd6m*Micw7`A$YXaX|3_C7;R4Dn0W%6slEIEA0IK1P}aCDEs%R?GGT--zwSPD%t-T zl`PJhr6~2YLek+gwEyq({~umF?4dAvpVkI>2PB|ooI}PG5t)8+h&*nJOHuQpY7EtBP1FR4`nyFl=fUDJ; z{X%5d*MB9i!9plr!TJP+c}ph4NL+{RP&`y2NJeY+F;f6q1Enmp1{Bg3yFQGvwypw# z7Wc{^Is=z!llB4Rf&IfbR22MXCZVV=8L85RX?um>9l~lK-#yVG`&x~Xq_!W$Wz#T` zt;X3}*?PCEasPstEREL*BF6l~f>ItY zjuc;;4@o*DkV=tM>q9NrX>!QppR&kKV4MT~cAwbu+?HHiX3j0BBd+m?vUwjB3>sNY^55{Wa53`w~*yY8879RGWl(jq;?( z5{2(mh3}Veno<@-*2Pj07TW>fuMlC4Q^6H}CDATk9NE)ex90NV^1VOLZf|`pW?q&` ziB&pMy$$B2Gd0?N2(pOA^lY`PK3s&u))H3efp^=?i+xAQ&94#~7uGcADzFSO&PhRkC{b0rsEK%Rd5Szb}{l z9rODe9s3&{`+tXymDf(>;eIX+PM^iGzc0J}tGCLySXuiEvLZrGW9Ei!VoA#!Q8=9x zq222)r(3IDiAFxiI?2EY-{I+lNqZJkkC6c-|H8V?KfP$S77HO>x`CJ+lE9= z=53uGPUJ`V!4I~VcKm@mhZ7&US`Qha1$63*I15^g1 z4q{1s4I%@n7?=b8v0)4=)@z^>lnTyou-CsDM98_Llbd-dN~~ z!QLH5+3hxAex`n^J!h_{tUXp|CyA%)%Oa)YDvvUvb8%<2Xh(z%v;1cPEo<7HT$1J> zBGLA~xKq%A(leIlQ=hw1dqZDeCE7715mXcm?HH; zxn5JR>2kuRFw5rBxkqV-7RFm=I%^o^11c4PzG&ha7G;G~9WMDy$kh#P=xB3aSssO; z_m|4hR_a3PO5ssm(*p$Yd=zi@KFosTZY2n3blYsUc{Tt&Nz5DTPc~;N)h|nE(|AS( zu*4&%o*K<0#Wh>Wi_I2_EmP3sr=f1+MEJiNwQr@etgu2&il5IPiMj31cX09Od@cNC zz1Go%^<|CRTE}V>s~x^^95X~dx8y1-vWz3DVE1W8cHSAQfbO)IYc0cQO%q94PM0RG zhv*1b-o0RW^YY5xEv*t4`1W$)!BlF)YpdO5>%kAXOmV3(QRS$9y|G)nEqoFW2!hi3 zUI9c*8-#Z6Zl9=41rVJPMTktD2{p3FEvz0$gZyzTcdmEwV-bID23yG$j`!Q=jWqV3 zirB;S#_>njgIW z>-GqJaY-v#nGhfB*Pnx2Z~UVd(p4&_Qk7q-Sw0*pHj}?1)g*a74Sp>$ygH~T4$r2o z--z^f8SZWAIKoQptcxAluo@n&>kOKU%3Xp)m!;J#+1*>MS8Nw8vyz|YWjh_rQMQ$(&as#L&L$sr3N|2_BKmBkB-X$W`jeV` zIelGIMMVw8As^8-+yvZnD2mQT>Im07_ze+to@E*)A2@xy_zMWcDN)7~t}9ErU50qs zS%DPn{QHKbWN13gbWCB62D{4+Gi{+{g2uiMepo`kPye81vf20!&29r6M~Bu0J$$a1 zd@oMgnsr>UIdGm{?)qxbO?A?94g9+kK4I>~kDQfzw)>K;o0g}|Wk!irE4|%yHz^A^ zy=oQ>_7ws=<(LSU>iY>~wSKi*G6tqO-(YQ>XhS8z=B<{OP6yHz-nqpxudOaM`r{0KgHTgU=#R;CwV zS}n9dAtD8ZlJHAn@bHY#Hb)`b09B^%Y7XGPc1*TuKHEB{n7eJ4OIr8cwl8g+FF*dk zy8f;@_@f>6?-k)s_Rrs5*xz2*-(J}N&%Ll`J8~hP&j4M?rx*6`<^NCf#AkB&ObJE& zw-Hv?NMj%h8k2-6jfkX+7Gr8jRU%|)n~Xx(hyy5IQqr(IsvW> z!Yvw9xeXPqVt`c>1Kl<`1WV3_E;`Zl7yn&j2Z7|0@)E}^uX*R;OT_UB#hNtvj3LqW z`ud=Z^pB#;6W_h!Mpmo9vhx;a?zNjHDe+n5Tj9M$G$qt~PrZ|tX8e!|%6XVryh1xr zh<7n;Fd^p<4g{lI!u*Rn^IT*+5}39P%J3iW33E!$mQ5hm&Vo1+YqUVAz?2V@La9S} zS?8P-2xP@Fi+Kb{_z3Lap%T9kK$i0$KsQk1yFg3~0o@HN`_1QnkeNWJLX=}_NTZ_S)7E4Y2Mmi_JXWj&WwIJPu(y%j0$Wnu@IXK$@mH3Q&;)8XYwnlTWK*(sg7~ znu!r)VsRdzdjt-H>tb${}zGtMXsE> zDHi<9Dx}BGa;idna``RGYN}jxi?y~N`u;mK5NLTV_r2FCmYn-#`n`oItukEq1d-Tq zKq)UfztM9WWliaZuK=_KH7-&e4bJd^HtV|?fig;yG(NgSb$HhsTab=n4QhF3dp z8{!?Y9@MIx((`5P3+4_t7oerjIQ8sbpEpbHZ&&%%-xcI~8|#jq zg{T1h2e-4%$BUMWElYQ8?U=r8>u9VdjLUl2&v@+VDO=KbhT%lxO@o72hL|SW59%@M zg(T2@BA-SvK|QnQs(O*i8A)(dFnvmT!q&1iZh8v;&MZ30UP+tqqy4Kc3ZtYOO;r;1 zkfemJdG7&D7%DaNykOiyBJ+(!>tcM*j&I9~7Mbm(-6Ro8JN!1_RFyvdbhjIp{pE8d z*{(aCwEQD3D#`VfW00Eh=0(8J0Q5|)hEh|R!3i)-B#mCWYuG3^r z)Y?bkfW<1Y#>h{V&`R~^7lVM9y}bV^gSqF9yrE8P8G12a(co&j7a2sNvZ$nM53zgk ztM=tbW)0?B?xT(hEB-8IydSUGA9f#GT{VHnm*a&(;FktS0!_#KV!4ttgSi|l8Iws0 zCzVRWDJbHcF_x=Tj$3^kzc4Z4&l|5CN3^>5Kr&L|_+a|DydS2`o#bP4VN8h`Y*B7Ns9 z&c@XDU<&ULGYguFamgUj2a^mxVcZw|mmsR9zaN~XQ6bQpKnSGaY<_#JOIsK082r0U zZymYg5o@27s0I!sI znE$K2^Nwm_Yu7j+MS2yf(vjXl5S5Pf4g%794N(Frpb!u#N|Rni2<;$6k*a_cX#&zj zKoIF50@BL?{U&;H2#I>my?@+w*ZSP9tbrx(lV^4&^UloP`}eZvP%R(Z`>J-Gyrd&` zPWg#&n^O}B{fl>1wEE$-s}9jxgvU1`BX36C3KlM)6PI!YN9Tf?-}TJyC}grsnr=WM zYT3)pXMrWiejitc_jwj_K#Y%f;)17|ET*@Pt+1uNN-j~>dZa5iGah(j>`~Im&H{gw zWrfIKFvOS=GT`Vp4D2@y?7tZX)-JfoCki}Nj{sm`05$sCgLUNZhi#707ytmHy1=_z zuSID}C+hB;Xsy;2#du#nx1XCa>FEn1vhYzYH4)kw9JG^#pDE0)wExBb znqyGa>U&S#dRA)WL78Ly`ch@ZR}-g$D?4u^@m{tz&Z+xtVA3(wW61|BRSQ~Oj;q6Y zNBt-DZ3zwDQgf*DiHbsIKl)ou&f=eWKMgdLJn6@%Z_%RMKP$~2Eo zR~Fjx?$Y~)9#XxTWXba)?rwy(Z<*-MjOi=;V$shROqR)+lw?WO;Nn`bexUiF7$8JV zRFUPX^U#Q%#5DRAmi%#jXak{!e@_lssyTs;3l+x}Nu01|2bZ41e2Qda1IFt<4O+U~ zJ~6G~KSzkmCoys(TQ(02oX0r0hUZVE=u+SQ($PlxbRk48j&X}*rG)gY%w=6)UtVh= z)81Y&+AouL@D8Ti$S6uig+7PK$=88&nXT{Q^pdGJmaRryElf=Pl4^uEvMdZ538bWV zkf7OcZ`^7QG{K1k)x8h2Z+bi9Q8yM|%qB_Awl2yN^yZZ>E2bdHckUPNH|`hnIm|5_ z!^$8{Mm~_E(J}0Ws+OdciO{pm^09O$7#=scOsRZ2WgBSKMF%zu!5_iZe&HX>i9;=D zKGcYFn*Y|+9vMOE9a*hS;-}I~OC2jQcpZs2l+%(Cd8E^fMTrGpYt47hUA_45K4(HR z&BsX$-kPpKPqwbo5^(#vkeS^EWSinF$))&|Nkt`%kkcUhA! zEWql!`r4GteKFk0MEnZjxZs>y@d?s0DNLi2cA^wyOV~*s8X%Y(Ug}wup6;|sj&Ys< z24!zn?kmzNs%Oc(+bekeBKm`24Wy2;)zU6v#^*z}pf zv5=}4kHE(P_Ls<|HZzWOiHPhO2Aeb>Xi zE+}Yg=iL5sS6)T2I5j6Qmx+_>dfgwFHSJ-3SsBkmH3iQO{x%hpr z27yfI)Ov9*j^r2cK?v)|Pmp=u%ed4sUu&8(TzKGnu=&NsKO*CG@1t#*_^9bI>AlEh z=g9cDhkF3|t4q*$YKk~TeY}o9LDRyarS{Jn{ZH3K6C(Rm8Ju5^XwiS7z8U0ZfE{mp z=6IQbs*L)Lve58*tztXg!q?d{IP(Lpr;Wdeh;kL^S`X!Ww!0E(<|;MOP}VAQ!GD&l zWOwY6#V6hn$Usl;dvKG^E{>D-d@JVH6fh{x!0{%dn_v96O-GO1X9_Qt^qgR(z5)B$ zeb!SRm-$R8j1}r5YMue$FPc|m={R#Y)q+Rnjc8am!qnD-cxLl9_x9U5^s2S`pSO9W zg!B)+mfuu~3mjx(J_OSu-f@(Kr7U+@~7zc?@07X66tg@4HRs^=6Sz{X@8D54C?Y>!t;W<9aomtegx zJ?iV`0U)pCEi+|3ZpLk4jwG{iH)(;0Sp*!fIXcX3UylEhT>MpHXQ~`;SHE$arEbra z!4E$9&Aa7k03&7{PDh{w1;=$fFu~`3t+0y96niSdFE8hUlP|7?FbfyZgIY%1Zh)u? z?ELg_##g-l%Kt1vy#z zJS;4CYYlrEfAXR(Lz3c~MT!TcI0mfJ#R<9DI;=!fY<)f2lXYqunH$QS+igkgL+Zr* zZTnK;lrlt5hoh}ORda^2Iom8mzO|P=eu6*8v_1O;WJmUV!Wqz$5}lODZl{WBux;nt zsMxf-TzV>eg=+;a&zzmaibgNfm*M@Xo5q!At1-T6!^EFpF}he?H$aenHDZk;^<*W7 zu&M(qNAk3i5{+Co>(p(Yku&MUv>zZ$+1~Sa3RpR$f;wp~WN~R}$|#)_s=GkI+N4WC z6JK)Dx&w>xdGjb8PvbM!YsYvfZ&HT5F(Q96Xr0h_LTy5g{E?xk(5ZNwT0_4F(RL?8 z9tN-k1Yw^Xr07m8tx0equT*>P+8dKgl#A6Q0x7()nr_;Yo=I`;gyI8-KU{45=o-f@9z)J*w?Lly0GsR?d2PaK_+ za;!;0IH`i_LYge-Zr^f!eUZP=nk*+MzME2vXd+M)NnW@TCMJKawg~6XNBeK=#h3r z`)L<+8G(5xv8_^`m76ha&R?)UpL(CCvpD(OyX8UrwHke~NNlw@l?xoIK}8pDa5vq>iN-MTS*iTMr(H(q>{JTd5mRgqn&lY4Mu-r`Qs zS#}TX3m*Q#DleiGh+5;%`QaI==)K2~JlVR5tzOn~H?jH>cIq}z6rhCai@l4W zPB95i?KSTi>aA23n9TF*EJC>BeaA=q$jK%rJ0tc*&FXVD#rxK+F5SAwuXHc9 z#G*D%YV>^{E!e!iZDX22k0QHH``j7tnXTlj3$1DwEolmHt4cKVhWE1TdtW-#R2ewi%VF9=BHCCoEu*<)Fti18Ct8W-xqXr+XQ?9M0BjZjFPfj*{XuX3kN8}v7-6u!&NQk6SX}2MMQvK=^FD$x0>ZNEqLc>%8<2yv zPWFT8{Vao<>G}mWE_Gq4$sv08}a$;wjA$$jxsO*KZQnZxYvU z64(DViL1d9%AN$w22chTiXi|QM@~%edSReZMXFOPv+rTQoA85< zAxztG4{cFlb2Uev1){pAZ&GlAJ__zQ+De*uOGLJ+w#6b47RGz5 z9fu6ZC#;&=4=W4r#R)f$@}9Okwb*YR+1l}VV)p--X;gVte#LB=dr?4oBeguYm()js znn*Z788qz>Es*s{p|(>bHf9i}S4pNB9Y?*=V;)C*xyq(yh{SBKT1~N1@P*oG-LvDa zD`T~c?=2QPCQ83Sw~{~cq|X+|EoqoLIByS(!=Skv!83DV{2g&8{d=8Vxw>%H zq!!i}G%fSoTy8q#X~BfKX&vMsd68Llho(8G5x;rH9VLlUQ9(Q&Yv1y=-W@G(>GGQ_Snv+ zM2;W#;lZ#ziI74x4GozPT_&#;=L<2(<0*0vGdMQQG|yXJ5{%x%E=Yx0*xBH(kOme| zK<>-txn%Yqr+DSnLyMJeKgmEjhYy*^&$+AdT&b$kwd$IhS$3m2YtJ+B9^Z=*wc44a zF3h*6Ajz_qzKr#SVDIH)8@_sODwn4|FCJ(igXPW`{GNHfRl_gPFfdb_+ij_4kpx@m1jd17|B_xvb zo%VO=mIS^pDX0QAMZRs7q2$9=P5W6TRKt|8X(U;Gcp_?R=cAgVS2<9N z3@UVMV_VIFyWQZ7Xp7fdO%2LU@7R2gXYZ$P?`UaoQlxzyAJB-GpN_vgWUSE=qW6mL zs@~_Jd#y3lgVJs8gXP)BQ=a%0PHiy|pJu_+&5&FX*i0pH6WmHn;iaMio!t++=gqNl zI_8#c%^f*l*aM%OgG=%zXogu^hxDmU`!&PaHLi)IW1uM&*PM`1ry)!)`U-shERD}$ zpPJIJ6@qEY!-6KTMO^bf2d1ke?>XaWKlE?bAMizx*{^e4l{hE znta|^YGuV!k`|*8MWc zvpY?ElkgC_B_X?s4&4gCK!t9NovhDvhc17L0&i2L>7zim1b3AZM|FgClD(EXrqGG43xD;gY!D0hATVG@pVHVF56kcYZnReEvErbR>DH#bT!C$JNbKz>* zYO8+ANS~%iLn=tDOXtJQn7yU%%rqepdY(`;rVKp}q z&>35lOj)C969$WpnS3UQ7O?Z^m!2W$m_X zA7kQ6(?3sSL`oV0XKtA&749(A30RF!g(&xH2#u$C^qo{0xx^v`5!mEbc>I`gzvE3) zTu-;no^+{xeEUC*!Q7w%@lyuUNI=ylXFv8ay0@4${@z?qU3IMTftL>L&; z9Nz~*f&ci{U{Lr*>EcCxRV`(0K^^t)KcI$p&(sgB0e@Hm6d{9)A{q?Z1&IC~uCHyV zr=X+{=X9Ye#Nxgc0jAYsU;-~jL^!a8L05^96zqU{?;tySknIgiH)oKm=Z~Zm6wD#~ zKWhmX^*S zXUI1;G^&w)uGfLCK;&KE1;6h@G#FI==OVVqD)9TT2u)3OQ-F>v2TUcQLr4Hy7<39n z<*L1{2MFZh47q9#fRd4Q;0GIv$^=FLaM=_Ce6sK{Aw+{gy?}!Ud6$mrpc#S(0!Q4p zc2r0J_!U_Qeqa8J{uwCExCjPhqJS6tX*8n2pw7P*LbDWSnr}Y?>>Dvqz~ZPSN8L511Sg^u!xkhS0)t|A>=H4H3RfdU^KyfQYT z!JuM*O;l4ywb1qu8IW*v57mTzBnGmxv;%qm;4tV<96p^1eCNY}?mF7(uSI?-gk}kO z)h#n(=YTB?S|EY0gt{IVwYT0C(G79~zU~6U6L5Mwq5}cnEowz2tD($uMzw}oN*Un} z1|3oUM=>;O$TQcD9vqoKc>vTMMV_;R>I=2t-=VKgonI@VnL-}SK8?`%*82)Z=u$r! z=0^30TJ;8@3xhhE{%cV*t8f*>sgW5W32b3duob#0>f=;YkEjI|5P~ph>Az4zGl%@t z6gZjv-C$4~>z|rKex8cz548pXLJo^s$~h+_sw=zljDRKnx?qwQa$P*i*=A{qv@M-N8Z zFXU_of0BY|FzEJQ(MPiqvUPZdLuK|I#xFy@TR$3)W&k;>9o_d&eh7h|W-?TC%i+7* z`=bS;y)|<7I(qTU6ZAd$pE4FIAK>u)1A>37fMx|gW)WT%scZGk*K&Xpz4lNMG{!jqT0&>;?u9g07Flcr1UkXU2 zlu^3?bv7v?90nauLyty#bL8xD^ukIy>wEaW%qXaHD-M0==l)U%%@RBkaYi_LXsSK> zuJlit19kB3(95l#D4>}@&K5`Sfar>jnD|wOKppuy^wIuv5i~2vSphy0g=jFSe=(93 m#OWLL06~3Td>Bqs_JeTX?Qwu>V+;&Q;9o9qR{Bs4|Ls2rwMirZ