SlideShare a Scribd company logo
REVERSING[2] Reverse Engineering
목차
 들어가기 전에..
 바이너리 파일 쓰는 법
 File Format이란?
 PE File Format
 전체 구조
 PE Header
 IMAGE_DOS_HEADER
 IMAGE_NT_HEADER
 IMAGE_FILE_HEADER
 IMAGE_OPTIONAL_HEADER
 IMAGE_SECTION_HEADER
 RVA
 총 정리
 실행 압축
 압축
 실행 압축
 실습-UPX 패킹 분석
 과제
 PE viewer 만들기
 부록
 참고 사이트
들어가기 전에.. • 바이너리 파일 쓰는 법
• File Format이란?
바이너리 파일 쓰는 법
• 바이너리 파일에 struct 데이터를 썼다. 각각의 정수 값들이 가지고있던
값을 쓴다. (-1과 0xF0000000에 주목해 보자. 정수 인코딩 그대로 써 있다.)
• 인텔 CPU에서 실험하여 리틀 엔디안 형식으로 써 있다.
• 이번에 살펴 볼 PE파일 뿐만 아니라 대부분의 파일은 파일 앞부분에
struct을 쓴다.
• 파일을 이용하는 프로그램은 파일을 읽어서 struct에 넣은 후 값을
이용하여 적절한 작업을 한다 .
FILE FORMAT이란?
• 파일 형식
• 저장을 목적으로 정보를 컴퓨터 파일로 인코딩하는 특별한 방식
• 일반적으로 확장자를 통하여 구분한다.
• 특정한 규칙에 따라서 데이터를 저장함.
• 컴퓨터는 특정 규칙에 따라 파일 내용을 읽고 작업해야 하기 때문
• Ex) JPEG 파일은 오른쪽 그림과 같은 순서로 데이터들이 저장되어 있다.
• 그림을 보여주는 프로그램은 JPEG 파일을 보여주기 위해 특정한 값을 필요로 한
다. (예 : 이미지의 크기 등)
• 이 때, 약속된 위치에 있는 값을 읽어 정보를 얻을 수 있다.
• ->이렇게 파일을 어떤 방식으로 쓸 지 정해 놓은 형식이 파일 형식이다.
PE FILE FORMAT
• 전체 구조
• PE Header
• RVA
• 총 정리
PE FILE FORMAT
 PE란?
 Portable Executable File Format의 약자
 파일이(File) 다른 곳에 옮겨져도(Portable) 실행이 가능하도록(Executable) 만들어 놓은 구성 방식(Format)
 다른 OS와의 이식성을 높이려는 의도이지만 실제로는 Windows 계열에서만 사용
 UNIX는 또 다른 File Format을 이용
 32비트 형태의 실행파일은 PE 또는 PE32, 64비트는 PE+ 또는 PE32+라고 함
 PE 헤더 : 실행 파일을 실행하기 위한 각종 정보들이 적혀 있음
전체 구조
전체 구조
PE HEADER
 코드가 실행되기 전 PE 헤더의 정보를 읽음
 PE헤더 내용에 따라 메모리/리소스 할당
 PE가 잘못되면 실행하는 데 필요한 정보를 불러오지 못 함
 로딩 단계부터 실패
