Artefak Penting Di Windows-II

Bab ini membahas tentang beberapa artefak penting di Windows dan metode ekstraksinya menggunakan Python.

Aktivitas Pengguna

Windows memiliki NTUSER.DATfile untuk menyimpan berbagai aktivitas pengguna. Setiap profil pengguna memiliki sarang sepertiNTUSER.DAT, yang menyimpan informasi dan konfigurasi yang terkait dengan pengguna tersebut secara khusus. Oleh karena itu, ini sangat berguna untuk keperluan investigasi oleh analis forensik.

Skrip Python berikut akan mengurai beberapa kunci dari NTUSER.DATuntuk menjelajahi tindakan pengguna di sistem. Sebelum melangkah lebih jauh, untuk skrip Python, kita perlu menginstal modul pihak ketiga yaituRegistry, pytsk3, pyewf dan Jinja2. Kita dapat menggunakan pip untuk menginstalnya.

Kami dapat mengikuti langkah-langkah berikut untuk mengekstrak informasi NTUSER.DAT file -

  • Pertama, telusuri semuanya NTUSER.DAT file dalam sistem.

  • Kemudian parse file WordWheelQuery, TypePath and RunMRU kunci untuk masing-masing NTUSER.DAT mengajukan.

  • Akhirnya kita akan menulis artefak ini, yang sudah diproses, menjadi laporan HTML dengan menggunakan Jinja2 fmodule.

Kode Python

Mari kita lihat bagaimana menggunakan kode Python untuk tujuan ini -

Pertama-tama, kita perlu mengimpor modul Python berikut -

from __future__ import print_function
from argparse import ArgumentParser

import os
import StringIO
import struct

from utility.pytskutil import TSKUtil
from Registry import Registry
import jinja2

Sekarang, berikan argumen untuk penangan baris perintah. Di sini ia akan menerima tiga argumen - pertama adalah jalur ke file bukti, kedua adalah jenis file bukti dan ketiga adalah jalur keluaran yang diinginkan ke laporan HTML, seperti yang ditunjukkan di bawah ini -

if __name__ == '__main__':
   parser = argparse.ArgumentParser('Information from user activities')
   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',help = "Path to report file")
   args = parser.parse_args()
   main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.REPORT)

Sekarang, mari kita definisikan main() berfungsi untuk mencari semua NTUSER.DAT file, seperti yang ditunjukkan -

def main(evidence, image_type, report):
   tsk_util = TSKUtil(evidence, image_type)
   tsk_ntuser_hives = tsk_util.recurse_files('ntuser.dat','/Users', 'equals')
   
   nt_rec = {
      'wordwheel': {'data': [], 'title': 'WordWheel Query'},
      'typed_path': {'data': [], 'title': 'Typed Paths'},
      'run_mru': {'data': [], 'title': 'Run MRU'}
   }

Sekarang, kami akan mencoba menemukan kuncinya NTUSER.DAT file dan setelah Anda menemukannya, tentukan fungsi pemrosesan pengguna seperti yang ditunjukkan di bawah ini -

for ntuser in tsk_ntuser_hives:
   uname = ntuser[1].split("/")

open_ntuser = open_file_as_reg(ntuser[2])
try:
   explorer_key = open_ntuser.root().find_key("Software").find_key("Microsoft")
      .find_key("Windows").find_key("CurrentVersion").find_key("Explorer")
   except Registry.RegistryKeyNotFoundException:
      continue
   nt_rec['wordwheel']['data'] += parse_wordwheel(explorer_key, uname)
   nt_rec['typed_path']['data'] += parse_typed_paths(explorer_key, uname)
   nt_rec['run_mru']['data'] += parse_run_mru(explorer_key, uname)
   nt_rec['wordwheel']['headers'] = \ nt_rec['wordwheel']['data'][0].keys()
   nt_rec['typed_path']['headers'] = \ nt_rec['typed_path']['data'][0].keys()
   nt_rec['run_mru']['headers'] = \ nt_rec['run_mru']['data'][0].keys()

Sekarang, teruskan objek kamus dan jalurnya ke write_html() metode sebagai berikut -

write_html(report, nt_rec)

Sekarang, tentukan metode yang dibutuhkan pytsk menangani file dan membacanya ke dalam kelas Registry melalui StringIO kelas.

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)

Sekarang, kita akan menentukan fungsi yang akan mengurai dan menangani WordWheelQuery kunci dari NTUSER.DAT mengajukan sebagai berikut -

