Python Digital Network Forensics-I

W tym rozdziale wyjaśniono podstawy związane z przeprowadzaniem analizy kryminalistycznej sieci przy użyciu języka Python.

Zrozumieć Network Forensics

Kryminalistyka sieci to gałąź kryminalistyki cyfrowej, która zajmuje się monitorowaniem i analizą ruchu w sieci komputerowej, zarówno lokalnej, jak i WAN (sieci rozległej), w celu gromadzenia informacji, gromadzenia dowodów lub wykrywania włamań. Kryminalistyka sieci odgrywa kluczową rolę w badaniu przestępstw cyfrowych, takich jak kradzież własności intelektualnej lub wyciek informacji. Obraz komunikacji sieciowej pomaga badaczowi rozwiązać kilka kluczowych pytań w następujący sposób:

  • Jakie strony internetowe odwiedzono?

  • Jakie treści zostały przesłane do naszej sieci?

  • Jakie treści zostały pobrane z naszej sieci?

  • Do jakich serwerów uzyskuje się dostęp?

  • Czy ktoś wysyła poufne informacje poza zapory firmowe?

Internetowa wyszukiwarka dowodów (IEF)

IEF to cyfrowe narzędzie kryminalistyczne do znajdowania, analizowania i przedstawiania dowodów cyfrowych znajdujących się na różnych nośnikach cyfrowych, takich jak komputer, smartfony, tablety itp. Jest bardzo popularne i używane przez tysiące specjalistów medycyny sądowej.

Korzystanie z IEF

Ze względu na swoją popularność IEF jest w dużym stopniu używany przez kryminalistów. Niektóre zastosowania IEF są następujące:

  • Ze względu na potężne możliwości wyszukiwania służy do jednoczesnego przeszukiwania wielu plików lub nośników danych.

  • Służy również do odzyskiwania usuniętych danych z nieprzydzielonego miejsca w pamięci RAM za pomocą nowych technik rzeźbienia.

  • Jeśli badacze chcą odbudować strony internetowe w ich oryginalnym formacie w dniu ich otwarcia, mogą użyć IEF.

  • Służy również do wyszukiwania woluminów dysków logicznych lub fizycznych.

Zrzut raportów z IEF do CSV przy użyciu Pythona

IEF przechowuje dane w bazie danych SQLite, a następujący skrypt Pythona dynamicznie identyfikuje tabele wyników w bazie danych IEF i zrzuca je do odpowiednich plików CSV.

Ten proces odbywa się w krokach pokazanych poniżej

  • Najpierw wygeneruj bazę wyników IEF, która będzie plikiem bazy danych SQLite z rozszerzeniem .db.

  • Następnie przeprowadź zapytanie do tej bazy danych, aby zidentyfikować wszystkie tabele.

  • Na koniec zapisz te tabele wyników w oddzielnym pliku CSV.

Kod w Pythonie

Zobaczmy, jak w tym celu wykorzystać kod Pythona -

W przypadku skryptu Python zaimportuj niezbędne biblioteki w następujący sposób -

from __future__ import print_function

import argparse
import csv
import os
import sqlite3
import sys

Teraz musimy podać ścieżkę do pliku bazy danych IEF -

if __name__ == '__main__':
   parser = argparse.ArgumentParser('IEF to CSV')
   parser.add_argument("IEF_DATABASE", help="Input IEF database")
   parser.add_argument("OUTPUT_DIR", help="Output DIR")
   args = parser.parse_args()

Teraz potwierdzimy istnienie bazy danych IEF w następujący sposób -

if not os.path.exists(args.OUTPUT_DIR):
   os.makedirs(args.OUTPUT_DIR)
if os.path.exists(args.IEF_DATABASE) and \ os.path.isfile(args.IEF_DATABASE):
   main(args.IEF_DATABASE, args.OUTPUT_DIR)
else:
   print("[-] Supplied input file {} does not exist or is not a " "file".format(args.IEF_DATABASE))
   sys.exit(1)

Teraz, tak jak to zrobiliśmy we wcześniejszych skryptach, połącz się z bazą danych SQLite w następujący sposób, aby wykonać zapytania za pomocą kursora -

def main(database, out_directory):
   print("[+] Connecting to SQLite database")
   conn = sqlite3.connect(database)
   c = conn.cursor()

Następujące wiersze kodu pobiorą nazwy tabel z bazy danych -

print("List of all tables to extract")
c.execute("select * from sqlite_master where type = 'table'")
tables = [x[2] for x in c.fetchall() if not x[2].startswith('_') and not x[2].endswith('_DATA')]

Teraz wybierzemy wszystkie dane z tabeli i za pomocą fetchall() na obiekcie kursora zapiszemy listę krotek zawierających dane tabeli w całości w zmiennej -

print("Dumping {} tables to CSV files in {}".format(len(tables), out_directory))

for table in tables:
c.execute("pragma table_info('{}')".format(table))
table_columns = [x[1] for x in c.fetchall()]

c.execute("select * from '{}'".format(table))
table_data = c.fetchall()

Teraz, używając CSV_Writer() metodę zapiszemy zawartość w pliku CSV -

csv_name = table + '.csv'
csv_path = os.path.join(out_directory, csv_name)
print('[+] Writing {} table to {} CSV file'.format(table,csv_name))

with open(csv_path, "w", newline = "") as csvfile:
   csv_writer = csv.writer(csvfile)
   csv_writer.writerow(table_columns)
   csv_writer.writerows(table_data)

Powyższy skrypt pobierze wszystkie dane z tabel bazy danych IEF i zapisze zawartość do wybranego przez nas pliku CSV.

Praca z danymi w pamięci podręcznej