PE HEADER – DOS HEADER
PE HEADER – DOS HEADER
winnt.h에 정의돼 있는 DOS header struct
PE HEADER – DOS HEADER
e_magic
PE헤더의 첫 번째 값, Dos 헤더의 첫 번째 값
MZ이라는 표식이 들어간다.
(PE를 만든 Mark Zbikowski의 약자)
PE파일인지 아닌지를 체크하는 용도로 사용됨
PE HEADER – DOS HEADER
e_lfanew
Dos 헤더의 마지막 값
NT Header의 위치를 저장(포인터같은 역할)
(NT header는 바로 다음에 살펴볼 헤더이다)
PE HEADER – NT HEADER
Dos헤더의 e_lfanew값
00 00 00 F0 (리틀 엔디언을 변환)
00 00 00 F0 부터 NT 헤더가 시작
프로그램을 실행할 시
• 파일 맨 앞에 있는 Dos 헤더의 e_lfanew
값을 이용하여 NT 헤더에 접근
• NT 헤더에서 필요한 값을 이용하여
메모리를 확보하는 등 프로그램 실행
작업을 수행
PE HEADER – NT HEADER
DOS stub
• DOS모드와의 호환을 위한 부분
• DOS에서는 DOS stub에 적힌 내용이 코드로 인식되어 실행 됨
• 보통은 DOS에서는 실행되지 않는다는 메시지를 띄우고 종료
• 잘 이용하면 DOS와 Windows 모두 사용 가능하게 만들 수도 있음
PE HEADER – NT HEADER
winnt.h에 정의돼 있는 NT header struct
64비트와 32비트일 경우 다르다. 32비트를 먼저 보기로 했으니 32비트를 기준으로 하겠음
PE HEADER – NT HEADER
Signature
• NT헤더의 시작
• PE 파일임을 표시하는 용도
• DWORD(4바이트)로, 뒤의 00 00도 포함됨
• 딱히 사용되지는 않아 바이러스 개발자가 표식
쓰는 곳으로 이용했다고 함 -> 그래서 최근 OS는
50 45 00 00 을 체크하여 실행한다고 함
PE HEADER – NT HEADER
IMAGE_FILE_HEADER struct
• NT 헤더 struct 내에 있는 또 다른 struct
PE HEADER – NT HEADER – FILE HEADER
winnt.h에 정의돼 있는 File header struct
빨간 네모 안 4개의 값이 중요하다.
이 4개의 값이 잘못되어 있으면 프로그램이 정상적으로 실행되지 않는다.
PE HEADER – NT HEADER – FILE HEADER
Machine
• File header의 첫 번째 값
• 어떤 CPU에서 실행될 수 있는가를 알려줌
• CPU별로 고유의 값이 winnt.h에 정의돼 있음
아래에서 값은 014C(리틀 엔디안이므로)
PE HEADER – NT HEADER – FILE HEADER
Machine
• winnt.h에 정의되어 있는 CPU 값
• 예에서 값이 014C였으므로 intel
386(32비트 인텔) 환경에서
돌아간다는 것을 알 수 있다
PE HEADER – NT HEADER – FILE HEADER
NumberOfSections
• PE파일은 코드, 데이터, 리소스 등이 각각의 섹션에
나뉘어서 저장된다
• 그 섹션의 개수를 나타냄
• 반드시 0보다 커야 한다
• 정의된 섹션 수와 실제 수가 다르면 실행 에러 발생
PE HEADER – NT HEADER – FILE HEADER
TimeDateStamp
• 프로그램을 빌드한 날짜
• 정확히는 obj파일이 컴파일러를 통해 exe로 생성한
시간
• 델파이는 항상 1992년으로 표시한다고 한다
• 조작 가능, 항상 정확한 것도 아님
• 아래 코드처럼 이용하여 시간 형태로 인쇄할 수 있다
PE HEADER – NT HEADER – FILE HEADER
Symbols
• PE 파일 형식이 기반으로 삼은 형식때문에
생긴 것. (COFF)
• 더 이상 사용하지 않기 때문에 값은 항상
0으로 설정해야 한다고 함
PE HEADER – NT HEADER – FILE HEADER
SizeOfOptionalHeader
• NT Header struct의 다음 내용인 Optional Header
struct의 크기를 의미
• Optional header는 32비트와 64비트일 때 다른
형태이기 때문
• Struct의 크기 종류는 32비트일 때와 64비트 일 때로
두 종류이지만, SizeOfOptionalHeader를 구조체
크기로 이용하기 때문에 이를 잘 활용하면
PE헤더를 꼬아 놓을 수 있다 -> PE헤더를 꼬아
놓으면 리버싱하기 어려워 짐
PE HEADER – NT HEADER – FILE HEADER
Characteristics
• 파일의 속성을 나타냄
• 실행이 가능한 형태인지, 혹은 DLL 파일인지 등
• Bit OR 형식으로 조합됨
• winnt.h 에 값이 정의되어 있음
• 밑의 예에서는 0102(리틀 엔디안에 의해)
PE HEADER – NT HEADER – FILE HEADER
Characteristics
• winnt.h에 정의되어 있는 값
• 예에서는 0102 -> File is executable, 32 bit word machine
• PE 파일중 excutable하지 않은 것 : obj, dll 파일 등이 있음
PE HEADER – NT HEADER
IMAGE_OPTIONAL_HEADER struct
• NT 헤더 struct 내에 있는 또 다른 struct
• PE(PE32)에서는 IMAGE_OPTIONAL_HEADER32
• PE+(PE32+)에서는 IMAGE_OPTIONAL_HEADER64
• 이 헤더가 두 종류이기 때문에 NT 헤더가 두 종류가 됨
PE HEADER – NT HEADER – OPTIONAL HEADER
• winnt.h에 정의돼 있는 Optional header struct
• 이 중 10개의 멤버가 가장 중요
• 잘못된 값이 들어있을 시 프로그램이 정상 실행 되지 않음
PE HEADER – NT HEADER – OPTIONAL HEADER
중요한 10개의 멤버들
• Magic
• AddressOfEntryPoint
• ImageBase
• SectionAlignment
• FileAlignment
• SizeOfImage
• SizeOfHeaders
• Subsystem
• NumberOfRvaAndSizes
• DataDirectory
PE HEADER – NT HEADER – OPTIONAL HEADER
Magic <중요>
• IMAGE_OPTIONAL_HEADER32일 경우 10B
• IMAGE_OPTIONAL_HEADER64일 경우 20B
PE HEADER – NT HEADER – OPTIONAL HEADER
Major/MinorLinkerVersion
• 실행파일을 만든 링커의 버전
• 딱히 중요치 않음
• 위의 경우 0x0C.00 이라 할 수 있음(minor가 소수점 아래)
PE HEADER – NT HEADER – OPTIONAL HEADER
SizeOfCode
• 실제 개발자가 만든 코드의 크기
• 악성코드 - 자신의 코드를 복제할 위치를 잡기 위해 이용
• 개발자 – 코드 세션의 무결성 검사를 할 때 이용
PE HEADER – NT HEADER – OPTIONAL HEADER
SizeOfInitializedData
• 파일에 실제로 공간을 잡아야 하는 변수의 총 크기
• 초기화한 변수만 속함(초기화 값을 이용해야 하기 때문)
PE HEADER – NT HEADER – OPTIONAL HEADER
SizeOfUninitializedData
• 실행 파일 자체에 따로 공간을 잡아줄 필요가 없는 변수의 총 크기
• 초기화하지 않은 변수가 속함
• 이러한 부분 때문에 파일이 실행되어 메모리에 올라갈 때 크기가
달라짐
PE HEADER – NT HEADER – OPTIONAL HEADER
AddressOfEntryPoint <중요>
• EP(Entry Point)의 RVA(Relative Virtual Address)
• 최초로 실행되는 코드의 시작주소
PE HEADER – NT HEADER – OPTIONAL HEADER
BaseOfCode
• Code 영역의 시작주소
• 컴파일러 옵션으로 변경 가능하지만 보통 0x1000
• 중요해 보이지만 실제로 ntdll.dll에 구현 되어있는 로더는 이 필드를
사용하지 않는 것으로 보임
PE HEADER – NT HEADER – OPTIONAL HEADER
BaseOfData
• Data 영역의 시작주소
• 중요해 보이지만 실제로 ntdll.dll에 구현 되어있는 로더는 이 필드를
사용하지 않는 것으로 보임
PE HEADER – NT HEADER – OPTIONAL HEADER
ImageBase <중요>
• 실제 가상 메모리에 올라가는 번지를 가리킴
• PE 파일이 로딩되는 시작 주소
• 특별한 옵션이 없는 한 대부분 0x400000, DLL은 0x10000000
• 프로그램이 시작되는 주소 : ImageBase + AddressOfEntryPoint
• RVA 계산의 기준
PE HEADER – NT HEADER – OPTIONAL HEADER
SectionAlignment <중요>
• 메모리에서 Section의 최소 단위
• 메모리의 Section 크기는 반드시 SectionAlignment의 배수이어야 함
• 보통 0x1000
• 예를 들어 코드 섹션의 크기가 0x800이고 SectionAlignment가
0x1000이면 차이인 0x200만큼은 0으로 채움
PE HEADER – NT HEADER – OPTIONAL HEADER
FileAlignment <중요>
• 파일에서 Section의 최소 단위
• 파일의 Section 크기는 반드시 FileAlignment의 배수이어야 함
PE HEADER – NT HEADER – OPTIONAL HEADER
Major/MinorOperatingSystemVersion
• 이 파일을 실행할 수 있는 Windows의 최소 Version
• Major가 소수점 앞, Minor가 소수점 뒷자리
• 위의 예에서는 6.0
PE HEADER – NT HEADER – OPTIONAL HEADER
• Windows 버전에 따른 Version number
PE HEADER – NT HEADER – OPTIONAL HEADER
Major/MinorImageVersion
• 실행 파일의 버전 (ex. Internet explorer11의 11)
• Major가 소수점 앞, Minor가 소수점 뒷자리
• 잘 사용되지 않음
PE HEADER – NT HEADER – OPTIONAL HEADER
Major/MinorSubsystemVersion
• 실행파일을 실행하는 데 필요한 서브시스템의 버전
• Major가 소수점 앞, Minor가 소수점 뒷자리
PE HEADER – NT HEADER – OPTIONAL HEADER
Win32VersionValue
• VC++ 6.0 SDK까지는 예약 영역이었으며 7.0부터
Win32VersionValue라는 이름으로 바뀜
• 사용하지 않는 영역으로 남아있으며 보통 0으로 채움
PE HEADER – NT HEADER – OPTIONAL HEADER
SizeOfImage <중요>
• 가상 메모리에서 PE image가 차지하는 크기
• 일반적으로 파일의 크기와 메모리에 로딩된 크기는 다름
• Section Alignment까지 적용한 값. 반드시 Section Alignment의 배수
• 로더가 이 헤더 값을 보고 메모리 공간을 확보함
• PE image란 메모리에 올라온 형태의 PE File을 의미함
PE HEADER – NT HEADER – OPTIONAL HEADER
SizeOfHeader <중요>
• PE헤더의 전체 크기
• File Alignment의 배수
• 파일 시작에서 SizeOfHeader 옵셋만큼 떨어진 위치에 첫 번째
섹션이 위치
PE HEADER – NT HEADER – OPTIONAL HEADER
Checksum
• Checksum 계산 알고리즘은 IMAGHELP.DLL에 있음
• 모든 드라이버, 부팅 시 로드된 DLL, 중요한 윈도우 프로세스가
로드한 DLL 파일을 검증할 때 사용
PE HEADER – NT HEADER – OPTIONAL HEADER
Subsystem <중요>
• 어떤 subsystem을 이용하는지 기록
• Subsystem의 번호는 winnt.h에 정의되어 있음
• 이 값을 보고 시스템 드라이버 파일인지 일반 실행 파일인지
구분할 수 있음
PE HEADER – NT HEADER – OPTIONAL HEADER
• winnt.h에 정의되어 있는 Subsystem 값
• GUI/CUI도 이 값으로 구분
• 위의 예에서는 0x3, CUI를 의미
PE HEADER – NT HEADER – OPTIONAL HEADER
DllCharacteristics
• 원래는 DLL이라는 전제 하에 어떤 상황에서 DLL 초기화 함수를
호출할 지 지시하는 플래그
• 지금은 대부분 0으로 설정
• winnt.h에 정의되어 있는 값을 OR로 조합하여 이용
PE HEADER – NT HEADER – OPTIONAL HEADER
• winnt.h에 정의되어 있는 DllCharacteristics 값
PE HEADER – NT HEADER – OPTIONAL HEADER
SizeOfStack/HeapReserve, SizeOfStack/HeapCommit
• Reserved로 정의된 만큼의 스택/힙을 사용 가능
• 넘으면 오류를 낼 수 있음. 최대 크기의 의미
• Commit은 한 번에 할당할 메모리의 양
PE HEADER – NT HEADER – OPTIONAL HEADER
LoaderFlags
• 예전엔 디버깅 지원에 관계된 목적으로 있던 것 같음
• 지금은 사용하지 않는 필드
• 0으로 채워져 있음
PE HEADER – NT HEADER – OPTIONAL HEADER
NumberOfRvaAndSizes <중요>
• 바로 밑에 있는 DataDirectory의 배열 수
• 실제로 밑에서 IMAGE_NUMBEROF_DIRECTORY_ENTRIES가 정의되어
있지만(16) PE로더는 이 필드 값을 보고 배열의 크기를 인식
• 즉 16이 아닐 수도 있다
PE HEADER – NT HEADER – OPTIONAL HEADER
DataDirectory <중요>
• 보통 명시된 수(IMAGE_NUMBEROF_DIRECTORY_ENTRIES,
16(0x10))만큼의 배열
• IMAGE_DATA_DIRECTORY struct의 배열, winnt.h에 정의되어 있음
• 배열의 각 항목마다 정의된 값을 가짐
PE HEADER – NT HEADER – OPTIONAL HEADER
• winnt.h에 정의되어 있는 Data Directory와
IMAGE_NUMBEROF_DIRECTORY_ENTRIES
• VirtualAddress를 이용하여 각 항목이 의미하는
데이터를 얻으러 갈 수 있음
PE HEADER – NT HEADER – OPTIONAL HEADER
• 각 배열 항목마다의 용도
PE HEADER – NT HEADER – OPTIONAL HEADER
• 각 배열 항목마다의 용도
PE HEADER – SECTION HEADER
File Header의 NumberOfSections 수만큼 Section Header struct이 붙는다.
PE HEADER – SECTION HEADER
winnt.h에 정의돼 있는 Section header struct
빨간 네모 안 5개의 값이 중요하다.
PE HEADER – SECTION HEADER
Name
• 8바이트 크기의 Char 배열
• Section의 이름
• 맨 끝이 NULL로 끝나지 않거나, ASCII가 아니거나, NULL로만 채워도 됨
• 참고용일 뿐이고, 장담할 수 없음(.data섹션을 .code라 해도 영향 무)
• .text : 실행되는 코드
• .data : 초기화된 전역변수
• .rdata : 읽기 전용 데이터
• .bss : 초기화되지 않은 전역변수
• .idata : 다른 dll로부터 가져다 쓰는 함수들의 정보
• .edate : 다른 모듈이 이 파일을 사용할 때 사용하도록 해 놓은 함수 리스트
• .rsrc : 리소스
• .reloc : reloctaion을 위한 정보
PE HEADER – SECTION HEADER
Misc_VirtualSize <중요>
• DWORD짜리 union이며 PhysicalAddress나 VirtualSize로 이용
• PhysicalAddress : obj파일에서 사용. Section의 physical address를 의미
• VirtualSize
• PE 로더에 의해 이미지가 메모리에 올려진 후에 해당 섹션이 얼마만큼의 크기를 가지고 있게 되는 지의 정보
• Section alignment가 적용되지 않은 실제 값을 가지고 있음
PE HEADER – SECTION HEADER
VirtualAddress <중요>
• PE파일이 메모리에 올려진 후의 해당하는 섹션의 시작 주소
• RVA (Relative virtual address)
• Optional Header의 Section Alignment의 배수
PE HEADER – SECTION HEADER
SizeOfRawData <중요>
• Raw data(실제 파일)상에서 해당 섹션의 실제 사용 크기
• 해당 섹션의 빈 공간이 얼마나 있는가를 알아내기 위해 반드시 필요
• Optional Header의 File Alignment의 배수 (이 헤더 필드의 값은 File alignment가 적용된 섹션의 크기임)
• Obj파일에는 실제 크기(File alignment가 적용되지 않은)가 적혀 있음
• 위의 예에서는 Section은 있지만 내용이 없어서 0임 ->앞으로의 예에서는 아래 section을 보겠음
PE HEADER – SECTION HEADER
• Section헤더는 section의 수만큼 있으므로 아래의 예를 보았다
• .text(코드) section의 크기가 3C00
• 예에서 File alignment는 200으로 3C00의 약수임
PE HEADER – SECTION HEADER
PointerToRawData <중요>
• Raw data(실제 파일)상에서 섹션의 시작 위치
• RAW 값(File offset, 파일의 시작부터 얼마나 떨어져 있는가)
PE HEADER – SECTION HEADER
PointerToRelocations
• obj파일에서만 사용 – relocation 정보에 접근하기 위한 file offset
• 실행 파일에서는 의미가 없으므로 0으로 채움
PE HEADER – SECTION HEADER
PointerToLinenumbers
• Line number table의 file offset
• Source file의 line number와 관련이 있음
• 디버깅에 이용
• 별로 중요하게 다뤄지지 않는듯
PE HEADER – SECTION HEADER
NumberOfRelocations/Linenumbers
• NumberOfRelocation
• PointerToRelocations 를 따라가면 있는 Relocation table의 수
• Obj파일에서만 의미가 있음
• NumberOfLinenumber
• PointerToLinenumbers 를 따라가면 있는 Line number table의 수
PE HEADER – SECTION HEADER
Characteristics <중요>
• Section의 속성
• Bit OR로 계산
• 실행 여부, 초기화된 section인지 등을 담고 있음
• winnt.h에 값이 정의되어 있음
PE HEADER – SECTION HEADER
• winnt.h에 값이 정의된 값
• 위의 예에서는 60 00 00 20
• 코드 section이며, execute가능, read가능
• 각 section의 특징은 이 값을 읽어 판단해야
한다 (section 이름으로 판단하지 말고)
RVA
 Relative Virtual Address
 메모리에서의 주소 offset
 ImageBase를 기준으로 계산
 ImageBase로부터 얼마나 떨어져 있는가 (ImageBase는 말 그대로 PE image의 base다)
 Virtual address = ImageBase + RVA
 RVA를 이용하는 헤더 필드
 Optional header의 AddressOfEntryHeader
 Optional header의 DataDirectory의 VirtualAddress
 Section header의 VirtualAddress
 앞으로 나올 헤더 필드들… (IAT 등)
가상 메모리 주소
Image base RVA
가상 메모리에
올라온
PE 이미지
Image base
가상 메모리
RVA
RVA – RVA TO RAW
 RVA to RAW
 RVA값을 RAW(file offset)으로 변환하기
 RVA는 실행 시 메모리의 주소. 헤더에 RVA 형태로 적혀 있음
 헤더에 RVA로 적힌 주소에 적힌 내용을 파일에서의 찾고 싶으면 RVA를 RAW로 변환해야 함
가상 메모리에
올라온
PE 이미지
Image base
가상 메모리
RVA
PE 파일
0
파일
RAW
RVA – RVA TO RAW
Image base
Section2의
VirtualAddress
찾고자 하는
정보의
RVA
0
찾고자 하는
정보의
RAW
Section2의
PointerToRaw
계산
RVA – RVA TO RAW
Image base
Section2의
VirtualAddress
찾고자 하는
정보의
RVA
0
찾고자 하는
정보의
RAW
Section2의
PointerToRaw
찾고자 하는 정보의 RAW – 속한 section의 PointerToRaw = 찾고자 하는 정보의 RVA – 속한 section의 VirtualAddress
RVA – RVA TO RAW – 연습문제 1
 Q1. RVA = 5000일 때, File offset(RAW)는?
