Важные артефакты в Windows-I
В этой главе будут объяснены различные концепции криминалистической экспертизы Microsoft 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 для просмотра.
Давайте посмотрим, как использовать код 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 с этими метаданными.
Код 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.
Наконец, нам нужно обработать каждый улей и вывести проанализированные значения в консоль для интерпретации.
Код 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> улей -
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')
Теперь с помощью следующего метода мы можем обработать SOFTWARE улей -
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.