SlideShare a Scribd company logo
REVERSING[3] Reverse Engineering
목차
 실습
 수작업 PE 파일 만들기
 DOS header
 NT header
 File header
 Optional header
 Section header
 Header NULL padding
 Section 내용
 Section NULL padding
 미뤄둔 내용 수정
 코드로 PE 파일 만들기
 부록
 참고 사이트
수작업 PE 파일 만들기
• DOS header
• NT header
• Section header
• Header NULL padding
• Section 내용
• Section NULL padding
• 미뤄둔 내용 수정
수작업 PE 파일 만들기
 아직 PE 헤더에서 배우지 않은 부분이 있어 완전한 PE 파일을 만들 수는 없다.
 이번 실습에서는 제대로 된 PE 파일을 만드는 것이 목적은 아니다.
 아무 변수도 없고 코드만 달랑 들어있는 가장 기초적인 PE를 만들 것이다.
 코드로는 MOV EAX, 1 과 ADD EAX, 2 그리고 Ret만 넣어보자.
 목표
 올리 디버거에서 실행했을 때, 코드가 보이게 만드는 것
 하는 이유
 실제로 만들어 보면 PE헤더에 대한 이해도가 높아진다.
 리틀 엔디안으로 숫자를 읽고 쓰는 데 익숙해진다.
 기계어 코드를 만들고 이용하는 데 익숙해진다.
 Stack overflow같은 공격을 할 때, 기계어 코드를 만들어 넣어야 한다.
 헥사 에디터로 프로그램을 수정하는 것에 익숙해 진다.
수작업 PE 파일 만들기
 인라인 어셈블리 코드를 이용하여 기계어를 쉽게 얻었다.
 B80100000083C002C3
 총 9바이트이다.