Z bazy wyników IEF możemy pobrać więcej informacji, które niekoniecznie są obsługiwane przez sam IEF. Możemy pobrać dane z pamięci podręcznej, produkt bi do celów informacyjnych, od dostawcy usług poczty elektronicznej, takiego jak Yahoo, Google itp., Korzystając z bazy danych wyników IEF.

Poniżej znajduje się skrypt Pythona do uzyskiwania dostępu do informacji o danych w pamięci podręcznej z poczty Yahoo, dostępnej w przeglądarce Google Chrome, przy użyciu bazy danych IEF. Zwróć uwagę, że kroki byłyby mniej więcej takie same, jak w ostatnim skrypcie Pythona.

Najpierw zaimportuj niezbędne biblioteki dla Pythona w następujący sposób -

from __future__ import print_function
import argparse
import csv
import os
import sqlite3
import sys
import json

Teraz podaj ścieżkę do pliku bazy danych IEF wraz z dwoma argumentami pozycyjnymi akceptowanymi przez program obsługi wiersza poleceń, tak jak to zrobiono w ostatnim skrypcie -

if __name__ == '__main__':
   parser = argparse.ArgumentParser('IEF to CSV')
   parser.add_argument("IEF_DATABASE", help="Input IEF database")
   parser.add_argument("OUTPUT_DIR", help="Output DIR")
   args = parser.parse_args()

Teraz potwierdź istnienie bazy danych IEF w następujący sposób -

directory = os.path.dirname(args.OUTPUT_CSV)

if not os.path.exists(directory):os.makedirs(directory)
if os.path.exists(args.IEF_DATABASE) and \ os.path.isfile(args.IEF_DATABASE):
   main(args.IEF_DATABASE, args.OUTPUT_CSV)
   else: print("Supplied input file {} does not exist or is not a " "file".format(args.IEF_DATABASE))
sys.exit(1)

Teraz nawiąż połączenie z bazą danych SQLite w następujący sposób, aby wykonać zapytania za pomocą kursora -

def main(database, out_csv):
   print("[+] Connecting to SQLite database")
   conn = sqlite3.connect(database)
   c = conn.cursor()

Możesz użyć następujących wierszy kodu, aby pobrać wystąpienia rekordu pamięci podręcznej kontaktów Yahoo Mail -

print("Querying IEF database for Yahoo Contact Fragments from " "the Chrome Cache Records Table")
   try:
      c.execute("select * from 'Chrome Cache Records' where URL like " "'https://data.mail.yahoo.com" "/classicab/v2/contacts/?format=json%'")
   except sqlite3.OperationalError:
      print("Received an error querying the database --    database may be" "corrupt or not have a Chrome Cache Records table")
      sys.exit(2)

Teraz lista krotek zwróconych z powyższego zapytania do zapisania w zmiennej w następujący sposób -

contact_cache = c.fetchall()
contact_data = process_contacts(contact_cache)
write_csv(contact_data, out_csv)

Zauważ, że tutaj użyjemy dwóch metod, a mianowicie process_contacts() do konfigurowania listy wyników, a także iterowania przez każdy rekord pamięci podręcznej kontaktów i json.loads() do przechowywania danych JSON wyodrębnionych z tabeli w zmiennej w celu dalszej manipulacji -

def process_contacts(contact_cache):
   print("[+] Processing {} cache files matching Yahoo contact cache " " data".format(len(contact_cache)))
   results = []
   
   for contact in contact_cache:
      url = contact[0]
      first_visit = contact[1]
      last_visit = contact[2]
      last_sync = contact[3]
      loc = contact[8]
	   contact_json = json.loads(contact[7].decode())
      total_contacts = contact_json["total"]
      total_count = contact_json["count"]
      
      if "contacts" not in contact_json:
         continue
      for c in contact_json["contacts"]:
         name, anni, bday, emails, phones, links = ("", "", "", "", "", "")
            if "name" in c:
            name = c["name"]["givenName"] + " " + \ c["name"]["middleName"] + " " + c["name"]["familyName"]
            
            if "anniversary" in c:
            anni = c["anniversary"]["month"] + \"/" + c["anniversary"]["day"] + "/" + \c["anniversary"]["year"]
            
            if "birthday" in c:
            bday = c["birthday"]["month"] + "/" + \c["birthday"]["day"] + "/" + c["birthday"]["year"]
            
            if "emails" in c:
               emails = ', '.join([x["ep"] for x in c["emails"]])
            
            if "phones" in c:
               phones = ', '.join([x["ep"] for x in c["phones"]])
            
            if "links" in c:
              links = ', '.join([x["ep"] for x in c["links"]])

Teraz w przypadku firmy, tytułu i notatek używana jest metoda get, jak pokazano poniżej -

company = c.get("company", "")
title = c.get("jobTitle", "")
notes = c.get("notes", "")

Teraz dołączmy listę metadanych i wyodrębnionych elementów danych do listy wyników w następujący sposób -

results.append([url, first_visit, last_visit, last_sync, loc, name, bday,anni, emails, phones, links, company, title, notes,total_contacts, total_count])
return results

Teraz, używając CSV_Writer() metodę, zapiszemy zawartość w pliku CSV -

def write_csv(data, output):
   print("[+] Writing {} contacts to {}".format(len(data), output))
   with open(output, "w", newline="") as csvfile:
      csv_writer = csv.writer(csvfile)
      csv_writer.writerow([
         "URL", "First Visit (UTC)", "Last Visit (UTC)",
         "Last Sync (UTC)", "Location", "Contact Name", "Bday",
         "Anniversary", "Emails", "Phones", "Links", "Company", "Title",
         "Notes", "Total Contacts", "Count of Contacts in Cache"])
      csv_writer.writerows(data)

Za pomocą powyższego skryptu możemy przetwarzać buforowane dane z poczty Yahoo za pomocą bazy danych IEF.