개요
- VIOLENT PYTHON 서적의 내용을 참고해서 정리한 페이지이다.
- 디지털 포렌식에서는 이미지를 분석할 때 교환 이미지 파일형식(Exchange Image File Format, exif)이라고 알려진 이미지의 메타데이터를 조사한다.
- 파이썬을 사용해서 exif 메터데이터를 확인할 수 있는 라이브러리를 조사하고 간단한 사용방법을 정리해둔다.
- 참고로 대부분의 이미지 파일 형식은 exif 를 포함할 수 있다고 한다. png파일 형식도 원래는 exif를 포함할 수 없었으나 2017년부터는 가능해졌다고 한다. (출처: https://stackoverflow.com/questions/9542359/does-png-contain-exif-data-like-jpg)
- 대부분의 SNS에 사진을 업로드하게 되면 exif데이터를 삭제된 상태로 업로드되게 된다.
파이썬 라이브러리 조사
PIL
- 2011년까지는 파이썬의 메인 이미지 처리 라이브러리였던 것 같다.
- 2011년 이후로는 개발되지 않고 있다.
Pillow
- PIL을 fork해서 개발되고 있는 라이브러리이다.
- 요새 이미지 처리쪽에서 대세는 이 라이브러리인 것 같다.
- PIL에 파이썬3 서포트 기능을 추가했다고 한다.
pip install pillow
exif
- exif 라는 메타데이터 만을 전문적으로 분석해주는 라이브러리도 있는 것 같다.
- https://pypi.org/project/exif/
pip install exif
샘플이미지
여기에서 메타 데이터가 포함된 샘플 이미지 파일을 얻을 수 있다.
샘플코드
Pillow를 사용한 샘플코드
- 다음 코드를 사용해서 이미지 파일에 메타데이터, 특히 GPS 좌표가 들어가 있는지 확인할 수 있다.
- 그러나 GPS의 구체적인 위치를 얻어내는 데에는 실패했다.
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
def get_exif(image_file_path):
exif_info = {}
gps_info = {}
imgFile = Image.open(image_file_path)
info = imgFile.getexif()
if info:
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
exif_info[decoded] = value
print(exif_info)
# GPS
exif_gps = exif_info['GPSInfo']
if exif_gps:
print(f"[*] {image_file_path} contains GPS MetaData")
for key in exif_info['GPSInfo'].keys():
decoded = GPSTAGS.get(key, key)
gps_info[decoded] = exif_info['GPSInfo'][key]
return exif_info, gps_info
if __name__ == '__main__':
file_name = "20230725_183324.jpg"
exif_info, gps_info = get_exif(file_name)
print(exif_info)
print(gps_info)
exif를 사용한 샘플코드
- Pillow보다 exif를 사용한 샘플코드가 더 잘 동작했다. (출처: https://stackoverflow.com/questions/72530975/extract-gps-data-using-python-and-pil-is-failing)
- GPS의 구체적인 위치도 파악이 가능하다.
from exif import Image
from gmplot import gmplot
from geopy.geocoders import Nominatim
import webbrowser
import os
def decimal_coords(coords, ref):
decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
if ref == 'S' or ref == 'W':
decimal_degrees = -decimal_degrees
return decimal_degrees
file_name = "20230725_183324"
input = f'{file_name}.jpg'
output = f'{file_name}-location.html'
with open(input, 'rb') as src:
img = Image(src)
lat = decimal_coords(img.gps_latitude, img.gps_latitude_ref)
lon = decimal_coords(img.gps_longitude, img.gps_longitude_ref)
gmap = gmplot.GoogleMapPlotter(lat, lon, 12)
gmap.marker(lat, lon, 'red')
gmap.draw(output)
address = Nominatim(user_agent='GetLoc')
location = address.reverse(f'{lat}, {lon}')
print(location.address)
webbrowser.open(f'file:///{os.getcwd()}/{output}', new=1)
exif정보를 삭제하는 방법
- 출처: https://stackoverflow.com/questions/19786301/python-remove-exif-info-from-images
- Pillow 라이브러리를 사용해서 다음 코드로 exif정보를 삭제한 이미지를 저장할 수 있다.
from PIL import Image
image = Image.open('image_file.jpeg')
# next 3 lines strip exif
data = list(image.getdata())
image_without_exif = Image.new(image.mode, image.size)
image_without_exif.putdata(data)
image_without_exif.save('image_file_without_exif.jpeg')
# as a good practice, close the file handler after saving the image.
image_without_exif.close()
- 또는 exif-delete(https://pypi.org/project/exif-delete/)와 같은 전용 라이브러리를 사용해도 좋을 것 같다.
참고
- https://en.wikipedia.org/wiki/Python_Imaging_Library
- https://dzone.com/articles/getting-gps-exif-data-with-python
- https://github.com/ianare/exif-samples
- https://stackoverflow.com/questions/72530975/extract-gps-data-using-python-and-pil-is-failing
- https://www.adobe.com/jp/creativecloud/file-types/image/raster/exif-file.html