DOS HEADER
DOS HEADER
• e_magic과 e_lfanew를 제외한
필드는 실행에 영향을 끼치지
않는다.
• 그냥 0으로 채워도 된다.
• e_magic
• MZ이라는 표식이
들어간다.
• e_lfanew
• NT Header의 위치를 저장
• DOS stub은 쓰지 않을
계획이므로 e_lfanew는 바로
다음 위치를 가리키도록
했다.
DOS HEADER
NT HEADER
NT HEADER
Signature
• NT헤더의 시작
• PE 파일임을 표시하는 용도
• DWORD(4바이트)로, 뒤의 00 00도 포함됨
NT HEADER_FILE HEADER
빨간 네모 안 4개의 값이 중요하다.
이 4개의 값이 잘못되어 있으면 프로그램이 정상적으로 실행되지 않는다.
NT HEADER_FILE HEADER
Machine
• Intel에 해당하는 것은 014C
• 리틀 엔디안으로 4C 01
NT HEADER_FILE HEADER
NumberOfSections
• 섹션의 개수를 나타냄
• 반드시 0보다 커야 한다
• 정의된 섹션 수와 실제 수가 다르면 실행 에러 발생
• Text섹션만 만들 것이므로 1을 넣자.
TimeDateStamp와 PointerToSymolTable,
NumberOfSystembols는 그냥 0으로 채우자
NT HEADER_FILE HEADER
SizeOfOptionalHeader
• 32비트 PE 파일의 Optional Header 크기는
E0이다.
NT HEADER_FILE HEADER
Characteristics
• 파일의 속성을 나타냄
• EXE를 만들 것이므로 0x0102이다. 이는 리틀 엔디안으로 0201이다.
NT HEADER_FILE HEADER
• 파일 헤더를 다 쓴 모습이다
NT HEADER_OPTIONAL HEADER
• Optional 헤더는 32비트 기준으로 쓰겠다.
• 빨간 네모 친 10가지가 특히 신경 쓸
부분이다.
NT HEADER_OPTIONAL HEADER
Magic
• IMAGE_OPTIONAL_HEADER32일 경우 10B
Major, Minor Linker Version
• 0으로 채움
SizeOfCode
• 기계어 코드 길이는 9 바이트이다.
• 그런데 sizeofcode는 filealignment를 적용한 값이 들어갈 것이다.
• Filealignment는 256byte(0x100)로 할 것이므로, 100을 쓴다.
NT HEADER_OPTIONAL HEADER
• 사용할 데이터가 따로 없으니
SizeOfInitializedData와 SizeOfUninitializedData는
0으로 채운다.
• AddressOfEntryPoint와 BaseOfCode는 아직 코드가
어느 위치에 들어갈 지 모르기 때문에 나중에 채운다
• 찾기 쉽도록 F로 채워 둔다
• 파일 오프셋을 기억해 두자!
• BaseOfData는 데이터를 사용하지 않으므로 0으로
채운다.
NT HEADER_OPTIONAL HEADER
• ImageBase는 흔히 사용하는 00040000으로 해 보자.
• Section Alignment는 0x100으로 해 보자(256byte)
• 원래 Section Alignment는 한 페이지 크기보다 작을 수 없다.
• 페이지란, 가상 메모리를 관리하는 최소 단위이다.
• 하지만 그보다 작게 해도 프로그램에 이상은 없다.
• Windows 운영체제가 실제로 프로그램을 로딩 할
때 페이지 크기만큼 메모리를 할당할 뿐이다.
• File Alignment도 0x100으로 해 보자.
• 사실 512~65,536사이여야 하지만, 작을 경우 알아서 처리 된다…
• File alignment와 section alignment가 같을 경우, 거의 같게 올라온다
(bss 등의 예외를 제외하면)
• Null padding이 같기 때문
NT HEADER_OPTIONAL HEADER
• 여기까지 쓴 모습이다.
• 나중에 쓰기로 한 AddressOfEntryPoint와
BaseOfCode의 위치를 잘 기억하자 (0x68, 0x6C)
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
NT HEADER_OPTIONAL HEADER
• Major, Minor OperatingSystemVersion은 최소 실행 가능 OS 버전이다.
• XP로 해 보자. XP에 해당하는 숫자는 5.1이다. Major에 5, Minor에 1을 쓴다.
• Major, Minor ImageVersion은 프로그램의 버전이다.
• 프로그래머가 프로그램 버전을 관리하고 싶을 때 이용하는 필드이다.
• 그냥 0으로 채워도 상관 없다.
• Major, Minor SubsystemVersion도 OperatingSystemVersion과 똑같이 맞춰준다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
NT HEADER_OPTIONAL HEADER
• Win32VersionValue는 0으로 채운다.
• 더 이상 쓰이지 않는 필드
• SizeOfImage는 PE 이미지의 총 크기이다.
• section alignment의 배수여야 한다.
• 아직 text 섹션을 쓰지 않았으므로 일단 F로 채우고 나중에 다시 쓴다.
• SizeOfHeaders는 헤더 영역의 총 크기이다.
• Section alignment의 배수여야 한다.
• 헤더를 전부 쓰고 채우자. 일단 F로 채운다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
NT HEADER_OPTIONAL HEADER
• 중간 모습이다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
NT HEADER_OPTIONAL HEADER
CheckSum
• 파일이 변했는지 판단할 때 사용하는 필드이다. 지금은 신경 쓸 것 없다.
• 0으로 채운다.
Subsystem
• 콘솔 프로그램으로 만들기 위해서는 3을 써야 한다. (CUI)
DllCharacteristics
• PE파일이 DLL파일일 때 의미가 있다.
• 0으로 채운다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
NT HEADER_OPTIONAL HEADER
SizeOfStack, Heap Reserve
• 디폴트 힙과 스택의 최대 크기
• 프로그램을 만들 때, 링커가 일반적으로 1M로 설정한다 (0x100000)
SizeOfStack, Heap Commit
• 한 번에 할당할 메모리의 양
• 이 크기로 가상 메모리의 스택, 힙 영역을 물리 메모리에 매핑
• 링커가 일반적으로 1페이지(0x1000) 크기로 써 준다. 이대로 써 주자.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
NT HEADER_OPTIONAL HEADER
LoaderFlags
• 지금은 사용하지 않는 필드
• 0으로 채운다
NumberOfRvaAndSizes
• 바로 아래 있는 배열 요소의 개수
• 기본적으로 16개를 사용하므로 16(0x10)을 써 준다.
DataDirectory
• 함수 import 등에 이용되지만 아직 배우지 않았으므로 0으로 채운다.
• 배열 하나당 8바이트이므로, 8*16, 총128개의 0을 쓴다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
NT HEADER_OPTIONAL HEADER
• Optional Header를 끝까지 쓴 모습이다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
SECTION HEADER
SECTION HEADER
winnt.h에 정의돼 있는 Section header struct
빨간 네모 안 5개의 값이 중요하다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
SECTION HEADER
Name
• 이름은 .text라고 하자
• 이름 배열의 남은 부분은 0으로 채운다.
VirtualSize
• 해당 section의 얼마 만큼이 실제로 의미 있는
데이터인지 쓴다.
• Section Alignment가 적용되지 않은 값
• 실제 코드 크기인 9를 쓴다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
SECTION HEADER
VirtualAddress
• PE 이미지(메모리에 올려진 PE 파일)에서 섹션의
시작 주소
• RVA
• file alignment와 section alignment를 같게
했으므로 파일에서의 코드영역 시작 위치를 쓰면
된다.
• 코드 섹션은 헤더를 다 쓴 뒤 헤더의 파일
alignment를 맞춰주고 쓸 것이다. 일단 F로
채웠다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
SECTION HEADER
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
SizeOfRawData
• 파일에서의 해당 section의 크기
• File alignment가 적용된 크기
• NULL padding까지 포함한 크기
• 실제 code 내용 사이즈는 9이지만 file
alignment가 0x100이므로 0x100을 써 준다.
PointerToRawData
• 해당 section의 파일에서의 위치
• 헤더를 다 쓰고 채우자. 일단 F로 채웠다.
SECTION HEADER
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
PointerToRelocations, NumberOfRelocations
• Obj 파일에서만 의미 있다. 0으로 채운다.
PointerToLine, NumberOfLinenumbers
• 디버깅에 이용되는 필드이다. 0으로 채운다.
SECTION HEADER
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
Characteristics
• 해당 section의 권한, 특징
• 실행가능 파일을 만들 것이므로 0x60000020
SECTION HEADER
• Section header를 끝까지 쓴 모습이다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
SECTION HEADER
• Section헤더는 Section 개수만큼 있다.
• 개수가 일정치 않다.
• Section 헤더 배열의 마지막을 알리는
NULL로 이루어진 Section 헤더를
추가한다.
• Section 헤더의 크기만큼 0을
추가한다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
헤더~SECTION 내용 사이 NULL PADDING
HEADER FILE ALIGNMENT
• 헤더 영역의 file alignment를 맞추기
위해 0을 추가했다.
• File alignment 는 0x100이었다.
• 0x200이 다음 내용(실제
section의 내용) 시작 주소가 될
수 있도록 1FF까지 0을 채운다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
SECTION 내용
SECTION 내용
 맨 처음 구한 기계어를 쓴다.
 B80100000083C002C3
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
SECTION 내용 사이 NULL PADDING
SECTION 내용 사이 NULL PADDING
• Section의 file alignment를 맞추기
위해 0을 추가했다.
• 2FF까지 0을 채운다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
미뤄둔 내용 수정
• AddressOfEntryPoint (0x68)
• Section alignment와 file alignment가
같으므로 파일에서의 주소가 RVA가
된다.
• 코드영역의 시작 부분에 있는 코드에서
시작할 것이므로, 코드가 있는 section의
위치를 쓰면 된다.
• 0x200을 쓴다.
• BaseOfCode (0x6C)
• 코드 영역의 시작 위치, 0x200를 쓴다.
• 나중에 쓸 것
• AddressOfEntryPoint(0x68)
• BaseOfCode(0x6C)
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
미뤄둔 내용 수정
• SizeOfImage (0x90)
• Section alignment와 file alignment가
같으므로 PE 파일 크기를 쓰면 된다.
• 0x300을 쓴다.
• SizeOfHeader (0x94)
• 헤더의 크기(file alignment적용)는
0x200이다.
• 나중에 쓸 것
• SizeOfImage(0x90)
• SizeofHeader(0x94)
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
미뤄둔 내용 수정
• VirtualAddress (0x144)
• Section alignment와 file alignment가
같으므로 PE 파일에서의 section 시작
위치를 쓰면 된다.
• 0x200을 쓴다.
• PointerToRawData
• 파일에서의 section 시작 위치, 0x200을
쓴다.
• 나중에 쓸 것
• VirtualAddrss(0x144)
• PointerToRawData(0x148)
올리 디버거에서 실행
• 에러가 뜨긴 하지만 실행이 된다.
• File, section alignment때문인 것 같다.
코드로 PE 파일 만들기 • 코드로 PE 파일 만들기
코드로 PE 파일 만들기
 앞에서 만든 PE 파일을 코드로 쓴다.
 조금 더 편하게 만들 수 있다.
 목표
 실제로 PE 파일을 만들고 쓰는 코드를 만들어 본다. 후에 간간이 응용할 일이 있을 코드다.
 하는 이유
 헤더파일에 정의된, 운영체제가 제공하는 Struct를 이용하는 것에 익숙해진다.
 바이너리 파일을 쓰는 것에 익숙해진다.