RVA – RVA TO RAW – 연습문제 1 풀이
 Q1. RVA = 5000일 때, File offset(RAW)는?
 RVA 5000을 따라가보면 .text영역임을 알 수 있다
 위에서 도출한 식을 이용하면
 RAW – 400 = 5000(RVA) – 1000(.text 섹션의 VirtualAddress)
 따라서, RAW = 4400
 주의
 Section헤더의 VirtualAddress와 그냥 Virtual address를 헷갈리지 말자
RVA =
5000
RVA – RVA TO RAW – 연습문제 2
 Q2. RVA = 13314일 때, File offset(RAW)는?
RVA – RVA TO RAW – 연습문제 2 풀이
 Q2. RVA = 13314일 때, File offset(RAW)는?
 RVA를 따라가서 어느 section에 속하는지 확인하자
 .rsrc가 의심됨
 .rsrc의 시작주소(VirtualAddress)에 VirtualSize값을 더해
13314를 포함하는지 확인
 B000 + 8314 = 13314로 딱 끝에 포함한다
 .rsrc섹션에 포함됨을 알았으니 1번 문제와 같이 계산한다
 RAW = 13314 – B000 + 8400 = 10714
RVA =
13314
RVA – RVA TO RAW – 연습문제 3
 Q3. RVA = ABA8일 때, File offset(RAW)는?
RVA – RVA TO RAW – 연습문제 3 풀이
 Q3. RVA = ABA8일 때, File offset(RAW)는?
 RVA를 따라가서 어느 section에 속하는지 확인하자
 .data가 의심됨
 . data의 시작주소(VirtualAddress)에 VirtualSize값을 더해
ABA8을 포함하는지 확인
 9000 + 1BA8 = ABA8 로 딱 끝에 포함한다
 . data 섹션에 포함됨을 알았으니 1번 문제와 같이 계산한다
 RAW = ABA8(RVA) – 9000(VA) + 7C00(PointerToRawData) = 97A8
 그런데 97A8은 파일에서 .rsrc에 속한다
 RVA로는 .data, RAW로는 .rsrc에 속한다는 것은 말도 안 됨
 이럴 때는 “해당 RVA에 대한 RAW 값은 정의할 수 없다”고 해야 함
 값이 이상한 이유
 VirtualSize값이 SizeOfRawData 값보다 크기 때문
 이런 식으로 특이 케이스가 생김 -> 앞으로 살펴볼 것
RVA =
ABA8
총 정리
 중요한 것, 헷갈리는 것 묶어서 정리해 봄
 주목할 점
 무엇에 쓰이는가
 File에 관련되었는지 Memory와 관련되었는가
 RVA인가 RAW인가
 Alignment가 적용되었는가
총 정리 – DOS HEADER
총 정리 – DOS HEADER
PE 파일임을 표시
File alignment가 적용된, 다음
헤더가 시작되는 주소 (RAW)
총 정리 – NT HEADER
PE32인 경우와 PE32+인 경우로, 2종류
총 정리 – NT HEADER
PE파일임을 표시
파일에 대한 정보들
파일 실행을 위해 필요한 정보들
PE32와 PE32+의 차이를 만든다
PE HEADER – NT HEADER – FILE HEADER
PE HEADER – NT HEADER – FILE HEADER
파일을 이용할 수 있는 CPU
파일에 있는 section의 수
파일의 속성
파일이 사용하는 Optional Header의 크기
총 정리 – NT HEADER – OPTIONAL HEADER
중요한 10개의 멤버들
• Magic
• AddressOfEntryPoint
• ImageBase
• SectionAlignment
• FileAlignment
• SizeOfImage
• SizeOfHeaders
• Subsystem
• NumberOfRvaAndSizes
• Dadadirectory
총 정리 – NT HEADER – OPTIONAL HEADER
PE32와 PE32+의 Optional header를 구분
PE32와 PE32+일 때의 값이 다름
총 정리 – NT HEADER – OPTIONAL HEADER
Section alignment가 적용된,
메모리에서의 Entry Point (시작 코드 주소)
(RVA)
Section alignment가 적용된,
PE image가 올라가는 시작 주소
RVA값 계산의 기준이 된다
ImageBase + RVA값 = 가상메모리 주소
총 정리 – NT HEADER – OPTIONAL HEADER
Section Alignment
메모리에서 각 section의 최소 단위
File Alignment
파일에서 각 section의 최소 단위
총 정리 – NT HEADER – OPTIONAL HEADER
Section alignment가 적용된,
메모리에서 PE image의 총 크기
File alignment가 적용된, 파일에서 헤더의 크기
총 정리 – NT HEADER – OPTIONAL HEADER
어떤 subsystem을 이용하는가
총 정리 – NT HEADER – OPTIONAL HEADER
바로 아래 있는 DataDirectory 배열의 크기
실행에 필요한 여러 정보로 접근하기 위한 테이블
각 인덱스마다 역할이 정해져 있음
총 정리 – NT HEADER – OPTIONAL HEADER
총 정리 – NT HEADER – OPTIONAL HEADER
해당 정보로 접근하기 위한 주소 (RVA)
총 정리 – SECTION HEADER
총 정리 – SECTION HEADER
Section alignment가 적용되지 않은, 메모리에서의 section의 크기
File alignment가 적용된, File에서의 section의 크기
총 정리 – SECTION HEADER
Section alignment가 적용된,
메모리에서의 section이 시작되는 주소(RVA)
File alignment가 적용된,
파일에서의 section이 시작되는 주소(RAW)
총 정리 – SECTION HEADER
Section의 성질, 역할 등
Name이 아니라 Characteristics를 이용하여
판단해야 함
Windows reversing study_basic_3
실행 압축
• 압축
• 실행 압축
• UPX 분석
압축
 실행 압축을 살펴보기 전에 압축에 대해 간단히 알아보자
 데이터 압축
 비손실 압축
 흔하게 아는 압축
 압축을 풀면 원본 파일이 나온다.
 손실 압축
 데이터에 의도적으로 손상을 주어서 압축률을 높임
 주로 멀티미디어 파일들(jpg, mp3, mp4 등)이 이용
 사람의 눈과 귀가 알아차리지 못하는 수준에서 데이터 손상을 입힌다.
 가청 주파수를 넘는 영역을 의도적으로 제거하는 등
 원본으로 되돌릴 수 없다.
압축
 대체 어떻게 비손실 압축을 할 수 있나?
 유명한 비손실 압축 알고리즘의 하나인 Huffman 알고리즘을 가볍게 살펴보자.
 AABBAC라는 문자열이 있다고 하자. 이는 총 6바이트이다.
 각 문자들이 사용된 횟수를 세어 보자. A는 3, B는 2, C는 1번이다.
 가장 많이 사용된 A에게 0이라는 1bit를 부여하고, B는 10, C는 11을 부여할 수 있다.
 그러면 001010011로 나타낼 수 있다. 이는 9bit, 즉 1바이트 +1비트이다.
 이것이 Huffman 알고리즘의 핵심이다.
 구체적 방법이 궁금하다면 참고 사이트를 찾아가볼 것
실행 압축
 실행 압축
 실행(PE)파일을 대상으로 한다.
 비 손실 압축을 이용한다.
 파일 내부에 압축 해제 코드를 포함하고 있어서 실행되는 순간에 메모리에서 압축을 해제시킨 후 실행한다.
 실행 압축된 파일 역시 PE파일이다.
 내부에 원본 PE 파일과 decoding 루틴이 있다.
 EP(Entry point)는 decoding 루틴의 시작부분이다.
 실행 파일 압축기를 PE 패커(Packer)라고 한다. Run-Time Packer라고도 한다.
실행 압축
항목 일반 압축 실행 압축
대상 파일 모든 파일 PE 파일(exe, dll, sys 등)
압축 결과물 압축(zip, rar 등) 파일 PE 파일(exe, dll, sys 등)
압축해제 방식 전용 압축해제 프로그램 내부의 decoding 루틴
파일 실행 여부 자체 실행 불가 자체 실행 가능
장점 모든 파일에 대해
높은 압축률로 압축 가능
별도의 해제 프로그램 없이
바로 실행 가능
단점 전용 압축해제 프로그램이 없으면
사용할 수 없음
실행때마다 decoding 루틴이 호출되기 때
문에 실행시간이 미세하게 느려 짐
실행 압축 실습 – UPX 분석
 UPX 패킹은 EXE파일의 크기를 줄이기 위해 사용되는 순수한 의도의 패커다.
 Virus total이라는 바이러스 진단 홈페이지에서 UPX 패킹된 프로그램은 바이러스로 진단하지 않는다.
 악성 코드에 많이 사용되는 패킹이 적용된 프로그램은 바이러스로 진단한다.
 구글에 치면 다운받을 수 있다. 패킹 프로그램(패커)를 이용하여 패킹을 하거나 해제할 수 있다.
 다운 링크는 참고 사이트에 있다.
 분석을 방해하기 위한 패커가 아니기 때문에 단순하다.
실행 압축 실습 – UPX 분석
 간단한 프로그램을 만들었다.
 원래 크기는 49KB였다.
 UPX 패킹을 적용했다.
 35KB가 되었다.
 파일 크기가 약간 줄었다.
실행 압축 실습 – UPX 분석
 패킹을 적용하지 않은 원본 파일과 패킹이 적용된 파일을 올리디버거로 열어보았다.
 열기만 하고 진행은 안 했는데, 주소가 다르다. 이는 패킹이 적용된 코드의 EP가 다르다는 것을 의미한다. PE헤더 역시
변형되었다.
<Origin> <Packed>
실행 압축 실습 – UPX 분석
 PE viewer로 비교해 보았다.
실행 압축 실습 – UPX 분석
 패킹된 코드를 살펴보자.
 UPX 패커의 특징은 맨 처음에 PUSHAD 명령어가 있다는 것이다.
 PUSHAD는 레지스터 값 전부를 스택에 저장하는 명령어다. 이와
대응되는 명령어는 POPAD이다.
 UPX 패커는 PUSHAD로 백업해 둔 레지스터 값을 디코딩 루틴이
끝난 후 다시 복원한다.
 이를 이용하면 쉽게 OEP(origin EP, 원래 EP)를 찾을 수 있다.
 이 방법은 뒤에서 알아보고, 일단 디코딩 루틴을 살펴보자.
 Pushad 후에 ESI와 EDI에 수를 넣는다. 이 수는 각각 압축된 코드
가 저장된 주소와 압축 해제한 코드를 저장할 주소이다.
 ESI와 EDI에 주소를 동시에 설정하는 패턴은 Source에서
Destination으로 복사하는 코드가 나올 거라고 예측할 수 있는
패턴이다.
실행 압축 실습 – UPX 분석
 여기서, ESI와 EDI에 저장된 값에 주목해 보자.
 ESI에는 0x40F015, EDI에는 계산 결과 0x401000이 들어간다.
 섹션의 RVA값과 ImageBase값을 조사해 보면 ESI가 가리키는 주소는 두 번째 섹션, EDI
가 가리키는 값은 첫 번째 섹션에 속한다는 것을 알 수 있다.
 UPX 패킹은 두 번째 섹션에 압축된 코드와 디코딩하는 코드가, 첫 번째 섹션에 디코딩
