Windows-II의 중요한 아티팩트
이 장에서는 Windows의 몇 가지 중요한 아티팩트와 Python을 사용한 추출 방법에 대해 설명합니다.
사용자 활동
Windows 데 NTUSER.DAT다양한 사용자 활동을 저장하기위한 파일. 모든 사용자 프로필에는 다음과 같은 하이브가 있습니다.NTUSER.DAT, 특정 사용자와 관련된 정보 및 구성을 저장합니다. 따라서 법의학 분석가의 조사 목적에 매우 유용합니다.
다음 Python 스크립트는 다음의 일부 키를 구문 분석합니다. NTUSER.DAT시스템에서 사용자의 행동을 탐색합니다. 계속 진행하기 전에 Python 스크립트의 경우 타사 모듈을 설치해야합니다.Registry, pytsk3, pyewf 및 Jinja2. pip를 사용하여 설치할 수 있습니다.
다음 단계에 따라 정보를 추출 할 수 있습니다. NTUSER.DAT 파일-
먼저 모두 검색 NTUSER.DAT 시스템의 파일.
그런 다음 WordWheelQuery, TypePath and RunMRU 각각의 키 NTUSER.DAT 파일.
마지막으로 이미 처리 된 이러한 아티팩트를 다음을 사용하여 HTML 보고서에 작성합니다. Jinja2 fmodule.
파이썬 코드
이 목적으로 파이썬 코드를 사용하는 방법을 살펴 보겠습니다.
우선, 다음 Python 모듈을 가져와야합니다.
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
이제 명령 줄 처리기에 대한 인수를 제공합니다. 여기에서 세 개의 인수를받습니다. 첫 번째는 증거 파일의 경로, 두 번째는 증거 파일의 유형, 세 번째는 아래에 표시된 HTML 보고서에 대한 원하는 출력 경로입니다.
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)
이제 정의하겠습니다. main() 모두 검색 기능 NTUSER.DAT 다음과 같이 파일-
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'}
}
이제 우리는 키를 찾으려고 노력할 것입니다. NTUSER.DAT 파일을 찾은 후 아래와 같이 사용자 처리 기능을 정의하십시오.
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()
이제 사전 객체와 해당 경로를 write_html() 다음과 같이 방법-
write_html(report, nt_rec)
이제 방법을 정의하십시오. pytsk 파일 핸들을 사용하여 레지스트리 클래스로 읽어들입니다. StringIO 수업.
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)
이제 우리는 구문 분석하고 처리 할 함수를 정의합니다. WordWheelQuery 키에서 NTUSER.DAT 다음과 같이 파일-
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
이제 우리는 구문 분석하고 처리 할 함수를 정의합니다. TypedPaths 키에서 NTUSER.DAT 다음과 같이 파일-
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
이제 우리는 구문 분석하고 처리 할 함수를 정의합니다. RunMRU 키에서 NTUSER.DAT 다음과 같이 파일-
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
이제 다음 함수가 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)
드디어 보고서 용 HTML 문서를 작성할 수 있습니다. 위의 스크립트를 실행 한 후 HTML 문서 형식의 NTUSER.DAT 파일에서 정보를 가져옵니다.
LINK 파일
바로 가기 파일은 사용자 또는 운영 체제가 자주 사용하거나 두 번 클릭하거나 연결된 저장소와 같은 시스템 드라이브에서 액세스하는 파일에 대한 바로 가기 파일을 만들 때 생성됩니다. 이러한 종류의 바로 가기 파일을 링크 파일이라고합니다. 이러한 링크 파일에 액세스하여 조사자는 이러한 파일에 액세스 한 시간 및 위치와 같은 창의 활동을 찾을 수 있습니다.
이러한 Windows LINK 파일에서 정보를 가져 오는 데 사용할 수있는 Python 스크립트에 대해 설명하겠습니다.
Python 스크립트의 경우 타사 모듈을 설치합니다. pylnk, pytsk3, pyewf. 다음 단계에 따라 정보를 추출 할 수 있습니다.lnk 파일
먼저 lnk 시스템 내의 파일.
그런 다음 해당 파일을 반복하여 해당 파일에서 정보를 추출하십시오.
이제 마침내이 정보를 CSV 보고서로 보내야합니다.
파이썬 코드
이 목적으로 파이썬 코드를 사용하는 방법을 살펴 보겠습니다.
먼저 다음 Python 라이브러리를 가져옵니다.
from __future__ import print_function
from argparse import ArgumentParser
import csv
import StringIO
from utility.pytskutil import TSKUtil
import pylnk
이제 명령 줄 처리기에 대한 인수를 제공합니다. 여기에서 세 가지 인수를받습니다. 첫 번째는 증거 파일의 경로, 두 번째는 증거 파일의 유형, 세 번째는 CSV 보고서에 대한 원하는 출력 경로입니다.
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)
이제 다음 개체를 만들어 증거 파일을 해석합니다. TSKUtil 파일 시스템을 반복하여 다음으로 끝나는 파일을 찾습니다. lnk. 정의하여 수행 할 수 있습니다.main() 다음과 같이 기능-
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'
]
이제 다음 코드의 도움으로 우리는 lnk 다음과 같이 함수를 생성하여 파일-
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)
이제 두 개의 함수를 정의해야합니다. 하나는 pytsk 파일 객체 및 기타는 아래와 같이 CSV 보고서 작성에 사용됩니다-
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)
위의 스크립트를 실행 한 후 발견 된 정보를 lnk CSV 보고서의 파일-
파일 프리 페치
응용 프로그램이 특정 위치에서 처음으로 실행될 때마다 Windows는 prefetch files. 이는 애플리케이션 시작 프로세스의 속도를 높이는 데 사용됩니다. 이 파일의 확장자는.PF 그리고 이것들은 ”\Root\Windows\Prefetch” 폴더.
디지털 포렌식 전문가는 사용자의 세부 정보와 함께 지정된 위치에서 프로그램 실행 증거를 공개 할 수 있습니다. 프리 페치 파일은 프로그램이 삭제되거나 제거 된 후에도 항목이 남아 있기 때문에 검사자에게 유용한 아티팩트입니다.
아래와 같이 Windows 프리 페치 파일에서 정보를 가져 오는 Python 스크립트에 대해 설명하겠습니다.
Python 스크립트의 경우 타사 모듈을 설치합니다. pylnk, pytsk3 과 unicodecsv. 이전 장에서 논의한 Python 스크립트에서 이미 이러한 라이브러리로 작업 한 것을 기억하십시오.
정보를 추출하려면 아래 단계를 따라야합니다. prefetch 파일-
먼저 .pf 확장 파일 또는 프리 페치 파일.
이제 서명 확인을 수행하여 오탐을 제거하십시오.
다음으로 Windows 프리 페치 파일 형식을 구문 분석합니다. 이것은 Windows 버전에 따라 다릅니다. 예를 들어 Windows XP의 경우 17, Windows Vista 및 Windows 7의 경우 23, Windows 8.1의 경우 26, Windows 10의 경우 30입니다.
마지막으로 파싱 된 결과를 CSV 파일로 작성합니다.
파이썬 코드
이 목적으로 파이썬 코드를 사용하는 방법을 살펴 보겠습니다.
먼저 다음 Python 라이브러리를 가져옵니다.
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
이제 명령 줄 처리기에 대한 인수를 제공합니다. 여기서 두 개의 인수를받습니다. 첫 번째는 증거 파일의 경로이고 두 번째는 증거 파일의 유형입니다. 또한 프리 페치 파일을 스캔 할 경로를 지정하기위한 선택적 인수를 허용합니다.
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)
이제 다음 개체를 만들어 증거 파일을 해석합니다. TSKUtil 파일 시스템을 반복하여 다음으로 끝나는 파일을 찾습니다. .pf. 정의하여 수행 할 수 있습니다.main() 다음과 같이 기능-
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)
이제 아래와 같이 서명의 유효성을 검사하는 방법을 정의하십시오.
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)
이제 Windows 프리 페치 파일 처리를 시작하십시오. 여기에서는 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)
이제 다음과 같이 struct를 사용하여 프리 페치 된 파일에 포함 된 데이터를 추출합니다.
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 ]
Windows XP 용 프리 페치 버전을 제공했지만 다른 Windows 용 프리 페치 버전이 발생하면 어떻게 될까요? 그런 다음 다음과 같이 오류 메시지를 표시해야합니다.
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)
이제 결과를 CSV 보고서에 쓰는 방법을 다음과 같이 정의합니다.
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)
위의 스크립트를 실행 한 후 Windows XP 버전의 프리 페치 파일에서 스프레드 시트로 정보를 가져옵니다.