코드로 PE 파일 만들기
 첨부된 코드를 따라해 보자.
 앞에서 손으로 만든 것을 그대로 코드로 옮겼다.
부록 • 참고 사이트
참고 사이트
 PE 파일을 직접 만들어보고 글을 쓴 블로그
 조금 더 지켜야 하는 규칙을 잘 지켜서 썼음
 http://zesrever.tistory.com/58
 PE를 전문으로 다룬 리버싱 책 미리보기
 책 내용 전부를 볼 수는 없지만, 책 내용에서 검색을 이용하면 인터넷에서 잘 찾아지지 않는 내용을 찾을 수 있다.
 https://books.google.co.kr/books?id=ItWDDQAAQBAJ&printsec=frontcover&dq=%EB%A6%AC%EB%B2%84%EC
%8A%A4+%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81&hl=ko&sa=X&ved=0ahUKEwiF-6-
x6t3UAhUBzpQKHUXYBZkQ6AEIKzAB#v=onepage&q&f=false

More Related Content

PPTX
Linux reversing study_basic_2
 
PPTX
Windows reversing study_basic_3
 
PPTX
Pwnable study basic_2
 
PPTX
Assembly 스터디 2
 
PPTX
Assembly 스터디 1
 
PPTX
System+os study 1
 
PPTX
Windows reversing study_basic_7
 
