정보보호 공부

[악성코드] PE 파일(포맷) Part 1 - 개념 및 생성과정과 구조

모카롤 2021. 8. 22. 17:28

기나긴 서론

 

윈도우 보안을 공부하다보면 기본적으로 PE 파일 구조를 분석해야하는 경우가 존재한다. 왜냐하면 윈도우에서 돌아가는 exe 파일 및 dll, bin, sys 파일들이 다 PE 파일의 일종이기 때문이고, 우리가 무심코 다운받는 악성파일들도 대게 exe 파일들이기 때문이다.

 

따라서 학교에서 보안 수업을 듣다보면 PE 파일 구조에 대한 설명이 빠지지 않았는데, 수업시간에 수업을 들을 때는 그저 지루한 수업의 일부라고 생각했다. 특히 필자의 경우에는 새로운 정보 습득이라기 보다는 당장 이 강의의 학점에 직결된 수업이므로 열심히 필기하고 듣고, 최대한 이해한다는 마음가짐으로 수업을 들었기 때문에(죄송합니다, 교수님...) 더더욱 흥미가 생기지 않을 수 밖에 없었다.

 

그러다 보안회사에서 인턴 생활을 하면서 PE 파일을 분석하는 작업을 2달에서 3달가량 진행하게 되었는데, 이때 참 많이 배운 것 같다. 그리고 그 동안 배운 것과 그를 기반으로 만든 PE 파일 분석 툴을 다른 회사 동료분들께 소개할 기회가 있어서 발표를 한 적이 있었는데, 그 발표 자료를 기반으로 PE 파일 설명을 블로그에 정리해보려고 한다.

 

 

※ 해당 블로그 정리 글은 강병탁 교수님의 악성코드 수업 자료를 기반으로 작성되었으며,

그 외 참고 자료는 본 글 마지막에 정리해두겠습니다. 참고 부탁드립니다. ※

 

 


PE 파일이란?

 

PE 파일이란 무엇일까? 위키피디아에 검색해보면 아래와 같이 뜬다.

PE 포맷(Portable Executable)은 윈도우 운영 체제에서 사용되는 실행 파일, DLL, object 코드, FON 폰트 파일 등을 위한 파일 형식이다. PE 포맷은 윈도우 로더가 실행 가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데이터 구조체이다. 이것은 링킹을 위한 동적 라이브러리 참조, API 익스포트와 임포트 테이블, 자원 관리 데이터 그리고 TLS 데이터를 포함한다. 윈도우 NT 운영체제에서, PE 포맷은 EXE, DLL, SYS (디바이스 드라이버), 그리고 다른 파일 종류들에서 쓰인다. 

 

읽어보면 도대체 무슨 말인지 이해하기가 쉽지 않다. 위키피디아가 수많은 정보들을 축약해서 정리해놓았기 때문이다. 하나씩 차근차근 이해하기 전에 일단 PE 파일이 무엇인지 간단하게 살펴보면 아래와 같이 정리할 수 있다.

 

Portable Executable File Format

 

우리가 만든 파일(File)이

실행할 수 있는, 이식 가능한 다른 곳에 옮겨져도(Portable)

실행이 가능하도록(Executable)

만들어 놓은 포맷(Format)

 

 

즉, 윈도우 운영체제에서 우리가 만들고 사용하는 파일이 다른 윈도우 운영체제의 PC로 옮겨져도 실행이 가능하도록 만들어 놓은 포맷 혹은 파일을 PE 포맷, PE 파일이라고 부르는 것이다.

 

대표적으로 exe 파일이 있다. 예를 들어 우리가 뭔가의 설치 파일을 웹사이트에서 다운 받으면 *.exe 파일로 다운받는 경우가 많은데, 이 파일은 윈도우 운영체제를 사용하고 있는 모든 컴퓨터에서 실행이 가능하고, 실행시키면 관련 프로그램이 설치가 된다. 

살짝 삼천포로 빠지자면, python으로 만든 프로그램을 파이썬을 돌릴 환경이 구축되지 않은 윈도우에서 돌리고 싶다면 pyinstaller라는 윈도우 빌드 모듈을 이용해서 exe로 빌드가 가능하다! 그러면 해당 exe 파일로 모든 윈도우에서 실행이 가능하게 된다. 

 

그렇기 때문에 말 그대로 윈도우 상에서 배포 및 실행을 용이하게 만든 파일 포맷을 PE 파일이라고 생각하면 편할 것 같다. 

 

 

 


PE 파일 생성 과정

 

PE 파일 생성 과정 (*악성코드(강병탁) 수업 자료 발췌 및 수정)

 

