Python数字网络取证-I


本章将解释使用 Python 执行网络取证所涉及的基础知识。

了解网络取证


网络取证是数字取证的一个分支,它处理本地和 WAN(广域网)的计算机网络流量的监控和分析,用于信息收集、证据收集或入侵检测。网络取证在调查诸如知识产权盗窃或信息泄露等数字犯罪方面发挥着关键作用。一张网络通信图可以帮助调查员解决以下几个关键问题:

  • 访问了哪些网站?

  • 我们的网络上传了什么样的内容?

  • 从我们的网络下载了什么样的内容?

  • 正在访问哪些服务器?

  • 有人在公司防火墙之外发送敏感信息吗?

互联网证据查找器 (IEF)


IEF 是一种数字取证工具,用于查找、分析和呈现在计算机、智能手机、平板电脑等不同数字媒体上发现的数字证据。它非常受欢迎并被成千上万的取证专业人士使用。

使用 IEF


由于其受欢迎程度,IEF 在很大程度上被取证专业人员使用。 IEF的一些用途如下:

  • 由于其强大的搜索功能,它用于同时搜索多个文件或数据媒体。

  • 它还用于通过新的雕刻技术从 RAM 的未分配空间中恢复已删除的数据。

  • 如果调查人员想在打开之日以原始格式重建网页,则可以使用 IEF。

  • 它还用于搜索逻辑或物理磁盘卷。

使用 Python 将报告从 IEF 转储到 CSV


IEF 将数据存储在 SQLite 数据库中,以下 Python 脚本将动态识别 IEF 数据库中的结果表并将它们转储到相应的 CSV 文件中。

此过程按如下所示的步骤完成

  • 首先,生成 IEF 结果数据库,它将是一个以 .db 扩展名结尾的 SQLite 数据库文件。

  • 然后,查询该数据库以识别所有表。

  • 最后,将此结果表写入单个 CSV 文件。

Python代码

让我们看看如何为此目的使用 Python 代码:

对于 Python 脚本,导入必要的库如下:

from __future__ import print_function

import argparse
import csv
import os
import sqlite3
import sys

现在,我们需要提供 IEF 数据库文件的路径:

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

现在,我们将确认IEF数据库的存在如下:

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)

现在,就像我们在前面的脚本中所做的那样,与 SQLite 数据库建立连接,通过游标执行查询:

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

以下代码行将从数据库中获取表的名称:

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')]

现在,我们将从表中选择所有数据并使用 获取所有() 在游标对象上的方法中,我们将包含整个表数据的元组列表存储在一个变量中:

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()

现在,通过使用 CSV_Writer() 方法我们将内容写入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)

上面的脚本将从 IEF 数据库的表中获取所有数据,并将内容写入我们选择的 CSV 文件。

使用缓存数据

从 IEF 结果数据库中,我们可以获取更多 IEF 本身不一定支持的信息。我们可以使用 IEF 结果数据库从 Yahoo、Google 等电子邮件服务提供商处获取缓存的数据,这是信息的双产品。

以下是使用IEF数据库从谷歌浏览器访问雅虎邮件缓存数据信息的Python脚本。请注意,这些步骤与上一个 Python 脚本中的步骤或多或少相同。

首先,导入Python所需的库,如下:

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

现在,提供 IEF 数据库文件的路径以及命令行处理程序接受的两个位置参数,如上一个脚本中所做的那样:

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

现在,确认IEF数据库的存在如下:

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)

现在,如下连接 SQLite 数据库,通过游标执行查询:

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

你可以使用以下代码行获取 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)

现在,将从上述查询返回的元组列表保存到一个变量中,如下所示:

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

请注意,这里我们将使用两种方法,即 process_contacts() 用于设置结果列表以及遍历每个联系人缓存记录和 json.loads() 将从表中提取的 JSON 数据存储到变量中以供进一步操作:

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"]])

现在对于公司,标题和注释,使用get方法如下所示:

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

现在,让我们将元数据列表和提取的数据元素附加到结果列表中,如下所示:

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   

现在,通过使用 CSV_Writer() 方法,我们将内容写入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",
            "注意s", "Total Contacts", "Count of Contacts in Cache"])
        csv_writer.writerows(data)

借助上述脚本,我们可以使用 IEF 数据库处理来自 Yahoo 邮件的缓存数据。