PE FORMAT : 실행파일에 데이터 추가하여 로딩하기 윈도우





Loading EXE after adding the data to it 





우선, 잘 돌아가는 Hello World 프로그램에 뒷부분에 4KB (4096Bytes) 의 데이터를 추가한다. 



정확히 0x1000 만큼의 데이터가 0x18E00 에서 0x19E00 까지 추가되었다. 속성으로 확인 해 보자.






WinDBG 를 이용해 파일을 연 후 메모리 서치를 해보면 내가 추가 한 부분은 메모리에서 검색 되지 않는다. 아래 그림을 보자.












Why?


왜 안될까? 이유는 간단하다. EXE 는 PE 포맷으로 구성 되어있는데, 이 포맷은 실행 파일의 크기 정보를 담고 있다. 

우리는 파일을 열어 뒷부분에 0x1000 만큼의 데이터를 추가 해 주긴 했지만, PE 포맷에 저장되어 있는 파일 사이즈는 변경 해 주지 
않았기 때문에 추가 한 부분이 로딩이 되지 않는 것이다. PE 포맷을 분석해서 이 부분을 수정 해 주어야 우리가 원하는 나쁜짓(!)을 해낼 수 있다.

PE 포맷을 보여주는 프로그램은 여러가지가 있다. 

- PEView (무료, 데이터 수정 불가능)
- PE Explorer (상용)
- Stud PE (무료, 데이터 수정 가능)
- PE Browse (무료, 데이터 수정 불가능)

PEView 는 Read-Only 로 파일을 열기 때문에 동시 작업에 병맛이지만 브라우징이 깔끔하므로 스크린샷용으로 사용하겠다. PE Explorer 는 상용이지만 병맛이다. PE Browse 는 꽤 심도 있는 기능을 제공 하는것 같지만 사용해 보지 않았다. Stud PE 가 데이터도 수정 가능하고, 축약된 형태로 정보를 표현하므로 요것도 같이 사용하겠다. 














Analyse it




우선 기본적으로 알아야 할 사실이 있다. X86 CPU 에서는 파일을 4KB 단위로 저장한다. 이는 페이징 기능 때문인데, 자세한 내용은 다른 블로그 포스트 들을 참고 하도록 하고 파일이 4KB 단위여야 한다는 사실에 주목하자. 위에서 봤던 그림을 다시 불러오자.




실제 파일 사이즈는 99.5KB 와 103KB 지만, 디스크에는 4KB 단위로 존재해야 하므로 각각 100KB 와 104KB 로 디스크에 저장 된다.


두번째로 알아야 할 사실은, PE 포맷 내에는 구성 요소들이 존재하는데 이들은 HEADER 또는 SECTION 형태로 존재 한다. 쉽게 설명하자면 HEADER 는 SECTION 에 대한 간략한 인포메이션을 제공하고, SECTION 은 실제 데이터를 담고 있는 틀이다.

파일 내에 존재하는 섹션들은 모두 파일 오프셋 상에서 특정 단위로 존재해야 한다. 예를 들어 단위가 0x200 이라 가정 할때 어떤 섹션도 0x1330서 시작 될 수 없다. 섹션 시작 오프셋의 단위가 0x200 이므로 0x1400에서 섹션이 시작 되어야 한다. PE 포맷에는 이렇게 섹션의 시작 오프셋 단위를 지정하는 값이 존재하는데 IMAGE_OPTIONAL_HEADERFile Alignment 라는 값으로 존재한다.

이는 메모리 상에서도 마찬가지다. 메모리상에서도 섹션들의 시작 주소 단위가 존재한다. 예를 들어 이 값이 0x1000 이라면 어떠한 섹션도  메모리에 배치될때 0x403310 에서 시작 할 수 없다. 단위가 0x1000 이므로 0x404000 에서 시작 해야 한다. 보통 File Alignment 값보다 이 값이 크기때문에 파일이 메모리에 올라가는데 필요한 사이즈가 실제 파일 사이즈 보다 크다. 메모리 상에서 섹션의 시작 주소 단위를 지정하는 이 값 또한 IMAGE_OPTIONAL_HEADER 에 존재하며 Section Alignment 라는 값으로 존재한다.





위 그림은 Sample 로 잡은 ConsoleSample.exe 에서의 Section Alignment 값과 File Alignment 값이다.

그림의 왼쪽 부분에서 알 수 있듯이 파일의 마지막 섹션은 .reloc 섹션이다. 우리가 데이터를 추가하면, 이 섹션의 끝부분에 추가된다. HEADER 정보를 통해 .reloc 섹션에 대해서 알아보자.







