김승현

KISA Academy - 리버스 코드 엔지니어링 중급 (4~12강) 본문

교육/KisaGym

KISA Academy - 리버스 코드 엔지니어링 중급 (4~12강)

kshind 2024. 7. 8. 19:28

4강 [이론] PE 파일의 개괄적 구조와 실행전후 변화

PE(PE-COFF) 파일이란? 

윈도우 운영체제에서 사용하는 실행파일의 포멧

ex) EXE/DLL/SYS 등

일부 영역을 제외하곤 실행 전후로 모습이 거의 유사함

 

PE파일

Header와 여러 개의 Section으로 이루어져 있음.

 

header에서 집중해서 봐야 할 부분

  1. ImageBase
    1. 해당 PE파일이 메모리에서 매핑되는 시작 주소
  2. AddressOfEntryPoiont
    1. PE파일이 매핑된 후 가장 먼저 실행될 코드의 위치

----  보통 Header를 읽으면 위의 정보와 section 개수와 위치값, 이름, protection을 얻을 수 있음(section table)

---- 보통의 r 권한만 있음 

 

필수적인 Section

  • .text Section
    • 보통 컴파일된 기계어 코드가 포함됨 
    • 코드니까 보통 r x 권한이 있음
  • .data Section 
    • 보통 전역변수들이 포함됨 - 식별가능한 문자열들이 잘 발견됨
      • (strings 같은 함수에서 이 부분의 문자열이 나오는 경우가 많음)
    • 보통 r w 권한이 있음 
  • .idata Section(i는 import)
    • 보통 EXE파일 내 위치함
    • DLL이름, API이름으로 되어 있음 보통
    • 실행파일의 기능을 엿볼 수 있는 Section( [ex] internetConnect이런 이름이 있으면 연결 하는 구나를 할 수 있음)
    • r권한이 있고 바인딩하는 과정도 있을 때가 있어서 w권한도 있을 때 있음

section과 header 각각 사이엔 padding 공간이 포함되어 있음 0000 이런 거로 채워짐

 

예시 - a.exe

page 단위로(*page: 최소한의 접근 통제 단위 ) 배치됨. 이에 각 protection의 단위는 page.  

페이지에 적제 했는데 만약 공간이 남으면 해당 부분은 padding 영역이 됨.

 


5강 [이론] PE 파일의 주요 자료구조 분석 - DOS 헤더와 DOS Stub 코드

DOS Header란?

- 구버전 OS인 MS-DOM와의 호환을 위해 존재하는 헤더, 주로 DOS Stub 영역의 코드를 실행하는 데 사용

최근엔 거의 참조하지 않지만 호환을 위해 꼭 알아야 하는 영역!

 

PE 파일은 DOS 헤더로 시작함. 디스크 상에선 파일의 첫 부분임 (매직코드 MZ가 DOS 그거 2bytes)

e_lfanew는 PE헤더의 위치를 가짐 요즘 대부분의 윈도우 로더는 e_magic과 elfanew만을 참조함...

 

로더라는 프로그램이 메모리에 올라가면,

로더는 MZ라는 문자열을 찾음 (이미지 도스 헤더에 있는),

그 후 점프를 해서 e_lfanew로 이동하고 PE Header(PE)로 이동함. 정상적인 PE_COFF 형식을 갖춘 지 확인하는 느낌

e_cblp, e_cp와 같은 헤더의 변수들은 시작할 때 셋 되어야 할 레지스터 값들이라고 함 이 값 올라가며 DOS Stub Code가 같이 올라감 stub code엔 처음엔 기계어 코드가 있고 This program cannot be run in ... 이런 문자열이 후반부에 존재함 화면에 저 문자열을 출력해주는 코드임 

 

결국 DOS 영역은 dos 환겨에선 실행할 수 없다는 걸 알려주기 위해 존재하는 영역이라고 생각하면 좋음

 


6강 [실습] PE 파일의 주요 자료구조 분석 - DOS 헤더와 DOS Stub 코드 분석 실습

 


7강 [이론] PE 파일의 주요 자료구조 분석 - PE 헤더

IMAGE_NT_HEADER란?

실행파일을 가상주소공간에 매핑시키고 코드를 실행하는 데 필요한 주요 정보를 담음

IMAGE_NT_HEADER는 PE 포멧 파일의 중요한 자료구조 중 하나.

 

PE헤더는 PE_COFF에서

DOS Header, DOS Stub Code 다음으로 오는 것으로 IMAGE_NT_HEADER이다. 이 위치는

DOS Header 젤 마지막에 IMAGE_DOS_HEADER.e_lfanew를 보면 알 수 있음

그 위치 첫 시작의 시그니처를 확인 하면 여기가 맞구나라는 걸 알 수 있음

 