PE 파일의 생성 과정은 위와 같다.

 

  1. 소스코드 작성
  2. 바이너리로 변경 (컴파일)
  3. 필요한 라이브러리 연결 (링킹)
  4. exe 파일로 빌드 (빌드)

 

아마 c언어로 exe 파일을 빌드해본 사람들은 위 4개의 과정이 매우 익숙할 것이다. 만약 익숙하지 않다면 이제 이해하면 된다. 필자의 경우에도 1학년 때 visual studio를 이용해서 c언어로 exe 파일을 빌드했었는데 그 당시에는 컴파일, 링킹, 빌드란 단어를 이해도 하지 못한 채로 그냥 기본 컴파일, 링킹 설정에 빌드 버튼을 눌러 exe 를 빌드했었다. 

 

각설하고 본론으로 돌아와보면, PE 파일 생성 과정도 중요하지만, 그 무엇보다 여기서 더 주의깊게 봐야할 부분은 바로 PE 헤더이다. PE 파일을 빌드할 때, 파일 실행 시 필요한 정보들을 약속된 규약에 맞춰 PE 파일의 헤더에 기입한다. 그렇기 때문에 PE 파일의 헤더 정보를 보고 운영체제가 해당 프로그램을 실행시키게 된다. 

 

그래서 위키피디아에서 "PE 포맷은 윈도우 로더가 실행 가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데이터 구조체이다." 라고 설명을 한 것이다. 

 

 


PE 파일 구조

 

32비트 PE구조 (위키피디아)

 

32비트의 PE구조는 위의 사진과 같다. 꽤 복잡하고 뭐가 너무 많다. 이렇게 PE 파일 구조를 하나하나 살펴보면 끝이 없고, 결국 길을 잃게 되고 만다. 따라서 악성코드 분석시 중요한 부분들을 위주로 정리하려고 한다. PE 구조 분석은 크게 3가지로 나눠서 진행할 것이며, PE 구조 분석은 양이 방대해 본 글에서는 첫번째 DOS Header만 다루고 나머지는 추후에 정리하려고 한다.

 

 


1. DOS Header

 

DOS 헤더 (*53c 블로거 자료와 악성코드(강병탁) 수업 자료 발췌 및 수정)

 

DOS 헤더에서는 e_magic이라는 DOS Signature 값이 중요하다. 위 그림에서 볼 수 있듯이, 0x00에 위치한 e_magic 값을 가지고 실제로 해당 파일이 PE 파일인지 아닌지를 판단할 수 있다. 왜냐하면 PE 파일의 경우에는 e_magic에 4D 5A(MZ)값으로 고정되기 때문이고, 다시 말해서 이 e_magic값이 4D 5A여야만 PE 파일로 인식해 실행이 가능하다.

 

정말로 그런지 궁금하다면 바로 확인할 수 있는 방법이 있다. 자신의 컴퓨터에 있는 exe 파일을 아무거나 찾아서 메모장(notepad)으로 열어보자. 필자의 경우에는 UPX 패커를 열어봤으며, 아래와 같이 맨 처음에 MZ가 뜨는 것을 볼 수 있다. 

(참고로 용량이 작은 exe 파일을 여는 것을 추천!)

 

UPX 패커 분석

 

따라서 필자가 PE 분석 툴을 만들 때도, e_magic 값이 MZ인지 확인함으로써 입력으로 받은 파일이 PE 파일인지 아닌지를 초반에 필터링하게 개발했었다. 

 

 

 

 


매번 PE 파일이 뭔지 뜬구름 잡듯이 이해가 잘 안 되기도 하고, 정확히 이 PE 포맷이 왜 중요한지나 이걸 배워서 어디다가 쓸 수 있을지에 대해 근본적인 고민을 했었는데, 악성코드 분석 업무 때문에 막상 PE 파일을 분석하다 보니 필자의 지식이나 이해가 참 많이 부족했다는 것을 알았다. 그래서 해당 블로그 글을 정리하는 것도 있는데, 다른 분들도 본 글을 통해서 어렴풋이 PE 파일이 무엇인지 이해하는데 도움이 되었으면 좋겠다. :)

 

 

 

 

참고자료

  1. 리버스 엔지니어링 바이블 – 코드 재창조의 미학 (강병탁 저)
  2. Python pefile 모듈 : https://github.com/erocarrera/pefile 
  3. 헤더 정보 : https://53c-hi.tistory.com/category/%EB%A6%AC%EB%B2%84%EC%8B%B1?page=2
  4. 헤더 정보 : https://furysecurity.tistory.com/32?category=712491
  5. 헤더 구조체 공식 문서 : https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header