Zone Identifier - Export Tool
글 작성자: pental
인터넷에서 다운로드 받은 파일이 악성코드일 가능성은 언제나 있다.
그래서 브라우저는 파일을 다운로드 받을 때 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
이 글은
(새창열림)
본 저작자 표시, 비영리 규칙 하에 배포할 수 있습니다. 자세한 내용은 Creative Commons 라이선스를 확인하세요.
Creative Commons
본 저작자 표시
비영리
'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
댓글을 사용할 수 없습니다.