포함 된 메타 데이터 조사

이 장에서는 Python 디지털 포렌식을 사용하여 임베디드 메타 데이터를 조사하는 방법에 대해 자세히 알아 봅니다.

소개

포함 된 메타 데이터는 해당 데이터로 설명 된 개체가있는 동일한 파일에 저장된 데이터에 대한 정보입니다. 즉, 디지털 파일 자체에 저장된 디지털 자산에 대한 정보입니다. 항상 파일과 연관되며 분리 될 수 없습니다.

디지털 포렌식의 경우 특정 파일에 대한 모든 정보를 추출 할 수 없습니다. 반면에 포함 된 메타 데이터는 조사에 중요한 정보를 제공 할 수 있습니다. 예를 들어, 텍스트 파일의 메타 데이터에는 작성자, 길이, 작성된 날짜 및 해당 문서에 대한 간단한 요약 정보가 포함될 수 있습니다. 디지털 이미지에는 이미지 길이, 셔터 속도 등과 같은 메타 데이터가 포함될 수 있습니다.

메타 데이터 속성 및 그 추출을 포함하는 아티팩트

이 섹션에서는 메타 데이터 속성을 포함하는 다양한 아티팩트와 Python을 사용한 추출 프로세스에 대해 알아 봅니다.

오디오 및 비디오

이들은 메타 데이터가 포함 된 매우 일반적인 두 가지 아티팩트입니다. 이 메타 데이터는 조사 목적으로 추출 할 수 있습니다.

다음 Python 스크립트를 사용하여 오디오 또는 MP3 파일과 비디오 또는 MP4 파일에서 공통 속성 또는 메타 데이터를 추출 할 수 있습니다.

이 스크립트의 경우 오디오 및 비디오 파일에서 메타 데이터를 추출 할 수있는 mutagen이라는 타사 Python 라이브러리를 설치해야합니다. 다음 명령을 사용하여 설치할 수 있습니다.

pip install mutagen

이 Python 스크립트를 위해 가져와야하는 유용한 라이브러리 중 일부는 다음과 같습니다.

from __future__ import print_function

import argparse
import json
import mutagen

명령 줄 처리기는 MP3 또는 MP4 파일의 경로를 나타내는 하나의 인수를 사용합니다. 그런 다음mutagen.file() 다음과 같이 파일에 대한 핸들을 여는 방법-

if __name__ == '__main__':
   parser = argparse.ArgumentParser('Python Metadata Extractor')
   parser.add_argument("AV_FILE", help="File to extract metadata from")
   args = parser.parse_args()
   av_file = mutagen.File(args.AV_FILE)
   file_ext = args.AV_FILE.rsplit('.', 1)[-1]
   
   if file_ext.lower() == 'mp3':
      handle_id3(av_file)
   elif file_ext.lower() == 'mp4':
      handle_mp4(av_file)

이제 두 개의 핸들을 사용해야합니다. 하나는 MP3에서 데이터를 추출하고 다른 하나는 MP4 파일에서 데이터를 추출하는 데 사용됩니다. 이러한 핸들을 다음과 같이 정의 할 수 있습니다.

def handle_id3(id3_file):
   id3_frames = {'TIT2': 'Title', 'TPE1': 'Artist', 'TALB': 'Album','TXXX':
      'Custom', 'TCON': 'Content Type', 'TDRL': 'Date released','COMM': 'Comments',
         'TDRC': 'Recording Date'}
   print("{:15} | {:15} | {:38} | {}".format("Frame", "Description","Text","Value"))
   print("-" * 85)
   
   for frames in id3_file.tags.values():
      frame_name = id3_frames.get(frames.FrameID, frames.FrameID)
      desc = getattr(frames, 'desc', "N/A")
      text = getattr(frames, 'text', ["N/A"])[0]
      value = getattr(frames, 'value', "N/A")
      
      if "date" in frame_name.lower():
         text = str(text)
      print("{:15} | {:15} | {:38} | {}".format(
         frame_name, desc, text, value))