def parse_wordwheel(explorer_key, username):
   try:
      wwq = explorer_key.find_key("WordWheelQuery")
   except Registry.RegistryKeyNotFoundException:
      return []
   mru_list = wwq.value("MRUListEx").value()
   mru_order = []
   
   for i in xrange(0, len(mru_list), 2):
      order_val = struct.unpack('h', mru_list[i:i + 2])[0]
   if order_val in mru_order and order_val in (0, -1):
      break
   else:
      mru_order.append(order_val)
   search_list = []
   
   for count, val in enumerate(mru_order):
      ts = "N/A"
      if count == 0:
         ts = wwq.timestamp()
      search_list.append({
         'timestamp': ts,
         'username': username,
         'order': count,
         'value_name': str(val),
         'search': wwq.value(str(val)).value().decode("UTF-16").strip("\x00")
})
   return search_list

Sekarang, kita akan menentukan fungsi yang akan mengurai dan menangani TypedPaths kunci dari NTUSER.DAT mengajukan sebagai berikut -

def parse_typed_paths(explorer_key, username):
   try:
      typed_paths = explorer_key.find_key("TypedPaths")
   except Registry.RegistryKeyNotFoundException:
      return []
   typed_path_details = []
   
   for val in typed_paths.values():
      typed_path_details.append({
         "username": username,
         "value_name": val.name(),
         "path": val.value()
      })
   return typed_path_details

Sekarang, kita akan menentukan fungsi yang akan mengurai dan menangani RunMRU kunci dari NTUSER.DAT mengajukan sebagai berikut -

def parse_run_mru(explorer_key, username):
   try:
      run_mru = explorer_key.find_key("RunMRU")
   except Registry.RegistryKeyNotFoundException:
      return []
   
   if len(run_mru.values()) == 0:
      return []
   mru_list = run_mru.value("MRUList").value()
   mru_order = []
   
   for i in mru_list:
      mru_order.append(i)
   mru_details = []
   
   for count, val in enumerate(mru_order):
      ts = "N/A"
      if count == 0:
         ts = run_mru.timestamp()
      mru_details.append({
         "username": username,
         "timestamp": ts,
         "order": count,
         "value_name": val,
         "run_statement": run_mru.value(val).value()
      })
   return mru_details

Sekarang, fungsi berikut akan menangani pembuatan laporan HTML -

def write_html(outfile, data_dict):
   cwd = os.path.dirname(os.path.abspath(__file__))
   env = jinja2.Environment(loader=jinja2.FileSystemLoader(cwd))
   template = env.get_template("user_activity.html")
   rendering = template.render(nt_data=data_dict)
   
   with open(outfile, 'w') as open_outfile:
      open_outfile.write(rendering)

Akhirnya kita bisa menulis dokumen HTML untuk laporan. Setelah menjalankan script diatas, kita akan mendapatkan informasi dari file NTUSER.DAT dalam format dokumen HTML.

TAUTKAN file

File pintasan dibuat ketika pengguna atau sistem operasi membuat file pintasan untuk file yang sering digunakan, diklik dua kali atau diakses dari drive sistem seperti penyimpanan terpasang. Jenis file shortcut seperti itu disebut file link. Dengan mengakses file link ini, penyidik ​​dapat menemukan aktivitas window seperti waktu dan lokasi dari mana file tersebut diakses.

Mari kita bahas script Python yang bisa kita gunakan untuk mendapatkan informasi dari file Windows LINK ini.

Untuk skrip Python, instal modul pihak ketiga yaitu pylnk, pytsk3, pyewf. Kami dapat mengikuti langkah-langkah berikut untuk mengekstrak informasilnk file

  • Pertama, cari lnk file di dalam sistem.

  • Kemudian, ekstrak informasi dari file itu dengan mengulanginya.

  • Sekarang, akhirnya kami membutuhkan informasi ini untuk laporan CSV.

Kode Python

Mari kita lihat bagaimana menggunakan kode Python untuk tujuan ini -

Pertama, impor pustaka Python berikut -

from __future__ import print_function
from argparse import ArgumentParser

import csv
import StringIO

from utility.pytskutil import TSKUtil
import pylnk

Sekarang, berikan argumen untuk penangan baris perintah. Di sini ia akan menerima tiga argumen - pertama adalah jalur ke file bukti, kedua adalah jenis file bukti dan ketiga adalah jalur keluaran yang diinginkan ke laporan CSV, seperti yang ditunjukkan di bawah ini -

if __name__ == '__main__':
   parser = argparse.ArgumentParser('Parsing LNK files')
   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)

Sekarang, tafsirkan file bukti dengan membuat objek TSKUtil dan lakukan iterasi melalui sistem file untuk menemukan file yang diakhiri dengan lnk. Itu bisa dilakukan dengan mendefinisikanmain() berfungsi sebagai berikut -

def main(evidence, image_type, report):
   tsk_util = TSKUtil(evidence, image_type)
   lnk_files = tsk_util.recurse_files("lnk", path="/", logic="endswith")
   
   if lnk_files is None:
      print("No lnk files found")
      exit(0)
   columns = [
      'command_line_arguments', 'description', 'drive_serial_number',
      'drive_type', 'file_access_time', 'file_attribute_flags',
      'file_creation_time', 'file_modification_time', 'file_size',
      'environmental_variables_location', 'volume_label',
      'machine_identifier', 'local_path', 'network_path',
      'relative_path', 'working_directory'
   ]