pe헤더의 구조

  • Signature (PE)
  • IMAGE_FILE_HEADER
    • 어떤 아키텍쳐가 대상인지, 언제 빌드가 됐는지 등에 대한 정보를 담음
  • IMAGE_OPTIONAL_HEADER
    • 중요한 정보를 담음 가상주소공간 어디에 적제될지, 어디서 코드를 시작하면 되는지에 대한 정보를 담음
    • 코드 시작방식 등을 공부하고 싶다면 이 영역을 공부해야함
    • 주요 멤버
      • ImageBase
        • 가상 주소 공간의 위치
      • AddressOfEntryPoint
        • 메모리에 로드된 후 가장 먼저 실행될 코드의 위치
      • FileAlignment
        • 주소 시작 위치 지정 결정
      • SectionAlignment
        • 메모리 상에서 각 섹션의 정렬 단위

Virtual address - 매핑될 메모리의 주소

Offset - 이격

AddressOfEntryPoint, FileAlignment, SectionAlignment 모두 오프셋 값으로 표현함

값이 50이면 MZ로부터 50만큼 떨어져 있다는 것을 나타

 

ImageBase는 위와 다르게 절댓값으로 표현됨

 

실행파일이 더블클릭되면

가상주소공간에 올라가고 분석되기 시작, mz가 제대로 되어 있다면 IMAGE_DOS_HEADER.e_lfanew를 읽고

PE헤더를 읽음 PE 시그니처가 있는지 확인한 후 여러 일(시그니처부터 쭉..)을 하고 ImageBase값 확인 ImageBase 위치 가상주소공간에 매핑함 그 이후 쭉 메모리에 매핑 저장될 때 분리되어 다르게가 아니라 거의 비슷하게 매핑됨 

로더 프로그램 자기 일이 끝난 후 코드를 실행해야 겠다는 시점이 존재 이 값은 AddressOfEntryPoint에 존재(x 권한 넘김)

 

파일 내 젤 먼저 실행되는 코드의 위치를 알고 싶으면

ImageBase + AddressOfEntryPoint 위치로 이동해야함 

-> AddressOfEntryPoint는 offset이기 때문.

 


8강 [실습] PE 파일의 주요 자료구조 분석 - PE 헤더 분석 실습

stud_PE 프로그램 사용

- 시각화가 잘 되어 있기 때문

시작 주소와 ImageBase의 위치가 동일함

 

SectionAlignment가 00001000이면 header부터 section1, section2, section3 이렇게 있으면 블럭 단위가 1000으로 나뉜다는 느낌 (사진에선 단위가 1000인 것)   단위는 페이지임!    

.text가 1000보다 커서 2개의 페이지를 잡아먹는다고 보면 됨 (추가적으로 남은 건 padding)

00403000엔 다음 Section이 들어감.

이런 매핑 방법은 protection 때문 

 


9강 [이론] PE 파일의 주요 자료구조 분석 - 섹션테이블

 

섹션 테이블이란?

로더가 각 섹션을 메모리에 로드 하기 전 참조하는 테이블    => 로더를 위해 존재하는 테이블이라 볼 수 있

동일한 자료구조가 배열처럼 나열되어 있음(테이블)

 