def handle_mp4(mp4_file):
   cp_sym = u"\u00A9"
   qt_tag = {
      cp_sym + 'nam': 'Title', cp_sym + 'art': 'Artist',
      cp_sym + 'alb': 'Album', cp_sym + 'gen': 'Genre',
      'cpil': 'Compilation', cp_sym + 'day': 'Creation Date',
      'cnID': 'Apple Store Content ID', 'atID': 'Album Title ID',
      'plID': 'Playlist ID', 'geID': 'Genre ID', 'pcst': 'Podcast',
      'purl': 'Podcast URL', 'egid': 'Episode Global ID',
      'cmID': 'Camera ID', 'sfID': 'Apple Store Country',
      'desc': 'Description', 'ldes': 'Long Description'}
genre_ids = json.load(open('apple_genres.json'))

이제이 MP4 파일을 다음과 같이 반복해야합니다.

print("{:22} | {}".format('Name', 'Value'))
print("-" * 40)

for name, value in mp4_file.tags.items():
   tag_name = qt_tag.get(name, name)
   
   if isinstance(value, list):
      value = "; ".join([str(x) for x in value])
   if name == 'geID':
      value = "{}: {}".format(
      value, genre_ids[str(value)].replace("|", " - "))
   print("{:22} | {}".format(tag_name, value))

위의 스크립트는 MP3 및 MP4 파일에 대한 추가 정보를 제공합니다.

이미지

이미지는 파일 형식에 따라 다른 종류의 메타 데이터를 포함 할 수 있습니다. 그러나 대부분의 이미지에는 GPS 정보가 포함되어 있습니다. 타사 Python 라이브러리를 사용하여이 GPS 정보를 추출 할 수 있습니다. 다음 Python 스크립트를 사용하여 동일한 작업을 수행 할 수 있습니다.

먼저 타사 Python 라이브러리를 다운로드하십시오. Python Imaging Library (PIL) 다음과 같이-

pip install pillow

이렇게하면 이미지에서 메타 데이터를 추출하는 데 도움이됩니다.

이미지에 포함 된 GPS 세부 정보를 KML 파일에 쓸 수도 있지만이를 위해서는 이름이 지정된 타사 Python 라이브러리를 다운로드해야합니다. simplekml 다음과 같이-

pip install simplekml

이 스크립트에서 먼저 다음 라이브러리를 가져와야합니다.

from __future__ import print_function
import argparse

from PIL import Image
from PIL.ExifTags import TAGS

import simplekml
import sys

이제 명령 줄 처리기는 기본적으로 사진의 파일 경로를 나타내는 하나의 위치 인수를 허용합니다.

parser = argparse.ArgumentParser('Metadata from images')
parser.add_argument('PICTURE_FILE', help = "Path to picture")
args = parser.parse_args()

이제 좌표 정보를 채울 URL을 지정해야합니다. URL은gmapsopen_maps. 또한 PIL 라이브러리에서 제공하는 DMS (Degree Minute Second) 튜플 좌표를 십진수로 변환하는 함수가 필요합니다. 다음과 같이 할 수 있습니다-

gmaps = "https://www.google.com/maps?q={},{}"
open_maps = "http://www.openstreetmap.org/?mlat={}&mlon={}"

def process_coords(coord):
   coord_deg = 0
   
   for count, values in enumerate(coord):
      coord_deg += (float(values[0]) / values[1]) / 60**count
   return coord_deg

이제 우리는 image.open() 파일을 PIL 객체로 여는 기능.

img_file = Image.open(args.PICTURE_FILE)
exif_data = img_file._getexif()

if exif_data is None:
   print("No EXIF data found")
   sys.exit()
for name, value in exif_data.items():
   gps_tag = TAGS.get(name, name)
   if gps_tag is not 'GPSInfo':
      continue

찾은 후 GPSInfo 태그, 우리는 GPS 참조를 저장하고 좌표를 process_coords() 방법.

lat_ref = value[1] == u'N'
lat = process_coords(value[2])

if not lat_ref:
   lat = lat * -1
lon_ref = value[3] == u'E'
lon = process_coords(value[4])

if not lon_ref:
   lon = lon * -1

