심심해서 혼자 놀다가(2)..
저번에 심심해서 간단하게 스테가노그래피로 파일을 숨겼었다.
그러다 파일 시그니처를 이용해서 숨긴 파일들을 찾을 수 있을 것이라고 생각했다.
HxD 에디터가 없다는 가정 하에,
파일에 대한 Hex Dump 값부터 파이썬으로 나타내야 겠다고 생각했다.
이 부분은 stackoverflow 코드를 많이 참고했고,
그 Hex Dump를 나타내는 코드를 단계별로 변형시켰다.
간단한 테스트를 위해 몇몇 확장자(PNG, JPEG, GIF, ZIP)의 시그니처를 이용했고,
차후 여러 시그니처가 추가되서 길어질 코드를 대비하여 시그니처 파일을 분리했다.
<signature.py>
file_signature = ['ff d8 ff e0',
'ff d8 ff e8',
'89 50 4e 47 0d 0a 1a 0a',
'50 4b 03 04',
'47 49 46 38 37 61',
'47 49 46 38 39 61',
'25 50 44 46 2d 31 2e'
]
file_header_footer = {'ff d8 ff e0':'ff d9',
'ff d8 ff e8':'ff d9',
'89 50 4e 47 0d 0a 1a 0a':'49 45 4e 44 ae 42 60 82',
'50 4b 03 04':'50 4b 05 06',
'47 49 46 38 37 61':'00 3b',
'47 49 46 38 39 61':'00 3b',
'25 50 44 46 2d 31 2e':'25 25 45 4f 46'
}
file_extension = {'ff d8 ff e0':'jpeg',
'ff d8 ff e8':'jpeg',
'89 50 4e 47 0d 0a 1a 0a':'png',
'50 4b 03 04':'zip',
'47 49 46 38 37 61':'gif',
'47 49 46 38 39 61':'gif',
'25 50 44 46 2d 31 2e':'pdf'
}
<hiddenfile_find.py>
import itertools
import argparse
import sys
import os
from math import ceil
from signature import *
def hex_group_formatter(iterable):
chunks = [iter(iterable)] * 4
return ' '.join(
' '.join(format(x, '0>2x') for x in chunk)
for chunk in itertools.zip_longest(*chunks, fillvalue=0))
def hex_viewer(filename, chunk_size=16):
template = ' {:<53}'
with open(filename, 'rb') as stream:
for chunk_count in itertools.count(0):
chunk = stream.read(chunk_size)
if not chunk:
return
yield template.format(
hex_group_formatter(chunk)
)
def file_out(string, header_signature):
global out_file_cnt, unit
out_file_cnt += 1
out_file_name = 'file_out_' + str(out_file_cnt) + '.' + file_extension[header_signature]
f = open(out_file_name,'wb+')
f.write(bytes.fromhex(string))
f.close()
out_file_size = os.path.getsize(out_file_name)
print('[*] Out_file :', out_file_name,' \t','Size :', size_return(out_file_size))
def size_return(bytes):
size_result = str(bytes) + 'Byte'
if (bytes > 1024):
size_result = str(int(ceil(bytes/1024))) + 'KB'
elif (bytes > 1024*1024):
size_result = str(int(ceil(bytes/(1024*1024)))) + 'MB'
elif (bytes > 1024*1024*1024):
size_result = str(ceil(bytes/(1024*1024*1024))) + 'GB'
elif (bytes > 1024*1024*1024*1024):
size_result = str(int(ceil(bytes/(1024*1024*1024*1024)))) + 'TB'
return size_result
def usage():
print("syntax: ./hiddenfile_find <file>")
if __name__ == '__main__':
if(len(sys.argv) != 2):
usage()
exit()
parser = argparse.ArgumentParser(description='Hexadeciaml viewer.')
parser.add_argument('file', nargs='?', default=sys.argv[1], help='the file to process')
args = parser.parse_args()
file_size = os.path.getsize(sys.argv[1])
print('\n[*] Input_file :', sys.argv[1],'\t','Size :', size_return(file_size),'\n')
cnt = -1
out_file_cnt = 0
out_file_flag = 0
string = ''
for line in hex_viewer(args.file):
string += line.replace(" ", " ")
#print(hex(len(string)))
#print(string[6373626-30:6373626])
while (cnt < len(file_signature)-1):
cnt += 1
if (string.find(file_signature[cnt]) != -1):
file_index_start = string.index(file_signature[cnt])
header_signature = string[file_index_start:file_index_start+len(file_signature[cnt])]
footer_signature = file_header_footer[header_signature]
out_file_flag = 1
if(string[file_index_start:].find(footer_signature)!= -1):
file_index_end = string[file_index_start:].index(footer_signature)+ file_index_start + len(footer_signature)
else:
out_file_flag = 0
continue
#print(file_index_start)
#print(file_index_end)
#print(string[167280-20:167280])
if (out_file_flag == 1):
out_file_flag = 0
new_file = string[file_index_start:file_index_end]
#print(new_file)
# 파일 추출
file_out(new_file, header_signature)
# 추출 파일 삭제
next_index = file_index_end + 1
string = string[:file_index_start] + string[next_index:]
#print(string)
cnt = -1
#print(string)
명령 프롬프트로 해당 Python 파일경로에 가서
python hiddenfile_find.py [filename]
형식으로 실행하면 시그니처를 비교하면서 파일을 분리해줄 것이다.
평범한 고양이 사진에서 중요한 파일.txt가 담긴 압축파일이 추출된 것을 확인할 수 있다.
친구의 피드백
+ ) 파일 시그니처별 헤더나 특성도 이용해보라고 한다.
++ ) 핸드폰으로 찍은 사진 어딘가에 위치좌표도 찾을 수 있다고 한다.
나중에 더 많이 심심해지면 찾아봐야지.
수정일 : 2020.12.27.(Sun)
reference
Python Hex Viewer - codereview.stackexchange.com/questions/147225/python-hex-viewer