В этой главе будут объяснены различные концепции, связанные с экспертизой Microsoft Windows, и важные артефакты, которые исследователь может получить в процессе расследования.
Вступление
Артефакты — это объекты или области в компьютерной системе, которые имеют важную информацию, связанную с действиями, выполняемыми пользователем компьютера. Тип и расположение этой информации зависит от операционной системы. Во время криминалистического анализа эти артефакты играют очень важную роль в одобрении или неодобрении наблюдения исследователя.
Важность артефактов Windows для криминалистики
Артефакты Windows приобретают значение по следующим причинам:
-
Около 90% трафика в мире приходится на компьютеры, использующие Windows в качестве операционной системы. Вот почему для цифровых криминалистов артефакты Windows очень важны.
-
Операционная система Windows хранит различные типы доказательств, связанных с деятельностью пользователя в компьютерной системе. Это еще одна причина, которая показывает важность артефактов Windows для цифровой криминалистики.
-
Много раз следователь вращает расследование вокруг старых и традиционных областей, таких как пользовательские данные. Артефакты Windows могут привести исследование к нетрадиционным областям, таким как данные, созданные системой, или артефакты.
-
Windows предоставляет большое количество артефактов, которые полезны для следователей, а также для компаний и частных лиц, проводящих неформальные расследования.
-
Рост киберпреступности в последние годы является еще одной причиной значимости артефактов Windows.
Около 90% трафика в мире приходится на компьютеры, использующие Windows в качестве операционной системы. Вот почему для цифровых криминалистов артефакты Windows очень важны.
Операционная система Windows хранит различные типы доказательств, связанных с деятельностью пользователя в компьютерной системе. Это еще одна причина, которая показывает важность артефактов Windows для цифровой криминалистики.
Много раз следователь вращает расследование вокруг старых и традиционных областей, таких как пользовательские данные. Артефакты Windows могут привести исследование к нетрадиционным областям, таким как данные, созданные системой, или артефакты.
Windows предоставляет большое количество артефактов, которые полезны для следователей, а также для компаний и частных лиц, проводящих неформальные расследования.
Рост киберпреступности в последние годы является еще одной причиной значимости артефактов Windows.
Артефакты Windows и их скрипты Python
В этом разделе мы собираемся обсудить некоторые артефакты Windows и скрипты Python для извлечения информации из них.
Корзина
Это один из важных артефактов Windows для криминалистического расследования. В корзине Windows находятся файлы, которые были удалены пользователем, но еще не удалены системой. Даже если пользователь полностью удаляет файл из системы, он служит важным источником расследования. Это связано с тем, что экзаменатор может извлекать из удаленных файлов ценную информацию, например, исходный путь к файлу, а также время его отправки в корзину.
Обратите внимание, что хранение данных корзины зависит от версии Windows. В следующем скрипте Python мы будем иметь дело с Windows 7, где он создает два файла: файл $ R, который содержит фактическое содержимое переработанного файла, и файл $ I, который содержит исходное имя файла, путь, размер файла при удалении файла. ,
Для скрипта Python нам нужно установить сторонние модули, а именно pytsk3, pyewf и unicodecsv . Мы можем использовать pip для их установки. Мы можем выполнить следующие шаги для извлечения информации из корзины —
-
Во-первых, нам нужно использовать рекурсивный метод для сканирования через папку $ Recycle.bin и выбрать все файлы, начиная с $ I.
-
Далее мы будем читать содержимое файлов и анализировать доступные структуры метаданных.
-
Теперь мы будем искать связанный файл $ R.
-
Наконец, мы запишем результаты в файл CSV для просмотра.
Во-первых, нам нужно использовать рекурсивный метод для сканирования через папку $ Recycle.bin и выбрать все файлы, начиная с $ I.
Далее мы будем читать содержимое файлов и анализировать доступные структуры метаданных.
Теперь мы будем искать связанный файл $ R.
Наконец, мы запишем результаты в файл CSV для просмотра.
Давайте посмотрим, как использовать код Python для этой цели —
Во-первых, нам нужно импортировать следующие библиотеки Python —
from __future__ import print_function from argparse import ArgumentParser import datetime import os import struct from utility.pytskutil import TSKUtil import unicodecsv as csv
Далее нам нужно предоставить аргумент для обработчика командной строки. Обратите внимание, что здесь он будет принимать три аргумента: первый — это путь к файлу доказательств, второй — тип файла доказательств, а третий — желаемый выходной путь к отчету CSV, как показано ниже —
if __name__ == '__main__': parser = argparse.ArgumentParser('Recycle Bin evidences') parser.add_argument('EVIDENCE_FILE', help = "Path to evidence file") parser.add_argument('IMAGE_TYPE', help = "Evidence file format", choices = ('ewf', 'raw')) parser.add_argument('CSV_REPORT', help = "Path to CSV report") args = parser.parse_args() main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.CSV_REPORT)
Теперь определите функцию main (), которая будет обрабатывать всю обработку. Он будет искать файл $ I следующим образом:
def main(evidence, image_type, report_file): tsk_util = TSKUtil(evidence, image_type) dollar_i_files = tsk_util.recurse_files("$I", path = '/$Recycle.bin',logic = "startswith") if dollar_i_files is not None: processed_files = process_dollar_i(tsk_util, dollar_i_files) write_csv(report_file,['file_path', 'file_size', 'deleted_time','dollar_i_file', 'dollar_r_file', 'is_directory'],processed_files) else: print("No $I files found")
Теперь, если мы нашли файл $ I , он должен быть отправлен в функцию process_dollar_i (), которая будет принимать объект tsk_util, а также список файлов $ I , как показано ниже —
def process_dollar_i(tsk_util, dollar_i_files): processed_files = [] for dollar_i in dollar_i_files: file_attribs = read_dollar_i(dollar_i[2]) if file_attribs is None: continue file_attribs['dollar_i_file'] = os.path.join('/$Recycle.bin', dollar_i[1][1:])
Теперь найдите файлы $ R следующим образом:
recycle_file_path = os.path.join('/$Recycle.bin',dollar_i[1].rsplit("/", 1)[0][1:]) dollar_r_files = tsk_util.recurse_files( "$R" + dollar_i[0][2:],path = recycle_file_path, logic = "startswith") if dollar_r_files is None: dollar_r_dir = os.path.join(recycle_file_path,"$R" + dollar_i[0][2:]) dollar_r_dirs = tsk_util.query_directory(dollar_r_dir) if dollar_r_dirs is None: file_attribs['dollar_r_file'] = "Not Found" file_attribs['is_directory'] = 'Unknown' else: file_attribs['dollar_r_file'] = dollar_r_dir file_attribs['is_directory'] = True else: dollar_r = [os.path.join(recycle_file_path, r[1][1:])for r in dollar_r_files] file_attribs['dollar_r_file'] = ";".join(dollar_r) file_attribs['is_directory'] = False processed_files.append(file_attribs) return processed_files
Теперь определите метод read_dollar_i () для чтения файлов $ I , другими словами, для анализа метаданных. Мы будем использовать метод read_random () для чтения первых восьми байтов подписи. Это не вернет ничего, если подпись не совпадает. После этого нам нужно будет прочитать и распаковать значения из файла $ I, если это допустимый файл.
def read_dollar_i(file_obj): if file_obj.read_random(0, 8) != '\x01\x00\x00\x00\x00\x00\x00\x00': return None raw_file_size = struct.unpack('<q', file_obj.read_random(8, 8)) raw_deleted_time = struct.unpack('<q', file_obj.read_random(16, 8)) raw_file_path = file_obj.read_random(24, 520)
Теперь, после извлечения этих файлов нам нужно интерпретировать целые числа в понятные человеку значения с помощью функции sizeof_fmt (), как показано ниже —
file_size = sizeof_fmt(raw_file_size[0]) deleted_time = parse_windows_filetime(raw_deleted_time[0]) file_path = raw_file_path.decode("utf16").strip("\x00") return {'file_size': file_size, 'file_path': file_path,'deleted_time': deleted_time}
Теперь нам нужно определить функцию sizeof_fmt () следующим образом:
def sizeof_fmt(num, suffix = 'B'): for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: if abs(num) < 1024.0: return "%3.1f%s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f%s%s" % (num, 'Yi', suffix)
Теперь определим функцию для интерпретируемых целых чисел в форматированную дату и время следующим образом:
def parse_windows_filetime(date_value): microseconds = float(date_value) / 10 ts = datetime.datetime(1601, 1, 1) + datetime.timedelta( microseconds = microseconds) return ts.strftime('%Y-%m-%d %H:%M:%S.%f')
Теперь мы определим метод write_csv () для записи обработанных результатов в файл CSV следующим образом:
def write_csv(outfile, fieldnames, data): with open(outfile, 'wb') as open_outfile: csvfile = csv.DictWriter(open_outfile, fieldnames) csvfile.writeheader() csvfile.writerows(data)
Когда вы запустите приведенный выше скрипт, мы получим данные из файлов $ I и $ R.
Заметки
Windows Sticky Notes заменяет реальную привычку писать ручкой и бумагой. Эти заметки использовались для размещения на рабочем столе различных вариантов цветов, шрифтов и т. Д. В Windows 7 файл Sticky Notes хранится в виде файла OLE, поэтому в следующем скрипте Python мы исследуем этот файл OLE для извлечения метаданных из Sticky Notes.
Для этого скрипта Python нам нужно установить сторонние модули, а именно olefile, pytsk3, pyewf и unicodecsv. Мы можем использовать команду pip для их установки.
Мы можем выполнить шаги, описанные ниже, для извлечения информации из файла Sticky note, а именно StickyNote.sn —
-
Во-первых, откройте файл улик и найдите все файлы StickyNote.snt.
-
Затем проанализируйте метаданные и содержимое из потока OLE и запишите содержимое RTF в файлы.
-
Наконец, создайте отчет CSV с этими метаданными.
Во-первых, откройте файл улик и найдите все файлы StickyNote.snt.
Затем проанализируйте метаданные и содержимое из потока OLE и запишите содержимое RTF в файлы.
Наконец, создайте отчет CSV с этими метаданными.
Код Python
Давайте посмотрим, как использовать код Python для этой цели —
Сначала импортируйте следующие библиотеки Python —
from __future__ import print_function from argparse import ArgumentParser import unicodecsv as csv import os import StringIO from utility.pytskutil import TSKUtil import olefile
Затем определите глобальную переменную, которая будет использоваться в этом скрипте —
REPORT_COLS = ['note_id', 'created', 'modified', 'note_text', 'note_file']
Далее нам нужно предоставить аргумент для обработчика командной строки. Обратите внимание, что здесь он будет принимать три аргумента: первый — это путь к файлу улик, второй — тип файла улик, а третий — желаемый путь вывода следующим образом:
if __name__ == '__main__': parser = argparse.ArgumentParser('Evidence from Sticky Notes') parser.add_argument('EVIDENCE_FILE', help="Path to evidence file") parser.add_argument('IMAGE_TYPE', help="Evidence file format",choices=('ewf', 'raw')) parser.add_argument('REPORT_FOLDER', help="Path to report folder") args = parser.parse_args() main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.REPORT_FOLDER)
Теперь мы определим функцию main (), которая будет похожа на предыдущий скрипт, как показано ниже —
def main(evidence, image_type, report_folder): tsk_util = TSKUtil(evidence, image_type) note_files = tsk_util.recurse_files('StickyNotes.snt', '/Users','equals')
Теперь давайте пройдемся по полученным файлам. Затем мы вызовем функцию parse_snt_file () для обработки файла, а затем запишем файл RTF с помощью метода write_note_rtf () следующим образом:
report_details = [] for note_file in note_files: user_dir = note_file[1].split("/")[1] file_like_obj = create_file_like_obj(note_file[2]) note_data = parse_snt_file(file_like_obj) if note_data is None: continue write_note_rtf(note_data, os.path.join(report_folder, user_dir)) report_details += prep_note_report(note_data, REPORT_COLS,"/Users" + note_file[1]) write_csv(os.path.join(report_folder, 'sticky_notes.csv'), REPORT_COLS,report_details)
Далее нам нужно определить различные функции, используемые в этом скрипте.
Прежде всего мы определим функцию create_file_like_obj () для считывания размера файла, взяв объект файла pytsk . Затем мы определим функцию parse_snt_file (), которая будет принимать файлоподобный объект в качестве входных данных и используется для чтения и интерпретации файла заметок.
def parse_snt_file(snt_file): if not olefile.isOleFile(snt_file): print("This is not an OLE file") return None ole = olefile.OleFileIO(snt_file) note = {} for stream in ole.listdir(): if stream[0].count("-") == 3: if stream[0] not in note: note[stream[0]] = {"created": ole.getctime(stream[0]),"modified": ole.getmtime(stream[0])} content = None if stream[1] == '0': content = ole.openstream(stream).read() elif stream[1] == '3': content = ole.openstream(stream).read().decode("utf-16") if content: note[stream[0]][stream[1]] = content return note
Теперь создайте файл RTF, определив функцию write_note_rtf () следующим образом
def write_note_rtf(note_data, report_folder): if not os.path.exists(report_folder): os.makedirs(report_folder) for note_id, stream_data in note_data.items(): fname = os.path.join(report_folder, note_id + ".rtf") with open(fname, 'w') as open_file: open_file.write(stream_data['0'])
Теперь мы переведем вложенный словарь в плоский список словарей, которые больше подходят для таблицы CSV. Это будет сделано путем определения функции prep_note_report () . Наконец, мы определим функцию write_csv () .
def prep_note_report(note_data, report_cols, note_file): report_details = [] for note_id, stream_data in note_data.items(): report_details.append({ "note_id": note_id, "created": stream_data['created'], "modified": stream_data['modified'], "note_text": stream_data['3'].strip("\x00"), "note_file": note_file }) return report_details def write_csv(outfile, fieldnames, data): with open(outfile, 'wb') as open_outfile: csvfile = csv.DictWriter(open_outfile, fieldnames) csvfile.writeheader() csvfile.writerows(data)
После запуска вышеуказанного скрипта мы получим метаданные из файла Sticky Notes.
Файлы реестра
Файлы реестра Windows содержат много важных деталей, которые похожи на сокровищницу информации для судебного аналитика. Это иерархическая база данных, которая содержит детали, относящиеся к конфигурации операционной системы, действиям пользователя, установке программного обеспечения и т. Д. В следующем скрипте Python мы собираемся получить доступ к общей базовой информации из кустов SYSTEM и SOFTWARE .
Для этого скрипта Python нам нужно установить сторонние модули, а именно pytsk3, pyewf и Registry . Мы можем использовать pip для их установки.
Мы можем выполнить приведенные ниже шаги для извлечения информации из реестра Windows —
-
Во-первых, найдите кусты реестра для обработки как по имени, так и по пути.
-
Затем мы открываем эти файлы с помощью модулей StringIO и Registry.
-
Наконец нам нужно обработать каждый улей и вывести проанализированные значения на консоль для интерпретации.
Во-первых, найдите кусты реестра для обработки как по имени, так и по пути.
Затем мы открываем эти файлы с помощью модулей StringIO и Registry.
Наконец нам нужно обработать каждый улей и вывести проанализированные значения на консоль для интерпретации.
Код Python
Давайте посмотрим, как использовать код Python для этой цели —
Сначала импортируйте следующие библиотеки Python —
from __future__ import print_function from argparse import ArgumentParser import datetime import StringIO import struct from utility.pytskutil import TSKUtil from Registry import Registry
Теперь предоставьте аргумент для обработчика командной строки. Здесь он будет принимать два аргумента — первый — это путь к файлу доказательств, второй — тип файла доказательств, как показано ниже —
if __name__ == '__main__': parser = argparse.ArgumentParser('Evidence from Windows Registry') parser.add_argument('EVIDENCE_FILE', help = "Path to evidence file") parser.add_argument('IMAGE_TYPE', help = "Evidence file format", choices = ('ewf', 'raw')) args = parser.parse_args() main(args.EVIDENCE_FILE, args.IMAGE_TYPE)
Теперь мы определим функцию main () для поиска кустов SYSTEM и SOFTWARE в папке / Windows / System32 / config следующим образом:
def main(evidence, image_type): tsk_util = TSKUtil(evidence, image_type) tsk_system_hive = tsk_util.recurse_files('system', '/Windows/system32/config', 'equals') tsk_software_hive = tsk_util.recurse_files('software', '/Windows/system32/config', 'equals') system_hive = open_file_as_reg(tsk_system_hive[0][2]) software_hive = open_file_as_reg(tsk_software_hive[0][2]) process_system_hive(system_hive) process_software_hive(software_hive)
Теперь определим функцию открытия файла реестра. Для этого нам нужно собрать размер файла из метаданных pytsk следующим образом:
def open_file_as_reg(reg_file): file_size = reg_file.info.meta.size file_content = reg_file.read_random(0, file_size) file_like_obj = StringIO.StringIO(file_content) return Registry.Registry(file_like_obj)
Теперь с помощью следующего метода мы можем обработать SYSTEM> hive —
def process_system_hive(hive): root = hive.root() current_control_set = root.find_key("Select").value("Current").value() control_set = root.find_key("ControlSet{:03d}".format(current_control_set)) raw_shutdown_time = struct.unpack( '<Q', control_set.find_key("Control").find_key("Windows").value("ShutdownTime").value()) shutdown_time = parse_windows_filetime(raw_shutdown_time[0]) print("Last Shutdown Time: {}".format(shutdown_time)) time_zone = control_set.find_key("Control").find_key("TimeZoneInformation") .value("TimeZoneKeyName").value() print("Machine Time Zone: {}".format(time_zone)) computer_name = control_set.find_key("Control").find_key("ComputerName").find_key("ComputerName") .value("ComputerName").value() print("Machine Name: {}".format(computer_name)) last_access = control_set.find_key("Control").find_key("FileSystem") .value("NtfsDisableLastAccessUpdate").value() last_access = "Disabled" if last_access == 1 else "enabled" print("Last Access Updates: {}".format(last_access))
Теперь нам нужно определить функцию для интерпретируемых целых чисел в форматированную дату и время следующим образом:
def parse_windows_filetime(date_value): microseconds = float(date_value) / 10 ts = datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds = microseconds) return ts.strftime('%Y-%m-%d %H:%M:%S.%f') def parse_unix_epoch(date_value): ts = datetime.datetime.fromtimestamp(date_value) return ts.strftime('%Y-%m-%d %H:%M:%S.%f')
Теперь с помощью следующего метода мы можем обработать улей ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ —
def process_software_hive(hive): root = hive.root() nt_curr_ver = root.find_key("Microsoft").find_key("Windows NT") .find_key("CurrentVersion") print("Product name: {}".format(nt_curr_ver.value("ProductName").value())) print("CSD Version: {}".format(nt_curr_ver.value("CSDVersion").value())) print("Current Build: {}".format(nt_curr_ver.value("CurrentBuild").value())) print("Registered Owner: {}".format(nt_curr_ver.value("RegisteredOwner").value())) print("Registered Org: {}".format(nt_curr_ver.value("RegisteredOrganization").value())) raw_install_date = nt_curr_ver.value("InstallDate").value() install_date = parse_unix_epoch(raw_install_date) print("Installation Date: {}".format(install_date))
После запуска вышеуказанного сценария мы получим метаданные, хранящиеся в файлах реестра Windows.