Sekarang dengan bantuan kode berikut, kita akan melakukan iterasi lnk file dengan membuat fungsi sebagai berikut -

parsed_lnks = []

for entry in lnk_files:
   lnk = open_file_as_lnk(entry[2])
   lnk_data = {'lnk_path': entry[1], 'lnk_name': entry[0]}
   
   for col in columns:
      lnk_data[col] = getattr(lnk, col, "N/A")
   lnk.close()
   parsed_lnks.append(lnk_data)
write_csv(report, columns + ['lnk_path', 'lnk_name'], parsed_lnks)

Sekarang kita perlu mendefinisikan dua fungsi, satu akan membuka pytsk objek file dan lainnya akan digunakan untuk menulis laporan CSV seperti yang ditunjukkan di bawah ini -

def open_file_as_lnk(lnk_file):
   file_size = lnk_file.info.meta.size
   file_content = lnk_file.read_random(0, file_size)
   file_like_obj = StringIO.StringIO(file_content)
   lnk = pylnk.file()
   lnk.open_file_object(file_like_obj)
   return lnk
def write_csv(outfile, fieldnames, data):
   with open(outfile, 'wb') as open_outfile:
      csvfile = csv.DictWriter(open_outfile, fieldnames)
      csvfile.writeheader()
      csvfile.writerows(data)

Setelah menjalankan skrip di atas, kita akan mendapatkan informasi dari yang ditemukan lnk file dalam laporan CSV -

Ambil File

Setiap kali aplikasi berjalan untuk pertama kalinya dari lokasi tertentu, Windows akan membuat prefetch files. Ini digunakan untuk mempercepat proses startup aplikasi. Ekstensi untuk file-file ini adalah.PF dan ini disimpan di ”\Root\Windows\Prefetch” map.

Pakar forensik digital dapat mengungkap bukti pelaksanaan program dari lokasi tertentu beserta detail penggunanya. File prefetch adalah artefak yang berguna bagi pemeriksa karena entri mereka tetap ada bahkan setelah program dihapus atau di-uninstal.

Mari kita bahas skrip Python yang akan mengambil informasi dari file prefetch Windows seperti yang diberikan di bawah ini -

Untuk skrip Python, instal modul pihak ketiga yaitu pylnk, pytsk3 dan unicodecsv. Ingatlah bahwa kita telah bekerja dengan pustaka-pustaka ini dalam skrip Python yang telah kita bahas di bab-bab sebelumnya.

Kami harus mengikuti langkah-langkah yang diberikan di bawah ini untuk mengekstrak informasi prefetch file -

  • Pertama, pindai .pf file ekstensi atau file prefetch.

  • Sekarang, lakukan verifikasi tanda tangan untuk menghilangkan positif palsu.

  • Selanjutnya, parsing format file prefetch Windows. Ini berbeda dengan versi Windows. Misalnya, untuk Windows XP adalah 17, untuk Windows Vista dan Windows 7 adalah 23, 26 untuk Windows 8.1 dan 30 untuk Windows 10.

  • Terakhir, kami akan menulis hasil parsing dalam file CSV.

Kode Python

Mari kita lihat bagaimana menggunakan kode Python untuk tujuan ini -

Pertama, impor pustaka Python berikut -

from __future__ import print_function
import argparse
from datetime import datetime, timedelta

import os
import pytsk3
import pyewf
import struct
import sys
import unicodecsv as csv
from utility.pytskutil import TSKUtil

Sekarang, berikan argumen untuk penangan baris perintah. Di sini akan menerima dua argumen, pertama akan menjadi jalur ke file bukti dan kedua akan menjadi jenis file bukti. Ini juga menerima argumen opsional untuk menentukan jalur untuk memindai file prefetch -

if __name__ == "__main__":
   parser = argparse.ArgumentParser('Parsing Prefetch files')
   parser.add_argument("EVIDENCE_FILE", help = "Evidence file path")
   parser.add_argument("TYPE", help = "Type of Evidence",choices = ("raw", "ewf"))
   parser.add_argument("OUTPUT_CSV", help = "Path to write output csv")
   parser.add_argument("-d", help = "Prefetch directory to scan",default = "/WINDOWS/PREFETCH")
   args = parser.parse_args()
   
   if os.path.exists(args.EVIDENCE_FILE) and \
      os.path.isfile(args.EVIDENCE_FILE):
   main(args.EVIDENCE_FILE, args.TYPE, args.OUTPUT_CSV, args.d)
