E-posta Kullanarak Araştırma
Önceki bölümlerde adli ağın önemi ve süreci ve ilgili kavramlar hakkında tartışıldı. Bu bölümde, dijital adli tıpta e-postaların rolünü ve Python kullanarak incelemelerini öğrenelim.
E-postanın Araştırmadaki Rolü
E-postalar, iş iletişiminde çok önemli bir rol oynar ve internetteki en önemli uygulamalardan biri olarak ortaya çıkmıştır. Yalnızca bilgisayarlardan değil, aynı zamanda cep telefonları ve tabletler gibi diğer elektronik cihazlardan da mesajların yanı sıra belge göndermek için uygun bir moddur.
E-postaların olumsuz tarafı, suçluların şirketleri hakkında önemli bilgileri sızdırabilmeleridir. Bu nedenle, e-postaların dijital adli tıp alanındaki rolü son yıllarda artmıştır. Dijital adli tıpta, e-postalar çok önemli kanıtlar olarak kabul edilir ve E-posta Üstbilgi Analizi adli süreç sırasında kanıt toplamak için önemli hale gelmiştir.
Bir araştırmacının, e-posta adli araştırması gerçekleştirirken aşağıdaki hedefleri vardır:
- Ana suçluyu belirlemek için
- Gerekli delilleri toplamak için
- Bulguları sunmak
- Davayı oluşturmak için
E-posta Adli Bilişimindeki Zorluklar
E-posta adli tıp, günümüzdeki iletişimin çoğu e-postalara dayandığından, araştırmada çok önemli bir rol oynamaktadır. Ancak, e-posta adli tıp araştırmacısı, soruşturma sırasında aşağıdaki zorluklarla karşılaşabilir:
Sahte E-postalar
E-posta adli tıp alanındaki en büyük zorluk, üstbilgileri manipüle ederek ve yazarak oluşturulmuş sahte e-postaların kullanılmasıdır. Bu kategoride suçlular, kayıtlı bir kullanıcının süresi dolan geçici bir adresten e-posta almasına izin veren bir hizmet olan geçici e-postayı da kullanır. belirli bir süre sonra.
Adres sahteciliği
E-posta adli tıpta bir başka zorluk, suçluların bir e-postayı başkasınınki gibi sunmaya alıştıkları sahtekarlıktır. Bu durumda makine hem sahte hem de orijinal IP adresi alacaktır.
Anonim Yeniden E-posta Gönderme
Burada, E-posta sunucusu, daha fazla iletmeden önce, e-posta mesajındaki tanımlayıcı bilgileri çıkarır. Bu, e-posta araştırmaları için başka bir büyük zorluğa yol açar.
E-posta Adli Soruşturmasında Kullanılan Teknikler
E-posta adli bilişim, bir iletinin gerçek göndereni ve alıcısının yanı sıra aktarım tarihi / saati ve gönderenin niyeti gibi bazı diğer bilgileri tanımlamak için kanıt olarak e-postanın kaynağı ve içeriğinin incelenmesidir. Meta verileri araştırmayı, bağlantı noktası taramayı ve anahtar kelime aramasını içerir.
E-posta adli inceleme için kullanılabilecek yaygın tekniklerden bazıları şunlardır:
- Başlık Analizi
- Sunucu araştırması
- Ağ Cihazı İncelemesi
- Gönderen Posta Gönderen Parmak İzleri
- Yazılım Gömülü Tanımlayıcılar
Aşağıdaki bölümlerde, e-posta incelemesi amacıyla Python kullanarak nasıl bilgi getirileceğini öğreneceğiz.
EML dosyalarından Bilgilerin Çıkarılması
EML dosyaları temelde e-posta mesajlarını depolamak için yaygın olarak kullanılan dosya biçimindeki e-postalardır. Microsoft Outlook, Outlook Express ve Windows Live Mail gibi birden çok e-posta istemcisi ile uyumlu yapılandırılmış metin dosyalarıdır.
Bir EML dosyası, e-posta başlıklarını, gövde içeriğini, ek verilerini düz metin olarak depolar. İkili verileri kodlamak için base64 ve içerik bilgilerini depolamak için Quoted-Printable (QP) kodlamayı kullanır. EML dosyasından bilgi çıkarmak için kullanılabilecek Python betiği aşağıda verilmiştir -
Öncelikle, aşağıdaki Python kitaplıklarını aşağıda gösterildiği gibi içe aktarın -
from __future__ import print_function
from argparse import ArgumentParser, FileType
from email import message_from_file
import os
import quopri
import base64
Yukarıdaki kütüphanelerde, quopriEML dosyalarından QP kodlu değerlerin kodunu çözmek için kullanılır. Base64 kodlu herhangi bir verinin şifresi çözülebilir.base64 kütüphane.
Sonra, komut satırı işleyicisi için argüman sağlayalım. Burada, aşağıda gösterildiği gibi EML dosyasının yolu olabilecek tek bir argümanı kabul edeceğini unutmayın -
if __name__ == '__main__':
parser = ArgumentParser('Extracting information from EML file')
parser.add_argument("EML_FILE",help="Path to EML File", type=FileType('r'))
args = parser.parse_args()
main(args.EML_FILE)
Şimdi tanımlamalıyız main() isimli yöntemi kullanacağımız fonksiyon message_from_file()e-posta kitaplığından dosyayı nesne gibi okumak için. Burada sonuçta adı verilen değişkeni kullanarak başlıklara, gövde içeriğine, eklere ve diğer yük bilgilerine erişeceğiz.emlfile aşağıda verilen kodda gösterildiği gibi -
def main(input_file):
emlfile = message_from_file(input_file)
for key, value in emlfile._headers:
print("{}: {}".format(key, value))
print("\nBody\n")
if emlfile.is_multipart():
for part in emlfile.get_payload():
process_payload(part)
else:
process_payload(emlfile[1])
Şimdi tanımlamalıyız process_payload() kullanarak mesaj gövde içeriğini çıkaracağımız yöntem get_payload()yöntem. QP kodlu verilerin kodunu kullanarakquopri.decodestring()işlevi. E-postanın depolanmasını düzgün bir şekilde idare edebilmesi için içerik MIME türünü de kontrol edeceğiz. Aşağıda verilen koda uyun -
def process_payload(payload):
print(payload.get_content_type() + "\n" + "=" * len(payload.get_content_type()))
body = quopri.decodestring(payload.get_payload())
if payload.get_charset():
body = body.decode(payload.get_charset())
else:
try:
body = body.decode()
except UnicodeDecodeError:
body = body.decode('cp1252')
if payload.get_content_type() == "text/html":
outfile = os.path.basename(args.EML_FILE.name) + ".html"
open(outfile, 'w').write(body)
elif payload.get_content_type().startswith('application'):
outfile = open(payload.get_filename(), 'wb')
body = base64.b64decode(payload.get_payload())
outfile.write(body)
outfile.close()
print("Exported: {}\n".format(outfile.name))
else:
print(body)
Yukarıdaki betiği çalıştırdıktan sonra, konsolda çeşitli yükler ile birlikte başlık bilgilerini alacağız.
Python kullanarak MSG Dosyalarını Analiz Etme
E-posta mesajları birçok farklı biçimde gelir. MSG, Microsoft Outlook ve Exchange tarafından kullanılan bu tür bir formattır. MSG uzantılı dosyalar, başlıklar ve ana mesaj gövdesi için düz ASCII metni, köprüler ve ekler içerebilir.
Bu bölümde, Outlook API kullanarak MSG dosyasından nasıl bilgi çıkarılacağını öğreneceğiz. Aşağıdaki Python komut dosyasının yalnızca Windows'ta çalışacağını unutmayın. Bunun için, adlı üçüncü taraf Python kitaplığı kurmamız gerekiyor.pywin32 aşağıdaki gibi -
pip install pywin32
Şimdi, gösterilen komutları kullanarak aşağıdaki kitaplıkları içe aktarın -
from __future__ import print_function
from argparse import ArgumentParser
import os
import win32com.client
import pywintypes
Şimdi, komut satırı işleyicisi için bir argüman sağlayalım. Burada, biri MSG dosyasına giden yol, diğeri ise aşağıdaki gibi istenen çıktı klasörü olacak iki bağımsız değişkeni kabul edecektir -
if __name__ == '__main__':
parser = ArgumentParser(‘Extracting information from MSG file’)
parser.add_argument("MSG_FILE", help="Path to MSG file")
parser.add_argument("OUTPUT_DIR", help="Path to output folder")
args = parser.parse_args()
out_dir = args.OUTPUT_DIR
if not os.path.exists(out_dir):
os.makedirs(out_dir)
main(args.MSG_FILE, args.OUTPUT_DIR)
Şimdi tanımlamalıyız main() arayacağımız fonksiyon win32com kurmak için kitaplık Outlook API hangi daha fazla erişim sağlar MAPI ad alanı.
def main(msg_file, output_dir):
mapi = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
msg = mapi.OpenSharedItem(os.path.abspath(args.MSG_FILE))
display_msg_attribs(msg)
display_msg_recipients(msg)
extract_msg_body(msg, output_dir)
extract_attachments(msg, output_dir)
Şimdi, bu komut dosyasında kullandığımız farklı işlevleri tanımlayın. Aşağıda verilen kod,display_msg_attribs() konu, alıcı, BCC, CC, Boyut, GönderenAdı, gönderildi, vb. gibi bir mesajın çeşitli özelliklerini görüntülememizi sağlayan işlev.
def display_msg_attribs(msg):
attribs = [
'Application', 'AutoForwarded', 'BCC', 'CC', 'Class',
'ConversationID', 'ConversationTopic', 'CreationTime',
'ExpiryTime', 'Importance', 'InternetCodePage', 'IsMarkedAsTask',
'LastModificationTime', 'Links','ReceivedTime', 'ReminderSet',
'ReminderTime', 'ReplyRecipientNames', 'Saved', 'Sender',
'SenderEmailAddress', 'SenderEmailType', 'SenderName', 'Sent',
'SentOn', 'SentOnBehalfOfName', 'Size', 'Subject',
'TaskCompletedDate', 'TaskDueDate', 'To', 'UnRead'
]
print("\nMessage Attributes")
for entry in attribs:
print("{}: {}".format(entry, getattr(msg, entry, 'N/A')))
Şimdi tanımlayın display_msg_recipeints() Mesajları yineleyen ve alıcı ayrıntılarını görüntüleyen işlev.
def display_msg_recipients(msg):
recipient_attrib = ['Address', 'AutoResponse', 'Name', 'Resolved', 'Sendable']
i = 1
while True:
try:
recipient = msg.Recipients(i)
except pywintypes.com_error:
break
print("\nRecipient {}".format(i))
print("=" * 15)
for entry in recipient_attrib:
print("{}: {}".format(entry, getattr(recipient, entry, 'N/A')))
i += 1
Sonra, tanımlıyoruz extract_msg_body() Mesajdan gövde içeriğini, HTML'nin yanı sıra Düz metni çıkaran işlev.
def extract_msg_body(msg, out_dir):
html_data = msg.HTMLBody.encode('cp1252')
outfile = os.path.join(out_dir, os.path.basename(args.MSG_FILE))
open(outfile + ".body.html", 'wb').write(html_data)
print("Exported: {}".format(outfile + ".body.html"))
body_data = msg.Body.encode('cp1252')
open(outfile + ".body.txt", 'wb').write(body_data)
print("Exported: {}".format(outfile + ".body.txt"))
Sonra, tanımlayacağız extract_attachments() ek verilerini istenen çıktı dizinine aktaran işlev.
def extract_attachments(msg, out_dir):
attachment_attribs = ['DisplayName', 'FileName', 'PathName', 'Position', 'Size']
i = 1 # Attachments start at 1
while True:
try:
attachment = msg.Attachments(i)
except pywintypes.com_error:
break
Tüm işlevler tanımlandıktan sonra, tüm öznitelikleri aşağıdaki kod satırıyla konsola yazdıracağız -
print("\nAttachment {}".format(i))
print("=" * 15)
for entry in attachment_attribs:
print('{}: {}'.format(entry, getattr(attachment, entry,"N/A")))
outfile = os.path.join(os.path.abspath(out_dir),os.path.split(args.MSG_FILE)[-1])
if not os.path.exists(outfile):
os.makedirs(outfile)
outfile = os.path.join(outfile, attachment.FileName)
attachment.SaveAsFile(outfile)
print("Exported: {}".format(outfile))
i += 1
Yukarıdaki betiği çalıştırdıktan sonra, çıktı dizinindeki birkaç dosyayla birlikte konsol penceresinde ileti özniteliklerini ve eklerini alacağız.
Python kullanarak Google Takeout'tan MBOX dosyalarını yapılandırma
MBOX dosyaları, içinde depolanan mesajları bölen özel biçimlendirmeye sahip metin dosyalarıdır. Genellikle UNIX sistemleri, Thunderbolt ve Google Paket Servisi ile ilişkili olarak bulunurlar.
Bu bölümde, Google Paket Servisi'nden aldığımız MBOX dosyalarını yapılandıracağımız bir Python betiği göreceksiniz. Ancak bundan önce, bu MBOX dosyalarını Google hesabımızı veya Gmail hesabımızı kullanarak nasıl oluşturabileceğimizi bilmeliyiz.
Google Hesabı Posta Kutusunu MBX Biçimine Alma
Google hesabı posta kutusunun alınması, Gmail hesabımızın yedeğini almak anlamına gelir. Çeşitli kişisel veya profesyonel nedenlerle yedek alınabilir. Google'ın, Gmail verilerinin yedeklenmesini sağladığını unutmayın. Google hesabı posta kutumuzu MBOX biçiminde almak için, aşağıda verilen adımları izlemeniz gerekir -
Açık My account Gösterge Paneli.
Kişisel bilgiler ve gizlilik bölümüne gidin ve İçeriğinizi kontrol edin bağlantısını seçin.
Yeni bir arşiv oluşturabilir veya mevcut bir arşivi yönetebilirsiniz. Tıklarsak,CREATE ARCHIVE bağlantısını tıklayın, eklemek istediğimiz her Google ürünü için bazı onay kutuları alacağız.
Ürünleri seçtikten sonra, arşivimiz için dosya türünü ve maksimum boyutu seçme özgürlüğünün yanı sıra listeden seçim yapabileceğiniz teslim yöntemini de elde edeceğiz.
Son olarak, bu yedeği MBOX formatında alacağız.
Python Kodu
Şimdi, yukarıda tartışılan MBOX dosyası, aşağıda gösterildiği gibi Python kullanılarak yapılandırılabilir -
Öncelikle, aşağıdaki gibi Python kitaplıklarını içe aktarmanız gerekir -
from __future__ import print_function
from argparse import ArgumentParser
import mailbox
import os
import time
import csv
from tqdm import tqdm
import base64
Tüm kitaplıklar, daha önceki betiklerde kullanılmış ve açıklanmıştır. mailbox MBOX dosyalarını ayrıştırmak için kullanılan kitaplık.
Şimdi, komut satırı işleyicisi için bir bağımsız değişken sağlayın. Burada iki bağımsız değişkeni kabul edecektir - biri MBOX dosyasına giden yol, diğeri ise istenen çıktı klasörü olacaktır.
if __name__ == '__main__':
parser = ArgumentParser('Parsing MBOX files')
parser.add_argument("MBOX", help="Path to mbox file")
parser.add_argument(
"OUTPUT_DIR",help = "Path to output directory to write report ""and exported content")
args = parser.parse_args()
main(args.MBOX, args.OUTPUT_DIR)
Şimdi tanımlayacak main() işlev ve çağrı mbox Bir MBOX dosyasını yolunu sağlayarak ayrıştırabileceğimiz bir posta kutusu kitaplığı sınıfı -
def main(mbox_file, output_dir):
print("Reading mbox file")
mbox = mailbox.mbox(mbox_file, factory=custom_reader)
print("{} messages to parse".format(len(mbox)))
Şimdi, bir okuyucu yöntemi tanımlayın mailbox kütüphane aşağıdaki gibidir -
def custom_reader(data_stream):
data = data_stream.read()
try:
content = data.decode("ascii")
except (UnicodeDecodeError, UnicodeEncodeError) as e:
content = data.decode("cp1252", errors="replace")
return mailbox.mboxMessage(content)
Şimdi, daha ileri işlemler için aşağıdaki gibi bazı değişkenler oluşturun -
parsed_data = []
attachments_dir = os.path.join(output_dir, "attachments")
if not os.path.exists(attachments_dir):
os.makedirs(attachments_dir)
columns = [
"Date", "From", "To", "Subject", "X-Gmail-Labels", "Return-Path", "Received",
"Content-Type", "Message-ID","X-GM-THRID", "num_attachments_exported", "export_path"]
Sonra kullan tqdm bir ilerleme çubuğu oluşturmak ve yineleme sürecini aşağıdaki gibi izlemek için -
for message in tqdm(mbox):
msg_data = dict()
header_data = dict(message._headers)
for hdr in columns:
msg_data[hdr] = header_data.get(hdr, "N/A")
Şimdi, hava durumu mesajının yüklü olup olmadığını kontrol edin. Eğer sahipse o zaman tanımlayacağızwrite_payload() yöntem aşağıdaki gibidir -
if len(message.get_payload()):
export_path = write_payload(message, attachments_dir)
msg_data['num_attachments_exported'] = len(export_path)
msg_data['export_path'] = ", ".join(export_path)
Şimdi verilerin eklenmesi gerekiyor. Sonra arayacağızcreate_report() yöntem aşağıdaki gibidir -
parsed_data.append(msg_data)
create_report(
parsed_data, os.path.join(output_dir, "mbox_report.csv"), columns)
def write_payload(msg, out_dir):
pyld = msg.get_payload()
export_path = []
if msg.is_multipart():
for entry in pyld:
export_path += write_payload(entry, out_dir)
else:
content_type = msg.get_content_type()
if "application/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "image/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "video/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "audio/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "text/csv" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "info/" in content_type.lower():
export_path.append(export_content(msg, out_dir,
msg.get_payload()))
elif "text/calendar" in content_type.lower():
export_path.append(export_content(msg, out_dir,
msg.get_payload()))
elif "text/rtf" in content_type.lower():
export_path.append(export_content(msg, out_dir,
msg.get_payload()))
else:
if "name=" in msg.get('Content-Disposition', "N/A"):
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "name=" in msg.get('Content-Type', "N/A"):
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
return export_path
Yukarıdaki if-else ifadelerinin anlaşılmasının kolay olduğuna dikkat edin. Şimdi, dosya adını dosyadan çıkaracak bir yöntem tanımlamamız gerekiyor.msg aşağıdaki gibi nesne -
def export_content(msg, out_dir, content_data):
file_name = get_filename(msg)
file_ext = "FILE"
if "." in file_name: file_ext = file_name.rsplit(".", 1)[-1]
file_name = "{}_{:.4f}.{}".format(file_name.rsplit(".", 1)[0], time.time(), file_ext)
file_name = os.path.join(out_dir, file_name)
Şimdi, aşağıdaki kod satırlarının yardımıyla, dosyayı gerçekten dışa aktarabilirsiniz -
if isinstance(content_data, str):
open(file_name, 'w').write(content_data)
else:
open(file_name, 'wb').write(content_data)
return file_name
Şimdi, dosyadan dosya adlarını çıkarmak için bir işlev tanımlayalım. message bu dosyaların adlarını aşağıdaki gibi doğru bir şekilde temsil etmek için -
def get_filename(msg):
if 'name=' in msg.get("Content-Disposition", "N/A"):
fname_data = msg["Content-Disposition"].replace("\r\n", " ")
fname = [x for x in fname_data.split("; ") if 'name=' in x]
file_name = fname[0].split("=", 1)[-1]
elif 'name=' in msg.get("Content-Type", "N/A"):
fname_data = msg["Content-Type"].replace("\r\n", " ")
fname = [x for x in fname_data.split("; ") if 'name=' in x]
file_name = fname[0].split("=", 1)[-1]
else:
file_name = "NO_FILENAME"
fchars = [x for x in file_name if x.isalnum() or x.isspace() or x == "."]
return "".join(fchars)
Şimdi, bir CSV dosyası yazabiliriz. create_report() aşağıdaki gibi işlev -
def create_report(output_data, output_file, columns):
with open(output_file, 'w', newline="") as outfile:
csvfile = csv.DictWriter(outfile, columns)
csvfile.writeheader()
csvfile.writerows(output_data)
Yukarıda verilen komut dosyasını çalıştırdıktan sonra, CSV raporunu ve eklerle dolu dizini alacağız.