Các phần tử quan trọng trong Windows-I

Chương này sẽ giải thích các khái niệm khác nhau liên quan đến pháp y của Microsoft Windows và các hiện vật quan trọng mà điều tra viên có thể thu được từ quá trình điều tra.

Giới thiệu

Tạo tác là các đối tượng hoặc khu vực trong hệ thống máy tính có thông tin quan trọng liên quan đến các hoạt động được thực hiện bởi người sử dụng máy tính. Loại và vị trí của thông tin này phụ thuộc vào hệ điều hành. Trong quá trình phân tích pháp y, những hiện vật này đóng một vai trò rất quan trọng trong việc chấp thuận hoặc không chấp thuận quan sát của điều tra viên.

Tầm quan trọng của Windows Artifacts đối với pháp y

Các tạo tác Windows có ý nghĩa quan trọng do những lý do sau:

  • Khoảng 90% lưu lượng truy cập trên thế giới đến từ các máy tính sử dụng Windows làm hệ điều hành của chúng. Đó là lý do tại sao đối với các giám định viên pháp y kỹ thuật số, Windows tạo tác là thứ rất cần thiết.

  • Hệ điều hành Windows lưu trữ các loại bằng chứng khác nhau liên quan đến hoạt động của người dùng trên hệ thống máy tính. Đây là một lý do khác cho thấy tầm quan trọng của các tạo tác Windows đối với pháp y kỹ thuật số.

  • Nhiều lần điều tra viên xoay vòng cuộc điều tra xung quanh các lĩnh vực cũ và truyền thống như dữ liệu người dùng nhồi nhét. Các tạo tác Windows có thể dẫn dắt cuộc điều tra đến các lĩnh vực phi truyền thống như dữ liệu do hệ thống tạo ra hoặc các tạo tác.

  • Windows cung cấp rất nhiều hiện vật, rất hữu ích cho các nhà điều tra cũng như cho các công ty và cá nhân thực hiện các cuộc điều tra không chính thức.

  • Sự gia tăng tội phạm mạng trong những năm gần đây là một lý do khác khiến Windows tạo tác quan trọng.

Phần mềm Windows và Tập lệnh Python của chúng

Trong phần này, chúng ta sẽ thảo luận về một số tạo tác Windows và tập lệnh Python để lấy thông tin từ chúng.

Thùng rác

Nó là một trong những đồ tạo tác quan trọng của Windows để điều tra pháp y. Thùng rác Windows chứa các tệp đã bị người dùng xóa nhưng hệ thống chưa xóa về mặt vật lý. Ngay cả khi người dùng xóa hoàn toàn tệp khỏi hệ thống, nó vẫn đóng vai trò là nguồn điều tra quan trọng. Điều này là do người kiểm tra có thể trích xuất thông tin có giá trị, như đường dẫn tệp gốc cũng như thời gian nó được gửi đến Thùng rác, từ các tệp đã xóa.

Lưu ý rằng việc lưu trữ bằng chứng Thùng rác phụ thuộc vào phiên bản Windows. Trong tập lệnh Python sau, chúng ta sẽ xử lý Windows 7, nơi nó tạo hai tệp:$R tệp chứa nội dung thực của tệp tái chế và $I tệp chứa tên tệp gốc, đường dẫn, kích thước tệp khi tệp bị xóa.

Đối với tập lệnh Python, chúng ta cần cài đặt các mô-đun của bên thứ ba, cụ thể là pytsk3, pyewfunicodecsv. Chúng ta có thể sử dụngpipđể cài đặt chúng. Chúng ta có thể làm theo các bước sau để trích xuất thông tin từ Thùng rác -

  • Đầu tiên, chúng ta cần sử dụng phương pháp đệ quy để quét qua $Recycle.bin thư mục và chọn tất cả các tệp bắt đầu bằng $I.

  • Tiếp theo, chúng ta sẽ đọc nội dung của các tệp và phân tích cú pháp các cấu trúc siêu dữ liệu có sẵn.

  • Bây giờ, chúng tôi sẽ tìm kiếm tệp $ R được liên kết.

  • Cuối cùng, chúng tôi sẽ ghi kết quả vào tệp CSV để xem xét.

Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -

