Gömülü Meta Verileri Araştırma

Bu bölümde, gömülü meta verileri Python dijital adli tıp kullanarak araştırmayı ayrıntılı olarak öğreneceğiz.

Giriş

Gömülü meta veriler, aynı dosyada depolanan ve bu verilerle tanımlanan nesneye sahip olan verilerle ilgili bilgilerdir. Başka bir deyişle, dijital dosyanın kendisinde depolanan bir dijital varlık hakkındaki bilgidir. Her zaman dosyayla ilişkilendirilir ve asla ayrılamaz.

Dijital adli tıp durumunda, belirli bir dosya hakkındaki tüm bilgileri çıkaramayız. Öte yandan, gömülü meta veriler bize soruşturma için kritik olan bilgileri sağlayabilir. Örneğin, bir metin dosyasının meta verileri, yazar, uzunluğu, yazılı tarih ve hatta bu belge hakkında kısa bir özet hakkında bilgi içerebilir. Dijital bir görüntü, görüntünün uzunluğu, deklanşör hızı vb. Gibi meta verileri içerebilir.

Meta Veri Özniteliklerini İçeren Yapılar ve Ayıklama

Bu bölümde, meta veri özniteliklerini içeren çeşitli yapılar ve bunların Python kullanarak ayıklama sürecini öğreneceğiz.

Ses ve video

Bunlar, gömülü meta verilere sahip çok yaygın iki yapaydır. Bu meta veriler, araştırma amacıyla çıkarılabilir.

Ses veya MP3 dosyasından ve bir video veya MP4 dosyasından ortak öznitelikleri veya meta verileri çıkarmak için aşağıdaki Python komut dosyasını kullanabilirsiniz.

Bu komut dosyası için, ses ve video dosyalarından meta verileri çıkarmamıza izin veren mutagen adlı üçüncü taraf bir python kitaplığı yüklememiz gerektiğini unutmayın. Aşağıdaki komutun yardımı ile kurulabilir -

pip install mutagen

Bu Python betiği için içe aktarmamız gereken kullanışlı kitaplıklardan bazıları aşağıdaki gibidir -

from __future__ import print_function

import argparse
import json
import mutagen

Komut satırı işleyicisi, MP3 veya MP4 dosyalarının yolunu temsil eden bir bağımsız değişken alacaktır. Sonra kullanacağızmutagen.file() aşağıdaki gibi dosyaya bir tanıtıcı açma yöntemi -

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)

Şimdi, biri MP3'ten verileri çıkarmak ve diğeri MP4 dosyasından verileri çıkarmak için iki tutamaç kullanmamız gerekiyor. Bu kolları şu şekilde tanımlayabiliriz -

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

Şimdi, bu MP4 dosyasını aşağıdaki gibi yinelememiz gerekiyor -

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

Yukarıdaki komut dosyası bize MP3 ve MP4 dosyaları hakkında ek bilgi verecektir.

Görüntüler

Görüntüler, dosya formatına bağlı olarak farklı türde meta veriler içerebilir. Ancak, görüntülerin çoğu GPS bilgilerini içerir. Bu GPS bilgilerini üçüncü taraf Python kitaplıklarını kullanarak çıkarabiliriz. Aynı şeyi yapmak için aşağıdaki Python betiğini kullanabilirsiniz -

İlk olarak, adlı üçüncü taraf python kitaplığını indirin Python Imaging Library (PIL) aşağıdaki gibi -

pip install pillow

Bu, görüntülerden meta verileri çıkarmamıza yardımcı olacaktır.

Resimlere gömülü GPS ayrıntılarını da KML dosyasına yazabiliriz, ancak bunun için adlı üçüncü taraf Python kitaplığını indirmemiz gerekir. simplekml aşağıdaki gibi -

pip install simplekml

Bu komut dosyasında, önce aşağıdaki kitaplıkları içe aktarmamız gerekiyor -

from __future__ import print_function
import argparse

from PIL import Image
from PIL.ExifTags import TAGS

import simplekml
import sys

Şimdi, komut satırı işleyicisi, temelde fotoğrafların dosya yolunu temsil eden bir konumsal bağımsız değişkeni kabul edecektir.

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

Şimdi, koordinat bilgilerini dolduracak URL'leri belirtmemiz gerekiyor. URL'lergmaps ve open_maps. Ayrıca PIL kitaplığı tarafından sağlanan derece dakika saniye (DMS) demet koordinatını ondalık sayıya dönüştürmek için bir işleve ihtiyacımız var. Aşağıdaki gibi yapılabilir -

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

Şimdi kullanacağız image.open() dosyayı PIL nesnesi olarak açma işlevi.

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

Bulduktan sonra GPSInfo etiketi, GPS referansını saklayacağız ve koordinatları process_coords() yöntem.

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

Şimdi başla kml nesneden simplekml kütüphane aşağıdaki gibidir -

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

Artık işlenen bilgilerden koordinatları aşağıdaki gibi yazdırabiliriz -

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 Belgeleri

PDF belgeleri, görüntüler, metinler, formlar vb. Dahil olmak üzere çok çeşitli ortamlara sahiptir. PDF belgelerine gömülü meta verileri çıkardığımızda, ortaya çıkan verileri Genişletilebilir Meta Veri Platformu (XMP) adı verilen formatta alabiliriz. Aşağıdaki Python kodunun yardımıyla meta verileri çıkarabiliriz -

