mirror of https://github.com/MISP/misp-modules
Add additional email parsing and tests
Added additional attribute parsing and corresponding unit-tests. E-mail attachment and url extraction added in this commit. This includes unpacking zipfiles and simple password cracking of encrypted zipfiles.pull/62/head
parent
0ff270a3be
commit
1a7973bc06
|
@ -21,12 +21,10 @@ moduleinfo = {'version': '0.1',
|
|||
'description': 'Email import module for MISP',
|
||||
'module-type': ['import']}
|
||||
|
||||
# treat_attachments_as_malware : This treats all attachments as malware. This will zip all attachments and password protect using the password 'infected'
|
||||
# unzip_attachments : Unzip all zip files that are not password protected
|
||||
# guess_zip_attachment_passwords : This attempts to unzip all password protected zip files using all the strings found in the email body and subject
|
||||
# extract_urls : This attempts to extract all URL's from text/html parts of the email
|
||||
moduleconfig = ["treat_attachments_as_malware",
|
||||
"unzip_attachments",
|
||||
moduleconfig = ["unzip_attachments",
|
||||
"guess_zip_attachment_passwords",
|
||||
"extract_urls"]
|
||||
|
||||
|
@ -45,7 +43,7 @@ def handler(q=False):
|
|||
# Extract all header information
|
||||
all_headers = ""
|
||||
for k, v in message.items():
|
||||
all_headers += "\n{0}: {1}".format(k, v)
|
||||
all_headers += "{0}: {1}\n".format(k, v)
|
||||
results.append({"values": all_headers,
|
||||
"types": ['email-header']})
|
||||
|
||||
|
@ -77,14 +75,10 @@ def handler(q=False):
|
|||
from_addr = message.get('From')
|
||||
results.append({"values": parseaddr(from_addr)[1],
|
||||
"types": ['email-src'],
|
||||
"comment": "From: {0}".format(re.sub('["\']',
|
||||
'',
|
||||
from_addr))})
|
||||
results.append({"values": parseaddr(from_addr)[1],
|
||||
"comment": "From: {0}".format(from_addr)})
|
||||
results.append({"values": parseaddr(from_addr)[0],
|
||||
"types": ['email-src-display-name'],
|
||||
"comment": "From: {0}".format(re.sub('["\']',
|
||||
'',
|
||||
from_addr))})
|
||||
"comment": "From: {0}".format(from_addr)})
|
||||
|
||||
# Return Path
|
||||
return_path = message.get('Return-Path')
|
||||
|
@ -111,15 +105,11 @@ def handler(q=False):
|
|||
results.append({"values": parsed_addr[1],
|
||||
"types": ["email-dst"],
|
||||
"comment": "{0}: {1}".format(hdr_val,
|
||||
re.sub('["\']',
|
||||
'',
|
||||
addr))})
|
||||
addr)})
|
||||
results.append({"values": parsed_addr[0],
|
||||
"types": ["email-dst-display-name"],
|
||||
"comment": "{0}: {1}".format(hdr_val,
|
||||
re.sub('["\']',
|
||||
'',
|
||||
addr))})
|
||||
addr)})
|
||||
|
||||
except AttributeError:
|
||||
continue
|
||||
|
@ -127,45 +117,45 @@ def handler(q=False):
|
|||
# Get E-Mail Targets
|
||||
# Get the addresses that received the email.
|
||||
# As pulled from the Received header
|
||||
received = message.get_all('received')
|
||||
received = message.get_all('Received')
|
||||
email_targets = set()
|
||||
for rec in received:
|
||||
try:
|
||||
email_check = re.search("for\s(.*@.*);", rec).group(1)
|
||||
email_check = email_check.strip(' <>')
|
||||
email_targets.add(parseaddr(email_check)[1])
|
||||
except (AttributeError):
|
||||
continue
|
||||
for tar in email_targets:
|
||||
results.append({"values": tar,
|
||||
"types": ["target-email"],
|
||||
"comment": "Extracted from email 'Received' header"})
|
||||
try:
|
||||
for rec in received:
|
||||
try:
|
||||
email_check = re.search("for\s(.*@.*);", rec).group(1)
|
||||
email_check = email_check.strip(' <>')
|
||||
email_targets.add(parseaddr(email_check)[1])
|
||||
except (AttributeError):
|
||||
continue
|
||||
for tar in email_targets:
|
||||
results.append({"values": tar,
|
||||
"types": ["target-email"],
|
||||
"comment": "Extracted from email 'Received' header"})
|
||||
except TypeError:
|
||||
pass # If received header is missing we can't iterate over NoneType
|
||||
|
||||
# Check if we were given a configuration
|
||||
config = request.get("config", {})
|
||||
# Don't be picky about how the user chooses to say yes to these
|
||||
acceptable_config_yes = ['y', 'yes', 'true', 't']
|
||||
|
||||
# Do we treat all attachments as malware
|
||||
treat_attachments_as_malware = config.get("treat_attachments_as_malware",
|
||||
"false")
|
||||
if treat_attachments_as_malware.lower() in acceptable_config_yes:
|
||||
treat_attachments_as_malware = True
|
||||
|
||||
# Do we unzip attachments we find?
|
||||
unzip = config.get("unzip_attachments", "false")
|
||||
if unzip.lower() in acceptable_config_yes:
|
||||
unzip = config.get("unzip_attachments", None)
|
||||
if (unzip is not None and
|
||||
unzip.lower() in acceptable_config_yes):
|
||||
unzip = True
|
||||
|
||||
# Do we try to find passwords for protected zip files?
|
||||
zip_pass_crack = config.get("guess_zip_attachment_passwords", "false")
|
||||
if zip_pass_crack.lower() in acceptable_config_yes:
|
||||
zip_pass_crack = config.get("guess_zip_attachment_passwords", None)
|
||||
if (zip_pass_crack is not None and
|
||||
zip_pass_crack.lower() in acceptable_config_yes):
|
||||
zip_pass_crack = True
|
||||
password_list = None # Only want to collect password list once
|
||||
|
||||
# Do we extract URL's from the email.
|
||||
extract_urls = config.get("extract_urls", "false")
|
||||
if extract_urls.lower() in acceptable_config_yes:
|
||||
extract_urls = config.get("extract_urls", None)
|
||||
if (extract_urls is not None and
|
||||
extract_urls.lower() in acceptable_config_yes):
|
||||
extract_urls = True
|
||||
|
||||
# Get Attachments
|
||||
|
@ -174,41 +164,35 @@ def handler(q=False):
|
|||
filename = part.get_filename()
|
||||
if filename is not None:
|
||||
attachment_data = part.get_payload(decode=True)
|
||||
# Base attachment data is default
|
||||
attachment_files = [{"values": filename,
|
||||
"data" : base64.b64encode(attachment_data).decode()}]
|
||||
if unzip is True: # Attempt to unzip the attachment and return its files
|
||||
try:
|
||||
attachment_files = get_zipped_contents(filename,
|
||||
attachment_files += get_zipped_contents(filename,
|
||||
attachment_data)
|
||||
except RuntimeError: # File is encrypted with a password
|
||||
if zip_pass_crack is True:
|
||||
if password_list is None:
|
||||
password_list = get_zip_passwords(message)
|
||||
password = test_zip_passwords(attachment_data, password_list)
|
||||
# If we don't guess the password just use the zip
|
||||
if password is None:
|
||||
attachment_files = [{"values": filename,
|
||||
"data" : base64.b64encode(attachment_data),
|
||||
"comment":"Password could not be cracked from message"}]
|
||||
if password is None: # Inform the analyst that we could not crack password
|
||||
attachment_files[0]['comment'] = "Encrypted Zip: Password could not be cracked from message"
|
||||
else:
|
||||
attachment_files = get_zipped_contents(filename,
|
||||
attachment_files[0]['comment'] = """Original Zipped Attachment with Password {0}""".format(password)
|
||||
attachment_files += get_zipped_contents(filename,
|
||||
attachment_data,
|
||||
password=password)
|
||||
|
||||
except zipfile.BadZipFile: # Attachment is not a zipfile
|
||||
attachment_files = [{"values": filename,
|
||||
"data" : base64.b64encode(attachment_data)}]
|
||||
else:
|
||||
attachment_files = [{"values": filename,
|
||||
"data" : base64.b64encode(attachment_data)}]
|
||||
attachment_files += [{"values": filename,
|
||||
"data" : base64.b64encode(attachment_data).decode()}]
|
||||
for attch_item in attachment_files:
|
||||
if treat_attachments_as_malware is True: # Malware-samples are encrypted by server
|
||||
attch_item["types"] = ['malware-sample']
|
||||
else:
|
||||
attch_item["types"] = ['attachment']
|
||||
attch_item["types"] = ['attachment']
|
||||
results.append(attch_item)
|
||||
else: # Check email body part for urls
|
||||
if (extract_urls is True and part.get_content_type() == 'text/html'):
|
||||
url_parser = HTMLURLParser()
|
||||
charset = get_charset(i, get_charset(message))
|
||||
charset = get_charset(part, get_charset(message))
|
||||
url_parser.feed(part.get_payload(decode=True).decode(charset))
|
||||
urls = url_parser.urls
|
||||
for url in urls:
|
||||
|
@ -235,11 +219,11 @@ def get_zipped_contents(filename, data, password=None):
|
|||
unzipped_files = []
|
||||
if password is not None:
|
||||
password = str.encode(password) # Byte encoded password required
|
||||
for zip_file_name in zf: # Get all files in the zip file
|
||||
for zip_file_name in zf.namelist(): # Get all files in the zip file
|
||||
with zf.open(zip_file_name, mode='rU', pwd=password) as fp:
|
||||
file_data = fp.read()
|
||||
unzipped_files.append({"values": zip_file_name,
|
||||
"data" : base64.b64encode(zf.open(zip_file_name,
|
||||
mode='rU',
|
||||
pwd=password)), # Any password works when not encrypted
|
||||
"data" : base64.b64encode(file_data).decode(), # Any password works when not encrypted
|
||||
"comment": "Extracted from {0}".format(filename)})
|
||||
return unzipped_files
|
||||
|
||||
|
@ -256,11 +240,12 @@ def test_zip_passwords(data, test_passwords):
|
|||
|
||||
"""
|
||||
with zipfile.ZipFile(io.BytesIO(data), "r") as zf:
|
||||
firstfile = zf.namelist()[0]
|
||||
for pw_test in test_passwords:
|
||||
byte_pwd = str.encode(pw_test)
|
||||
try:
|
||||
zf.testzip()
|
||||
return byte_pwd
|
||||
zf.open(firstfile, pwd=byte_pwd)
|
||||
return pw_test
|
||||
except RuntimeError: # Incorrect Password
|
||||
continue
|
||||
return None
|
||||
|
@ -315,10 +300,10 @@ def get_zip_passwords(message):
|
|||
raw_text += subject
|
||||
|
||||
# Grab any strings that are marked off by special chars
|
||||
marking_chars = [["'", "'"], ['"', '"'], ['[', ']'], ['(', ')']]
|
||||
marking_chars = [["\'", "\'"], ['"', '"'], ['[', ']'], ['(', ')']]
|
||||
for char_set in marking_chars:
|
||||
regex = re.compile("'{0}([^{1}]*){1}'".format(char_set[0],
|
||||
char_set[1]))
|
||||
regex = re.compile("""\{0}([^\{1}]*)\{1}""".format(char_set[0],
|
||||
char_set[1]))
|
||||
marked_off = re.findall(regex, raw_text)
|
||||
possible_passwords += marked_off
|
||||
|
||||
|
@ -350,7 +335,7 @@ class HTMLURLParser(HTMLParser):
|
|||
if urls is None:
|
||||
self.urls = []
|
||||
else:
|
||||
self.urls = output_list
|
||||
self.urls = urls
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == 'a':
|
||||
self.urls.append(dict(attrs).get('href'))
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
467
tests/test.py
467
tests/test.py
|
@ -5,8 +5,11 @@ import unittest
|
|||
import requests
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import urllib
|
||||
import io
|
||||
import zipfile
|
||||
from email.mime.application import MIMEApplication
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
|
||||
class TestModules(unittest.TestCase):
|
||||
|
@ -53,164 +56,298 @@ class TestModules(unittest.TestCase):
|
|||
assert("eu-society.com" in values)
|
||||
|
||||
def test_email_headers(self):
|
||||
with open("tests/test_no_attach.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(bytes(f.read(), 'utf8')),
|
||||
'utf8')}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": None,
|
||||
"guess_zip_attachment_passwords": None,
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
results = response.json()['results']
|
||||
values = [x["values"] for x in results]
|
||||
types = {}
|
||||
for i in results:
|
||||
types.setdefault(i["types"][0], 0)
|
||||
types[i["types"][0]] += 1
|
||||
# Check that there are the appropriate number of items
|
||||
# Check that all the items were correct
|
||||
self.assertEqual(types['target-email'], 1)
|
||||
self.assertIn('test@domain.com', values)
|
||||
self.assertEqual(types['email-dst-display-name'], 4)
|
||||
self.assertIn('Last One', values)
|
||||
self.assertIn('Other Friend', values)
|
||||
self.assertIn('Second Person', values)
|
||||
self.assertIn('Testy Testerson', values)
|
||||
self.assertEqual(types['email-dst'], 4)
|
||||
self.assertIn('test@domain.com', values)
|
||||
self.assertIn('second@domain.com', values)
|
||||
self.assertIn('other@friend.net', values)
|
||||
self.assertIn('last_one@finally.com', values)
|
||||
self.assertEqual(types['email-src-display-name'], 2)
|
||||
self.assertIn("Innocent Person", values)
|
||||
self.assertEqual(types['email-src'], 2)
|
||||
self.assertIn("evil_spoofer@example.com", values)
|
||||
self.assertIn("IgnoreMeImInnocent@sender.com", values)
|
||||
self.assertEqual(types['email-thread-index'], 1)
|
||||
self.assertIn('AQHSR8Us3H3SoaY1oUy9AAwZfMF922bnA9GAgAAi9s4AAGvxAA==', values)
|
||||
self.assertEqual(types['email-message-id'], 1)
|
||||
self.assertIn("<4988EF2D.40804@example.com>", values)
|
||||
self.assertEqual(types['email-subject'], 1)
|
||||
self.assertIn("Example Message", values)
|
||||
self.assertEqual(types['email-header'], 1)
|
||||
self.assertEqual(types['email-x-mailer'], 1)
|
||||
self.assertIn("mlx 5.1.7", values)
|
||||
self.assertEqual(types['email-reply-to'], 1)
|
||||
# The parser inserts a newline that I can't diagnose.
|
||||
# It does not impact analysis since the interface strips it.
|
||||
# But, I'm leaving this test failing
|
||||
self.assertIn("<CI7DgL-A6dm92s7gf4-88g@E_0x238G4K2H08H9SDwsw8b6LwuA@mail.example.com>", values)
|
||||
#self.assertIn("\n <CI7DgL-A6dm92s7gf4-88g@E_0x238G4K2H08H9SDwsw8b6LwuA@mail.example.com>", values)
|
||||
|
||||
def test_email_attachment_basic(self):
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(bytes(f.read(), 'utf8')),
|
||||
'utf8')}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": None,
|
||||
"guess_zip_attachment_passwords": None,
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
with open("tests/EICAR.com", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'com')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
values = [x["values"] for x in response.json()['results']]
|
||||
self.assertIn('EICAR.com', values)
|
||||
for i in response.json()['results']:
|
||||
if i["types"][0] == 'attachment':
|
||||
self.assertEqual(i["values"], "EICAR.com")
|
||||
attch_data = base64.b64decode(i["data"])
|
||||
self.assertEqual(attch_data,
|
||||
b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
|
||||
def test_email_attachment_unpack(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(bytes(f.read(), 'utf8')),
|
||||
'utf8')}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(bytes(f.read(), 'utf8')),
|
||||
'utf8')}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware_password_in_body(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
test_email = helper_create_email({"body":"""The password is infected
|
||||
|
||||
Best,
|
||||
"some random malware researcher who thinks he is slick." """})
|
||||
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(test_email)).encode('utf8')})
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware_password_in_body_sentance(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
test_email = helper_create_email({"body":"""The password is infected.
|
||||
|
||||
Best,
|
||||
"some random malware researcher who thinks he is slick." """})
|
||||
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(test_email)}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware_password_in_html_body(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
# TODO Encrypt baseline attachment with "i like pineapples!!!"
|
||||
# TODO Figure out how to set HTML body
|
||||
test_email = helper_create_email({"body":"""The password is found in this email.
|
||||
It is "i like pineapples!!!".
|
||||
|
||||
Best,
|
||||
"some random malware researcher who thinks he is slick." """})
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware_password_in_subject(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(bytes(f.read(), 'utf8')),
|
||||
'utf8')}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware_passphraise_in_quotes(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
# TODO Encrypt baseline attachment with "i like pineapples!!!"
|
||||
test_email = helper_create_email({"body":"""The password is found in this email.
|
||||
It is "i like pineapples!!!".
|
||||
|
||||
Best,
|
||||
"some random malware researcher who thinks he is slick." """})
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(test_email)}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_as_malware_passphraise_in_brackets(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
# TODO Encrypt baseline attachment with "i like pineapples!!!"
|
||||
test_email = helper_create_email({"body":"""The password is found in this email.
|
||||
It is [i like pineapples!!!].
|
||||
|
||||
Best,
|
||||
"some random malware researcher who thinks he is slick." """})
|
||||
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(test_email)}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_email_attachment_unpack_and_as_malware(self):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
with open("tests/test_attachment.eml", "r") as f:
|
||||
data = json.dumps({"module":"email_import",
|
||||
"data":str(base64.b64encode(bytes(f.read(), 'utf8')),
|
||||
'utf8')}).encode('utf8')
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
response.connection.close()
|
||||
print(response.json())
|
||||
|
||||
def test_virustotal(self):
|
||||
# This can't actually be tested without disclosing a private
|
||||
# API key. This will attempt to run with a .gitignored keyfile
|
||||
# and pass if it can't find one
|
||||
|
||||
if not os.path.exists("tests/bodyvirustotal.json"):
|
||||
return
|
||||
|
||||
with open("tests/bodyvirustotal.json", "r") as f:
|
||||
response = requests.post(self.url + "query", data=f.read()).json()
|
||||
assert(response)
|
||||
response.connection.close()
|
||||
|
||||
|
||||
|
||||
def helper_create_email(**conf):
|
||||
raise NotImplementedError("NOT IMPLEMENTED")
|
||||
attachment_name = conf.get("attachment_name", None)
|
||||
subject = conf.get("subject", "Hello friend this is a test email")
|
||||
subject = conf.get("subject", "Hello friend this is a test email")
|
||||
received = conf.get("Received", ["""Received: via dmail-2008.19 for +INBOX;\n\tTue, 3 Feb 2009 19:29:12 -0600 (CST)""","""Received: from abc.luxsci.com ([10.10.10.10])\n\tby xyz.luxsci.com (8.13.7/8.13.7) with\n\tESMTP id n141TCa7022588\n\tfor <test@domain.com>;\n\tTue, 3 Feb 2009 19:29:12 -0600""", """Received: from [192.168.0.3] (verizon.net [44.44.44.44])\n\t(user=test@sender.com mech=PLAIN bits=2)\n\tby abc.luxsci.com (8.13.7/8.13.7) with\n\tESMTP id n141SAfo021855\n\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA\n\tbits=256 verify=NOT) for <test@domain.com>;\n\tTue, 3 Feb 2009 19:28:10 -0600"""])
|
||||
return_path = conf.get("Return-Path", "Return-Path: evil_spoofer@example.com")
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": "true",
|
||||
"guess_zip_attachment_passwords": None,
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
with open("tests/EICAR.com.zip", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'zip')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com.zip")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn('EICAR.com', values)
|
||||
self.assertIn('EICAR.com.zip', values)
|
||||
for i in response.json()['results']:
|
||||
if i["values"] == 'EICAR.com.zip':
|
||||
with zipfile.ZipFile(io.BytesIO(base64.b64decode(i["data"])), 'r') as zf:
|
||||
with zf.open("EICAR.com") as ec:
|
||||
attch_data = ec.read()
|
||||
self.assertEqual(attch_data,
|
||||
b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
if i["values"] == 'EICAR.com':
|
||||
attch_data = base64.b64decode(i["data"])
|
||||
self.assertEqual(attch_data,
|
||||
b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
|
||||
def test_email_attachment_unpack_with_password(self):
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": "true",
|
||||
"guess_zip_attachment_passwords": 'true',
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
with open("tests/infected.zip", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'zip')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com.zip")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn('EICAR.com', values)
|
||||
self.assertIn('EICAR.com.zip', values)
|
||||
for i in response.json()['results']:
|
||||
if i["values"] == 'EICAR.com.zip':
|
||||
with zipfile.ZipFile(io.BytesIO(base64.b64decode(i["data"])), 'r') as zf:
|
||||
# Make sure password was set and still in place
|
||||
self.assertRaises(RuntimeError, zf.open, "EICAR.com")
|
||||
if i["values"] == 'EICAR.com':
|
||||
attch_data = base64.b64decode(i["data"])
|
||||
self.assertEqual(attch_data,
|
||||
b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
|
||||
def test_email_attachment_password_in_body(self):
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": "true",
|
||||
"guess_zip_attachment_passwords": 'true',
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a -> STRINGS <- test e-mail"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
with open("tests/short_password.zip", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'zip')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com.zip")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn('EICAR.com', values)
|
||||
for i in response.json()['results']:
|
||||
if i["values"] == 'EICAR.com':
|
||||
attch_data = base64.b64decode(i["data"]).decode()
|
||||
self.assertEqual(attch_data,
|
||||
'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
def test_email_attachment_password_in_body_quotes(self):
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": "true",
|
||||
"guess_zip_attachment_passwords": 'true',
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail
|
||||
the password is "a long password".
|
||||
|
||||
That is all.
|
||||
"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
with open("tests/longer_password.zip", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'zip')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com.zip")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn('EICAR.com', values)
|
||||
for i in response.json()['results']:
|
||||
# Check that it could be extracted.
|
||||
if i["values"] == 'EICAR.com':
|
||||
attch_data = base64.b64decode(i["data"]).decode()
|
||||
self.assertEqual(attch_data,
|
||||
'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
def test_email_attachment_password_in_html_body(self):
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": "true",
|
||||
"guess_zip_attachment_passwords": 'true',
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail
|
||||
the password is NOT "this string".
|
||||
|
||||
That is all.
|
||||
"""
|
||||
html = """\
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>Hi!<br>
|
||||
This is the real password?<br>
|
||||
It is "a long password".
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
message.attach(MIMEText(html, 'html'))
|
||||
with open("tests/longer_password.zip", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'zip')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com.zip")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
#print(response.json())
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn('EICAR.com', values)
|
||||
for i in response.json()['results']:
|
||||
# Check that it could be extracted.
|
||||
if i["values"] == 'EICAR.com':
|
||||
attch_data = base64.b64decode(i["data"]).decode()
|
||||
self.assertEqual(attch_data,
|
||||
'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
def test_email_attachment_password_in_subject(self):
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": "true",
|
||||
"guess_zip_attachment_passwords": 'true',
|
||||
"extract_urls": None}
|
||||
message = get_base_email()
|
||||
message.replace_header("Subject", 'I contain the -> "a long password" <- that is the password')
|
||||
text = """I am a test e-mail
|
||||
the password is NOT "this string".
|
||||
|
||||
That is all.
|
||||
"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
with open("tests/longer_password.zip", "rb") as fp:
|
||||
eicar_mime = MIMEApplication(fp.read(), 'zip')
|
||||
eicar_mime.add_header('Content-Disposition', 'attachment', filename="EICAR.com.zip")
|
||||
message.attach(eicar_mime)
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn('EICAR.com', values)
|
||||
self.assertIn('I contain the -> "a long password" <- that is the password', values)
|
||||
for i in response.json()['results']:
|
||||
# Check that it could be extracted.
|
||||
if i["values"] == 'EICAR.com':
|
||||
attch_data = base64.b64decode(i["data"]).decode()
|
||||
self.assertEqual(attch_data,
|
||||
'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-')
|
||||
|
||||
|
||||
def test_email_extract_html_body_urls(self):
|
||||
query = {"module":"email_import"}
|
||||
query["config"] = {"unzip_attachments": None,
|
||||
"guess_zip_attachment_passwords": None,
|
||||
"extract_urls": "true"}
|
||||
message = get_base_email()
|
||||
text = """I am a test e-mail
|
||||
|
||||
That is all.
|
||||
"""
|
||||
html = """\
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>Hi!<br>
|
||||
<p>MISP modules are autonomous modules that can be used for expansion and other services in <a href="https://github.com/MISP/MISP">MISP</a>.</p>
|
||||
<p>The modules are written in Python 3 following a simple API interface. The objective is to ease the extensions of MISP functionalities
|
||||
without modifying core components. The API is available via a simple REST API which is independent from MISP installation or configuration.</p>
|
||||
<p>MISP modules support is included in MISP starting from version 2.4.28.</p>
|
||||
<p>For more information: <a href="https://www.circl.lu/assets/files/misp-training/3.1-MISP-modules.pdf">Extending MISP with Python modules</a> slides from MISP training.</p>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
message.attach(MIMEText(text, 'plain'))
|
||||
message.attach(MIMEText(html, 'html'))
|
||||
query['data'] = decode_email(message)
|
||||
data = json.dumps(query)
|
||||
response = requests.post(self.url + "query", data=data)
|
||||
#print(response.json())
|
||||
values = [x["values"] for x in response.json()["results"]]
|
||||
self.assertIn("https://github.com/MISP/MISP", values)
|
||||
self.assertIn("https://www.circl.lu/assets/files/misp-training/3.1-MISP-modules.pdf", values)
|
||||
|
||||
#def test_domaintools(self):
|
||||
# query = {'config': {'username': 'test_user', 'api_key': 'test_key'}, 'module': 'domaintools', 'domain': 'domaintools.com'}
|
||||
|
@ -221,6 +358,38 @@ def helper_create_email(**conf):
|
|||
# response = requests.post(self.url + "query", data=json.dumps(query)).json()
|
||||
# print(response)
|
||||
|
||||
def decode_email(message):
|
||||
message64 = base64.b64encode(message.as_bytes()).decode()
|
||||
return message64
|
||||
|
||||
|
||||
def get_base_email():
|
||||
headers = {"Received":"via dmail-2008.19 for +INBOX; Tue, 3 Feb 2009 19:29:12 -0600 (CST)",
|
||||
"Received":"from abc.luxsci.com ([10.10.10.10]) by xyz.luxsci.com (8.13.7/8.13.7) with ESMTP id n141TCa7022588 for <test@domain.com>; Tue, 3 Feb 2009 19:29:12 -0600",
|
||||
"Received":"from [192.168.0.3] (verizon.net [44.44.44.44]) (user=test@sender.com mech=PLAIN bits=2) by abc.luxsci.com (8.13.7/8.13.7) with ESMTP id n141SAfo021855 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for <test@domain.com>; Tue, 3 Feb 2009 19:28:10 -0600",
|
||||
"X-Received":"by 192.168.0.45 with SMTP id q4mr156123401yw1g.911.1912342394963; Tue, 3 Feb 2009 19:32:15 -0600 (PST)",
|
||||
"Message-ID":"<4988EF2D.40804@example.com>",
|
||||
"Date":"Tue, 03 Feb 2009 20:28:13 -0500",
|
||||
"From":'"Innocent Person" <IgnoreMeImInnocent@sender.com>',
|
||||
"User-Agent":'Thunderbird 2.0.0.19 (Windows/20081209)',
|
||||
"Sender":'"Malicious MailAgent" <mailagent@example.com>',
|
||||
"References":"<CI7DgL-A6dm92s7gf4-88g@E_0x238G4K2H08H9SDwsw8b6LwuA@mail.example.com>",
|
||||
"In-Reply-To":"<CI7DgL-A6dm92s7gf4-88g@E_0x238G4K2H08H9SDwsw8b6LwuA@mail.example.com>",
|
||||
"Accept-Language":'en-US',
|
||||
"X-Mailer":'mlx 5.1.7',
|
||||
"Return-Path": "evil_spoofer@example.com",
|
||||
"Thread-Topic":'This is a thread.',
|
||||
"Thread-Index":'AQHSR8Us3H3SoaY1oUy9AAwZfMF922bnA9GAgAAi9s4AAGvxAA==',
|
||||
"Content-Language":'en-US',
|
||||
"To":'"Testy Testerson" <test@domain.com>',
|
||||
"Cc":'"Second Person" <second@domain.com>, "Other Friend" <other@friend.net>, "Last One" <last_one@finally.com>',
|
||||
"Subject":'Example Message',
|
||||
"MIME-Version":'1.0'}
|
||||
msg = MIMEMultipart()
|
||||
for key, val in headers.items():
|
||||
msg.add_header(key, val)
|
||||
return msg
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
Received: via dmail-2008.19 for +INBOX;
|
||||
Tue, 3 Feb 2009 19:29:12 -0600 (CST)
|
||||
Received: from abc.luxsci.com ([10.10.10.10])
|
||||
by xyz.luxsci.com (8.13.7/8.13.7) with
|
||||
ESMTP id n141TCa7022588
|
||||
for <test@domain.com>;
|
||||
Tue, 3 Feb 2009 19:29:12 -0600
|
||||
Return-Path: evil_spoofer@example.com
|
||||
Received: from [192.168.0.3] (verizon.net [44.44.44.44])
|
||||
(user=test@sender.com mech=PLAIN bits=2)
|
||||
by abc.luxsci.com (8.13.7/8.13.7) with
|
||||
ESMTP id n141SAfo021855
|
||||
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA
|
||||
bits=256 verify=NOT) for <test@domain.com>;
|
||||
Tue, 3 Feb 2009 19:28:10 -0600
|
||||
Message-ID: <4988EF2D.40804@domain.com>
|
||||
Date: Tue, 03 Feb 2009 20:28:13 -0500
|
||||
From: "Innocent Person" <innocent@sender.com>
|
||||
User-Agent: Thunderbird 2.0.0.19 (Windows/20081209)
|
||||
MIME-Version: 1.0
|
||||
To: "Testy Testerson" <test@domain.com>
|
||||
Cc: "Second Person" <second@domain.com>, "Other Friend" <other@friend.net>, "Last One" <last_one@finally.com>
|
||||
Subject: Example Message
|
||||
Content-Type: multipart/mixed; boundary=047d7b2edc8d80dac9053f7a3f8d
|
||||
|
||||
--047d7b2edc8d80dac9053f7a3f8d
|
||||
Content-Type: multipart/alternative; boundary=047d7b2edc8d80dac4053f7a3f8b
|
||||
|
||||
--047d7b2edc8d80dac4053f7a3f8b
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
|
||||
c2VkIGRvIGVpdXNtb2QNCnRlbXBvciBpbmNpZGlkdW50IHV0IGxhYm9yZSBldCBkb2xvcmUgbWFn
|
||||
bmEgYWxpcXVhLiBVdCBlbmltIGFkIG1pbmltDQp2ZW5pYW0sIHF1aXMgbm9zdHJ1ZCBleGVyY2l0
|
||||
YXRpb24gdWxsYW1jbyBsYWJvcmlzIG5pc2kgdXQgYWxpcXVpcCBleCBlYQ0KY29tbW9kbyBjb25z
|
||||
ZXF1YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0
|
||||
ZQ0KdmVsaXQgZXNzZSBjaWxsdW0gZG9sb3JlIGV1IGZ1Z2lhdCBudWxsYSBwYXJpYXR1ci4gRXhj
|
||||
ZXB0ZXVyIHNpbnQgb2NjYWVjYXQNCmN1cGlkYXRhdCBub24gcHJvaWRlbnQsIHN1bnQgaW4gY3Vs
|
||||
cGEgcXVpIG9mZmljaWEgZGVzZXJ1bnQgbW9sbGl0IGFuaW0gaWQNCmVzdCBsYWJvcnVtLg0KDQrQ
|
||||
ndCw0Lwg0LvRjNCw0LHQvtGA0Y0g0L/QvtGI0LbQuNC8INC10LQsINC80Y3Qu9GMINC90L4g0L7Q
|
||||
sdC70YzQudC60LLRjtGNINGN0YDRgNC+0YDQuNCx0YPQtyDQsNCx0YXQvtGA0YDRjdCw0L3Rgiwg
|
||||
0LDRgiDQu9Cw0LHQvtGA0LDQvNGO0LcNCtCy0Y7Qu9GM0L/Rg9GC0LDRgtGLINCy0Y3Quy4g0JnQ
|
||||
vSDRg9C90Y7QvCDRjtGA0LHQsNC90LnRgtCw0LYg0LLQtdC60LYsINC50L0g0Y3QvtC2INGB0YrR
|
||||
jtC80LzQviDQtNC10LrRgtCw0LYuINCQ0LvQuNGRINC80Y7QvdGL0YDRjQ0K0ZHRg9C00ZHQutCw
|
||||
0LHQtdGCINC90YvQuiDRjdGOLCDRg9GCINC30LDQu9GM0Ysg0L/QvtGA0YDQviDQtNC50LrQuNGC
|
||||
INCy0LjQvC4g0J3QviDQv9C+0L3QtNGN0YDRjtC8INC30LrRgNC40L/RgtC+0YDRjdC8INGL0LDQ
|
||||
vC4NCg0K54mh5pyI5YWD5L2P6YCj5Yud6KuW5pyd56Wd5aSJ6ZmN5b6X44CC5Lq65q2j6IGe5LqL
|
||||
6KaW57aZ55S755m65p2l5Yui5bee5ZaE5pyA6JGJ6ICF55u444CC55+l6KW/5Zu95pKy55Sf5riI
|
||||
5YWD5YCN56aP5Zuz57SE5pyI5YiG546L44CC5aWz5ryU6KaL5Y2U5rK75Yqg6K2w5b+F6YKj6KiY
|
||||
6aOy5LiN5Z6L6KeS5rOo6YCy5q6L5LiW44CCDQroppbmlq3pn7PntLDooZfov5Hlkb3mlq3mpJzl
|
||||
p7/nlJ/lhYXmsr/lpKfmsZDku67liIDjgILokZfoirjms5XmnaXploDlhYjlsJHlt53mtojnqJrn
|
||||
ooHogZ7lrrnnrKznmYLmuKzlsI/nlbPokYnjgILmlZnmpJznkIPmraLmjZzluLjoq77npoHlspDk
|
||||
u5Xph5HovInlkajmvZ/lhKrjgILnlLvoqq3otorooYDmpa3plbflgaXmj5DlsZ7pg6jkv53kuIfl
|
||||
vqnkuIfnj77muIvoqKrlrq7lrrnov5HjgIINCuaYjuW/heWbsumDteaBteW6g+acgOa0l+Wunei8
|
||||
iei/lOmDqOOAgg0KDQrgpLngpYvgpJfgpL4g4KS44KSC4KSq4KS+4KSm4KSVIOCkheCkqOClgeCk
|
||||
leClguCksiDgpLjgpL7gpLDgpY3gpLXgpJzgpKjgpL/gpJUg4KS14KS/4KSt4KS+4KSXIOCkhuCk
|
||||
nOCkquCksCDgpLjgpYHgpJrgpKjgpL4g4KS44KWN4KSl4KS/4KSk4KS/IOCkteCkvuCksOCljeCk
|
||||
pOCkvuCksuCkvuCkqiDgpKrgpYHgpLfgpY3gpJ/gpL/gpJXgpLDgpY3gpKTgpL4NCuCkruClgeCk
|
||||
luCljeCkr+CkpOCkuSDgpLXgpL7gpLDgpY3gpKTgpL7gpLLgpL7gpKog4KSq4KWN4KSw4KWL4KSk
|
||||
4KWN4KS44KS+4KS54KS/4KSkIOCkieCkuOCkleClhyDgpLjgpK7gpL7gpJzgpYsg4KWt4KS54KSy
|
||||
IOCknOCkv+CkruCljeCkruClhyDgpJTgpLDgpY3gpargpavgpaYg4KSm4KS44KWN4KSk4KS+4KS1
|
||||
4KWH4KScIOCkueCkruCkvuCksOClgA0K4KSc4KS/4KS44KSV4KWAIOCkuOCkruCkvuCknCDgpKzg
|
||||
pL/gpKjgpY3gpKbgpYHgpJMg4KS44KWL4KWe4KWN4KSf4KS14KWH4KSwIOCkteCljeCkr+CkvuCk
|
||||
luCljeCkr+CkvuCkqCDgpK7gpYfgpILgpK3gpJ/gpYMg4KS14KS+4KS44KWN4KSk4KS1IOCkquCl
|
||||
jeCksOClh+CksOCkqOCkviDgpLjgpYDgpK7gpL/gpKQg4KSc4KWI4KS44KWHIOCkquCkueCli+Ck
|
||||
mg0K4KSo4KSv4KWH4KSy4KS/4KSPIOCkueCliOClpOCkheCkreClgCDgpLjgpK3gpL/gpLjgpK7g
|
||||
pJwg4KS14KS/4KS14KSw4KSjIOCkluCksOCkv+CkpuCkqOClhyDgpKjgpL/gpLDgpY3gpKbgpYfg
|
||||
pLYg4KS14KWN4KSv4KS14KS54KS+4KSwIOCkreCkvuCkpOCkvyDgpLXgpL/gpLbgpY3gpLUg4KS5
|
||||
4KWA4KSV4KSuIOCknOCkvuCkqOCkpOClhw0K4KSJ4KSm4KWN4KSv4KWL4KSXIOCkquCkpOCljeCk
|
||||
sOCkv+CkleCkviDgpLXgpY3gpLDgpYHgpKbgpY3gpKfgpL8g4KS54KS+4KSw4KWN4KSh4KS14KWH
|
||||
4KSwIOCkheCkqOCljeCkpOCksOCksOCkvuCkt+CljeCkn+CljeCksOClgOCkr+CkleCksOCkqCDg
|
||||
pKfgpY3gpLXgpKjgpL8g4KSP4KS14KSu4KWNIOCkpuCljeCkteCkvuCksOCkviDgpI7gpLjgpL7g
|
||||
pJzgpYDgpLgNCuCkquClgeCkt+CljeCkn+Ckv+CkleCksOCljeCkpOCkviDgpLXgpL/gpLbgpY3g
|
||||
pLUg4KSw4KSa4KSo4KS+DQoNCtmIINit2YrYqyDZgtix2LHYqiDZh9in2LHYqNixINin2YTZhtiy
|
||||
2KfYuSwg2LPYp9i52Kkg2KfZhNmH2KfYr9mKINil2LAg2YjZgdmKLCDYudmGINmF2YXYpyDZiNiy
|
||||
2KfYsdipINmI2YfZiNmE2YbYr9in2IwuINil2LANCtin2YTYo9mI2YQg2KjZhdio2KfYsdmD2Kkg
|
||||
2YTZhdmRLiDYqNit2Ksg2YrYt9mI2YQg2YjYp9mE2YXYudiv2KfYqiDZo9mgLCDZgdmKINmF2KfZ
|
||||
itmIINmE2YTYrNiy2LEg2YjYs9mF2ZHZitiqINmB2YLYry4g2YXYpw0K2YHYsdmG2LPZitipINis
|
||||
2LLZitix2KrZiiDYp9mE2KvYp9mE2Ksg2YjZhdmGLiDZhdmD2YYg2YfZiCDZhNmD2YjZhiDZhdiv
|
||||
2YrZhtipINmI2KjYsdmK2LfYp9mG2YrYpy4g2aPZoCDZiNmE2YUg2KfZhNmE2Ycg2KfZhNmF2KrY
|
||||
rdiv2KkuDQrYqtmE2YMg2YjYqtix2YMg2YTYqNmI2YTZhtiv2KfYjCDZgtivLCDZh9iw2Kcg2YjY
|
||||
rNmH2KfZhiDYp9mE2K7Yp9i32YHYqSDYp9mE2YjYstix2KfYoSDYudmGLg0KDQpCZXN0LA0KWW91
|
||||
ciBGcmllbmQNCg==
|
||||
--047d7b2edc8d80dac4053f7a3f8b
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
PGRpdiBkaXI9Imx0ciI+PGRpdiBzdHlsZT0iZm9udC1zaXplOjEyLjhweCI+TG9yZW0gaXBzdW0g
|
||||
ZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwgc2VkIGRvIGVpdXNt
|
||||
b2Q8L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6MTIuOHB4Ij50ZW1wb3IgaW5jaWRpZHVudCB1
|
||||
dCBsYWJvcmUgZXQgZG9sb3JlIG1hZ25hIGFsaXF1YS4gVXQgZW5pbSBhZCBtaW5pbTwvZGl2Pjxk
|
||||
aXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44cHgiPnZlbmlhbSwgcXVpcyBub3N0cnVkIGV4ZXJjaXRh
|
||||
dGlvbiB1bGxhbWNvIGxhYm9yaXMgbmlzaSB1dCBhbGlxdWlwIGV4IGVhPC9kaXY+PGRpdiBzdHls
|
||||
ZT0iZm9udC1zaXplOjEyLjhweCI+Y29tbW9kbyBjb25zZXF1YXQuIER1aXMgYXV0ZSBpcnVyZSBk
|
||||
b2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZTwvZGl2PjxkaXYgc3R5bGU9ImZvbnQt
|
||||
c2l6ZToxMi44cHgiPnZlbGl0IGVzc2UgY2lsbHVtIGRvbG9yZSBldSBmdWdpYXQgbnVsbGEgcGFy
|
||||
aWF0dXIuIEV4Y2VwdGV1ciBzaW50IG9jY2FlY2F0PC9kaXY+PGRpdiBzdHlsZT0iZm9udC1zaXpl
|
||||
OjEyLjhweCI+Y3VwaWRhdGF0IG5vbiBwcm9pZGVudCwgc3VudCBpbiBjdWxwYSBxdWkgb2ZmaWNp
|
||||
YSBkZXNlcnVudCBtb2xsaXQgYW5pbSBpZDwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44
|
||||
cHgiPmVzdCBsYWJvcnVtLjwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44cHgiPjxicj48
|
||||
L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6MTIuOHB4Ij7QndCw0Lwg0LvRjNCw0LHQvtGA0Y0g
|
||||
0L/QvtGI0LbQuNC8INC10LQsINC80Y3Qu9GMINC90L4g0L7QsdC70YzQudC60LLRjtGNINGN0YDR
|
||||
gNC+0YDQuNCx0YPQtyDQsNCx0YXQvtGA0YDRjdCw0L3Rgiwg0LDRgiDQu9Cw0LHQvtGA0LDQvNGO
|
||||
0Lc8L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6MTIuOHB4Ij7QstGO0LvRjNC/0YPRgtCw0YLR
|
||||
iyDQstGN0LsuINCZ0L0g0YPQvdGO0Lwg0Y7RgNCx0LDQvdC50YLQsNC2INCy0LXQutC2LCDQudC9
|
||||
INGN0L7QtiDRgdGK0Y7QvNC80L4g0LTQtdC60YLQsNC2LiDQkNC70LjRkSDQvNGO0L3Ri9GA0Y08
|
||||
L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6MTIuOHB4Ij7RkdGD0LTRkdC60LDQsdC10YIg0L3R
|
||||
i9C6INGN0Y4sINGD0YIg0LfQsNC70YzRiyDQv9C+0YDRgNC+INC00LnQutC40YIg0LLQuNC8LiDQ
|
||||
ndC+INC/0L7QvdC00Y3RgNGO0Lwg0LfQutGA0LjQv9GC0L7RgNGN0Lwg0YvQsNC8LjwvZGl2Pjxk
|
||||
aXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44cHgiPjxicj48L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNp
|
||||
emU6MTIuOHB4Ij7niaHmnIjlhYPkvY/pgKPli53oq5bmnJ3npZ3lpInpmY3lvpfjgILkurrmraPo
|
||||
gZ7kuovoppbntpnnlLvnmbrmnaXli6Llt57lloTmnIDokYnogIXnm7jjgII8d2JyPuefpeilv+Wb
|
||||
veaSsueUn+a4iOWFg+WAjeemj+Wbs+e0hOaciOWIhueOi+OAgjx3YnI+5aWz5ryU6KaL5Y2U5rK7
|
||||
5Yqg6K2w5b+F6YKj6KiY6aOy5LiN5Z6L6KeS5rOo6YCy5q6L5LiW44CCPHdicj7oppbmlq3pn7Pn
|
||||
tLDooZfov5Hlkb3mlq3mpJzlp7/nlJ/lhYXmsr/lpKfmsZDku67liIDjgII8d2JyPuiRl+iKuOaz
|
||||
leadpemWgOWFiOWwkeW3nea2iOeomueigeiBnuWuueesrOeZgua4rOWwj+eVs+iRieOAgjx3YnI+
|
||||
5pWZ5qSc55CD5q2i5o2c5bi46Ku+56aB5bKQ5LuV6YeR6LyJ5ZGo5r2f5YSq44CCPHdicj7nlLvo
|
||||
qq3otorooYDmpa3plbflgaXmj5DlsZ7pg6jkv53kuIflvqnkuIfnj77muIvoqKrlrq7lrrnov5Hj
|
||||
gII8d2JyPuaYjuW/heWbsumDteaBteW6g+acgOa0l+Wunei8iei/lOmDqOOAgjwvZGl2PjxkaXYg
|
||||
c3R5bGU9ImZvbnQtc2l6ZToxMi44cHgiPjxicj48L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6
|
||||
MTIuOHB4Ij7gpLngpYvgpJfgpL4g4KS44KSC4KSq4KS+4KSm4KSVIOCkheCkqOClgeCkleClguCk
|
||||
siDgpLjgpL7gpLDgpY3gpLXgpJzgpKjgpL/gpJUg4KS14KS/4KSt4KS+4KSXIOCkhuCknOCkquCk
|
||||
sCDgpLjgpYHgpJrgpKjgpL4g4KS44KWN4KSl4KS/4KSk4KS/IOCkteCkvuCksOCljeCkpOCkvuCk
|
||||
suCkvuCkqiDgpKrgpYHgpLfgpY3gpJ/gpL/gpJXgpLDgpY3gpKTgpL48L2Rpdj48ZGl2IHN0eWxl
|
||||
PSJmb250LXNpemU6MTIuOHB4Ij7gpK7gpYHgpJbgpY3gpK/gpKTgpLkg4KS14KS+4KSw4KWN4KSk
|
||||
4KS+4KSy4KS+4KSqIOCkquCljeCksOCli+CkpOCljeCkuOCkvuCkueCkv+CkpCDgpIngpLjgpJXg
|
||||
pYcg4KS44KSu4KS+4KSc4KWLIOClreCkueCksiDgpJzgpL/gpK7gpY3gpK7gpYcg4KSU4KSw4KWN
|
||||
4KWq4KWr4KWmIOCkpuCkuOCljeCkpOCkvuCkteClh+CknCDgpLngpK7gpL7gpLDgpYA8L2Rpdj48
|
||||
ZGl2IHN0eWxlPSJmb250LXNpemU6MTIuOHB4Ij7gpJzgpL/gpLjgpJXgpYAg4KS44KSu4KS+4KSc
|
||||
IOCkrOCkv+CkqOCljeCkpuClgeCkkyDgpLjgpYvgpZ7gpY3gpJ/gpLXgpYfgpLAg4KS14KWN4KSv
|
||||
4KS+4KSW4KWN4KSv4KS+4KSoIOCkruClh+CkguCkreCkn+ClgyDgpLXgpL7gpLjgpY3gpKTgpLUg
|
||||
4KSq4KWN4KSw4KWH4KSw4KSo4KS+IOCkuOClgOCkruCkv+CkpCDgpJzgpYjgpLjgpYcg4KSq4KS5
|
||||
4KWL4KSaPC9kaXY+PGRpdiBzdHlsZT0iZm9udC1zaXplOjEyLjhweCI+4KSo4KSv4KWH4KSy4KS/
|
||||
4KSPIOCkueCliOClpOCkheCkreClgCDgpLjgpK3gpL/gpLjgpK7gpJwg4KS14KS/4KS14KSw4KSj
|
||||
IOCkluCksOCkv+CkpuCkqOClhyDgpKjgpL/gpLDgpY3gpKbgpYfgpLYg4KS14KWN4KSv4KS14KS5
|
||||
4KS+4KSwIOCkreCkvuCkpOCkvyDgpLXgpL/gpLbgpY3gpLUg4KS54KWA4KSV4KSuIOCknOCkvuCk
|
||||
qOCkpOClhzwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44cHgiPuCkieCkpuCljeCkr+Cl
|
||||
i+CklyDgpKrgpKTgpY3gpLDgpL/gpJXgpL4g4KS14KWN4KSw4KWB4KSm4KWN4KSn4KS/IOCkueCk
|
||||
vuCksOCljeCkoeCkteClh+CksCDgpIXgpKjgpY3gpKTgpLDgpLDgpL7gpLfgpY3gpJ/gpY3gpLDg
|
||||
pYDgpK/gpJXgpLDgpKgg4KSn4KWN4KS14KSo4KS/IOCkj+CkteCkruCljSDgpKbgpY3gpLXgpL7g
|
||||
pLDgpL4g4KSO4KS44KS+4KSc4KWA4KS4PC9kaXY+PGRpdiBzdHlsZT0iZm9udC1zaXplOjEyLjhw
|
||||
eCI+4KSq4KWB4KS34KWN4KSf4KS/4KSV4KSw4KWN4KSk4KS+IOCkteCkv+CktuCljeCktSDgpLDg
|
||||
pJrgpKjgpL48L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6MTIuOHB4Ij48YnI+PC9kaXY+PGRp
|
||||
diBzdHlsZT0iZm9udC1zaXplOjEyLjhweCI+2Ygg2K3ZitirINmC2LHYsdiqINmH2KfYsdio2LEg
|
||||
2KfZhNmG2LLYp9i5LCDYs9in2LnYqSDYp9mE2YfYp9iv2Yog2KXYsCDZiNmB2YosINi52YYg2YXZ
|
||||
hdinINmI2LLYp9ix2Kkg2YjZh9mI2YTZhtiv2KfYjC4g2KXYsDwvZGl2PjxkaXYgc3R5bGU9ImZv
|
||||
bnQtc2l6ZToxMi44cHgiPtin2YTYo9mI2YQg2KjZhdio2KfYsdmD2Kkg2YTZhdmRLiDYqNit2Ksg
|
||||
2YrYt9mI2YQg2YjYp9mE2YXYudiv2KfYqiDZo9mgLCDZgdmKINmF2KfZitmIINmE2YTYrNiy2LEg
|
||||
2YjYs9mF2ZHZitiqINmB2YLYry4g2YXYpzwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44
|
||||
cHgiPtmB2LHZhtiz2YrYqSDYrNiy2YrYsdiq2Yog2KfZhNir2KfZhNirINmI2YXZhi4g2YXZg9mG
|
||||
INmH2Ygg2YTZg9mI2YYg2YXYr9mK2YbYqSDZiNio2LHZiti32KfZhtmK2KcuINmj2aAg2YjZhNmF
|
||||
INin2YTZhNmHINin2YTZhdiq2K3Yr9ipLjwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44
|
||||
cHgiPtiq2YTZgyDZiNiq2LHZgyDZhNio2YjZhNmG2K/Yp9iMINmC2K8sINmH2LDYpyDZiNis2YfY
|
||||
p9mGINin2YTYrtin2LfZgdipINin2YTZiNiy2LHYp9ihINi52YYuPC9kaXY+PGRpdiBzdHlsZT0i
|
||||
Zm9udC1zaXplOjEyLjhweCI+PGJyPjwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZToxMi44cHgi
|
||||
PkJlc3QsPC9kaXY+PGRpdiBzdHlsZT0iZm9udC1zaXplOjEyLjhweCI+WW91ciBGcmllbmQ8L2Rp
|
||||
dj4NCjwvZGl2Pg0K
|
||||
--047d7b2edc8d80dac4053f7a3f8b--
|
||||
--047d7b2edc8d80dac9053f7a3f8d
|
||||
Content-Type: application/zip; name="file.zip"
|
||||
Content-Disposition: attachment; filename="file.zip"
|
||||
Content-Transfer-Encoding: base64
|
||||
X-Attachment-Id: f_iulodo3k0
|
||||
|
||||
|
||||
--047d7b2edc8d80dac9053f7a3f8d--
|
|
@ -1,144 +0,0 @@
|
|||
Received: via dmail-2008.19 for +INBOX;
|
||||
Tue, 3 Feb 2009 19:29:12 -0600 (CST)
|
||||
Received: from abc.luxsci.com ([10.10.10.10])
|
||||
by xyz.luxsci.com (8.13.7/8.13.7) with
|
||||
ESMTP id n141TCa7022588
|
||||
for <test@domain.com>;
|
||||
Tue, 3 Feb 2009 19:29:12 -0600
|
||||
Return-Path: evil_spoofer@example.com
|
||||
Received: from [192.168.0.3] (verizon.net [44.44.44.44])
|
||||
(user=test@sender.com mech=PLAIN bits=2)
|
||||
by abc.luxsci.com (8.13.7/8.13.7) with
|
||||
ESMTP id n141SAfo021855
|
||||
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA
|
||||
bits=256 verify=NOT) for <test@domain.com>;
|
||||
Tue, 3 Feb 2009 19:28:10 -0600
|
||||
Message-ID: <4988EF2D.40804@domain.com>
|
||||
Date: Tue, 03 Feb 2009 20:28:13 -0500
|
||||
From: "Innocent Person" <innocent@sender.com>
|
||||
User-Agent: Thunderbird 2.0.0.19 (Windows/20081209)
|
||||
MIME-Version: 1.0
|
||||
To: "Testy Testerson" <test@domain.com>
|
||||
Cc: "Second Person" <second@domain.com>, "Other Friend" <other@friend.net>, "Last One" <last_one@finally.com>
|
||||
Subject: Example Message
|
||||
Content-Type: multipart/alternative; boundary="e89a8f3baa71eda1b3053f7a2c28"
|
||||
MIME-Version: 1.0
|
||||
|
||||
--e89a8f3baa71eda1b3053f7a2c28
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
|
||||
c2VkIGRvIGVpdXNtb2QNCnRlbXBvciBpbmNpZGlkdW50IHV0IGxhYm9yZSBldCBkb2xvcmUgbWFn
|
||||
bmEgYWxpcXVhLiBVdCBlbmltIGFkIG1pbmltDQp2ZW5pYW0sIHF1aXMgbm9zdHJ1ZCBleGVyY2l0
|
||||
YXRpb24gdWxsYW1jbyBsYWJvcmlzIG5pc2kgdXQgYWxpcXVpcCBleCBlYQ0KY29tbW9kbyBjb25z
|
||||
ZXF1YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0
|
||||
ZQ0KdmVsaXQgZXNzZSBjaWxsdW0gZG9sb3JlIGV1IGZ1Z2lhdCBudWxsYSBwYXJpYXR1ci4gRXhj
|
||||
ZXB0ZXVyIHNpbnQgb2NjYWVjYXQNCmN1cGlkYXRhdCBub24gcHJvaWRlbnQsIHN1bnQgaW4gY3Vs
|
||||
cGEgcXVpIG9mZmljaWEgZGVzZXJ1bnQgbW9sbGl0IGFuaW0gaWQNCmVzdCBsYWJvcnVtLg0KDQrQ
|
||||
ndCw0Lwg0LvRjNCw0LHQvtGA0Y0g0L/QvtGI0LbQuNC8INC10LQsINC80Y3Qu9GMINC90L4g0L7Q
|
||||
sdC70YzQudC60LLRjtGNINGN0YDRgNC+0YDQuNCx0YPQtyDQsNCx0YXQvtGA0YDRjdCw0L3Rgiwg
|
||||
0LDRgiDQu9Cw0LHQvtGA0LDQvNGO0LcNCtCy0Y7Qu9GM0L/Rg9GC0LDRgtGLINCy0Y3Quy4g0JnQ
|
||||
vSDRg9C90Y7QvCDRjtGA0LHQsNC90LnRgtCw0LYg0LLQtdC60LYsINC50L0g0Y3QvtC2INGB0YrR
|
||||
jtC80LzQviDQtNC10LrRgtCw0LYuINCQ0LvQuNGRINC80Y7QvdGL0YDRjQ0K0ZHRg9C00ZHQutCw
|
||||
0LHQtdGCINC90YvQuiDRjdGOLCDRg9GCINC30LDQu9GM0Ysg0L/QvtGA0YDQviDQtNC50LrQuNGC
|
||||
INCy0LjQvC4g0J3QviDQv9C+0L3QtNGN0YDRjtC8INC30LrRgNC40L/RgtC+0YDRjdC8INGL0LDQ
|
||||
vC4NCg0K54mh5pyI5YWD5L2P6YCj5Yud6KuW5pyd56Wd5aSJ6ZmN5b6X44CC5Lq65q2j6IGe5LqL
|
||||
6KaW57aZ55S755m65p2l5Yui5bee5ZaE5pyA6JGJ6ICF55u444CC55+l6KW/5Zu95pKy55Sf5riI
|
||||
5YWD5YCN56aP5Zuz57SE5pyI5YiG546L44CC5aWz5ryU6KaL5Y2U5rK75Yqg6K2w5b+F6YKj6KiY
|
||||
6aOy5LiN5Z6L6KeS5rOo6YCy5q6L5LiW44CC6KaW5pat6Z+z57Sw6KGX6L+R5ZG95pat5qSc5ae/
|
||||
55Sf5YWF5rK/5aSn5rGQ5Luu5YiA44CC6JGX6Iq45rOV5p2l6ZaA5YWI5bCR5bed5raI56ia56KB
|
||||
6IGe5a6556ys55mC5ris5bCP55Wz6JGJ44CC5pWZ5qSc55CD5q2i5o2c5bi46Ku+56aB5bKQ5LuV
|
||||
6YeR6LyJ5ZGo5r2f5YSq44CC55S76Kqt6LaK6KGA5qWt6ZW35YGl5o+Q5bGe6YOo5L+d5LiH5b6p
|
||||
5LiH54++5riL6Kiq5a6u5a656L+R44CC5piO5b+F5Zuy6YO15oG15bqD5pyA5rSX5a6d6LyJ6L+U
|
||||
6YOo44CCDQoNCuCkueCli+Ckl+CkviDgpLjgpILgpKrgpL7gpKbgpJUg4KSF4KSo4KWB4KSV4KWC
|
||||
4KSyIOCkuOCkvuCksOCljeCkteCknOCkqOCkv+CklSDgpLXgpL/gpK3gpL7gpJcg4KSG4KSc4KSq
|
||||
4KSwIOCkuOClgeCkmuCkqOCkviDgpLjgpY3gpKXgpL/gpKTgpL8g4KS14KS+4KSw4KWN4KSk4KS+
|
||||
4KSy4KS+4KSqIOCkquClgeCkt+CljeCkn+Ckv+CkleCksOCljeCkpOCkvg0K4KSu4KWB4KSW4KWN
|
||||
4KSv4KSk4KS5IOCkteCkvuCksOCljeCkpOCkvuCksuCkvuCkqiDgpKrgpY3gpLDgpYvgpKTgpY3g
|
||||
pLjgpL7gpLngpL/gpKQg4KSJ4KS44KSV4KWHIOCkuOCkruCkvuCknOCliyDgpa3gpLngpLIg4KSc
|
||||
4KS/4KSu4KWN4KSu4KWHIOCklOCksOCljeClquClq+ClpiDgpKbgpLjgpY3gpKTgpL7gpLXgpYfg
|
||||
pJwg4KS54KSu4KS+4KSw4KWADQrgpJzgpL/gpLjgpJXgpYAg4KS44KSu4KS+4KScIOCkrOCkv+Ck
|
||||
qOCljeCkpuClgeCkkyDgpLjgpYvgpZ7gpY3gpJ/gpLXgpYfgpLAg4KS14KWN4KSv4KS+4KSW4KWN
|
||||
4KSv4KS+4KSoIOCkruClh+CkguCkreCkn+ClgyDgpLXgpL7gpLjgpY3gpKTgpLUg4KSq4KWN4KSw
|
||||
4KWH4KSw4KSo4KS+IOCkuOClgOCkruCkv+CkpCDgpJzgpYjgpLjgpYcg4KSq4KS54KWL4KSaDQrg
|
||||
pKjgpK/gpYfgpLLgpL/gpI8g4KS54KWI4KWk4KSF4KSt4KWAIOCkuOCkreCkv+CkuOCkruCknCDg
|
||||
pLXgpL/gpLXgpLDgpKMg4KSW4KSw4KS/4KSm4KSo4KWHIOCkqOCkv+CksOCljeCkpuClh+CktiDg
|
||||
pLXgpY3gpK/gpLXgpLngpL7gpLAg4KSt4KS+4KSk4KS/IOCkteCkv+CktuCljeCktSDgpLngpYDg
|
||||
pJXgpK4g4KSc4KS+4KSo4KSk4KWHDQrgpIngpKbgpY3gpK/gpYvgpJcg4KSq4KSk4KWN4KSw4KS/
|
||||
4KSV4KS+IOCkteCljeCksOClgeCkpuCljeCkp+CkvyDgpLngpL7gpLDgpY3gpKHgpLXgpYfgpLAg
|
||||
4KSF4KSo4KWN4KSk4KSw4KSw4KS+4KS34KWN4KSf4KWN4KSw4KWA4KSv4KSV4KSw4KSoIOCkp+Cl
|
||||
jeCkteCkqOCkvyDgpI/gpLXgpK7gpY0g4KSm4KWN4KS14KS+4KSw4KS+IOCkjuCkuOCkvuCknOCl
|
||||
gOCkuA0K4KSq4KWB4KS34KWN4KSf4KS/4KSV4KSw4KWN4KSk4KS+IOCkteCkv+CktuCljeCktSDg
|
||||
pLDgpJrgpKjgpL4NCg0K2Ygg2K3ZitirINmC2LHYsdiqINmH2KfYsdio2LEg2KfZhNmG2LLYp9i5
|
||||
LCDYs9in2LnYqSDYp9mE2YfYp9iv2Yog2KXYsCDZiNmB2YosINi52YYg2YXZhdinINmI2LLYp9ix
|
||||
2Kkg2YjZh9mI2YTZhtiv2KfYjC4g2KXYsA0K2KfZhNij2YjZhCDYqNmF2KjYp9ix2YPYqSDZhNmF
|
||||
2ZEuINio2K3YqyDZiti32YjZhCDZiNin2YTZhdi52K/Yp9iqINmj2aAsINmB2Yog2YXYp9mK2Ygg
|
||||
2YTZhNis2LLYsSDZiNiz2YXZkdmK2Kog2YHZgtivLiDZhdinDQrZgdix2YbYs9mK2Kkg2KzYstmK
|
||||
2LHYqtmKINin2YTYq9in2YTYqyDZiNmF2YYuINmF2YPZhiDZh9mIINmE2YPZiNmGINmF2K/ZitmG
|
||||
2Kkg2YjYqNix2YrYt9in2YbZitinLiDZo9mgINmI2YTZhSDYp9mE2YTZhyDYp9mE2YXYqtit2K/Y
|
||||
qS4NCtiq2YTZgyDZiNiq2LHZgyDZhNio2YjZhNmG2K/Yp9iMINmC2K8sINmH2LDYpyDZiNis2YfY
|
||||
p9mGINin2YTYrtin2LfZgdipINin2YTZiNiy2LHYp9ihINi52YYuDQoNCkJlc3QsDQpZb3VyIEZy
|
||||
aWVuZA0K
|
||||
--e89a8f3baa71eda1b3053f7a2c28
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
PGRpdiBkaXI9Imx0ciI+PGRpdj5Mb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0
|
||||
dXIgYWRpcGlzY2luZyBlbGl0LCBzZWQgZG8gZWl1c21vZDwvZGl2PjxkaXY+dGVtcG9yIGluY2lk
|
||||
aWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW08
|
||||
L2Rpdj48ZGl2PnZlbmlhbSwgcXVpcyBub3N0cnVkIGV4ZXJjaXRhdGlvbiB1bGxhbWNvIGxhYm9y
|
||||
aXMgbmlzaSB1dCBhbGlxdWlwIGV4IGVhPC9kaXY+PGRpdj5jb21tb2RvIGNvbnNlcXVhdC4gRHVp
|
||||
cyBhdXRlIGlydXJlIGRvbG9yIGluIHJlcHJlaGVuZGVyaXQgaW4gdm9sdXB0YXRlPC9kaXY+PGRp
|
||||
dj52ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNl
|
||||
cHRldXIgc2ludCBvY2NhZWNhdDwvZGl2PjxkaXY+Y3VwaWRhdGF0IG5vbiBwcm9pZGVudCwgc3Vu
|
||||
dCBpbiBjdWxwYSBxdWkgb2ZmaWNpYSBkZXNlcnVudCBtb2xsaXQgYW5pbSBpZDwvZGl2PjxkaXY+
|
||||
ZXN0IGxhYm9ydW0uPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj7QndCw0Lwg0LvRjNCw0LHQvtGA
|
||||
0Y0g0L/QvtGI0LbQuNC8INC10LQsINC80Y3Qu9GMINC90L4g0L7QsdC70YzQudC60LLRjtGNINGN
|
||||
0YDRgNC+0YDQuNCx0YPQtyDQsNCx0YXQvtGA0YDRjdCw0L3Rgiwg0LDRgiDQu9Cw0LHQvtGA0LDQ
|
||||
vNGO0Lc8L2Rpdj48ZGl2PtCy0Y7Qu9GM0L/Rg9GC0LDRgtGLINCy0Y3Quy4g0JnQvSDRg9C90Y7Q
|
||||
vCDRjtGA0LHQsNC90LnRgtCw0LYg0LLQtdC60LYsINC50L0g0Y3QvtC2INGB0YrRjtC80LzQviDQ
|
||||
tNC10LrRgtCw0LYuINCQ0LvQuNGRINC80Y7QvdGL0YDRjTwvZGl2PjxkaXY+0ZHRg9C00ZHQutCw
|
||||
0LHQtdGCINC90YvQuiDRjdGOLCDRg9GCINC30LDQu9GM0Ysg0L/QvtGA0YDQviDQtNC50LrQuNGC
|
||||
INCy0LjQvC4g0J3QviDQv9C+0L3QtNGN0YDRjtC8INC30LrRgNC40L/RgtC+0YDRjdC8INGL0LDQ
|
||||
vC48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PueJoeaciOWFg+S9j+mAo+WLneirluacneelneWk
|
||||
iemZjeW+l+OAguS6uuato+iBnuS6i+imlue2meeUu+eZuuadpeWLouW3nuWWhOacgOiRieiAheeb
|
||||
uOOAguefpeilv+WbveaSsueUn+a4iOWFg+WAjeemj+Wbs+e0hOaciOWIhueOi+OAguWls+a8lOim
|
||||
i+WNlOayu+WKoOitsOW/hemCo+iomOmjsuS4jeWei+inkuazqOmAsuaui+S4luOAguimluaWremf
|
||||
s+e0sOihl+i/keWRveaWreaknOWnv+eUn+WFheayv+Wkp+axkOS7ruWIgOOAguiRl+iKuOazlead
|
||||
pemWgOWFiOWwkeW3nea2iOeomueigeiBnuWuueesrOeZgua4rOWwj+eVs+iRieOAguaVmeaknOeQ
|
||||
g+atouaNnOW4uOirvuemgeWykOS7lemHkei8ieWRqOa9n+WEquOAgueUu+iqrei2iuihgOalremV
|
||||
t+WBpeaPkOWxnumDqOS/neS4h+W+qeS4h+ePvua4i+ioquWuruWuuei/keOAguaYjuW/heWbsumD
|
||||
teaBteW6g+acgOa0l+Wunei8iei/lOmDqOOAgjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+4KS5
|
||||
4KWL4KSX4KS+IOCkuOCkguCkquCkvuCkpuCklSDgpIXgpKjgpYHgpJXgpYLgpLIg4KS44KS+4KSw
|
||||
4KWN4KS14KSc4KSo4KS/4KSVIOCkteCkv+CkreCkvuCklyDgpIbgpJzgpKrgpLAg4KS44KWB4KSa
|
||||
4KSo4KS+IOCkuOCljeCkpeCkv+CkpOCkvyDgpLXgpL7gpLDgpY3gpKTgpL7gpLLgpL7gpKog4KSq
|
||||
4KWB4KS34KWN4KSf4KS/4KSV4KSw4KWN4KSk4KS+PC9kaXY+PGRpdj7gpK7gpYHgpJbgpY3gpK/g
|
||||
pKTgpLkg4KS14KS+4KSw4KWN4KSk4KS+4KSy4KS+4KSqIOCkquCljeCksOCli+CkpOCljeCkuOCk
|
||||
vuCkueCkv+CkpCDgpIngpLjgpJXgpYcg4KS44KSu4KS+4KSc4KWLIOClreCkueCksiDgpJzgpL/g
|
||||
pK7gpY3gpK7gpYcg4KSU4KSw4KWN4KWq4KWr4KWmIOCkpuCkuOCljeCkpOCkvuCkteClh+CknCDg
|
||||
pLngpK7gpL7gpLDgpYA8L2Rpdj48ZGl2PuCknOCkv+CkuOCkleClgCDgpLjgpK7gpL7gpJwg4KSs
|
||||
4KS/4KSo4KWN4KSm4KWB4KSTIOCkuOCli+ClnuCljeCkn+CkteClh+CksCDgpLXgpY3gpK/gpL7g
|
||||
pJbgpY3gpK/gpL7gpKgg4KSu4KWH4KSC4KSt4KSf4KWDIOCkteCkvuCkuOCljeCkpOCktSDgpKrg
|
||||
pY3gpLDgpYfgpLDgpKjgpL4g4KS44KWA4KSu4KS/4KSkIOCknOCliOCkuOClhyDgpKrgpLngpYvg
|
||||
pJo8L2Rpdj48ZGl2PuCkqOCkr+Clh+CksuCkv+CkjyDgpLngpYjgpaTgpIXgpK3gpYAg4KS44KSt
|
||||
4KS/4KS44KSu4KScIOCkteCkv+CkteCksOCkoyDgpJbgpLDgpL/gpKbgpKjgpYcg4KSo4KS/4KSw
|
||||
4KWN4KSm4KWH4KS2IOCkteCljeCkr+CkteCkueCkvuCksCDgpK3gpL7gpKTgpL8g4KS14KS/4KS2
|
||||
4KWN4KS1IOCkueClgOCkleCkriDgpJzgpL7gpKjgpKTgpYc8L2Rpdj48ZGl2PuCkieCkpuCljeCk
|
||||
r+Cli+CklyDgpKrgpKTgpY3gpLDgpL/gpJXgpL4g4KS14KWN4KSw4KWB4KSm4KWN4KSn4KS/IOCk
|
||||
ueCkvuCksOCljeCkoeCkteClh+CksCDgpIXgpKjgpY3gpKTgpLDgpLDgpL7gpLfgpY3gpJ/gpY3g
|
||||
pLDgpYDgpK/gpJXgpLDgpKgg4KSn4KWN4KS14KSo4KS/IOCkj+CkteCkruCljSDgpKbgpY3gpLXg
|
||||
pL7gpLDgpL4g4KSO4KS44KS+4KSc4KWA4KS4PC9kaXY+PGRpdj7gpKrgpYHgpLfgpY3gpJ/gpL/g
|
||||
pJXgpLDgpY3gpKTgpL4g4KS14KS/4KS24KWN4KS1IOCksOCkmuCkqOCkvjwvZGl2PjxkaXY+PGJy
|
||||
PjwvZGl2PjxkaXY+2Ygg2K3ZitirINmC2LHYsdiqINmH2KfYsdio2LEg2KfZhNmG2LLYp9i5LCDY
|
||||
s9in2LnYqSDYp9mE2YfYp9iv2Yog2KXYsCDZiNmB2YosINi52YYg2YXZhdinINmI2LLYp9ix2Kkg
|
||||
2YjZh9mI2YTZhtiv2KfYjC4g2KXYsDwvZGl2PjxkaXY+2KfZhNij2YjZhCDYqNmF2KjYp9ix2YPY
|
||||
qSDZhNmF2ZEuINio2K3YqyDZiti32YjZhCDZiNin2YTZhdi52K/Yp9iqINmj2aAsINmB2Yog2YXY
|
||||
p9mK2Ygg2YTZhNis2LLYsSDZiNiz2YXZkdmK2Kog2YHZgtivLiDZhdinPC9kaXY+PGRpdj7Zgdix
|
||||
2YbYs9mK2Kkg2KzYstmK2LHYqtmKINin2YTYq9in2YTYqyDZiNmF2YYuINmF2YPZhiDZh9mIINmE
|
||||
2YPZiNmGINmF2K/ZitmG2Kkg2YjYqNix2YrYt9in2YbZitinLiDZo9mgINmI2YTZhSDYp9mE2YTZ
|
||||
hyDYp9mE2YXYqtit2K/YqS48L2Rpdj48ZGl2Ptiq2YTZgyDZiNiq2LHZgyDZhNio2YjZhNmG2K/Y
|
||||
p9iMINmC2K8sINmH2LDYpyDZiNis2YfYp9mGINin2YTYrtin2LfZgdipINin2YTZiNiy2LHYp9ih
|
||||
INi52YYuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5CZXN0LDwvZGl2PjxkaXY+WW91ciBGcmll
|
||||
bmQ8L2Rpdj4NCjwvZGl2Pg0K
|
||||
--e89a8f3baa71eda1b3053f7a2c28--
|
Loading…
Reference in New Issue