PPTX
System+os study 4
 
Linux reversing study_basic_2
 
Windows reversing study_basic_3
 
Pwnable study basic_2
 
Assembly 스터디 2
 
Assembly 스터디 1
 
System+os study 1
 
Windows reversing study_basic_7
 
System+os study 4
 

What's hot (20)

PPTX
Windows reversing study_basic_9
 
PPTX
Windows reversing study_basic_1
 
PPTX
Windows reversing study_basic_5
 
PPTX
Pwnable study basic_1
 
PPTX
Pwnable study basic_3
 
PPTX
Linux reversing study_basic_4
 
PPTX
Linux reversing study_basic_3
 
PPTX
Linux reversing study_basic_1
 
PPTX
Python
 
PPTX
Windows reversing study_basic_2
 
PPTX
Windows reversing study_basic_8
 
PPTX
System+os study 3
 
PPTX
System+os study 5
 
PPTX
System+os study 7
 
PPTX
Windows reversing study_basic_6
 
PPTX
System+os study 6
 
PPTX
Web hacking introduction
 
PDF
[Kerference] 시작! 리버싱 - 김종범(KERT)
PDF
Apache avro
PDF
해커스쿨 FTZ 문제 풀이
Windows reversing study_basic_9
 
Windows reversing study_basic_1
 
Windows reversing study_basic_5
 
Pwnable study basic_1
 
Pwnable study basic_3
 
Linux reversing study_basic_4
 
Linux reversing study_basic_3
 
Linux reversing study_basic_1
 
Python
 
Windows reversing study_basic_2
 
Windows reversing study_basic_8
 
System+os study 3
 
System+os study 5
 