İlk olarak, adlı üçüncü taraf bir Python kitaplığı yükleyin. PyPDF2XMP formatında depolanan meta verileri okumak için. Aşağıdaki gibi kurulabilir -

pip install PyPDF2

Şimdi, meta verileri PDF dosyalarından çıkarmak için aşağıdaki kitaplıkları içe aktarın -

from __future__ import print_function
from argparse import ArgumentParser, FileType

import datetime
from PyPDF2 import PdfFileReader
import sys

Şimdi, komut satırı işleyicisi temelde PDF dosyasının dosya yolunu temsil eden bir konumsal bağımsız değişkeni kabul edecektir.

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

Şimdi kullanabiliriz getXmpMetadata() aşağıdaki gibi mevcut meta verileri içeren bir nesne sağlama yöntemi -

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

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

Kullanabiliriz custom_print() başlık, oluşturan, katkıda bulunan vb. gibi ilgili değerleri aşağıdaki gibi çıkarma ve yazdırma yöntemi -

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)

Ayrıca tanımlayabiliriz custom_print() PDF birden fazla yazılım kullanılarak oluşturulmuşsa aşağıdaki gibi yöntem -

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

Yazılım tarafından kaydedilen diğer özel mülkleri de aşağıdaki gibi çıkarabiliriz -

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

Yukarıdaki komut dosyası, PDF belgesini okuyacak ve yazılım tarafından saklanan bazı özel özellikler de dahil olmak üzere XMP formatında depolanan meta verileri, bu PDF'nin yapıldığı yardımı ile yazdıracaktır.

Windows Yürütülebilir Dosyaları

Bazen şüpheli veya yetkisiz bir yürütülebilir dosyayla karşılaşabiliriz. Ancak araştırma amacıyla, gömülü meta veriler nedeniyle faydalı olabilir. Yeri, amacı ve üretici, derleme tarihi gibi diğer öznitelikler gibi bilgileri alabiliriz. Python betiğini takip ederek derleme tarihini, başlıklardan ve içe aktarılan faydalı verileri ve ayrıca dışa aktarılan sembolleri alabiliriz.

Bu amaçla, önce üçüncü taraf Python kitaplığını kurun pefile. Aşağıdaki gibi yapılabilir -

pip install pefile

Bunu başarıyla yükledikten sonra, aşağıdaki kitaplıkları aşağıdaki gibi içe aktarın -

from __future__ import print_function

import argparse
from datetime import datetime
from pefile import PE

Şimdi, komut satırı işleyicisi, temelde çalıştırılabilir dosyanın dosya yolunu temsil eden bir konumsal bağımsız değişkeni kabul edecektir. Ayrıntılı ve ayrıntılı bir şekilde veya basitleştirilmiş bir şekilde ihtiyacınız olsun, çıktı stilini de seçebilirsiniz. Bunun için aşağıda gösterildiği gibi isteğe bağlı bir argüman vermeniz gerekir -

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

Şimdi, giriş çalıştırılabilir dosyasını PE sınıfını kullanarak yükleyeceğiz. Ayrıca çalıştırılabilir verileri kullanarak bir sözlük nesnesine dökeceğizdump_dict() yöntem.

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

Gömülü yazarlık, sürüm ve derleme süresi gibi temel dosya meta verilerini aşağıda gösterilen kodu kullanarak çıkarabiliriz -

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

Faydalı verileri başlıklardan aşağıdaki gibi çıkarabiliriz -

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

Şimdi, aşağıda gösterildiği gibi yürütülebilir dosyalardan içe ve dışa aktarma listesini çıkarın -

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

Şimdi yazdır exports, names ve addresses kodu aşağıda gösterildiği gibi kullanarak -

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

Yukarıdaki komut dosyası, temel meta verileri, başlıklardan bilgileri Windows çalıştırılabilir dosyalardan çıkaracaktır.

Office Belge Meta Verileri

Bilgisayardaki işin çoğu, MS Office'in üç uygulamasında yapılır - Word, PowerPoint ve Excel. Bu dosyalar, yazarları ve geçmişleri hakkında ilginç bilgileri açığa çıkarabilecek çok büyük meta verilere sahiptir.

2007 biçimindeki word (.docx), excel (.xlsx) ve powerpoint (.pptx) biçimindeki meta verilerin bir XML dosyasında saklandığını unutmayın. Bu XML dosyalarını aşağıda gösterilen Python betiğinin yardımıyla Python'da işleyebiliriz -

Öncelikle, gerekli kitaplıkları aşağıda gösterildiği gibi içe aktarın -

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

Şimdi, dosyanın bir ZIP dosyası olup olmadığını kontrol edin. Aksi takdirde, bir hata oluşturun. Şimdi, dosyayı açın ve aşağıdaki kodu kullanarak işlenecek temel öğeleri çıkarın -

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

Şimdi, meta verilerin çıkarılmasını başlatmak için bir sözlük oluşturun -

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

Kullanım iterchildren() XML dosyasındaki etiketlerin her birine erişim yöntemi -

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

Benzer şekilde, bunu belgenin içeriği hakkında istatistiksel bilgiler içeren app.xml dosyası için yapın -

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

Şimdi yukarıdaki komut dosyasını çalıştırdıktan sonra, belirli belge hakkında farklı ayrıntıları alabiliriz. Bu komut dosyasını yalnızca Office 2007 veya sonraki sürüm belgelerinde uygulayabileceğimizi unutmayın.