else:
   print("[-] Supplied input file {} does not exist or is not a ""file".format(args.EVIDENCE_FILE))
   sys.exit(1)

Sekarang, tafsirkan file bukti dengan membuat objek TSKUtil dan lakukan iterasi melalui sistem file untuk menemukan file yang diakhiri dengan .pf. Itu bisa dilakukan dengan mendefinisikanmain() berfungsi sebagai berikut -

def main(evidence, image_type, output_csv, path):
   tsk_util = TSKUtil(evidence, image_type)
   prefetch_dir = tsk_util.query_directory(path)
   prefetch_files = None
   
   if prefetch_dir is not None:
      prefetch_files = tsk_util.recurse_files(".pf", path=path, logic="endswith")
   
   if prefetch_files is None:
      print("[-] No .pf files found")
      sys.exit(2)
   print("[+] Identified {} potential prefetch files".format(len(prefetch_files)))
   prefetch_data = []
   
   for hit in prefetch_files:
      prefetch_file = hit[2]
      pf_version = check_signature(prefetch_file)

Sekarang, tentukan metode yang akan melakukan validasi tanda tangan seperti yang ditunjukkan di bawah ini -

def check_signature(prefetch_file):
   version, signature = struct.unpack("^<2i", prefetch_file.read_random(0, 8))
   
   if signature == 1094927187:
      return version
   else:
      return None
   
   if pf_version is None:
      continue
   pf_name = hit[0]
   
   if pf_version == 17:
      parsed_data = parse_pf_17(prefetch_file, pf_name)
      parsed_data.append(os.path.join(path, hit[1].lstrip("//")))
      prefetch_data.append(parsed_data)

Sekarang, mulailah memproses file prefetch Windows. Di sini kami mengambil contoh file prefetch Windows XP -

def parse_pf_17(prefetch_file, pf_name):
   create = convert_unix(prefetch_file.info.meta.crtime)
   modify = convert_unix(prefetch_file.info.meta.mtime)
def convert_unix(ts):
   if int(ts) == 0:
      return ""
   return datetime.utcfromtimestamp(ts)
def convert_filetime(ts):
   if int(ts) == 0:
      return ""
   return datetime(1601, 1, 1) + timedelta(microseconds=ts / 10)

Sekarang, ekstrak data yang disematkan dalam file yang diambil sebelumnya dengan menggunakan struct sebagai berikut -

pf_size, name, vol_info, vol_entries, vol_size, filetime, \
   count = struct.unpack("<i60s32x3iq16xi",prefetch_file.read_random(12, 136))
name = name.decode("utf-16", "ignore").strip("/x00").split("/x00")[0]

vol_name_offset, vol_name_length, vol_create, \
   vol_serial = struct.unpack("<2iqi",prefetch_file.read_random(vol_info, 20))
   vol_serial = hex(vol_serial).lstrip("0x")
   vol_serial = vol_serial[:4] + "-" + vol_serial[4:]
   vol_name = struct.unpack(
      "<{}s".format(2 * vol_name_length),
      prefetch_file.read_random(vol_info + vol_name_offset,vol_name_length * 2))[0]

vol_name = vol_name.decode("utf-16", "ignore").strip("/x00").split("/x00")[0]
return [
   pf_name, name, pf_size, create,
   modify, convert_filetime(filetime), count, vol_name,
   convert_filetime(vol_create), vol_serial ]

Seperti yang telah kami sediakan versi prefetch untuk Windows XP tetapi bagaimana jika akan menemui versi prefetch untuk Windows lainnya. Maka itu harus menampilkan pesan kesalahan sebagai berikut -

elif pf_version == 23:
   print("[-] Windows Vista / 7 PF file {} -- unsupported".format(pf_name))
   continue
elif pf_version == 26:
   print("[-] Windows 8 PF file {} -- unsupported".format(pf_name))
   continue
elif pf_version == 30:
   print("[-] Windows 10 PF file {} -- unsupported".format(pf_name))
continue

else:
   print("[-] Signature mismatch - Name: {}\nPath: {}".format(hit[0], hit[1]))
continue
write_output(prefetch_data, output_csv)

Sekarang, tentukan metode penulisan hasil ke dalam laporan CSV sebagai berikut -

def write_output(data, output_csv):
   print("[+] Writing csv report")
   with open(output_csv, "wb") as outfile:
      writer = csv.writer(outfile)
      writer.writerow([
         "File Name", "Prefetch Name", "File Size (bytes)",
         "File Create Date (UTC)", "File Modify Date (UTC)",
         "Prefetch Last Execution Date (UTC)",
         "Prefetch Execution Count", "Volume", "Volume Create Date",
         "Volume Serial", "File Path" ])
      writer.writerows(data)

Setelah menjalankan script diatas, kita akan mendapatkan informasi dari file prefetch versi Windows XP ke dalam spreadsheet.