Zone Identifier - Export Tool
인터넷에서 다운로드 받은 파일이 악성코드일 가능성은 언제나 있다.
그래서 브라우저는 파일을 다운로드 받을 때 NTFS의 ADS 영역에 이 파일을 어디서 다운로드 받았는지에 관한 정보를 저장한다.
이 정보의 이름을 Zone.Identifier 라고 하며, 이 정보는 보안 프로그램에 의해 사용된다.
각 파일의 Zone.Identifier 값으로 다운로드 여부를 판단하며 ZoneId 값이 3이면 인터넷으로 부터 다운로드 된 파일이라고 볼수 있다. Zone.Identifier 은 ADS 의 일종으로 아래와 값은 값들을 가진다.
Zone.Identifier | |
ZoneId=1 | Local Intra Net (로컬 인트라넷) |
ZoneId=2 | Urlzone_Trusted (신뢰 할 수 있는 사이트) |
ZoneId=3 | Internet (인터넷) |
ZoneId=4 | Urlzone_Untrusted (제한된 사이트) |
예를 들어서 파일을 하나 다운 받고 커맨드 창에 다음과 같이 입력한다.
more < [File Name]:Zone.Identifier
파일명 뒤에 ":Zone.Identifier" 라는 문자열을 붙여 입력하면, 다음과 같이 해당 파일을 어디서 다운로드 받았는지에 관한 정보가 표시되는 것을 확인할 수 있다.
도구 제작
import os
import csv
import subprocess
from pathlib import Path
import pandas as pd
downloads_path = str(Path.home() / "Downloads")
print(downloads_path)
file_list = os.listdir(downloads_path)
temp = []
for i in range(len(file_list)) :
query = "more < " + downloads_path + "\\\"" + file_list[i] + "\":Zone.Identifier"
sysMsg = subprocess.getstatusoutput(query)
temp.append([file_list[i], sysMsg[1]])
result = []
for i in range(len(temp)) :
try :
test = temp[i][1].split("\n")[2] # try
name = temp[i][0]
ReferrerUrl = (temp[i][1].split("\n")[2][12:])
HostUrl = (temp[i][1].split("\n")[3][8:])
result.append([name, ReferrerUrl, HostUrl])
except :
pass
print(result)
f = open('output.csv', 'w', encoding='utf-8-sig', newline='')
wr = csv.writer(f)
wr.writerow(["File Name","ReferrerUrl","HostUrl"])
for i in range(len(result)) :
wr.writerow([result[i][0], result[i][1], result[i][2]])
f.close()
r_csv = pd.read_csv("output.csv")
save_xlsx = pd.ExcelWriter("Result.xlsx")
r_csv.to_excel(save_xlsx, index = False)
save_xlsx.save()
os.remove("output.csv")
GUI 개발
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import uic
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
import os
import csv
import subprocess
from pathlib import Path
import pandas as pd
ui_error_path = "main.ui"
ui_error = uic.loadUiType(ui_error_path)[0]
class MainWindow(QMainWindow, ui_error):
def __init__(self):
super().__init__()
self.setupUi(self)
# Button
self.file_button.clicked.connect(self.error_file_select)
self.csv_button.clicked.connect(self.csv)
self.parse_button.clicked.connect(self.parse)
self.excel_button.clicked.connect(self.excel)
self.exit_button.clicked.connect(self.exit_select)
# Path Select
def error_file_select(self) :
try:
global file_path
file_filter = 'All files (*.*)'
file_path = QFileDialog.getOpenFileNames(self, 'Select File', filter=file_filter)
file_path = file_path[0]
_translate = QCoreApplication.translate
self.tableWidget.setColumnCount(1)
self.tableWidget.setRowCount(len(file_path))
self.tableWidget.verticalHeader().setVisible(False)
for i in range(len(file_path)):
item = QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(i, item)
for i in range(1):
item = QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(i, item)
item = QTableWidgetItem()
for i in range(len(file_path)):
for j in range(1):
self.tableWidget.setItem(i, j, item)
item = QTableWidgetItem()
for i in range(len(file_path)) :
item = self.tableWidget.verticalHeaderItem(i)
item.setText(_translate("MainWindow", str(i)))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "File"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setColumnWidth(0, 620)
for i in range(len(file_path)):
for j in range(1):
item = self.tableWidget.item(i, j)
item.setText(_translate("MainWindow", str(file_path[i])))
self.tableWidget.setSortingEnabled(__sortingEnabled)
table = self.tableWidget
header = table.horizontalHeader()
twidth = header.width()
width = []
for column in range(header.count()):
header.setSectionResizeMode(column, QHeaderView.ResizeToContents)
width.append(header.sectionSize(column))
wfactor = twidth / sum(width)
for column in range(header.count()):
header.setSectionResizeMode(column, QHeaderView.Interactive)
header.resizeSection(column, width[column]*wfactor)
except :
QMessageBox.information(self, "Error", "Error", QMessageBox.Ok, QMessageBox.Ok)
def parse(self) :
temp = []
for i in range(len(file_path)) :
query = "more < " + file_path[i] + ":Zone.Identifier"
sysMsg = subprocess.getstatusoutput(query)
temp.append([file_path[i], sysMsg[1]])
global result
result = []
for i in range(len(temp)) :
try :
test = temp[i][1].split("\n")[2] # try
name = temp[i][0]
ReferrerUrl = (temp[i][1].split("\n")[2][12:])
HostUrl = (temp[i][1].split("\n")[3][8:])
result.append([name, ReferrerUrl, HostUrl])
except :
pass
_translate = QCoreApplication.translate
self.zone_tableWidget.setColumnCount(3)
self.zone_tableWidget.setRowCount(len(result))
self.zone_tableWidget.verticalHeader().setVisible(False)
for i in range(len(result)):
item = QTableWidgetItem()
self.zone_tableWidget.setVerticalHeaderItem(i, item)
for i in range(3):
item = QTableWidgetItem()
self.zone_tableWidget.setHorizontalHeaderItem(i, item)
item = QTableWidgetItem()
for i in range(len(result)):
for j in range(3):
self.zone_tableWidget.setItem(i, j, item)
item = QTableWidgetItem()
for i in range(len(result)) :
item = self.zone_tableWidget.verticalHeaderItem(i)
item.setText(_translate("MainWindow", str(i)))
item = self.zone_tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "File"))
item = self.zone_tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "ReferrerUrl"))
item = self.zone_tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "HostUrl"))
__sortingEnabled = self.zone_tableWidget.isSortingEnabled()
self.zone_tableWidget.setSortingEnabled(False)
for i in range(len(result)):
for j in range(3):
item = self.zone_tableWidget.item(i, j)
item.setText(_translate("MainWindow", str(result[i][j])))
self.zone_tableWidget.setSortingEnabled(__sortingEnabled)
table = self.zone_tableWidget
header = table.horizontalHeader()
twidth = header.width()
width = []
for column in range(header.count()):
header.setSectionResizeMode(column, QHeaderView.ResizeToContents)
width.append(header.sectionSize(column))
wfactor = twidth / sum(width)
for column in range(header.count()):
header.setSectionResizeMode(column, QHeaderView.Interactive)
header.resizeSection(column, width[column]*wfactor)
def csv(self) :
try :
f = open('output.csv', 'w', encoding='utf-8-sig', newline='')
wr = csv.writer(f)
wr.writerow(["File Name","ReferrerUrl","HostUrl"])
for i in range(len(result)) :
wr.writerow([result[i][0], result[i][1], result[i][2]])
f.close()
QMessageBox.information(self, "Success", "Export CSV Success", QMessageBox.Ok, QMessageBox.Ok)
except :
QMessageBox.information(self, "Fail", "Export CSV Fail", QMessageBox.Ok, QMessageBox.Ok)
def excel(self) :
r_csv = pd.read_csv("output.csv")
save_xlsx = pd.ExcelWriter("Result.xlsx")
r_csv.to_excel(save_xlsx, index = False)
save_xlsx.save()
os.remove("output.csv")
QMessageBox.information(self, "Success", "Export Excel Success", QMessageBox.Ok, QMessageBox.Ok)
def exit_select(self) :
self.close()
# Main Function
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
if __name__ == "__main__":
main()
Referrence
https://kr.bandisoft.com/bandizip/help/zone-identifier/
https://en.wikipedia.org/wiki/NTFS#Alternate_data_streams_(ADS)
https://secuworld.tistory.com/31
'Forensics' 카테고리의 다른 글
[포렌식] 윈도우 카카오톡 데이터베이스 복호화 분석 및 구현 #1 (69) | 2024.03.23 |
---|---|
[KDFS] 2021년도 KDFS 디지털포렌식 챌린지 발표자료 (0) | 2022.08.20 |
[KDFS] 2021년도 KDFS 디지털포렌식챌린지 보고서 (0) | 2022.08.20 |
[Autopsy] 온라인 무료 강의 혜택 알림 - Autopsy (Covid19) (0) | 2020.04.18 |
[Autopsy] #1 - Autopsy 설치하기 (0) | 2020.04.14 |
댓글
이 글 공유하기
다른 글
-
[KDFS] 2021년도 KDFS 디지털포렌식 챌린지 발표자료
[KDFS] 2021년도 KDFS 디지털포렌식 챌린지 발표자료
2022.08.20 -
[KDFS] 2021년도 KDFS 디지털포렌식챌린지 보고서
[KDFS] 2021년도 KDFS 디지털포렌식챌린지 보고서
2022.08.20 -
[Autopsy] 온라인 무료 강의 혜택 알림 - Autopsy (Covid19)
[Autopsy] 온라인 무료 강의 혜택 알림 - Autopsy (Covid19)
2020.04.18 -
[Autopsy] #1 - Autopsy 설치하기
[Autopsy] #1 - Autopsy 설치하기
2020.04.14