본문 바로가기

High Level Technique/Reversing

DLL Load Using PE Patch

DLL Load Using PE Patch


DLL Injection을 하면서 프로그램 내에 강제로 DLL을 삽입을 시켰습니다. 이번에는 PE 패치를 통해서 DLL을 실행시켜보도록 하겠습니다.



리버싱 핵심원리에 나와있는 TextView 프로그램과 다릅니다. 버전이 업데이트된 파일같습니다.

textview.zip


그래도 한번 따라서 해보도록 하겠습니다.








IDT (Import Directory Table) 확인


IDT를 확인해 보면 여러가지 dll이 나타납니다.


COMCTL32.dll SHLWAPI.dll KERNEL32.dll USER32.dll GDI32.dll comdlg32.dll ADVAPI32.dll SHELL32.dll ole32.dll MSVBR70.dll


핵심원리에서는 4개의 dll만 들어가 있는데 제가 받은 프로그램은 10개나 들어가 있습니다.



핵심원리에서 사용된 myhack3.dll 파일을 사용하도록 하겠습니다.

myhack3.dll



DllMain(): 사용자 스레드를 실행. DownloadURL()과 DropFile()를 호출하여 실제 작업을 수행.


DownloadURL(): szURL에 명시된 인터넷 파일을 다운받아 szFile 경로에 저장. 


DropFile(): 다운받은 index.html 파일을 textview.exe 프로그램에 드롭시켜 그 내용을 보여줌. textview.exe 프로세스의 메인 Windows Handle을 구해서 WM_DROPFILES 메시지를 전송.

PID를 이용하여 Window Handle을 구하여 PostMessage(WM_DROPFILES) API를 호출.


dummy(): 외부로 서비스하는 Export 함수. 아무런 기능이 없지만 넣은 이유가 textview.exe 파일의 Import Table에 추가시킬 수 있도록 형식적인 완전성을 제공.

PE 파일에서 어떤 DLL을 임포트 한다는 것은 파일의 코드 내에서 그 DLL이 제공하는 Export 함수를 호출한다는 의미. PE헤더에는 DLL 이름, 함수 이름 등의 정보가 기록되어 있다.

형식적인 완전성을 위해 Export 함수를 최소한 하나 이상 제공해야 한다.



RVA값을 확인해 보면 14D6C 입니다.  IDT는 IMAGE_IMPORT_DESCRIPTOR 구조체 배열로 이루어져 있고, 배열에 마지막은 NULL 구조체로 끝납니다.


Import하는 DLL 파일 하나당 IMAGE_IMPORT_DESCRIPTOR 구조체가 하나씩 필요합니다.


구조체 하나당 크기는 14바이트 이므로 14*10 140바이트가 됩니다. RVA 범위는 14D6C ~ 14E47 입니다.


HxD를 이용하여 영역을 살펴보면 아래와 같습니다. 








영역확인


영역을 확인할 때는 pFile로 찾아야 합니다.



해당 영역다음에는 다른 데이터가 존재하기 때문에 새로 추가를 할 수 없습니다.






IMAGE_IMPORT_DESCRIPTOR 이동


추가할 공간이 없으면 다른 곳으로 옮긴 후 새로운 IMAGE_IMPORT_DESCRIPTOR를 추가시켜야 합니다.


- 파일의 빈 영역을 찾는다.

- 파일의 마지막 섹션의 크기를 늘린다.

- 파일 끝에 새로운 섹션을 추가한다.




파일의 빈 영역 찾기

SECTION .rdata 부분을 살펴보면 아래에 NULL로 채워진 공간이 존재합니다. 이러한 공간을 NULL Padding이라고 부릅니다.

하지만 이 영역을 사용하기 전에 진짜 NULL Padding인지 확인도 해야하고, 파일에 있는 영역이라고 해서 프로세스 가상 메모리에도 로딩되는 것이 아닙니다.


먼저 .rdata 섹션 헤더를 살펴보겠습니다.



파일과 메모리의 크기를 살펴보면 파일은 0x3000이고 메모리는 0x25CC 입니다. 실제로 사용되는 공간이 0x25CC라는 것입니다.

0x3000 - 0x25CC = 0xA34 이므로 IMAGE_IMPORT_DESCRIPTOR를 재구성 하는데 문제가 없습니다.


그러면 RAV: 0x16D90 위치에 생성하도록 하겠습니다.











IMPORT Table의 RVA값 변경


IMAGE_OPTIONAL_HEADER의 IMPORT Table 구조체 멤버는 IMAGE_IMPORT_DESCRIPTOR의 위치와 크기를 알려줍니다.