자, 시작 kml 의 개체 simplekml 다음과 같이 라이브러리-

kml = simplekml.Kml()
kml.newpoint(name = args.PICTURE_FILE, coords = [(lon, lat)])
kml.save(args.PICTURE_FILE + ".kml")

이제 다음과 같이 처리 된 정보에서 좌표를 인쇄 할 수 있습니다.

print("GPS Coordinates: {}, {}".format(lat, lon))
print("Google Maps URL: {}".format(gmaps.format(lat, lon)))
print("OpenStreetMap URL: {}".format(open_maps.format(lat, lon)))
print("KML File {} created".format(args.PICTURE_FILE + ".kml"))

PDF 문서

PDF 문서에는 이미지, 텍스트, 양식 등을 포함한 다양한 미디어가 있습니다. PDF 문서에 포함 된 메타 데이터를 추출 할 때 결과 데이터를 XMP (Extensible Metadata Platform) 형식으로 가져올 수 있습니다. 다음 Python 코드를 사용하여 메타 데이터를 추출 할 수 있습니다.

먼저 타사 Python 라이브러리를 설치하십시오. PyPDF2XMP 형식으로 저장된 메타 데이터를 읽습니다. 다음과 같이 설치할 수 있습니다.

pip install PyPDF2

이제 PDF 파일에서 메타 데이터를 추출하기 위해 다음 라이브러리를 가져옵니다.

from __future__ import print_function
from argparse import ArgumentParser, FileType

import datetime
from PyPDF2 import PdfFileReader
import sys

이제 명령 줄 처리기는 기본적으로 PDF 파일의 파일 경로를 나타내는 하나의 위치 인수를 허용합니다.

parser = argparse.ArgumentParser('Metadata from PDF')
parser.add_argument('PDF_FILE', help='Path to PDF file',type=FileType('rb'))
args = parser.parse_args()

이제 우리는 getXmpMetadata() 다음과 같이 사용 가능한 메타 데이터를 포함하는 객체를 제공하는 방법-

pdf_file = PdfFileReader(args.PDF_FILE)
xmpm = pdf_file.getXmpMetadata()

if xmpm is None:
   print("No XMP metadata found in document.")
   sys.exit()

우리는 사용할 수 있습니다 custom_print() 제목, 작성자, 기여자 등 관련 값을 추출하여 출력하는 방법은 다음과 같습니다.

custom_print("Title: {}", xmpm.dc_title)
custom_print("Creator(s): {}", xmpm.dc_creator)
custom_print("Contributors: {}", xmpm.dc_contributor)
custom_print("Subject: {}", xmpm.dc_subject)
custom_print("Description: {}", xmpm.dc_description)
custom_print("Created: {}", xmpm.xmp_createDate)
custom_print("Modified: {}", xmpm.xmp_modifyDate)
custom_print("Event Dates: {}", xmpm.dc_date)

우리는 또한 정의 할 수 있습니다 custom_print() 다음과 같이 여러 소프트웨어를 사용하여 PDF를 생성하는 경우 방법-

def custom_print(fmt_str, value):
   if isinstance(value, list):
      print(fmt_str.format(", ".join(value)))
   elif isinstance(value, dict):
      fmt_value = [":".join((k, v)) for k, v in value.items()]
      print(fmt_str.format(", ".join(value)))
   elif isinstance(value, str) or isinstance(value, bool):
      print(fmt_str.format(value))
   elif isinstance(value, bytes):
      print(fmt_str.format(value.decode()))
   elif isinstance(value, datetime.datetime):
      print(fmt_str.format(value.isoformat()))
   elif value is None:
      print(fmt_str.format("N/A"))
   else:
      print("warn: unhandled type {} found".format(type(value)))

다음과 같이 소프트웨어에 의해 저장된 다른 사용자 정의 속성을 추출 할 수도 있습니다.

if xmpm.custom_properties:
   print("Custom Properties:")
   
   for k, v in xmpm.custom_properties.items():
      print("\t{}: {}".format(k, v))