된 코드가 올라온다.
 첫 번째 섹션의 RAW data 오프셋과 두 번째 섹션의 RAW 오프셋이 같다. 또한 첫 번째
섹션의 RAW data size는 0이다.
 첫 번째 섹션은 메모리에만 존재한다. Bss영역처럼 메모리에 예약만 해 두고, 파일
에는 내용이 없다.
실행 압축 실습 – UPX 분석
 디코딩 루틴은 보통 같은 일을 반복하여, 규칙을
이용하여 디코딩된다. 따라서 루프가 많이 나온다.
 루프가 있는 부분이 핵심적인 코드일 가능성이 크다.
 bp를 걸고 F9로 실행하여 루프를 빠르게 나올 수 있다. 혹은 한
줄 씩 자동으로 실행하는 trace over나 animate over를 이용하면
편하다.
 UPX 패킹의 맨 처음 나오는 루프는 압축된 코드를
그대로 버퍼에 복사한다.
 별 의미없는 코드이다. 아래쪽에 크게 디코딩 코드가 있다.
실행 압축 실습 – UPX 분석
 방금 본 루프에 큰 범위로 디코딩 코드가 있다.
 그 루프의 마지막 부분에서 디코딩하여 나온 원본 코드를 버퍼에
저장한다.
 저장하고 다시 위로 올라가 의미 없는 복사를 한 뒤 디코딩 루틴에
들어간다.
 리소스도 코드와 함께 인코딩 되어 있다. Hello문자열도 이 때 디코
딩 되어 저장된다.
 코드는 1 바이트 씩 저장이 진행되고, 리소스는 4바이트 단위로
저장이 진행된다. 위 코드는 디코딩 된 코드를, 아래 코드는 디코
딩된 리소스를 저장한다.
실행 압축 실습 – UPX 분석
 디코딩이 끝나면 두 번째 루프가 나온다.
 UPX 패킹의 두 번째 루프는 디코딩한 원본 코드에 주소를
사용하는 코드가 있을 때, 주소를 복원해주는 루틴이다.
 Jump나 call과 같은 명령어인지 판단하고 그렇다면 주소를 복
원한다.
실행 압축 실습 – UPX 분석
 UPX 패킹의 세 번째 루프는 IAT를 설정하는 루틴이다.
 IAT는 프로그램이 라이브러리를 쓸 수 있도록 해 주며, PE 헤더에 속
한다.
 IAT는 추후 자세히 할 것임
실행 압축 실습 – UPX 분석
 쭉 내려오면 POPAD가 보인다. 처음에 PUSHAD로 백
업한 레지스터 값을 복원한다.
 무조건 점프로 0x004014E0로 점프한다.
 이 주소는 원본 프로그램의 Entry Point주소이다.
실행 압축 실습 – UPX 분석
 점프해 보면 이상한 코드가 보인다.
 이는 숫자가 기계어로 해석되지 않았기 때문이다.
 Ctrl+a를 누르면 기계어를 디스어셈블한 코드를 볼 수 있다.
Ctrl + A
실행 압축 실습 – UPX 분석
• 패킹이 해제된 코드는 원래 코드와 똑같다!
• 이렇게 수작업으로 OEP(original entry point, 원래 시작 코드)를 찾아보았다.
• 다른 패커들은 각자 알고리즘은 다르지만, 이와 비슷한 일을 처리한다.
<Origin> <Packed>
실행 압축 실습 – UPX OEP 쉽게 찾기
 UPX 패커의 특징은 맨 처음에 PUSHAD 명령어가 있다는 것이다.
 이를 이용하면 쉽게 OEP(origin EP, 원래 EP)를 찾을 수 있다.
 스택에 하드웨어 bp를 걸어 백업해 둔 레지스터 값들을 복원하는 순간에 멈추거나, 명령어 검색으로 POPAD를 찾아보는 방법을 이용
할 수 있다.
실행 압축 실습 – UPX OEP 쉽게 찾기
 하드웨어 bp를 이용하는 방법
 Pushad로 레지스터를 복원하며 사용한 스택의 주소를 메모리 덤프에서 찾는다. 정확한 주소에 있는 값을 클릭하고 오른쪽키를 눌러
메뉴를 띄우고, bp를 건다.
실행 압축 실습 – UPX OEP 쉽게 찾기
 명령어 찾기를 이용하는 방법
실행 압축 실습 – UPX – 메모리 덤프
 패킹을 직접 풀었을 경우 프로그램 코드에 bp가 걸리지 않는다.
 파일에 있는 고정된 코드가 아니라 메모리에만 올라오는 코드이기 때문에 올리디버거가 기억을 못 함
 이 때는 메모리 덤프를 떠서 디코딩 된 코드와 리소스를 저장하면 좋다
 메모리만 있던 내용을 아예 파일에 저장했기 때문에 디버거가 기억할 수 있게 된다.
 올리 디버거의 플러그인으로 제공되는 메모리 덤프 기능을 이용해서 덤프를 떠 보자.
 메모리 덤프란 메모리에 올라온 상태 그대로 저장하는 것이다.
 올리디버거 창의 메모리 덤프는 메모리를 그대로 보여주는 것이고, 저장할 때는 덤프를 뜬다고 한다. 간단하게 메모리 덤프라고
도 한다.
 메모리 덤프를 뜨면 디코딩되어 메모리에 올라와 있는 원래 코드를 파일에 저장할 수 있다.
 다운 경로는 부록 참고 사이트에 있다.
 참고 사이트에서는 importRCE 툴도 이용하는데, 당장은 필요하지 않다.
실행 압축 실습 – UPX – 메모리 덤프
 디코딩을 완료한 상태에서 오른쪽키 메뉴에서 Dump debugged process를 클릭한다.
 뜬 창 그대로 Dump를 누르고 저장한다.
실행 압축 실습 – UPX – 프로그램을 이용한 해제
 UPX 패킹은 오픈소스 프로그램이다.
 UPX 패킹이 적용되었다는 것만 알아내면 쉽게 풀 수 있다.
 PEiD라는 툴은 PE 헤더의 내용을 정리해서 보기 쉽게 해 주고, 패킹 여부를 알려주는 프로그램이다.
 모든 패킹 종류를 알지는 못 하지만 잘 알려진 패킹은 잘 알아낸다.
 다운 링크는 참고 사이트에 있다.
 그 외 Exeinfo PE등 여러 프로그램이 있다. 천천히 입맛에 맞는 것을 찾아 쓰면 된다.
실행 압축
 패커
 사용 목적
 PE 파일 크기를 줄이기 위해
 PE 파일의 내부 코드와 리소스를 감추기 위해
 평범하게 압축하는 순수한 의도의 패커와 원본 파일을 크게 변형하고, PE 헤더를 심하게 훼손시키는 불순한 의도의 패커
로 나뉜다. 후자는 악성 프로그램이 주로 사용한다.
 순수한 의도의 패커(VirusTotal에서 진단 안 됨) : UPX, ASPack 등
 불순한 의도의 패커(VirusTotal에서 진단 됨) : Upack, PESpin, NSAnti
실행 압축
 프로텍터
 단순히 실행 압축만 하는 것이 아니라 리버싱을 막기 위한 다양한 기법을 추가함
 원본 코드보다 커지는 경향이 있음
 사용 목적
 크래킹 방지
 코드 및 리소스 보호
 보안 프로그램의 진단을 막기 위해
 Ex) 일부 프로텍터는 ‘다형성 코드’를 제공한다. 이는 매번 다른 모양(이지만 같은 기능)의 코드가 생성되게 한다.
 종류
 상용 프로텍터 : ASProtect, Themida, SVKP 등
 공개용 프로텍터 : UltraProtect, Morphine 등
과제 • PE Header Viewer 만들기
• 문제 풀고 write up
PE HEADER VIEWER 만들기
 PE Header Viewer란?
 PE헤더에 어떤 값이 들어있는지 알려주는 프로그램
 시중에 다양한 PE Viewer가 있음
 프로그램 정적 분석 시 자주 이용
PE HEADER VIEWER 만들기
과제는 콘솔 기반 PE Header viewer를 만드는 것이다.
요구사항 :
• 인자로 넣은 파일을 열어서 분석
• 왼쪽 예와 같이 어떤 헤더에 속하는지 구분
• 값을 16진수로 표시
PE는 리버싱에서 매우 중요한 주제이다. 모든 기술의
기초가 된다.
점점 노하우와 설명을 붙여 자신만의 PE Viewer를
만들어보자.
PE HEADER VIEWER 만들기 - TIP
파일에서 struct을 읽는 기본적인 방법이다
C++스타일로 더 세련된 방법도 있지만 .. 한 번에 하나씩 하자..
이 방법이 마음에 안 들면 인터넷 찾아보기
부록 • 참고 사이트
참고 사이트
 PE헤더 필드 설명
 https://msdn.microsoft.com/en-us/library/ms809762.aspx
 영어지만 가장 잘 써 있음
 이제 안 쓴다고 사람들이 무시하는 필드도 설명해 줌
 Huffman 압축 알고리즘 설명
 http://wooyaggo.tistory.com/95
 UPX 패커 다운로드
 https://github.com/upx/upx/releases/tag/v3.94
 메모리 덤프
 http://blog.naver.com/ln8520nl/220734849758
 PEiD 다운로드
 http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml

More Related Content

PPTX
Windows reversing study_basic_7
 
PPTX
System+os study 1
 
PPTX
Windows reversing study_basic_4
 
PPTX
Windows reversing study_basic_5
 
PPTX
Pwnable study basic_2
 
PPTX
System+os study 4
 
PPTX
Assembly 스터디 1
 
PPTX
Windows reversing study_basic_1
 
Windows reversing study_basic_7
 
System+os study 1
 
Windows reversing study_basic_4
 
Windows reversing study_basic_5
 
Pwnable study basic_2
 
System+os study 4
 
Assembly 스터디 1
 
Windows reversing study_basic_1
 

What's hot (20)

PPTX
Pwnable study basic_1
 
PPTX
Windows reversing study_basic_9
 
PPTX
Pwnable study basic_3
 
PPTX
Linux reversing study_basic_4
 
PPTX
Linux reversing study_basic_2
 
PPTX
Windows reversing study_basic_8
 
PPTX
Assembly 스터디 2
 
PPTX
System+os study 7
 
PPTX
Python
 
PPTX
System+os study 3
 
PPTX
Linux reversing study_basic_3
 
PPTX
Windows reversing study_basic_6
 
PPTX
Windows reversing study_basic_2
 
PPTX
Linux reversing study_basic_1
 
PPTX
System+os study 5
 
PPTX
Web hacking introduction
 
PPTX
System+os study 6
 
PDF
[Kerference] 시작! 리버싱 - 김종범(KERT)
PDF
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
PPTX
파이썬 스터디 15장
Pwnable study basic_1
 
Windows reversing study_basic_9
 
Pwnable study basic_3
 
Linux reversing study_basic_4
 
Linux reversing study_basic_2
 
Windows reversing study_basic_8
 
Assembly 스터디 2
 
System+os study 7
 
Python
 
System+os study 3
 
Linux reversing study_basic_3
 
Windows reversing study_basic_6
 
Windows reversing study_basic_2
 
Linux reversing study_basic_1
 
System+os study 5
 
Web hacking introduction
 
System+os study 6
 
[Kerference] 시작! 리버싱 - 김종범(KERT)
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
파이썬 스터디 15장
Ad

Similar to Windows reversing study_basic_3 (20)