Virtual Size 는 실제 해당 섹션의 사이즈가 차지하는 크기다. 

Size Of Raw DataFile Alignment 값이 적용된 사이즈다. 파일로 디스크 상에 존재할때의 섹션의 사이즈다. 

그리고 빨간색으로 강조되어있는 IMAGE_SCN_CNT_INITIALIZED_DATA 는 이 섹션의 특성을 나타내는데, 이 섹션이 가지고 있는 데이터가 초기화된 데이터라는 것을 의미한다.

우리는 파일의 끝부분에 0x1000 만큼의 데이터를 추가 했다. 이것은 곧 .reloc Section 의 사이즈가 0x1000 만큼 커졌다는 것을 의미한다. 따라서 Virtual Size 도 0x1000 만큼 증가시켜 0x1CF4 가 되어야 하고, Size Of Raw Data 도 0x1E00 이 되어야 한다. 그리고 IMAGE_SCN_CNT_INITIALIZED_DATA 을 특성으로 가지고 있는 섹션들의 크기를 모두 더 한 값도 PE 파일 내 어딘가에 저장 되어 있을 텐데 이 값도 0x1000 만큼 증가 시켜 주어야 한다. 

아래 그림은 IMAGE_OPTIONAL_HEADER 의 내용이다. 





Size Of Image 는 해당 파일을 메모리 상에 올릴 때 확보 해야할 메모리 크기다. 우리는 파일에 끝부분에 0x1000 크기의  데이터를 추가했으므로 이 값 또한 0x1E000 이 되어야 한다. 

Size Of Initialized Data 는 초기화된 데이터를 가지고 있는 섹션들의 크기를 모두 합친 값이다. 0x11000 을 값으로 가지고 있는데 실제로 그러한지 확인 해 보자. 아래 그림은 Stud PE 에서 해당 EXE 의 섹션 정보를 요약해서 보여준 것을 나타낸다.







Characteristics 를 보면 .text 섹션을 제외한 나머지 4개의 섹션들이 모두  IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) 을 속성으로 가지고 있다. 이 섹션들의 크기를 모두 더하면 0x2400 + 0x1000 + 0xCE00 + 0xE00 = 0x11000 이다. 따라서 이 값도 0x1000 만큼 증가시켜 0x12000 이 되어야 한다. 

그리고 마지막으로  CheckSum 값이 존재 하는데 이 값도 적절하게 바뀌어야 한다. 이 값은 ImageHelp.dll 의 CheckSumMappedFile API 를 통해서 계산 할 수 있다. (첨부파일로 사용 예제를 추가 해 놓았다.)  Stud PE 에서는 자동으로 계산 해 준다. (This is why i always use Stud_PE!!!!)




자 그럼 한번 정리 해 보자. 우리는 파일의 끝에 0x1000 만큼의 데이터를 추가 하였으므로 .reloc 섹션의 사이즈를 0x1000 만큼 늘렸다. 따라서

1. 파일의 이미지 전체 크기를 나타내는 Size Of Image 값을 변경한다.
2. .reloc 섹션의 메모리 상 크기를 나타내는 Virtual Size 값을 변경한다.
3. .reloc 섹션의 파일 상 크기를 나타내는 Size Of Raw Data 값을 변경한다.
4. .reloc 섹션은 IMAGE_CNT_INITIALIZED_DATA 섹션이므로 Size Of Initialized Data 값을 변경한다.
5. 파일의 체크섬 값을 나타내는 CheckSum 값을 변경한다. (위에서 언급했듯이 CheckSum 값은 0x140 부터 4바이트를 0x00000000으로 세팅 한뒤 해당 파일에 대해서 MapFileAndCheckSum 또는CheckSumMappedFile API를 호출하면 된다. MapFileAndCheckSum 이 사용하기 훨씬 간단하다)













Edit It







IMAGE_OPTIONAL_HEADERSize Of Image 값과 Size Of Initialized Data 값을 수정하고





.reloc 섹션 헤더의 Virtual SizeSize Of Raw Data 값을 수정한다.





그리고 CheckSum 값을 수정한 뒤 실행하면 잘 돌아간다.





그리고 WinDBG 에서 메모리를 서치 해 보면 





로드 된다. 








이번 시간에는 파일에 추가적으로 데이터를 붙인 뒤 PE 포맷을 약간 수정하여 추가된 데이터를 로드하는 것에 대해서 알아 보았다.

이를 이용하면 여러가지 나쁜(!) 작업을 할 수 있다. 이것에 대해서는 개인이 스스로 응용 방법을 찾아보도록 하자.




2011. 7. 6 

By Anster.

덧글

댓글 입력 영역


시계

라운드 시계

위키피디아