위의 스크립트는 PDF 문서를 읽고 해당 PDF를 만든 소프트웨어에 저장된 일부 사용자 정의 속성을 포함하여 XMP 형식으로 저장된 메타 데이터를 인쇄합니다.

Windows 실행 파일

때때로 의심 스럽거나 승인되지 않은 실행 파일이 발생할 수 있습니다. 그러나 메타 데이터가 포함되어 있기 때문에 조사 목적으로 유용 할 수 있습니다. 위치, 목적 및 제조업체, 컴파일 날짜 등과 같은 기타 속성과 같은 정보를 얻을 수 있습니다. 다음 Python 스크립트의 도움으로 컴파일 날짜, 헤더에서 유용한 데이터, 가져온 기호 및 내보내기 기호를 가져올 수 있습니다.

이를 위해 먼저 타사 Python 라이브러리를 설치하십시오. pefile. 다음과 같이 할 수 있습니다-

pip install pefile

성공적으로 설치했으면 다음과 같이 다음 라이브러리를 가져옵니다.

from __future__ import print_function

import argparse
from datetime import datetime
from pefile import PE

이제 명령 줄 처리기는 기본적으로 실행 파일의 파일 경로를 나타내는 하나의 위치 인수를 허용합니다. 상세하고 장황한 방식으로 또는 단순화 된 방식으로 필요한 경우 출력 스타일을 선택할 수도 있습니다. 이를 위해 아래와 같이 선택적 인수를 제공해야합니다.

parser = argparse.ArgumentParser('Metadata from executable file')
parser.add_argument("EXE_FILE", help = "Path to exe file")
parser.add_argument("-v", "--verbose", help = "Increase verbosity of output",
action = 'store_true', default = False)
args = parser.parse_args()

이제 PE 클래스를 사용하여 입력 실행 파일을로드합니다. 또한 다음을 사용하여 실행 가능한 데이터를 사전 개체에 덤프합니다.dump_dict() 방법.

pe = PE(args.EXE_FILE)
ped = pe.dump_dict()

아래에 표시된 코드를 사용하여 포함 된 저작자, 버전 및 컴파일 시간과 같은 기본 파일 메타 데이터를 추출 할 수 있습니다.

file_info = {}
for structure in pe.FileInfo:
   if structure.Key == b'StringFileInfo':
      for s_table in structure.StringTable:
         for key, value in s_table.entries.items():
            if value is None or len(value) == 0:
               value = "Unknown"
            file_info[key] = value
print("File Information: ")
print("==================")

for k, v in file_info.items():
   if isinstance(k, bytes):
      k = k.decode()
   if isinstance(v, bytes):
      v = v.decode()
   print("{}: {}".format(k, v))
comp_time = ped['FILE_HEADER']['TimeDateStamp']['Value']
comp_time = comp_time.split("[")[-1].strip("]")
time_stamp, timezone = comp_time.rsplit(" ", 1)
comp_time = datetime.strptime(time_stamp, "%a %b %d %H:%M:%S %Y")
print("Compiled on {} {}".format(comp_time, timezone.strip()))

다음과 같이 헤더에서 유용한 데이터를 추출 할 수 있습니다.

for section in ped['PE Sections']:
   print("Section '{}' at {}: {}/{} {}".format(
      section['Name']['Value'], hex(section['VirtualAddress']['Value']),
      section['Misc_VirtualSize']['Value'],
      section['SizeOfRawData']['Value'], section['MD5'])
   )

이제 아래와 같이 실행 파일에서 가져 오기 및 내보내기 목록을 추출하십시오.

if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
   print("\nImports: ")
   print("=========")
   
   for dir_entry in pe.DIRECTORY_ENTRY_IMPORT:
      dll = dir_entry.dll
      
      if not args.verbose:
         print(dll.decode(), end=", ")
         continue
      name_list = []
      
      for impts in dir_entry.imports:
         if getattr(impts, "name", b"Unknown") is None:
            name = b"Unknown"
         else:
            name = getattr(impts, "name", b"Unknown")
			name_list.append([name.decode(), hex(impts.address)])
      name_fmt = ["{} ({})".format(x[0], x[1]) for x in name_list]
      print('- {}: {}'.format(dll.decode(), ", ".join(name_fmt)))
   if not args.verbose:
      print()