Đầu tiên, chúng ta cần nhập các thư viện Python sau:

from __future__ import print_function
from argparse import ArgumentParser

import datetime
import os
import struct

from utility.pytskutil import TSKUtil
import unicodecsv as csv

Tiếp theo, chúng ta cần cung cấp đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận ba đối số - đầu tiên là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là đường dẫn đầu ra mong muốn đến báo cáo CSV, như được hiển thị bên dưới -

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)

Bây giờ, xác định main()chức năng sẽ xử lý tất cả các quá trình. Nó sẽ tìm kiếm$I tập tin như sau -

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

Bây giờ, nếu chúng tôi tìm thấy $I tệp, sau đó nó phải được gửi đến process_dollar_i() chức năng sẽ chấp nhận tsk_util đối tượng cũng như danh sách $I các tệp, như được hiển thị bên dướ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:])

Bây giờ, hãy tìm kiếm các tệp $ R như sau:

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

Bây giờ, xác định read_dollar_i() phương pháp để đọc $Inói cách khác, phân tích cú pháp siêu dữ liệu. Chúng tôi sẽ sử dụngread_random()để đọc tám byte đầu tiên của chữ ký. Điều này sẽ không trả về nếu chữ ký không khớp. Sau đó, chúng ta sẽ phải đọc và giải nén các giá trị từ$I tệp nếu đó là tệp hợp lệ.

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)

Bây giờ, sau khi giải nén các tệp này, chúng ta cần giải thích các số nguyên thành các giá trị mà con người có thể đọc được bằng cách sử dụng sizeof_fmt() chức năng như hình dưới đây -

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}

Bây giờ, chúng ta cần xác định sizeof_fmt() chức năng như sau -

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)

Bây giờ, hãy xác định một hàm cho các số nguyên được diễn giải thành ngày và giờ được định dạng như sau:

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

Bây giờ, chúng ta sẽ xác định write_csv() để ghi kết quả đã xử lý vào tệp CSV như sau:

def write_csv(outfile, fieldnames, data):
   with open(outfile, 'wb') as open_outfile:
      csvfile = csv.DictWriter(open_outfile, fieldnames)
      csvfile.writeheader()
      csvfile.writerows(data)

Khi bạn chạy tập lệnh trên, chúng tôi sẽ lấy dữ liệu từ tệp $ I và $ R.

Ghi chú dính

Windows Sticky Notes thay thế thói quen viết bằng bút và giấy trong thế giới thực. Các ghi chú này được sử dụng để nổi trên màn hình nền với các tùy chọn khác nhau về màu sắc, phông chữ, v.v. Trong Windows 7, tệp Sticky Notes được lưu trữ dưới dạng tệp OLE do đó trong tập lệnh Python sau, chúng tôi sẽ điều tra tệp OLE này để trích xuất siêu dữ liệu từ Sticky Notes.

Đối với tập lệnh Python này, chúng tôi cần cài đặt các mô-đun của bên thứ ba, cụ thể là olefile, pytsk3, pyewfvà unicodecsv. Chúng ta có thể sử dụng lệnhpip để cài đặt chúng.

Chúng ta có thể làm theo các bước được thảo luận bên dưới để trích xuất thông tin từ tệp Sticky note cụ thể là StickyNote.sn -

  • Đầu tiên, mở tệp bằng chứng và tìm tất cả các tệp StickyNote.snt.

  • Sau đó, phân tích cú pháp siêu dữ liệu và nội dung từ luồng OLE và ghi nội dung RTF vào tệp.

  • Cuối cùng, tạo báo cáo CSV của siêu dữ liệu này.

Mã Python

Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -

Đầu tiên, nhập các thư viện Python sau:

from __future__ import print_function
from argparse import ArgumentParser

import unicodecsv as csv
import os
import StringIO

from utility.pytskutil import TSKUtil
import olefile

Tiếp theo, xác định một biến toàn cục sẽ được sử dụng trên tập lệnh này -

REPORT_COLS = ['note_id', 'created', 'modified', 'note_text', 'note_file']

Tiếp theo, chúng ta cần cung cấp đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận ba đối số - đầu tiên là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là đường dẫn đầu ra mong muốn như sau:

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)