PDF
Pe+file+format
PPTX
이무송 스터디 HEX Editor로 PE 분석하기.pptx
PPT
2006 03 15_pe & api hook
PDF
JetsonTX2 Python
PDF
OS Process, Thread, CPU Scheduling에 대해 알아봅시다.pdf
PPTX
하둡 타입과 포맷
PPTX
Linux programming study
PPTX
파이썬 파일처리 이해하기
PDF
05 pe 헤더(pe header)
PPTX
05 pe 헤더(pe header)
PDF
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
PPTX
뇌자T etc.windows multi threading programming
PDF
Data-Oriented Design과 유니티 DOTS
PDF
Elastic Search (엘라스틱서치) 입문
PDF
Cp2 w5
PDF
윈도우 커널 익스플로잇
PPTX
PE File Format and Packer - Inc0gnito 2016
PPTX
Windows via c++ chapter6
PPT
sqlserver7.0 데이타베이스
PPTX
이펙티브 C++ (7~9)
Pe+file+format
이무송 스터디 HEX Editor로 PE 분석하기.pptx
2006 03 15_pe & api hook
JetsonTX2 Python
OS Process, Thread, CPU Scheduling에 대해 알아봅시다.pdf
하둡 타입과 포맷
Linux programming study
파이썬 파일처리 이해하기
05 pe 헤더(pe header)
05 pe 헤더(pe header)
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
뇌자T etc.windows multi threading programming
Data-Oriented Design과 유니티 DOTS
Elastic Search (엘라스틱서치) 입문
Cp2 w5
윈도우 커널 익스플로잇
PE File Format and Packer - Inc0gnito 2016
Windows via c++ chapter6
sqlserver7.0 데이타베이스
이펙티브 C++ (7~9)
Ad