이제 인쇄 exports, namesaddresses 아래와 같이 코드를 사용하여-

if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
   print("\nExports: ")
   print("=========")
   
   for sym in pe.DIRECTORY_ENTRY_EXPORT.symbols:
      print('- {}: {}'.format(sym.name.decode(), hex(sym.address)))

위의 스크립트는 Windows 실행 파일의 헤더에서 기본 메타 데이터, 정보를 추출합니다.

Office 문서 메타 데이터

컴퓨터 작업의 대부분은 MS Office의 세 가지 응용 프로그램 인 Word, PowerPoint 및 Excel에서 수행됩니다. 이러한 파일은 저작자와 역사에 대한 흥미로운 정보를 노출 할 수있는 거대한 메타 데이터를 가지고 있습니다.

2007 년 단어 형식 (.docx), excel (.xlsx) 및 powerpoint (.pptx)의 메타 데이터는 XML 파일에 저장됩니다. 다음과 같은 Python 스크립트를 사용하여 Python에서 이러한 XML 파일을 처리 할 수 ​​있습니다.

먼저 아래와 같이 필요한 라이브러리를 가져옵니다.

from __future__ import print_function
from argparse import ArgumentParser
from datetime import datetime as dt
from xml.etree import ElementTree as etree

import zipfile
parser = argparse.ArgumentParser('Office Document Metadata’)
parser.add_argument("Office_File", help="Path to office file to read")
args = parser.parse_args()

이제 파일이 ZIP 파일인지 확인하십시오. 그렇지 않으면 오류를 발생시킵니다. 이제 파일을 열고 다음 코드를 사용하여 처리 할 핵심 요소를 추출합니다.

zipfile.is_zipfile(args.Office_File)
zfile = zipfile.ZipFile(args.Office_File)
core_xml = etree.fromstring(zfile.read('docProps/core.xml'))
app_xml = etree.fromstring(zfile.read('docProps/app.xml'))

이제 메타 데이터 추출을 시작하기위한 사전을 만듭니다.

core_mapping = {
   'title': 'Title',
   'subject': 'Subject',
   'creator': 'Author(s)',
   'keywords': 'Keywords',
   'description': 'Description',
   'lastModifiedBy': 'Last Modified By',
   'modified': 'Modified Date',
   'created': 'Created Date',
   'category': 'Category',
   'contentStatus': 'Status',
   'revision': 'Revision'
}

사용하다 iterchildren() XML 파일 내의 각 태그에 액세스하는 방법-

for element in core_xml.getchildren():
   for key, title in core_mapping.items():
      if key in element.tag:
         if 'date' in title.lower():
            text = dt.strptime(element.text, "%Y-%m-%dT%H:%M:%SZ")
         else:
            text = element.text
         print("{}: {}".format(title, text))

마찬가지로 문서의 내용에 대한 통계 정보를 포함하는 app.xml 파일에 대해이 작업을 수행하십시오.

app_mapping = {
   'TotalTime': 'Edit Time (minutes)',
   'Pages': 'Page Count',
   'Words': 'Word Count',
   'Characters': 'Character Count',
   'Lines': 'Line Count',
   'Paragraphs': 'Paragraph Count',
   'Company': 'Company',
   'HyperlinkBase': 'Hyperlink Base',
   'Slides': 'Slide count',
   'Notes': 'Note Count',
   'HiddenSlides': 'Hidden Slide Count',
}
for element in app_xml.getchildren():
   for key, title in app_mapping.items():
      if key in element.tag:
         if 'date' in title.lower():
            text = dt.strptime(element.text, "%Y-%m-%dT%H:%M:%SZ")
         else:
            text = element.text
         print("{}: {}".format(title, text))

이제 위의 스크립트를 실행 한 후 특정 문서에 대한 다른 세부 정보를 얻을 수 있습니다. 이 스크립트는 Office 2007 이상 버전 문서에만 적용 할 수 있습니다.