System+os study 7
 
Windows reversing study_basic_6
 
System+os study 6
 
Web hacking introduction
 
[Kerference] 시작! 리버싱 - 김종범(KERT)
Apache avro
해커스쿨 FTZ 문제 풀이
Ad

Similar to Windows reversing study_basic_4 (20)

PPTX
PE File Format and Packer - Inc0gnito 2016
PPTX
05 pe 헤더(pe header)
PDF
05 pe 헤더(pe header)
PDF
Pe+file+format
PPTX
이무송 스터디 HEX Editor로 PE 분석하기.pptx
PPT
2006 03 15_pe & api hook
PDF
[2007 CodeEngn Conference 01] 김기오 - NASM 어셈블러 사용법과 Calling Convention
PDF
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
PDF
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
PPTX
Chapter 17
PDF
Exception&log
PPT
Windows Debugging Technique #2
PPTX
[0618구경원]초보 게임프로그래머를 위한 c++
PDF
HI-ARC PS 101
PDF
JVM_트러블슈팅.pdf
PDF
Visual Studio를 이용한 어셈블리어 학습 part 1
PPTX
[아꿈사] The C++ Programming Language 9장 소스 파일과 프로그램
PDF
Buffer Overflow PPT (OneTwo)
PDF
Function calling convention
PPTX
Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅
PE File Format and Packer - Inc0gnito 2016
05 pe 헤더(pe header)
05 pe 헤더(pe header)
Pe+file+format
이무송 스터디 HEX Editor로 PE 분석하기.pptx
2006 03 15_pe & api hook
[2007 CodeEngn Conference 01] 김기오 - NASM 어셈블러 사용법과 Calling Convention
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
Chapter 17
Exception&log
Windows Debugging Technique #2
[0618구경원]초보 게임프로그래머를 위한 c++
HI-ARC PS 101
JVM_트러블슈팅.pdf
Visual Studio를 이용한 어셈블리어 학습 part 1
[아꿈사] The C++ Programming Language 9장 소스 파일과 프로그램
Buffer Overflow PPT (OneTwo)
Function calling convention
Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅
Ad