Import Table의 RVA 값이 14D6C 입니다. 이 값을 IMAGE_IMPORT_DESCRIPTOR의 새로운 RVA 값인 0x16D90으로 변경하고 size 값을 기존 0xDC(220)에 + 14를 해서 0xEA로 변경합니다.



위와 같이 변경합니다.














BOUND IMPORT TABLE 제거


BOUND IMPORT TABLE은 DLL 로딩 속도를 조금 향상시킬 수 있는 기법입니다.



새로운 DLL을 정상적으로 Import하기 위해서는 BOUND IMPORT Table에도 정보를 추가해야 합니다. 이 테이블은 옵션으로 반드시 존재할 필요는 없기 때문에 작업의 편의성을 위해 제거합니다.

하지만 위 프로그램에서는 0으로 되어있기 때문에 상관이 없습니다. 다른 파일을 패치하는 경우 위 테이블을 잘 확인해야 합니다.









새로운 IMAGE_IMPORT_DESCRIPTOR 생성


HxD 프로그램을 이용해서 기존의 IMAGE_IMPORT_DESCRIPTOR를 전부 복사해서 새로운 IDT 위치에 덮어쓰기 합니다.



위와 같이 추가 시킨 후에 새로 추가하는 DLL 파일을 위한 IMAGE_IMPORT_DESCRIPTOR를 구성하여 새로 생성한 IDT의 끝에 추가시킵니다.













Name, INT, IAT 세팅






새로운 DLL을 추가하기 위해서 작업을 해줘야 합니다.


먼저 복사해 온 IMAGE_IMPORT_DESCTIPTOR의 마지막을 살펴보면 NULL이 들어가 있는 곳을 볼 수 있는데 그 부분에 값을 넣어줍니다.



여기서 필요한 것이 RVA to RAW 인데, 현재 패치하고 있는 프로그램은 RVA와 RAW가 같기 때문에 그대로 사용하면 됩니다.


INT : 0x016E80

Name : 0x016E90

IAT : 0x016EA0


위와 같이 값을 바꿔줍니다.


0x016E80, 0x016EA0에 입력된 값 0x016EB0는 0x016EB0위치에 "0000dummy" 문자열이 저장되어 있습니다.



※ 이 부분이 이해하기도 힘들고, 값을 어떻게 바꿔야 할지, 그리고 값은 정확하게 바뀐건지 사실 잘 모르겠습니다. 적당한 위치를 찾고 거기에 맞게 값을 바꿔 넣어주면 됩니다.

핵심원리에서 설명하고 있는 부분들을 유추해서 만들었습니다.









IAT Section Characteristics 변경


IAT는 PE Loader에 의해서 메모리에 로딩될 때 실제 함수 주소로 덮어쓰여지기 때문에 해당 섹션은 반드시 Write 속성을 가지고 있어야 합니다.



Characteristics의 값을 확인해보면 0x40000040 입니다. 그 밑에 속성들이 보이네요.

여기에 IMAGE_SCN_MEM_WRITE(0x80000000) 인 값을 추가해 줍니다. OR 연산을 통해서 0xC0000040이 됩니다.


※ 실제로 값을 변경 해주어야 하는 것은 Textview_Patch.exe 파일입니다.




※ 원래의 Textview 프로그램은 쓰기 속성이 없었지만 실행이 잘 되었지만, TextView_Patch 파일은 위와 같이 Write 속성을 주지 않으면 실행이 안되는데, 이유는 IMAGE_OPTIONAL_HEADER 구조체의 Data Directory 배열중에 IMPORT Address Table에 있습니다.



위 그림의 IMPORT Address Table을 삺보면 0x14000 부터 0x14498까지 IMPORT Address Table 입니다. 위 영역에 존재하는 값은 쓰기 속성이 없어도 되는 것.


앞서 수정 했었던 값들은 해당 범위에 속해있지 않기 때문에 쓰기 속성을 주어야 했던 것입니다.








확인




PEView로 확인한 결과 위와 같이 적절히 myhack3.dll이 들어가 있는 것을 알 수 있습니다.




dummy 또한 적절히 들어가 있는 것을 알 수 있습니다.





실제로 Patch한 프로그램을 실행시켜 봤지만 실행 도중에 죽어버리는 현상이 나타났습니다. Windows 10이라서 그러는 건지는 조만간 다른 OS에서 테스트 해보고 올리도록 하겠습니다.



'High Level Technique > Reversing' 카테고리의 다른 글

API Hooking  (0) 2016.07.19
Code Injection  (0) 2016.07.15
DLL Ejection  (0) 2016.07.08
DLL Injection  (0) 2016.07.06
Windows Massage Hooking  (0) 2015.12.29