Windows reversing study_basic_3

  • 2. 목차  들어가기 전에..  바이너리 파일 쓰는 법  File Format이란?  PE File Format  전체 구조  PE Header  IMAGE_DOS_HEADER  IMAGE_NT_HEADER  IMAGE_FILE_HEADER  IMAGE_OPTIONAL_HEADER  IMAGE_SECTION_HEADER  RVA  총 정리  실행 압축  압축  실행 압축  실습-UPX 패킹 분석  과제  PE viewer 만들기  부록  참고 사이트
  • 3. 들어가기 전에.. • 바이너리 파일 쓰는 법 • File Format이란?
  • 4. 바이너리 파일 쓰는 법 • 바이너리 파일에 struct 데이터를 썼다. 각각의 정수 값들이 가지고있던 값을 쓴다. (-1과 0xF0000000에 주목해 보자. 정수 인코딩 그대로 써 있다.) • 인텔 CPU에서 실험하여 리틀 엔디안 형식으로 써 있다. • 이번에 살펴 볼 PE파일 뿐만 아니라 대부분의 파일은 파일 앞부분에 struct을 쓴다. • 파일을 이용하는 프로그램은 파일을 읽어서 struct에 넣은 후 값을 이용하여 적절한 작업을 한다 .
  • 5. FILE FORMAT이란? • 파일 형식 • 저장을 목적으로 정보를 컴퓨터 파일로 인코딩하는 특별한 방식 • 일반적으로 확장자를 통하여 구분한다. • 특정한 규칙에 따라서 데이터를 저장함. • 컴퓨터는 특정 규칙에 따라 파일 내용을 읽고 작업해야 하기 때문 • Ex) JPEG 파일은 오른쪽 그림과 같은 순서로 데이터들이 저장되어 있다. • 그림을 보여주는 프로그램은 JPEG 파일을 보여주기 위해 특정한 값을 필요로 한 다. (예 : 이미지의 크기 등) • 이 때, 약속된 위치에 있는 값을 읽어 정보를 얻을 수 있다. • ->이렇게 파일을 어떤 방식으로 쓸 지 정해 놓은 형식이 파일 형식이다.
  • 6. PE FILE FORMAT • 전체 구조 • PE Header • RVA • 총 정리
  • 7. PE FILE FORMAT  PE란?  Portable Executable File Format의 약자  파일이(File) 다른 곳에 옮겨져도(Portable) 실행이 가능하도록(Executable) 만들어 놓은 구성 방식(Format)  다른 OS와의 이식성을 높이려는 의도이지만 실제로는 Windows 계열에서만 사용  UNIX는 또 다른 File Format을 이용  32비트 형태의 실행파일은 PE 또는 PE32, 64비트는 PE+ 또는 PE32+라고 함  PE 헤더 : 실행 파일을 실행하기 위한 각종 정보들이 적혀 있음
  • 10. PE HEADER  코드가 실행되기 전 PE 헤더의 정보를 읽음  PE헤더 내용에 따라 메모리/리소스 할당  PE가 잘못되면 실행하는 데 필요한 정보를 불러오지 못 함  로딩 단계부터 실패
  • 11. PE HEADER – DOS HEADER
  • 12. PE HEADER – DOS HEADER winnt.h에 정의돼 있는 DOS header struct
  • 13. PE HEADER – DOS HEADER e_magic PE헤더의 첫 번째 값, Dos 헤더의 첫 번째 값 MZ이라는 표식이 들어간다. (PE를 만든 Mark Zbikowski의 약자) PE파일인지 아닌지를 체크하는 용도로 사용됨
  • 14. PE HEADER – DOS HEADER e_lfanew Dos 헤더의 마지막 값 NT Header의 위치를 저장(포인터같은 역할) (NT header는 바로 다음에 살펴볼 헤더이다)
  • 15. PE HEADER – NT HEADER Dos헤더의 e_lfanew값 00 00 00 F0 (리틀 엔디언을 변환) 00 00 00 F0 부터 NT 헤더가 시작 프로그램을 실행할 시 • 파일 맨 앞에 있는 Dos 헤더의 e_lfanew 값을 이용하여 NT 헤더에 접근 • NT 헤더에서 필요한 값을 이용하여 메모리를 확보하는 등 프로그램 실행 작업을 수행
  • 16. PE HEADER – NT HEADER DOS stub • DOS모드와의 호환을 위한 부분 • DOS에서는 DOS stub에 적힌 내용이 코드로 인식되어 실행 됨 • 보통은 DOS에서는 실행되지 않는다는 메시지를 띄우고 종료 • 잘 이용하면 DOS와 Windows 모두 사용 가능하게 만들 수도 있음
  • 17. PE HEADER – NT HEADER winnt.h에 정의돼 있는 NT header struct 64비트와 32비트일 경우 다르다. 32비트를 먼저 보기로 했으니 32비트를 기준으로 하겠음
  • 18. PE HEADER – NT HEADER Signature • NT헤더의 시작 • PE 파일임을 표시하는 용도 • DWORD(4바이트)로, 뒤의 00 00도 포함됨 • 딱히 사용되지는 않아 바이러스 개발자가 표식 쓰는 곳으로 이용했다고 함 -> 그래서 최근 OS는 50 45 00 00 을 체크하여 실행한다고 함
  • 19. PE HEADER – NT HEADER IMAGE_FILE_HEADER struct • NT 헤더 struct 내에 있는 또 다른 struct
  • 20. PE HEADER – NT HEADER – FILE HEADER winnt.h에 정의돼 있는 File header struct 빨간 네모 안 4개의 값이 중요하다. 이 4개의 값이 잘못되어 있으면 프로그램이 정상적으로 실행되지 않는다.
  • 21. PE HEADER – NT HEADER – FILE HEADER Machine • File header의 첫 번째 값 • 어떤 CPU에서 실행될 수 있는가를 알려줌 • CPU별로 고유의 값이 winnt.h에 정의돼 있음 아래에서 값은 014C(리틀 엔디안이므로)
  • 22. PE HEADER – NT HEADER – FILE HEADER Machine • winnt.h에 정의되어 있는 CPU 값 • 예에서 값이 014C였으므로 intel 386(32비트 인텔) 환경에서 돌아간다는 것을 알 수 있다
  • 23. PE HEADER – NT HEADER – FILE HEADER NumberOfSections • PE파일은 코드, 데이터, 리소스 등이 각각의 섹션에 나뉘어서 저장된다 • 그 섹션의 개수를 나타냄 • 반드시 0보다 커야 한다 • 정의된 섹션 수와 실제 수가 다르면 실행 에러 발생
  • 24. PE HEADER – NT HEADER – FILE HEADER TimeDateStamp • 프로그램을 빌드한 날짜 • 정확히는 obj파일이 컴파일러를 통해 exe로 생성한 시간 • 델파이는 항상 1992년으로 표시한다고 한다 • 조작 가능, 항상 정확한 것도 아님 • 아래 코드처럼 이용하여 시간 형태로 인쇄할 수 있다
  • 25. PE HEADER – NT HEADER – FILE HEADER Symbols • PE 파일 형식이 기반으로 삼은 형식때문에 생긴 것. (COFF) • 더 이상 사용하지 않기 때문에 값은 항상 0으로 설정해야 한다고 함
  • 26. PE HEADER – NT HEADER – FILE HEADER SizeOfOptionalHeader • NT Header struct의 다음 내용인 Optional Header struct의 크기를 의미 • Optional header는 32비트와 64비트일 때 다른 형태이기 때문 • Struct의 크기 종류는 32비트일 때와 64비트 일 때로 두 종류이지만, SizeOfOptionalHeader를 구조체 크기로 이용하기 때문에 이를 잘 활용하면 PE헤더를 꼬아 놓을 수 있다 -> PE헤더를 꼬아 놓으면 리버싱하기 어려워 짐
  • 27. PE HEADER – NT HEADER – FILE HEADER Characteristics • 파일의 속성을 나타냄 • 실행이 가능한 형태인지, 혹은 DLL 파일인지 등 • Bit OR 형식으로 조합됨 • winnt.h 에 값이 정의되어 있음 • 밑의 예에서는 0102(리틀 엔디안에 의해)
  • 28. PE HEADER – NT HEADER – FILE HEADER Characteristics • winnt.h에 정의되어 있는 값 • 예에서는 0102 -> File is executable, 32 bit word machine • PE 파일중 excutable하지 않은 것 : obj, dll 파일 등이 있음
  • 29. PE HEADER – NT HEADER IMAGE_OPTIONAL_HEADER struct • NT 헤더 struct 내에 있는 또 다른 struct • PE(PE32)에서는 IMAGE_OPTIONAL_HEADER32 • PE+(PE32+)에서는 IMAGE_OPTIONAL_HEADER64 • 이 헤더가 두 종류이기 때문에 NT 헤더가 두 종류가 됨
  • 30. PE HEADER – NT HEADER – OPTIONAL HEADER • winnt.h에 정의돼 있는 Optional header struct • 이 중 10개의 멤버가 가장 중요 • 잘못된 값이 들어있을 시 프로그램이 정상 실행 되지 않음
  • 31. PE HEADER – NT HEADER – OPTIONAL HEADER 중요한 10개의 멤버들 • Magic • AddressOfEntryPoint • ImageBase • SectionAlignment • FileAlignment • SizeOfImage • SizeOfHeaders • Subsystem • NumberOfRvaAndSizes • DataDirectory
  • 32. PE HEADER – NT HEADER – OPTIONAL HEADER Magic <중요> • IMAGE_OPTIONAL_HEADER32일 경우 10B • IMAGE_OPTIONAL_HEADER64일 경우 20B
  • 33. PE HEADER – NT HEADER – OPTIONAL HEADER Major/MinorLinkerVersion • 실행파일을 만든 링커의 버전 • 딱히 중요치 않음 • 위의 경우 0x0C.00 이라 할 수 있음(minor가 소수점 아래)
  • 34. PE HEADER – NT HEADER – OPTIONAL HEADER SizeOfCode • 실제 개발자가 만든 코드의 크기 • 악성코드 - 자신의 코드를 복제할 위치를 잡기 위해 이용 • 개발자 – 코드 세션의 무결성 검사를 할 때 이용
  • 35. PE HEADER – NT HEADER – OPTIONAL HEADER SizeOfInitializedData • 파일에 실제로 공간을 잡아야 하는 변수의 총 크기 • 초기화한 변수만 속함(초기화 값을 이용해야 하기 때문)
  • 36. PE HEADER – NT HEADER – OPTIONAL HEADER SizeOfUninitializedData • 실행 파일 자체에 따로 공간을 잡아줄 필요가 없는 변수의 총 크기 • 초기화하지 않은 변수가 속함 • 이러한 부분 때문에 파일이 실행되어 메모리에 올라갈 때 크기가 달라짐
  • 37. PE HEADER – NT HEADER – OPTIONAL HEADER AddressOfEntryPoint <중요> • EP(Entry Point)의 RVA(Relative Virtual Address) • 최초로 실행되는 코드의 시작주소
  • 38. PE HEADER – NT HEADER – OPTIONAL HEADER BaseOfCode • Code 영역의 시작주소 • 컴파일러 옵션으로 변경 가능하지만 보통 0x1000 • 중요해 보이지만 실제로 ntdll.dll에 구현 되어있는 로더는 이 필드를 사용하지 않는 것으로 보임
  • 39. PE HEADER – NT HEADER – OPTIONAL HEADER BaseOfData • Data 영역의 시작주소 • 중요해 보이지만 실제로 ntdll.dll에 구현 되어있는 로더는 이 필드를 사용하지 않는 것으로 보임
  • 40. PE HEADER – NT HEADER – OPTIONAL HEADER ImageBase <중요> • 실제 가상 메모리에 올라가는 번지를 가리킴 • PE 파일이 로딩되는 시작 주소 • 특별한 옵션이 없는 한 대부분 0x400000, DLL은 0x10000000 • 프로그램이 시작되는 주소 : ImageBase + AddressOfEntryPoint • RVA 계산의 기준
  • 41. PE HEADER – NT HEADER – OPTIONAL HEADER SectionAlignment <중요> • 메모리에서 Section의 최소 단위 • 메모리의 Section 크기는 반드시 SectionAlignment의 배수이어야 함 • 보통 0x1000 • 예를 들어 코드 섹션의 크기가 0x800이고 SectionAlignment가 0x1000이면 차이인 0x200만큼은 0으로 채움
  • 42. PE HEADER – NT HEADER – OPTIONAL HEADER FileAlignment <중요> • 파일에서 Section의 최소 단위 • 파일의 Section 크기는 반드시 FileAlignment의 배수이어야 함
  • 43. PE HEADER – NT HEADER – OPTIONAL HEADER Major/MinorOperatingSystemVersion • 이 파일을 실행할 수 있는 Windows의 최소 Version • Major가 소수점 앞, Minor가 소수점 뒷자리 • 위의 예에서는 6.0
  • 44. PE HEADER – NT HEADER – OPTIONAL HEADER • Windows 버전에 따른 Version number
  • 45. PE HEADER – NT HEADER – OPTIONAL HEADER Major/MinorImageVersion • 실행 파일의 버전 (ex. Internet explorer11의 11) • Major가 소수점 앞, Minor가 소수점 뒷자리 • 잘 사용되지 않음
  • 46. PE HEADER – NT HEADER – OPTIONAL HEADER Major/MinorSubsystemVersion • 실행파일을 실행하는 데 필요한 서브시스템의 버전 • Major가 소수점 앞, Minor가 소수점 뒷자리
  • 47. PE HEADER – NT HEADER – OPTIONAL HEADER Win32VersionValue • VC++ 6.0 SDK까지는 예약 영역이었으며 7.0부터 Win32VersionValue라는 이름으로 바뀜 • 사용하지 않는 영역으로 남아있으며 보통 0으로 채움
  • 48. PE HEADER – NT HEADER – OPTIONAL HEADER SizeOfImage <중요> • 가상 메모리에서 PE image가 차지하는 크기 • 일반적으로 파일의 크기와 메모리에 로딩된 크기는 다름 • Section Alignment까지 적용한 값. 반드시 Section Alignment의 배수 • 로더가 이 헤더 값을 보고 메모리 공간을 확보함 • PE image란 메모리에 올라온 형태의 PE File을 의미함
  • 49. PE HEADER – NT HEADER – OPTIONAL HEADER SizeOfHeader <중요> • PE헤더의 전체 크기 • File Alignment의 배수 • 파일 시작에서 SizeOfHeader 옵셋만큼 떨어진 위치에 첫 번째 섹션이 위치
  • 50. PE HEADER – NT HEADER – OPTIONAL HEADER Checksum • Checksum 계산 알고리즘은 IMAGHELP.DLL에 있음 • 모든 드라이버, 부팅 시 로드된 DLL, 중요한 윈도우 프로세스가 로드한 DLL 파일을 검증할 때 사용
  • 51. PE HEADER – NT HEADER – OPTIONAL HEADER Subsystem <중요> • 어떤 subsystem을 이용하는지 기록 • Subsystem의 번호는 winnt.h에 정의되어 있음 • 이 값을 보고 시스템 드라이버 파일인지 일반 실행 파일인지 구분할 수 있음
  • 52. PE HEADER – NT HEADER – OPTIONAL HEADER • winnt.h에 정의되어 있는 Subsystem 값 • GUI/CUI도 이 값으로 구분 • 위의 예에서는 0x3, CUI를 의미
  • 53. PE HEADER – NT HEADER – OPTIONAL HEADER DllCharacteristics • 원래는 DLL이라는 전제 하에 어떤 상황에서 DLL 초기화 함수를 호출할 지 지시하는 플래그 • 지금은 대부분 0으로 설정 • winnt.h에 정의되어 있는 값을 OR로 조합하여 이용
  • 54. PE HEADER – NT HEADER – OPTIONAL HEADER • winnt.h에 정의되어 있는 DllCharacteristics 값
  • 55. PE HEADER – NT HEADER – OPTIONAL HEADER SizeOfStack/HeapReserve, SizeOfStack/HeapCommit • Reserved로 정의된 만큼의 스택/힙을 사용 가능 • 넘으면 오류를 낼 수 있음. 최대 크기의 의미 • Commit은 한 번에 할당할 메모리의 양
  • 56. PE HEADER – NT HEADER – OPTIONAL HEADER LoaderFlags • 예전엔 디버깅 지원에 관계된 목적으로 있던 것 같음 • 지금은 사용하지 않는 필드 • 0으로 채워져 있음
  • 57. PE HEADER – NT HEADER – OPTIONAL HEADER NumberOfRvaAndSizes <중요> • 바로 밑에 있는 DataDirectory의 배열 수 • 실제로 밑에서 IMAGE_NUMBEROF_DIRECTORY_ENTRIES가 정의되어 있지만(16) PE로더는 이 필드 값을 보고 배열의 크기를 인식 • 즉 16이 아닐 수도 있다
  • 58. PE HEADER – NT HEADER – OPTIONAL HEADER DataDirectory <중요> • 보통 명시된 수(IMAGE_NUMBEROF_DIRECTORY_ENTRIES, 16(0x10))만큼의 배열 • IMAGE_DATA_DIRECTORY struct의 배열, winnt.h에 정의되어 있음 • 배열의 각 항목마다 정의된 값을 가짐
  • 59. PE HEADER – NT HEADER – OPTIONAL HEADER • winnt.h에 정의되어 있는 Data Directory와 IMAGE_NUMBEROF_DIRECTORY_ENTRIES • VirtualAddress를 이용하여 각 항목이 의미하는 데이터를 얻으러 갈 수 있음
  • 60. PE HEADER – NT HEADER – OPTIONAL HEADER • 각 배열 항목마다의 용도
  • 61. PE HEADER – NT HEADER – OPTIONAL HEADER • 각 배열 항목마다의 용도
  • 62. PE HEADER – SECTION HEADER File Header의 NumberOfSections 수만큼 Section Header struct이 붙는다.
  • 63. PE HEADER – SECTION HEADER winnt.h에 정의돼 있는 Section header struct 빨간 네모 안 5개의 값이 중요하다.
  • 64. PE HEADER – SECTION HEADER Name • 8바이트 크기의 Char 배열 • Section의 이름 • 맨 끝이 NULL로 끝나지 않거나, ASCII가 아니거나, NULL로만 채워도 됨 • 참고용일 뿐이고, 장담할 수 없음(.data섹션을 .code라 해도 영향 무) • .text : 실행되는 코드 • .data : 초기화된 전역변수 • .rdata : 읽기 전용 데이터 • .bss : 초기화되지 않은 전역변수 • .idata : 다른 dll로부터 가져다 쓰는 함수들의 정보 • .edate : 다른 모듈이 이 파일을 사용할 때 사용하도록 해 놓은 함수 리스트 • .rsrc : 리소스 • .reloc : reloctaion을 위한 정보
  • 65. PE HEADER – SECTION HEADER Misc_VirtualSize <중요> • DWORD짜리 union이며 PhysicalAddress나 VirtualSize로 이용 • PhysicalAddress : obj파일에서 사용. Section의 physical address를 의미 • VirtualSize • PE 로더에 의해 이미지가 메모리에 올려진 후에 해당 섹션이 얼마만큼의 크기를 가지고 있게 되는 지의 정보 • Section alignment가 적용되지 않은 실제 값을 가지고 있음
  • 66. PE HEADER – SECTION HEADER VirtualAddress <중요> • PE파일이 메모리에 올려진 후의 해당하는 섹션의 시작 주소 • RVA (Relative virtual address) • Optional Header의 Section Alignment의 배수
  • 67. PE HEADER – SECTION HEADER SizeOfRawData <중요> • Raw data(실제 파일)상에서 해당 섹션의 실제 사용 크기 • 해당 섹션의 빈 공간이 얼마나 있는가를 알아내기 위해 반드시 필요 • Optional Header의 File Alignment의 배수 (이 헤더 필드의 값은 File alignment가 적용된 섹션의 크기임) • Obj파일에는 실제 크기(File alignment가 적용되지 않은)가 적혀 있음 • 위의 예에서는 Section은 있지만 내용이 없어서 0임 ->앞으로의 예에서는 아래 section을 보겠음
  • 68. PE HEADER – SECTION HEADER • Section헤더는 section의 수만큼 있으므로 아래의 예를 보았다 • .text(코드) section의 크기가 3C00 • 예에서 File alignment는 200으로 3C00의 약수임
  • 69. PE HEADER – SECTION HEADER PointerToRawData <중요> • Raw data(실제 파일)상에서 섹션의 시작 위치 • RAW 값(File offset, 파일의 시작부터 얼마나 떨어져 있는가)
  • 70. PE HEADER – SECTION HEADER PointerToRelocations • obj파일에서만 사용 – relocation 정보에 접근하기 위한 file offset • 실행 파일에서는 의미가 없으므로 0으로 채움
  • 71. PE HEADER – SECTION HEADER PointerToLinenumbers • Line number table의 file offset • Source file의 line number와 관련이 있음 • 디버깅에 이용 • 별로 중요하게 다뤄지지 않는듯
  • 72. PE HEADER – SECTION HEADER NumberOfRelocations/Linenumbers • NumberOfRelocation • PointerToRelocations 를 따라가면 있는 Relocation table의 수 • Obj파일에서만 의미가 있음 • NumberOfLinenumber • PointerToLinenumbers 를 따라가면 있는 Line number table의 수
  • 73. PE HEADER – SECTION HEADER Characteristics <중요> • Section의 속성 • Bit OR로 계산 • 실행 여부, 초기화된 section인지 등을 담고 있음 • winnt.h에 값이 정의되어 있음
  • 74. PE HEADER – SECTION HEADER • winnt.h에 값이 정의된 값 • 위의 예에서는 60 00 00 20 • 코드 section이며, execute가능, read가능 • 각 section의 특징은 이 값을 읽어 판단해야 한다 (section 이름으로 판단하지 말고)
  • 75. RVA  Relative Virtual Address  메모리에서의 주소 offset  ImageBase를 기준으로 계산  ImageBase로부터 얼마나 떨어져 있는가 (ImageBase는 말 그대로 PE image의 base다)  Virtual address = ImageBase + RVA  RVA를 이용하는 헤더 필드  Optional header의 AddressOfEntryHeader  Optional header의 DataDirectory의 VirtualAddress  Section header의 VirtualAddress  앞으로 나올 헤더 필드들… (IAT 등) 가상 메모리 주소 Image base RVA 가상 메모리에 올라온 PE 이미지 Image base 가상 메모리 RVA
  • 76. RVA – RVA TO RAW  RVA to RAW  RVA값을 RAW(file offset)으로 변환하기  RVA는 실행 시 메모리의 주소. 헤더에 RVA 형태로 적혀 있음  헤더에 RVA로 적힌 주소에 적힌 내용을 파일에서의 찾고 싶으면 RVA를 RAW로 변환해야 함 가상 메모리에 올라온 PE 이미지 Image base 가상 메모리 RVA PE 파일 0 파일 RAW
  • 77. RVA – RVA TO RAW Image base Section2의 VirtualAddress 찾고자 하는 정보의 RVA 0 찾고자 하는 정보의 RAW Section2의 PointerToRaw 계산
  • 78. RVA – RVA TO RAW Image base Section2의 VirtualAddress 찾고자 하는 정보의 RVA 0 찾고자 하는 정보의 RAW Section2의 PointerToRaw 찾고자 하는 정보의 RAW – 속한 section의 PointerToRaw = 찾고자 하는 정보의 RVA – 속한 section의 VirtualAddress
  • 79. RVA – RVA TO RAW – 연습문제 1  Q1. RVA = 5000일 때, File offset(RAW)는?
  • 80. RVA – RVA TO RAW – 연습문제 1 풀이  Q1. RVA = 5000일 때, File offset(RAW)는?  RVA 5000을 따라가보면 .text영역임을 알 수 있다  위에서 도출한 식을 이용하면  RAW – 400 = 5000(RVA) – 1000(.text 섹션의 VirtualAddress)  따라서, RAW = 4400  주의  Section헤더의 VirtualAddress와 그냥 Virtual address를 헷갈리지 말자 RVA = 5000
  • 81. RVA – RVA TO RAW – 연습문제 2  Q2. RVA = 13314일 때, File offset(RAW)는?
  • 82. RVA – RVA TO RAW – 연습문제 2 풀이  Q2. RVA = 13314일 때, File offset(RAW)는?  RVA를 따라가서 어느 section에 속하는지 확인하자  .rsrc가 의심됨  .rsrc의 시작주소(VirtualAddress)에 VirtualSize값을 더해 13314를 포함하는지 확인  B000 + 8314 = 13314로 딱 끝에 포함한다  .rsrc섹션에 포함됨을 알았으니 1번 문제와 같이 계산한다  RAW = 13314 – B000 + 8400 = 10714 RVA = 13314
  • 83. RVA – RVA TO RAW – 연습문제 3  Q3. RVA = ABA8일 때, File offset(RAW)는?
  • 84. RVA – RVA TO RAW – 연습문제 3 풀이  Q3. RVA = ABA8일 때, File offset(RAW)는?  RVA를 따라가서 어느 section에 속하는지 확인하자  .data가 의심됨  . data의 시작주소(VirtualAddress)에 VirtualSize값을 더해 ABA8을 포함하는지 확인  9000 + 1BA8 = ABA8 로 딱 끝에 포함한다  . data 섹션에 포함됨을 알았으니 1번 문제와 같이 계산한다  RAW = ABA8(RVA) – 9000(VA) + 7C00(PointerToRawData) = 97A8  그런데 97A8은 파일에서 .rsrc에 속한다  RVA로는 .data, RAW로는 .rsrc에 속한다는 것은 말도 안 됨  이럴 때는 “해당 RVA에 대한 RAW 값은 정의할 수 없다”고 해야 함  값이 이상한 이유  VirtualSize값이 SizeOfRawData 값보다 크기 때문  이런 식으로 특이 케이스가 생김 -> 앞으로 살펴볼 것 RVA = ABA8
  • 85. 총 정리  중요한 것, 헷갈리는 것 묶어서 정리해 봄  주목할 점  무엇에 쓰이는가  File에 관련되었는지 Memory와 관련되었는가  RVA인가 RAW인가  Alignment가 적용되었는가
  • 86. 총 정리 – DOS HEADER
  • 87. 총 정리 – DOS HEADER PE 파일임을 표시 File alignment가 적용된, 다음 헤더가 시작되는 주소 (RAW)
  • 88. 총 정리 – NT HEADER PE32인 경우와 PE32+인 경우로, 2종류
  • 89. 총 정리 – NT HEADER PE파일임을 표시 파일에 대한 정보들 파일 실행을 위해 필요한 정보들 PE32와 PE32+의 차이를 만든다
  • 90. PE HEADER – NT HEADER – FILE HEADER
  • 91. PE HEADER – NT HEADER – FILE HEADER 파일을 이용할 수 있는 CPU 파일에 있는 section의 수 파일의 속성 파일이 사용하는 Optional Header의 크기
  • 92. 총 정리 – NT HEADER – OPTIONAL HEADER 중요한 10개의 멤버들 • Magic • AddressOfEntryPoint • ImageBase • SectionAlignment • FileAlignment • SizeOfImage • SizeOfHeaders • Subsystem • NumberOfRvaAndSizes • Dadadirectory
  • 93. 총 정리 – NT HEADER – OPTIONAL HEADER PE32와 PE32+의 Optional header를 구분 PE32와 PE32+일 때의 값이 다름
  • 94. 총 정리 – NT HEADER – OPTIONAL HEADER Section alignment가 적용된, 메모리에서의 Entry Point (시작 코드 주소) (RVA) Section alignment가 적용된, PE image가 올라가는 시작 주소 RVA값 계산의 기준이 된다 ImageBase + RVA값 = 가상메모리 주소
  • 95. 총 정리 – NT HEADER – OPTIONAL HEADER Section Alignment 메모리에서 각 section의 최소 단위 File Alignment 파일에서 각 section의 최소 단위
  • 96. 총 정리 – NT HEADER – OPTIONAL HEADER Section alignment가 적용된, 메모리에서 PE image의 총 크기 File alignment가 적용된, 파일에서 헤더의 크기
  • 97. 총 정리 – NT HEADER – OPTIONAL HEADER 어떤 subsystem을 이용하는가
  • 98. 총 정리 – NT HEADER – OPTIONAL HEADER 바로 아래 있는 DataDirectory 배열의 크기 실행에 필요한 여러 정보로 접근하기 위한 테이블 각 인덱스마다 역할이 정해져 있음
  • 99. 총 정리 – NT HEADER – OPTIONAL HEADER
  • 100. 총 정리 – NT HEADER – OPTIONAL HEADER 해당 정보로 접근하기 위한 주소 (RVA)
  • 101. 총 정리 – SECTION HEADER
  • 102. 총 정리 – SECTION HEADER Section alignment가 적용되지 않은, 메모리에서의 section의 크기 File alignment가 적용된, File에서의 section의 크기
  • 103. 총 정리 – SECTION HEADER Section alignment가 적용된, 메모리에서의 section이 시작되는 주소(RVA) File alignment가 적용된, 파일에서의 section이 시작되는 주소(RAW)
  • 104. 총 정리 – SECTION HEADER Section의 성질, 역할 등 Name이 아니라 Characteristics를 이용하여 판단해야 함
  • 106. 실행 압축 • 압축 • 실행 압축 • UPX 분석
  • 107. 압축  실행 압축을 살펴보기 전에 압축에 대해 간단히 알아보자  데이터 압축  비손실 압축  흔하게 아는 압축  압축을 풀면 원본 파일이 나온다.  손실 압축  데이터에 의도적으로 손상을 주어서 압축률을 높임  주로 멀티미디어 파일들(jpg, mp3, mp4 등)이 이용  사람의 눈과 귀가 알아차리지 못하는 수준에서 데이터 손상을 입힌다.  가청 주파수를 넘는 영역을 의도적으로 제거하는 등  원본으로 되돌릴 수 없다.
  • 108. 압축  대체 어떻게 비손실 압축을 할 수 있나?  유명한 비손실 압축 알고리즘의 하나인 Huffman 알고리즘을 가볍게 살펴보자.  AABBAC라는 문자열이 있다고 하자. 이는 총 6바이트이다.  각 문자들이 사용된 횟수를 세어 보자. A는 3, B는 2, C는 1번이다.  가장 많이 사용된 A에게 0이라는 1bit를 부여하고, B는 10, C는 11을 부여할 수 있다.  그러면 001010011로 나타낼 수 있다. 이는 9bit, 즉 1바이트 +1비트이다.  이것이 Huffman 알고리즘의 핵심이다.  구체적 방법이 궁금하다면 참고 사이트를 찾아가볼 것
  • 109. 실행 압축  실행 압축  실행(PE)파일을 대상으로 한다.  비 손실 압축을 이용한다.  파일 내부에 압축 해제 코드를 포함하고 있어서 실행되는 순간에 메모리에서 압축을 해제시킨 후 실행한다.  실행 압축된 파일 역시 PE파일이다.  내부에 원본 PE 파일과 decoding 루틴이 있다.  EP(Entry point)는 decoding 루틴의 시작부분이다.  실행 파일 압축기를 PE 패커(Packer)라고 한다. Run-Time Packer라고도 한다.
  • 110. 실행 압축 항목 일반 압축 실행 압축 대상 파일 모든 파일 PE 파일(exe, dll, sys 등) 압축 결과물 압축(zip, rar 등) 파일 PE 파일(exe, dll, sys 등) 압축해제 방식 전용 압축해제 프로그램 내부의 decoding 루틴 파일 실행 여부 자체 실행 불가 자체 실행 가능 장점 모든 파일에 대해 높은 압축률로 압축 가능 별도의 해제 프로그램 없이 바로 실행 가능 단점 전용 압축해제 프로그램이 없으면 사용할 수 없음 실행때마다 decoding 루틴이 호출되기 때 문에 실행시간이 미세하게 느려 짐
  • 111. 실행 압축 실습 – UPX 분석  UPX 패킹은 EXE파일의 크기를 줄이기 위해 사용되는 순수한 의도의 패커다.  Virus total이라는 바이러스 진단 홈페이지에서 UPX 패킹된 프로그램은 바이러스로 진단하지 않는다.  악성 코드에 많이 사용되는 패킹이 적용된 프로그램은 바이러스로 진단한다.  구글에 치면 다운받을 수 있다. 패킹 프로그램(패커)를 이용하여 패킹을 하거나 해제할 수 있다.  다운 링크는 참고 사이트에 있다.  분석을 방해하기 위한 패커가 아니기 때문에 단순하다.
  • 112. 실행 압축 실습 – UPX 분석  간단한 프로그램을 만들었다.  원래 크기는 49KB였다.  UPX 패킹을 적용했다.  35KB가 되었다.  파일 크기가 약간 줄었다.
  • 113. 실행 압축 실습 – UPX 분석  패킹을 적용하지 않은 원본 파일과 패킹이 적용된 파일을 올리디버거로 열어보았다.  열기만 하고 진행은 안 했는데, 주소가 다르다. 이는 패킹이 적용된 코드의 EP가 다르다는 것을 의미한다. PE헤더 역시 변형되었다. <Origin> <Packed>
  • 114. 실행 압축 실습 – UPX 분석  PE viewer로 비교해 보았다.
  • 115. 실행 압축 실습 – UPX 분석  패킹된 코드를 살펴보자.  UPX 패커의 특징은 맨 처음에 PUSHAD 명령어가 있다는 것이다.  PUSHAD는 레지스터 값 전부를 스택에 저장하는 명령어다. 이와 대응되는 명령어는 POPAD이다.  UPX 패커는 PUSHAD로 백업해 둔 레지스터 값을 디코딩 루틴이 끝난 후 다시 복원한다.  이를 이용하면 쉽게 OEP(origin EP, 원래 EP)를 찾을 수 있다.  이 방법은 뒤에서 알아보고, 일단 디코딩 루틴을 살펴보자.  Pushad 후에 ESI와 EDI에 수를 넣는다. 이 수는 각각 압축된 코드 가 저장된 주소와 압축 해제한 코드를 저장할 주소이다.  ESI와 EDI에 주소를 동시에 설정하는 패턴은 Source에서 Destination으로 복사하는 코드가 나올 거라고 예측할 수 있는 패턴이다.
  • 116. 실행 압축 실습 – UPX 분석  여기서, ESI와 EDI에 저장된 값에 주목해 보자.  ESI에는 0x40F015, EDI에는 계산 결과 0x401000이 들어간다.  섹션의 RVA값과 ImageBase값을 조사해 보면 ESI가 가리키는 주소는 두 번째 섹션, EDI 가 가리키는 값은 첫 번째 섹션에 속한다는 것을 알 수 있다.  UPX 패킹은 두 번째 섹션에 압축된 코드와 디코딩하는 코드가, 첫 번째 섹션에 디코딩 된 코드가 올라온다.  첫 번째 섹션의 RAW data 오프셋과 두 번째 섹션의 RAW 오프셋이 같다. 또한 첫 번째 섹션의 RAW data size는 0이다.  첫 번째 섹션은 메모리에만 존재한다. Bss영역처럼 메모리에 예약만 해 두고, 파일 에는 내용이 없다.
  • 117. 실행 압축 실습 – UPX 분석  디코딩 루틴은 보통 같은 일을 반복하여, 규칙을 이용하여 디코딩된다. 따라서 루프가 많이 나온다.  루프가 있는 부분이 핵심적인 코드일 가능성이 크다.  bp를 걸고 F9로 실행하여 루프를 빠르게 나올 수 있다. 혹은 한 줄 씩 자동으로 실행하는 trace over나 animate over를 이용하면 편하다.  UPX 패킹의 맨 처음 나오는 루프는 압축된 코드를 그대로 버퍼에 복사한다.  별 의미없는 코드이다. 아래쪽에 크게 디코딩 코드가 있다.
  • 118. 실행 압축 실습 – UPX 분석  방금 본 루프에 큰 범위로 디코딩 코드가 있다.  그 루프의 마지막 부분에서 디코딩하여 나온 원본 코드를 버퍼에 저장한다.  저장하고 다시 위로 올라가 의미 없는 복사를 한 뒤 디코딩 루틴에 들어간다.  리소스도 코드와 함께 인코딩 되어 있다. Hello문자열도 이 때 디코 딩 되어 저장된다.  코드는 1 바이트 씩 저장이 진행되고, 리소스는 4바이트 단위로 저장이 진행된다. 위 코드는 디코딩 된 코드를, 아래 코드는 디코 딩된 리소스를 저장한다.
  • 119. 실행 압축 실습 – UPX 분석  디코딩이 끝나면 두 번째 루프가 나온다.  UPX 패킹의 두 번째 루프는 디코딩한 원본 코드에 주소를 사용하는 코드가 있을 때, 주소를 복원해주는 루틴이다.  Jump나 call과 같은 명령어인지 판단하고 그렇다면 주소를 복 원한다.
  • 120. 실행 압축 실습 – UPX 분석  UPX 패킹의 세 번째 루프는 IAT를 설정하는 루틴이다.  IAT는 프로그램이 라이브러리를 쓸 수 있도록 해 주며, PE 헤더에 속 한다.  IAT는 추후 자세히 할 것임
  • 121. 실행 압축 실습 – UPX 분석  쭉 내려오면 POPAD가 보인다. 처음에 PUSHAD로 백 업한 레지스터 값을 복원한다.  무조건 점프로 0x004014E0로 점프한다.  이 주소는 원본 프로그램의 Entry Point주소이다.
  • 122. 실행 압축 실습 – UPX 분석  점프해 보면 이상한 코드가 보인다.  이는 숫자가 기계어로 해석되지 않았기 때문이다.  Ctrl+a를 누르면 기계어를 디스어셈블한 코드를 볼 수 있다. Ctrl + A
  • 123. 실행 압축 실습 – UPX 분석 • 패킹이 해제된 코드는 원래 코드와 똑같다! • 이렇게 수작업으로 OEP(original entry point, 원래 시작 코드)를 찾아보았다. • 다른 패커들은 각자 알고리즘은 다르지만, 이와 비슷한 일을 처리한다. <Origin> <Packed>
  • 124. 실행 압축 실습 – UPX OEP 쉽게 찾기  UPX 패커의 특징은 맨 처음에 PUSHAD 명령어가 있다는 것이다.  이를 이용하면 쉽게 OEP(origin EP, 원래 EP)를 찾을 수 있다.  스택에 하드웨어 bp를 걸어 백업해 둔 레지스터 값들을 복원하는 순간에 멈추거나, 명령어 검색으로 POPAD를 찾아보는 방법을 이용 할 수 있다.
  • 125. 실행 압축 실습 – UPX OEP 쉽게 찾기  하드웨어 bp를 이용하는 방법  Pushad로 레지스터를 복원하며 사용한 스택의 주소를 메모리 덤프에서 찾는다. 정확한 주소에 있는 값을 클릭하고 오른쪽키를 눌러 메뉴를 띄우고, bp를 건다.
  • 126. 실행 압축 실습 – UPX OEP 쉽게 찾기  명령어 찾기를 이용하는 방법
  • 127. 실행 압축 실습 – UPX – 메모리 덤프  패킹을 직접 풀었을 경우 프로그램 코드에 bp가 걸리지 않는다.  파일에 있는 고정된 코드가 아니라 메모리에만 올라오는 코드이기 때문에 올리디버거가 기억을 못 함  이 때는 메모리 덤프를 떠서 디코딩 된 코드와 리소스를 저장하면 좋다  메모리만 있던 내용을 아예 파일에 저장했기 때문에 디버거가 기억할 수 있게 된다.  올리 디버거의 플러그인으로 제공되는 메모리 덤프 기능을 이용해서 덤프를 떠 보자.  메모리 덤프란 메모리에 올라온 상태 그대로 저장하는 것이다.  올리디버거 창의 메모리 덤프는 메모리를 그대로 보여주는 것이고, 저장할 때는 덤프를 뜬다고 한다. 간단하게 메모리 덤프라고 도 한다.  메모리 덤프를 뜨면 디코딩되어 메모리에 올라와 있는 원래 코드를 파일에 저장할 수 있다.  다운 경로는 부록 참고 사이트에 있다.  참고 사이트에서는 importRCE 툴도 이용하는데, 당장은 필요하지 않다.
  • 128. 실행 압축 실습 – UPX – 메모리 덤프  디코딩을 완료한 상태에서 오른쪽키 메뉴에서 Dump debugged process를 클릭한다.  뜬 창 그대로 Dump를 누르고 저장한다.
  • 129. 실행 압축 실습 – UPX – 프로그램을 이용한 해제  UPX 패킹은 오픈소스 프로그램이다.  UPX 패킹이 적용되었다는 것만 알아내면 쉽게 풀 수 있다.  PEiD라는 툴은 PE 헤더의 내용을 정리해서 보기 쉽게 해 주고, 패킹 여부를 알려주는 프로그램이다.  모든 패킹 종류를 알지는 못 하지만 잘 알려진 패킹은 잘 알아낸다.  다운 링크는 참고 사이트에 있다.  그 외 Exeinfo PE등 여러 프로그램이 있다. 천천히 입맛에 맞는 것을 찾아 쓰면 된다.
  • 130. 실행 압축  패커  사용 목적  PE 파일 크기를 줄이기 위해  PE 파일의 내부 코드와 리소스를 감추기 위해  평범하게 압축하는 순수한 의도의 패커와 원본 파일을 크게 변형하고, PE 헤더를 심하게 훼손시키는 불순한 의도의 패커 로 나뉜다. 후자는 악성 프로그램이 주로 사용한다.  순수한 의도의 패커(VirusTotal에서 진단 안 됨) : UPX, ASPack 등  불순한 의도의 패커(VirusTotal에서 진단 됨) : Upack, PESpin, NSAnti
  • 131. 실행 압축  프로텍터  단순히 실행 압축만 하는 것이 아니라 리버싱을 막기 위한 다양한 기법을 추가함  원본 코드보다 커지는 경향이 있음  사용 목적  크래킹 방지  코드 및 리소스 보호  보안 프로그램의 진단을 막기 위해  Ex) 일부 프로텍터는 ‘다형성 코드’를 제공한다. 이는 매번 다른 모양(이지만 같은 기능)의 코드가 생성되게 한다.  종류  상용 프로텍터 : ASProtect, Themida, SVKP 등  공개용 프로텍터 : UltraProtect, Morphine 등
  • 132. 과제 • PE Header Viewer 만들기 • 문제 풀고 write up
  • 133. PE HEADER VIEWER 만들기  PE Header Viewer란?  PE헤더에 어떤 값이 들어있는지 알려주는 프로그램  시중에 다양한 PE Viewer가 있음  프로그램 정적 분석 시 자주 이용
  • 134. PE HEADER VIEWER 만들기 과제는 콘솔 기반 PE Header viewer를 만드는 것이다. 요구사항 : • 인자로 넣은 파일을 열어서 분석 • 왼쪽 예와 같이 어떤 헤더에 속하는지 구분 • 값을 16진수로 표시 PE는 리버싱에서 매우 중요한 주제이다. 모든 기술의 기초가 된다. 점점 노하우와 설명을 붙여 자신만의 PE Viewer를 만들어보자.
  • 135. PE HEADER VIEWER 만들기 - TIP 파일에서 struct을 읽는 기본적인 방법이다 C++스타일로 더 세련된 방법도 있지만 .. 한 번에 하나씩 하자.. 이 방법이 마음에 안 들면 인터넷 찾아보기
  • 136. 부록 • 참고 사이트
  • 137. 참고 사이트  PE헤더 필드 설명  https://msdn.microsoft.com/en-us/library/ms809762.aspx  영어지만 가장 잘 써 있음  이제 안 쓴다고 사람들이 무시하는 필드도 설명해 줌  Huffman 압축 알고리즘 설명  http://wooyaggo.tistory.com/95  UPX 패커 다운로드  https://github.com/upx/upx/releases/tag/v3.94  메모리 덤프  http://blog.naver.com/ln8520nl/220734849758  PEiD 다운로드  http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml