오늘은 Windows 운영 체제에서 가장 중요한
파일 형식인 Portable Executable(PE)에 대해 이야기하려 합니다.
PE 파일은 .exe, .dll, .sys 등과 같이 실행 가능한 파일들을 가리키며,
이 파일들 간의 복잡한 의존성을 분석하는 것은 소프트웨어 개발과 보안 분석에 있어 매우 중요합니다.
이번 포스팅에서는 PE 파일의 Import Table, Export Table, 그리고 Import Address Table(IAT)을 이용해서
의존성을 분석하고, 이를 그래프로 시각화하는 방법을 소개하겠습니다.
Import table과 export table 그리고 iat의 차이점
Import Table, Export Table,
그리고 Import Address Table (IAT)은
모두 Portable Executable (PE) 파일 형식의 구성요소입니다.
각 테이블이 나타내는 정보가 다르므로 각각의 목적과 기능을 이해하는 것이 중요합니다.
Import Table이란?
이 테이블은 PE 파일이 실행되기 위해 필요한
외부 라이브러리(DLL 파일)들의 정보를 담고 있습니다.
Import Table에는 각 DLL 파일의 이름과 해당 DLL에서 호출할 함수들의 목록이 포함되어 있습니다.
즉, 이 PE 파일이 실행되기 위해 어떤 외부 DLL에 의존하는지,
그리고 그 DLL에서 어떤 함수들을 사용하는지를 알려주는 테이블입니다.
Export Table이란?
이 테이블은 DLL 파일이 외부에 제공하는 함수나
변수의 정보를 담고 있습니다.
DLL 파일은 여러 개의 PE 파일에서 공유하여
사용할 수 있는 라이브러리로서,
그 안에 정의된 여러 함수들을 외부에 제공합니다.
Export Table은 이러한 함수들의 목록과
그 함수들의 주소 정보를 제공합니다.
따라서, 다른 PE 파일들이 이 DLL 파일을 어떻게
활용할 수 있는지를 알려주는 테이블입니다.
Import Address Table (IAT)이란?
이 테이블은 PE 파일이 Import Table을 통해 가져온 외부 함수들의 주소를 저장하는 곳입니다.
즉, Import Table에서 나열한 각 함수에 대한 실제 메모리 주소를 가지고 있습니다.
PE 파일이 실행되면, 로더는 이 IAT를 채워 넣어서, PE 파일이 각 함수를 호출할 때 메모리에서 바로 찾을 수 있도록 합니다.
Import Table은 '무엇'이 필요한지(어떤 DLL과 함수들이 필요한지),
Export Table은 '무엇'을 제공하는지(어떤 함수와 변수들을 제공하는지),
IAT는 '어디에' 있는지(각 함수의 메모리 주소는 어디인지)를 나타냅니다.
이 세 가지 테이블은 PE 파일이 외부 라이브러리와 어떻게 상호작용하는지를 이해하는데 중요한 역할을 합니다.
PE 파일 의존성 그래프 생성
필요한 라이브러리 이 작업을 수행하기 위해 pefile과 networkx라는 두 가지 파이썬 라이브러리를 사용하겠습니다.
pefile은 PE 파일을 분석하고 파싱하는데 필요한 라이브러리이며,
networkx는 그래프를 생성하고 시각화하는데 사용됩니다.
먼저, 주어진 디렉토리에서 모든 PE 파일을 찾고 이들을 파싱하여 그래프의 노드로 추가합니다.
그런 다음 각 PE 파일의 Import Table을 분석하여 필요한 DLL을 그래프에 추가하고,
이들 사이의 의존성을 간선으로 표현합니다.
PE 파일 의존성 그래프 업데이트 그 다음 단계에서는 모든 PE 파일의 Export Table을 분석합니다.
이를 통해 각 DLL이 제공하는 함수를 알 수 있습니다.
이 함수들을 사용하는 다른 PE 파일을 찾아 그래프에 의존성을 추가합니다.
IAT 정보 출력 마지막으로, 각 PE 파일의 Import Address Table(IAT)를 분석하여
각 함수가 실제로 어떤 메모리 주소에서 호출되는지를 출력합니다.
그래프 시각화 모든 정보를 바탕으로 그래프를 생성한 후에는
networkx와 matplotlib를 이용해서 그래프를 시각화합니다.
이를 통해 각 PE 파일 간의 복잡한 의존성을 한눈에 확인할 수 있습니다.
(아래는 예시 코드입니다)
import os
import pefile
import networkx as nx
import matplotlib.pyplot as plt
def create_dependency_graph(directory):
G = nx.DiGraph()
pe_files = {}
# 모든 PE 파일을 파싱한다.
for filename in os.listdir(directory):
filepath = os.path.join(directory, filename)
# PE 파일이 아닌 경우 건너뛴다.
if not pefile.isPE(filepath):
continue
pe = pefile.PE(filepath)
# 파싱한 PE 파일을 저장한다.
pe_files[filename] = pe
# 현재 파일 노드를 그래프에 추가
G.add_node(filename)
# 모든 PE 파일의 Import 정보를 통해 그래프를 만든다.
for filename, pe in pe_files.items():
if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
dll_name = entry.dll.decode('utf-8')
G.add_node(dll_name)
G.add_edge(filename, dll_name) # 현재 파일에서 DLL로 의존성 표시
# IAT 정보를 출력한다.
for imp in entry.imports:
print(f'{filename} imports function {imp.name} from {dll_name} at address {hex(imp.address)}')
# 모든 PE 파일의 Export 정보를 통해 그래프를 업데이트한다.
for filename, pe in pe_files.items():
if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
# 해당 PE 파일이 export하는 함수를 사용하는 다른 PE 파일을 찾는다.
for user_filename, user_pe in pe_files.items():
if hasattr(user_pe, "DIRECTORY_ENTRY_IMPORT"):
for entry in user_pe.DIRECTORY_ENTRY_IMPORT:
if entry.dll.decode('utf-8') == filename:
for imp in entry.imports:
if imp.name == exp.name:
G.add_edge(user_filename, filename) # 다른 파일에서 현재 파일로 의존성 표시
return G
# 디렉토리 지정 (PE 파일들이 위치한 디렉토리를 지정해야 함)
directory = './PE_files_directory'
G = create_dependency_graph(directory)
# 그래프를 그림
nx.draw(G, with_labels=True)
plt.show()
정리
이 포스트에서는 PE 파일의 Import Table, Export Table,
그리고 IAT를 이용해 PE 파일 간의 의존성을 분석하고 시각화하는 방법을 살펴봤습니다.
다시 한번 정리해보면,
Import Table: PE 파일이 실행되기 위해 필요한 외부 라이브러리(DLL 파일)들의 정보 |
Export Table: DLL 파일이 외부에 제공하는 함수나 변수의 정보 (다른 PE 파일들이 이 DLL 파일을 어떻게 활용할 수 있는지를 알려주는 테이블) |
Import Address Table (IAT): PE 파일이 Import Table을 통해 가져온 외부 함수들의 주소를 저장하는 곳 |
Import Table은 '무엇'이 필요한지
(어떤 DLL과 함수들이 필요한지)
Export Table은 '무엇'을 제공하는지
(어떤 함수와 변수들을 제공하는지),
IAT는 '어디에' 있는지
(각 함수의 메모리 주소는 어디인지)
이 방법을 통해 복잡한 소프트웨어 시스템의 구조를 이해하고, 문제를 분석하고, 솔루션을 찾는 데 도움이 될 수 있습니다.
다음 포스팅에서는 더 심화된 분석 기법을 적용해보겠습니다.
그럼, 즐겁게 코딩하시길 바랍니다!
궁금하신 사항은 댓글에 남겨주세요
댓글에 남겨주신 내용은
추후 정리해서 올려드리겠습니다
구독 신청하시면 업로드 시 알려드릴게요!
-
조금이라도 도움이 되셨다면
공감&댓글 부탁드리겠습니다
감사합니다!
'개념' 카테고리의 다른 글
비트 (Bit)와 바이트 (Bite)와 옥텟이란? feat. 2진수 10진수 계산법 (쉬운 설명, 개념, 정리, 계산법, 아스키코드, 안시 코드 표) (2) | 2024.01.04 |
---|---|
2진수와 10진수 (2진법 10진법) (쉬운 설명, 개념, 제곱, 승) (1) | 2024.01.04 |
http와 https는 무슨 차이일까? (정의 비교 설명 | 네트워크 헤더 프로토콜 ssl) (0) | 2023.12.19 |
제로트러스트 (Zero Trust)란 무엇일까?? (0) | 2023.12.13 |
와이어샤크 (Whireshark) 사용법#2 (쉬운 설명, 필터, 캡처, 연산자) (2) | 2023.12.07 |