본문 바로가기

2. Reversing (리버싱)

[2024.11.02]리버씽씽이_4주차 활동

4주차에는 유튜브 리버싱 강의를 12강 ~ 14강까지 학습하였다.

https://www.youtube.com/playlist?list=PLY12b4RRLcSdsxgVvTW3mnNzMjVrd8JhO

 

리버싱 강의

리버싱에 대해 공부합시다.

www.youtube.com

 

<NT Header>

 

IMAGE_NT_HEADERS 구조체

signature PE 값을 가짐.(dos에서 MZ를 갖는 것처럼)

 

 

IMAGE_FILE_HEADER 구조체 (IMAGE_NT_HEADERS의 멤버)

<#1 WORD Machine>

  • CPU 호환칩의 고유한 번호를 저장 (리틀 엔디안 방식)
  •  4C 01 → 014C, 32bit 인텔 호환칩에서 사용함

<#2 WORD NumberOfSections>

  • PE 파일은 코드, 데이터, 리소스 등이 각각 섹션에 나뉘어 저장
  • NumberOfSections는 PE 파일 섹션의 개수를 알려줌 (값은 무조건 0보다 커야함)
  • 섹션의 개수와 실제 섹션 개수가 다르면 실행 불가함

<#3 WORD SizeOfOptionalHeader>

  • IMAGE_OPTIONAL_HEADER32의 크기를 명시 (운영체제 때문)
  • 64bit를 사용하게 되면 크기가 달라짐
  • IMAGE_OPTIONAL_HEADER32의 크기가 달라져도 SizeOptionalHeader로 크기를 인식

<#4 WORD Characteristics>

  • 파일 속성을 나타내는 값
  • 파일 속성: 실행 가능한 형태(exe) 혹은 DLL 파일인지 정보를 Bit OR로 저장
  • Characteristics 값이 없는 파일이 존재 (obj, res, dll)

NT Header-OptionalHeader

IMAGE_OPTIONAL_HEADER32 PE Header의 구조체 중 가장 큰 구조체

<#1. WORD Magic>

  • 구조체의 크기를 나타냄. 사이즈를 담는 멤버
  • IMAGE_OPTIONAL_HEADER32 = 10B
  • IMAGE_OPTIONAL_HEADER64 = 20B

<#2. DWORD AddressOfEntryPoint>

  • EP(Entry Point)의 RVA(상대주소) 값을 가짐
  • 프로그램의 최초로 실행되는 코드의 시작주소로 매우 중요함

<#3. DWORD ImageBase>

  • 프로세스의 가상 메모리는 0~FFFFFF의 범위 (32bit)
  • 넓은 가상 메모리에서 PE 파일이 로드되는 시작주소를 나타냄
  • PE로더가 PE파일을 실행하기 위해 프로세스를 생성하고 파일을 메모리에 로드한 후 EIP(RIP)레지스터 값을 ImageBase+AddressOfEntryPoint Point 값으로 세팅함

매핑: 메모리에 파일을 적재하는 것, 로드: 매핑을 실제로 하는 것

 

Cf> Entrypoint & ImageBase 차이점

  • EP: 실행파일이 시작될 때 실행되는 시작 함수의 주소
  • IB: 실행파일이 로드될 때 BaseAddress(기본주소)를 나타내는 값
  • →  EP 와 IB 는 모두 파일의 메모리의 로딩과 관련

<#4. DWORD SectionAlignment & DWORD FileAlignment>

  • 메모리에서 섹션의 최소단위를 나타내는 것 = SectionAlignment
  • PE파일의 바디 부분은 섹션으로 나뉘는데, 이때 파일에서 섹션의 최소단위를 나타내는 것 = FileAlignment

<#5. DWORD SizeOfImage>

  • PE 파일이 메모리에 로딩되었을 때 가상 메모리 PE IMAGE(메모리에 로딩된 상태)가 차지하는 크기를 나타냄
  • (일반적으로) 파일의 크기와 메모리에 로딩된 파일의 크기는 다름

<#6. DWORD SizeOfHeaders>

  • PE 파일 전체의 크기를 나타냄

<#7. WORD Subsystem>

  • .sys인지 .dll or .exe인지 구별

<#8. DWORD NumberOfRvaAndSizes>

  • IMAGE_OPTIONAL_HEADER32의 마지막 멤버인 DataDirectory의 배열의 개수를 나타냄

<#9. IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]>

  • IMAGE_OPTIONAL_HEADER32 구조체의 배열

 

<Section Header>

  • Section Header: 각 섹션의 속성(Property)을 정의

code, data, rsrc 3가지로 나누어서 섹션을 저장하는 이유

  • 프로그램 복잡함 감소
  • 프로그램 안전성
  • → code/data/rsrc 마다 각각의 섹션별로 권한이 주어져 있음
    • code: 실행, 읽기 권한
    • data: 비실행, 읽기 권한
    • rsrc: 비실행, 읽기 권한

Section Header 구조체

<#1. DWORD VirtualSize>

  • 메모리에서 섹션이 차지하는 크기

<#2. DWORD VirtualAddress>

  • 메모리에서 섹션의 시작주소(RVA = 상대주소, dos header의 VA(절대 주소)가 아님)
  • File header의 SectionAlignment값에 따라 저장

<#3. DWORD SizeOfRawData>

  • 파일에서 섹션이 차지하는 크기

<#4. DWORD PointerToRawData>

  • 파일에서 섹션의 시작주소(RVA = 상대주소)
  • File header의 FileAlignment값에 따라 저장

<#5. DWORD Characteristics>

  • 섹션의 속성을 Bit OR 연산으로 저장
  • WORD Characteristics(파일의 속성을 Bit OR 연산으로 저장)와 다름

virtual이 붙은건 메모리, 아닌 건 파일에서 시작

VirtualAddress PointerToRawData의 값은 일반적으로 다름