Bây giờ, chúng ta sẽ xác định main() chức năng sẽ tương tự như tập lệnh trước đó như được hiển thị bên dưới:

def main(evidence, image_type, report_folder):
   tsk_util = TSKUtil(evidence, image_type)
   note_files = tsk_util.recurse_files('StickyNotes.snt', '/Users','equals')

Bây giờ, chúng ta hãy lặp lại các tệp kết quả. Sau đó, chúng tôi sẽ gọiparse_snt_file() để xử lý tệp và sau đó chúng tôi sẽ ghi tệp RTF với write_note_rtf() phương pháp như sau -

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)

Tiếp theo, chúng ta cần xác định các hàm khác nhau được sử dụng trong script này.

Trước hết, chúng tôi sẽ xác định create_file_like_obj() chức năng để đọc kích thước của tệp bằng cách lấy pytskđối tượng tệp. Sau đó, chúng tôi sẽ xác địnhparse_snt_file() hàm sẽ chấp nhận đối tượng giống tệp làm đầu vào của nó và được sử dụng để đọc và diễn giải tệp ghi chú dính.

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

Bây giờ, hãy tạo một tệp RTF bằng cách xác định write_note_rtf() chức năng như sau

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

Bây giờ, chúng tôi sẽ dịch từ điển lồng nhau thành một danh sách phẳng các từ điển thích hợp hơn cho bảng tính CSV. Nó sẽ được thực hiện bằng cách xác địnhprep_note_report()chức năng. Cuối cùng, chúng tôi sẽ xác địnhwrite_csv() chức năng.

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)

Sau khi chạy tập lệnh trên, chúng ta sẽ nhận được siêu dữ liệu từ tệp Sticky Notes.

Tệp đăng ký

Các tệp đăng ký Windows chứa nhiều chi tiết quan trọng giống như một kho tàng thông tin cho một nhà phân tích pháp y. Nó là một cơ sở dữ liệu phân cấp có chứa các chi tiết liên quan đến cấu hình hệ điều hành, hoạt động của người dùng, cài đặt phần mềm, v.v. Trong tập lệnh Python sau, chúng ta sẽ truy cập thông tin cơ sở chung từSYSTEMSOFTWARE nổi mề đay.

Đối với tập lệnh Python này, chúng tôi cần cài đặt các mô-đun của bên thứ ba, cụ thể là pytsk3, pyewfregistry. Chúng ta có thể sử dụngpip để cài đặt chúng.

Chúng tôi có thể làm theo các bước được cung cấp bên dưới để trích xuất thông tin từ sổ đăng ký Windows -

  • Đầu tiên, tìm tổ hợp đăng ký để xử lý theo tên của nó cũng như theo đường dẫn.

  • Sau đó, chúng tôi mở các tệp này bằng cách sử dụng mô-đun StringIO và Registry.

  • Cuối cùng, chúng ta cần xử lý từng hive và in các giá trị đã phân tích cú pháp vào bảng điều khiển để diễn giải.

Mã Python

Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -

Đầu tiên, nhập các thư viện Python sau:

from __future__ import print_function
from argparse import ArgumentParser

import datetime
import StringIO
import struct

from utility.pytskutil import TSKUtil
from Registry import Registry

Bây giờ, cung cấp đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai đối số - thứ nhất là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng, như hình dưới đây -

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)

Bây giờ chúng ta sẽ xác định main() chức năng tìm kiếm SYSTEMSOFTWARE tổ ong trong /Windows/System32/config thư mục như sau -

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)

Bây giờ, xác định chức năng để mở tệp đăng ký. Vì mục đích này, chúng tôi cần thu thập kích thước tệp từpytsk siêu dữ liệu như sau:

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)

Bây giờ, với sự trợ giúp của phương pháp sau, chúng tôi có thể xử lý SYSTEM> tổ ong -

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

Bây giờ, chúng ta cần xác định một hàm cho các số nguyên được diễn giải thành ngày và giờ được định dạng như sau:

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

Bây giờ với sự trợ giúp của phương pháp sau, chúng tôi có thể xử lý SOFTWARE tổ ong -

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

Sau khi chạy tập lệnh trên, chúng ta sẽ nhận được siêu dữ liệu được lưu trữ trong các tệp Windows Registry.