PE Header 뒤에 나옴(DOS Header, DOS Stub Code, PE Header, Section Table, Section#1~ ...)

section에는 컴파일러마다 다르지만 보통 .text, .data ,,, etc

 

섹션 테이블의 각 엔트리들은 하나의 섹션들을 담당함( 섹션과 1ㄷ1 대응, PE Header에 S.T의 엔트리 개수가 나타남 )

 

Section Table의 멤버

  • 섹션의 이름 (.text, .data, .idata ...등의 이름이 보임 )
  • PointerToRawData : 파일 상에서 해당 섹션의 위치 ( base )
    • 만약 400이라면 파일의 시작 지점부터 정확히 400만큼 떨어진 위치에 첫 번째 섹션이 존재한다는 뜻
      • 파일 내부에서 Section의 주소 블로그
  • VirtualAddress : 메모리에 올라갔을 때의 위치 ( offset )
    • 메모리에 올라간 파일의 시작 위치에서부터 1000만큼 떨어진 위치에 첫 번째 섹션을 매핑
      • 파일이 실행될 때 메모리에 올라오는 Section의 주소 (Image Base로부터의 Offset) 블로그

 

섹션테이블의 역할

  1. 섹션이 해당 파일 어디에 있고 이를 어디에 적제해야 하는지 알려줌 
  2. Protection을 알려줌 (R, W, X) - Characteristics 멤버에서

 


10강 [실습] PE 파일의 주요 자료구조 분석 - 섹션테이블 분석 실습

분석 도구

CFF Explorer

실행 및 파일 insert 화면

Section Table 값 확인을 위해 Nav에서 Section Header 클릭 

행: 한 섹션에 대한 자료구조들

열: 각 자료구조에 대한 섹션의 값

파일 상에서 위치가 궁금하면 Raw Address

가상 메모리에서 궁금할 땐 Virtual Address

 

어디에 적제된지 알고 싶으면 Virtual Address + ImageBase 값을 해야 함 만약 ImageBase가 00400000이라

.text는, 00401000

.data는, 00403000

*ImageBase란 해당 실행 파일이 매핑될 가상 주소 공간의 주솟값

xdbg를 통한 확인

protaction값은 권한이며 마이크로소프트 공식 홈페이지에서 flag값의 권한을 찾아볼 수 있음

IMAGE_SCN_MEM_EXECUTE : 0x20000000

IMAGE_SCN_MEM_READ : 0X400000000

IMAGE_SCN_MEM_WRITE : 0X800000000

 

-> 0x600000000이라면 실행과 읽기 권한을 포함했다는 뜻 ( 2 + 4 )

위의 0x60500060은 .text Section인데 여긴 기계어 코드의 영역임. 코드기에 읽고 그 코드를 실행하기에 RX가 포함됨E

 

E(Excute)와 R(Read)권한이 실제로 있는 것을 확인 가능함

 


11강 [이론] PE 파일의 주요 자료구조 분석 - 임포트 매커니즘

EXE 확장자를 가진 PE-COFF 파일은 가상주소 공간에서 매핑되어도 DLL내 API를 호출하지 않고는 혼자 일 할 수 없음

그렇기에 PE-COFF 포맷에는 실행 과정에서 참조해야 하는 DLL과 API들을 구조화하여 유지하는데 이를 Import Table이라고 함

 

PEE-COFF파일은 import를 IMAGE_IMPORT_DESCRIPTOR를 통해 체계화하고 구조화하고 있음

IMAGE_IMPORT_DESCRIPTOR는 PE-COFF파일의 헤더 중 OPTIONAL_HEADER에 포함되어 있음

정확히는, OPTIONAL_HEADER의 IMAGE_DIRECTORY_ENTRY_IMPORT를 통해 이동 가능함

 

임포트 테이블은 section에 존재. 일반적으로 .idata에 존재하는 경우가 多 (idata의 i가 import의 i)

이 섹션을 분석하면 함수명이나 이런 문자열을 자주 얻을 수 있음

 

IMAGE_IMPORT_DESCRIPTOR라는 자료구조는 하나의 실행 파일 내에 여러 개 존재할 수 있음 = 배열

끝은 NULL 이들이 모여 import table을 이룸

 

DLL이나 API의 주소 값들은 빌드하는 단계에서 알 수 없음. 가상주소 공간 상의 위치는 랜덤함

-> 보안 상의 목적으로 ( 공격자에 의해서 특정 코드를 실행하거나 정보 참조를 막기 위함)

-> ASLR( Address Space Layout Randomization )

 

바인딩

DLL내 API주소를 찾고 그 주소를 자료구조에 Overwriting하는 과정 Loader에 의해 실행

프로그램 실행 중 필요에 따라 동적으로 binding이 이루어질 수 있음( Dynamic Binding)

 

IMAGE_IMPORT_DESCRIPTOR엔 총 다섯 개의 멤버가 있음

  1. OriginalFirstThunk
  2. TimeDateStamp
  3. ForwarderChain
  4. Name
    1. 참조하는 DLL의 이름이 들어 있음
  5. FirstThunk
    1. 포인터 값임. 함수의 주소 값이 들어 있음 IAT( Import Address Table)의 시작 주소 값을 가짐

4번째 멤버인 Name에서 xxx.dll이 있으면 5번째 멤버의 IAT를 참조하여 얻은 주소는 xxx.dll의 함수의 시작 주소임

-> IAT에는 바인딩 이후 함수들의 주소들이 입력됨

 


12강 [실습] PE 파일의 주요 자료구조 분석 - 임포트 매커니즘 분석 실습

분석 도구

CFF Explorer

실행 및 파일 insert 화면

 

navigator에서 Data Directory 클릭

-> import와 관련된 멤버들 확인 가능. 해당 자료 구조에서는 Offset, Size, Value, Section을 볼 수 있음 

 

Import Directory RVA의 Value는 메모리 상에서의 Offset임.

-> ImageBase의 값에 7000을 더해야지 Import Directory의 주소를 알 수 있음

 

각 IMAGE_IMPORT_DESCRITOR들

파란색은 첫 IMAGE_IMPORT_DESCRITOR의 Name, 초록색은 FirstThunk이다. 각 주소는 00407520, 00407104로 가기

0x00407520

KERNEL32.dll과 관련된 것임을 알 수 있음

0x00407104

 

해당 파일은 KERNEL32.dll, ntdll.dll, msvcrt.dll  3개의 라이브러리를 참조하 IMAGE_IMPORT_DESCRIPTOR는 2개임을 알 수 있음