Windows reversing study_basic_4

  • 2. 목차  실습  수작업 PE 파일 만들기  DOS header  NT header  File header  Optional header  Section header  Header NULL padding  Section 내용  Section NULL padding  미뤄둔 내용 수정  코드로 PE 파일 만들기  부록  참고 사이트
  • 3. 수작업 PE 파일 만들기 • DOS header • NT header • Section header • Header NULL padding • Section 내용 • Section NULL padding • 미뤄둔 내용 수정
  • 4. 수작업 PE 파일 만들기  아직 PE 헤더에서 배우지 않은 부분이 있어 완전한 PE 파일을 만들 수는 없다.  이번 실습에서는 제대로 된 PE 파일을 만드는 것이 목적은 아니다.  아무 변수도 없고 코드만 달랑 들어있는 가장 기초적인 PE를 만들 것이다.  코드로는 MOV EAX, 1 과 ADD EAX, 2 그리고 Ret만 넣어보자.  목표  올리 디버거에서 실행했을 때, 코드가 보이게 만드는 것  하는 이유  실제로 만들어 보면 PE헤더에 대한 이해도가 높아진다.  리틀 엔디안으로 숫자를 읽고 쓰는 데 익숙해진다.  기계어 코드를 만들고 이용하는 데 익숙해진다.  Stack overflow같은 공격을 할 때, 기계어 코드를 만들어 넣어야 한다.  헥사 에디터로 프로그램을 수정하는 것에 익숙해 진다.
  • 5. 수작업 PE 파일 만들기  인라인 어셈블리 코드를 이용하여 기계어를 쉽게 얻었다.  B80100000083C002C3  총 9바이트이다.
  • 7. DOS HEADER • e_magic과 e_lfanew를 제외한 필드는 실행에 영향을 끼치지 않는다. • 그냥 0으로 채워도 된다. • e_magic • MZ이라는 표식이 들어간다. • e_lfanew • NT Header의 위치를 저장 • DOS stub은 쓰지 않을 계획이므로 e_lfanew는 바로 다음 위치를 가리키도록 했다.
  • 10. NT HEADER Signature • NT헤더의 시작 • PE 파일임을 표시하는 용도 • DWORD(4바이트)로, 뒤의 00 00도 포함됨
  • 11. NT HEADER_FILE HEADER 빨간 네모 안 4개의 값이 중요하다. 이 4개의 값이 잘못되어 있으면 프로그램이 정상적으로 실행되지 않는다.
  • 12. NT HEADER_FILE HEADER Machine • Intel에 해당하는 것은 014C • 리틀 엔디안으로 4C 01
  • 13. NT HEADER_FILE HEADER NumberOfSections • 섹션의 개수를 나타냄 • 반드시 0보다 커야 한다 • 정의된 섹션 수와 실제 수가 다르면 실행 에러 발생 • Text섹션만 만들 것이므로 1을 넣자. TimeDateStamp와 PointerToSymolTable, NumberOfSystembols는 그냥 0으로 채우자
  • 14. NT HEADER_FILE HEADER SizeOfOptionalHeader • 32비트 PE 파일의 Optional Header 크기는 E0이다.
  • 15. NT HEADER_FILE HEADER Characteristics • 파일의 속성을 나타냄 • EXE를 만들 것이므로 0x0102이다. 이는 리틀 엔디안으로 0201이다.
  • 16. NT HEADER_FILE HEADER • 파일 헤더를 다 쓴 모습이다
  • 17. NT HEADER_OPTIONAL HEADER • Optional 헤더는 32비트 기준으로 쓰겠다. • 빨간 네모 친 10가지가 특히 신경 쓸 부분이다.
  • 18. NT HEADER_OPTIONAL HEADER Magic • IMAGE_OPTIONAL_HEADER32일 경우 10B Major, Minor Linker Version • 0으로 채움 SizeOfCode • 기계어 코드 길이는 9 바이트이다. • 그런데 sizeofcode는 filealignment를 적용한 값이 들어갈 것이다. • Filealignment는 256byte(0x100)로 할 것이므로, 100을 쓴다.
  • 19. NT HEADER_OPTIONAL HEADER • 사용할 데이터가 따로 없으니 SizeOfInitializedData와 SizeOfUninitializedData는 0으로 채운다. • AddressOfEntryPoint와 BaseOfCode는 아직 코드가 어느 위치에 들어갈 지 모르기 때문에 나중에 채운다 • 찾기 쉽도록 F로 채워 둔다 • 파일 오프셋을 기억해 두자! • BaseOfData는 데이터를 사용하지 않으므로 0으로 채운다.
  • 20. NT HEADER_OPTIONAL HEADER • ImageBase는 흔히 사용하는 00040000으로 해 보자. • Section Alignment는 0x100으로 해 보자(256byte) • 원래 Section Alignment는 한 페이지 크기보다 작을 수 없다. • 페이지란, 가상 메모리를 관리하는 최소 단위이다. • 하지만 그보다 작게 해도 프로그램에 이상은 없다. • Windows 운영체제가 실제로 프로그램을 로딩 할 때 페이지 크기만큼 메모리를 할당할 뿐이다. • File Alignment도 0x100으로 해 보자. • 사실 512~65,536사이여야 하지만, 작을 경우 알아서 처리 된다… • File alignment와 section alignment가 같을 경우, 거의 같게 올라온다 (bss 등의 예외를 제외하면) • Null padding이 같기 때문
  • 21. NT HEADER_OPTIONAL HEADER • 여기까지 쓴 모습이다. • 나중에 쓰기로 한 AddressOfEntryPoint와 BaseOfCode의 위치를 잘 기억하자 (0x68, 0x6C) • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C)
  • 22. NT HEADER_OPTIONAL HEADER • Major, Minor OperatingSystemVersion은 최소 실행 가능 OS 버전이다. • XP로 해 보자. XP에 해당하는 숫자는 5.1이다. Major에 5, Minor에 1을 쓴다. • Major, Minor ImageVersion은 프로그램의 버전이다. • 프로그래머가 프로그램 버전을 관리하고 싶을 때 이용하는 필드이다. • 그냥 0으로 채워도 상관 없다. • Major, Minor SubsystemVersion도 OperatingSystemVersion과 똑같이 맞춰준다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C)
  • 23. NT HEADER_OPTIONAL HEADER • Win32VersionValue는 0으로 채운다. • 더 이상 쓰이지 않는 필드 • SizeOfImage는 PE 이미지의 총 크기이다. • section alignment의 배수여야 한다. • 아직 text 섹션을 쓰지 않았으므로 일단 F로 채우고 나중에 다시 쓴다. • SizeOfHeaders는 헤더 영역의 총 크기이다. • Section alignment의 배수여야 한다. • 헤더를 전부 쓰고 채우자. 일단 F로 채운다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 24. NT HEADER_OPTIONAL HEADER • 중간 모습이다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 25. NT HEADER_OPTIONAL HEADER CheckSum • 파일이 변했는지 판단할 때 사용하는 필드이다. 지금은 신경 쓸 것 없다. • 0으로 채운다. Subsystem • 콘솔 프로그램으로 만들기 위해서는 3을 써야 한다. (CUI) DllCharacteristics • PE파일이 DLL파일일 때 의미가 있다. • 0으로 채운다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 26. NT HEADER_OPTIONAL HEADER SizeOfStack, Heap Reserve • 디폴트 힙과 스택의 최대 크기 • 프로그램을 만들 때, 링커가 일반적으로 1M로 설정한다 (0x100000) SizeOfStack, Heap Commit • 한 번에 할당할 메모리의 양 • 이 크기로 가상 메모리의 스택, 힙 영역을 물리 메모리에 매핑 • 링커가 일반적으로 1페이지(0x1000) 크기로 써 준다. 이대로 써 주자. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 27. NT HEADER_OPTIONAL HEADER LoaderFlags • 지금은 사용하지 않는 필드 • 0으로 채운다 NumberOfRvaAndSizes • 바로 아래 있는 배열 요소의 개수 • 기본적으로 16개를 사용하므로 16(0x10)을 써 준다. DataDirectory • 함수 import 등에 이용되지만 아직 배우지 않았으므로 0으로 채운다. • 배열 하나당 8바이트이므로, 8*16, 총128개의 0을 쓴다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 28. NT HEADER_OPTIONAL HEADER • Optional Header를 끝까지 쓴 모습이다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 30. SECTION HEADER winnt.h에 정의돼 있는 Section header struct 빨간 네모 안 5개의 값이 중요하다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 31. SECTION HEADER Name • 이름은 .text라고 하자 • 이름 배열의 남은 부분은 0으로 채운다. VirtualSize • 해당 section의 얼마 만큼이 실제로 의미 있는 데이터인지 쓴다. • Section Alignment가 적용되지 않은 값 • 실제 코드 크기인 9를 쓴다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94)
  • 32. SECTION HEADER VirtualAddress • PE 이미지(메모리에 올려진 PE 파일)에서 섹션의 시작 주소 • RVA • file alignment와 section alignment를 같게 했으므로 파일에서의 코드영역 시작 위치를 쓰면 된다. • 코드 섹션은 헤더를 다 쓴 뒤 헤더의 파일 alignment를 맞춰주고 쓸 것이다. 일단 F로 채웠다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144)
  • 33. SECTION HEADER • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148) SizeOfRawData • 파일에서의 해당 section의 크기 • File alignment가 적용된 크기 • NULL padding까지 포함한 크기 • 실제 code 내용 사이즈는 9이지만 file alignment가 0x100이므로 0x100을 써 준다. PointerToRawData • 해당 section의 파일에서의 위치 • 헤더를 다 쓰고 채우자. 일단 F로 채웠다.
  • 34. SECTION HEADER • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148) PointerToRelocations, NumberOfRelocations • Obj 파일에서만 의미 있다. 0으로 채운다. PointerToLine, NumberOfLinenumbers • 디버깅에 이용되는 필드이다. 0으로 채운다.
  • 35. SECTION HEADER • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148) Characteristics • 해당 section의 권한, 특징 • 실행가능 파일을 만들 것이므로 0x60000020
  • 36. SECTION HEADER • Section header를 끝까지 쓴 모습이다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 37. SECTION HEADER • Section헤더는 Section 개수만큼 있다. • 개수가 일정치 않다. • Section 헤더 배열의 마지막을 알리는 NULL로 이루어진 Section 헤더를 추가한다. • Section 헤더의 크기만큼 0을 추가한다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 39. HEADER FILE ALIGNMENT • 헤더 영역의 file alignment를 맞추기 위해 0을 추가했다. • File alignment 는 0x100이었다. • 0x200이 다음 내용(실제 section의 내용) 시작 주소가 될 수 있도록 1FF까지 0을 채운다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 41. SECTION 내용  맨 처음 구한 기계어를 쓴다.  B80100000083C002C3 • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 42. SECTION 내용 사이 NULL PADDING
  • 43. SECTION 내용 사이 NULL PADDING • Section의 file alignment를 맞추기 위해 0을 추가했다. • 2FF까지 0을 채운다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 44. 미뤄둔 내용 수정 • AddressOfEntryPoint (0x68) • Section alignment와 file alignment가 같으므로 파일에서의 주소가 RVA가 된다. • 코드영역의 시작 부분에 있는 코드에서 시작할 것이므로, 코드가 있는 section의 위치를 쓰면 된다. • 0x200을 쓴다. • BaseOfCode (0x6C) • 코드 영역의 시작 위치, 0x200를 쓴다. • 나중에 쓸 것 • AddressOfEntryPoint(0x68) • BaseOfCode(0x6C) • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 45. 미뤄둔 내용 수정 • SizeOfImage (0x90) • Section alignment와 file alignment가 같으므로 PE 파일 크기를 쓰면 된다. • 0x300을 쓴다. • SizeOfHeader (0x94) • 헤더의 크기(file alignment적용)는 0x200이다. • 나중에 쓸 것 • SizeOfImage(0x90) • SizeofHeader(0x94) • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 46. 미뤄둔 내용 수정 • VirtualAddress (0x144) • Section alignment와 file alignment가 같으므로 PE 파일에서의 section 시작 위치를 쓰면 된다. • 0x200을 쓴다. • PointerToRawData • 파일에서의 section 시작 위치, 0x200을 쓴다. • 나중에 쓸 것 • VirtualAddrss(0x144) • PointerToRawData(0x148)
  • 47. 올리 디버거에서 실행 • 에러가 뜨긴 하지만 실행이 된다. • File, section alignment때문인 것 같다.
  • 48. 코드로 PE 파일 만들기 • 코드로 PE 파일 만들기
  • 49. 코드로 PE 파일 만들기  앞에서 만든 PE 파일을 코드로 쓴다.  조금 더 편하게 만들 수 있다.  목표  실제로 PE 파일을 만들고 쓰는 코드를 만들어 본다. 후에 간간이 응용할 일이 있을 코드다.  하는 이유  헤더파일에 정의된, 운영체제가 제공하는 Struct를 이용하는 것에 익숙해진다.  바이너리 파일을 쓰는 것에 익숙해진다.
  • 50. 코드로 PE 파일 만들기  첨부된 코드를 따라해 보자.  앞에서 손으로 만든 것을 그대로 코드로 옮겼다.
  • 51. 부록 • 참고 사이트
  • 52. 참고 사이트  PE 파일을 직접 만들어보고 글을 쓴 블로그  조금 더 지켜야 하는 규칙을 잘 지켜서 썼음  http://zesrever.tistory.com/58  PE를 전문으로 다룬 리버싱 책 미리보기  책 내용 전부를 볼 수는 없지만, 책 내용에서 검색을 이용하면 인터넷에서 잘 찾아지지 않는 내용을 찾을 수 있다.  https://books.google.co.kr/books?id=ItWDDQAAQBAJ&printsec=frontcover&dq=%EB%A6%AC%EB%B2%84%EC %8A%A4+%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81&hl=ko&sa=X&ved=0ahUKEwiF-6- x6t3UAhUBzpQKHUXYBZkQ6AEIKzAB#v=onepage&q&f=false