티스토리 뷰

해당 포스팅 내용은 리버싱 핵심원리(이승원 저) 를 따라서 공부하려고 했던 것이지만, 실제로 제공된 소스파일을

컴파일 했을 때, 저자가 제공한 EXE 와 binary 가 상이해서 직접 주소를 찾아가면서 만들어가는 과정입니다.

아마, 대부분 myHack.cpp를 컴파일하면 책대로 나오지 않을 겁니다. 책의 내용의 많은 부분이 적용되지 않아서

직접 고민하고 시행착오를 겪어서, 이후에 해당 내용을 공부하고자 하는 분들께 도움이 되길 바랍니다.

이 글에서 사용하는 파일은 https://reversecore.com/104 

 

"리버싱 핵심 원리" 소스 코드와 실습 예제 파일입니다.

1. 소스 코드 (ver 1.0.2) Tistory : 소스코드.zip DropBox : 소스코드.zip * 암호 : reversecore < 릴리즈 히스토리 > ver 1.0.2 - "44장 InjDll.exe - DLL 인젝션 전용 도구" InjDll.cpp 오류 수정 (20121110) v..

reversecore.com

에서 제공받고, 특히 DLL_Injection 에서 25_PE_Patch를_이용한_DLL_로딩 이라는 폴더에 존재하는 프로젝트입니다.

여기서 다룰 기법은 Dll Injection 중에서 특별히 PE PATCH 라는 방법입니다. 24장에서 다룬 Dll injection 은

프로세스가 종료되었다 다시 생성되면 의도적으로 inject 한 dll 은 올라가지 않습니다. 다시 load 해줘야 하는데

PE-patch 방법은 아예 프로그램의 binary 의 Import directory Table 에 우리가 injection 하고싶은 dll 을 써놓음으로써

프로세스가 실행될 때마다 의도적으로 injection 한 dll 이 load 됩니다.

ㅇTextview 파일을 peView 로 열면 위와같은 화면을 볼 수 있는데요. Dll injection 을 하고싶으니깐

IMAGE_NT_HEADERS -> IMAGE_OPTIONAL_HEADER 를 열어서 IMPORT table 이 어디있는지 확인해볼께요.

offset 180에 RVA(001182A4) 에 있다고 쓰여져 있다는걸 알 수 있습니다.

여기서 001182A4 는 RVA 이므로 실제로 IMPORT table 의 내용을 조회하려면 RAW값으로 바꿔서 찾아가야합니다.

1182A4 는 .idata section 에 속하는 RVA 이기 때문에, .idata section 의 값을 이용해 계산합니다.

계산식은 아래와 같습니다. 아래의 식을 모르면 아예 진행이 불가능하기에 숙지해야합니다.

RAW = RVA - BASE + PointerToRawData  

RAW = 1182A4 - 00EF000[IMAGE_SECTION_HEADER .rdata 의 RVA ] +  00C7800

= C7AA4 

입니다. 진짜 맞는지 보겠습니다. HXD 로 TextView.exe 를 엽니다.

그림 1-1

 

실제로 64h byte 의 binary 가 있습니다. 

이제 여기서부터 여정이 시작됩니다. 

이 IDT(import directory table) 는 IMAGE_IMPORT_DESCRIPTOR(IID) 구조체 배열로 이루어져 있습니다.

또한, 마지막은 NULL 구조체로 끝납니다.

이제 하고자 하는것은, 저 NULL 앞에 우리가 inject 하고 싶은 myhack3.dll 을 끼워넣으면 TextView.exe 는 myhack3.dll이

원래 자기가 가지고 있는 dll  인 마냥 매번 실행 때 load 해서 사용하게 됩니다. 

그러면, 저것을 어떻게 끼워넣을것인가가 핵심임이 분명합니다. 어릴적부터 컴퓨터는 그냥 주어진대로 사용하는 것이기 때문에 불가능 할 것 같지만, 결국 이러한 조작은 binary 를 바꾸어서 pe 정보를 바꾸어버리면 너무나도 당연하게 되는 일인 것입니다. 

여기서 3가지 방법이 있습니다. 하나는 가장 쉽게 떠올릴 수 있는 방법이죠

그림 1-1 에 있는 binary 에 myhack.dll 를 부르는 binary 를 추가하는 방법입니다만, 그 바로 아래에 다른 binary 가 있기 때문에 자칫하면 런타임에 예상치 못한 AccessViolation 이 발생할 수도 있습니다. 

그래서 IDT 를 아예 다른 곳으로 빼낸 후에 확장시켜야 됩니다. 

보통 섹션의 말미에 null-padding(0으로만 채워져있는 영역) 이 있기 마련입니다. .rdata 를 찾아서 가봅니다

그림 1-2 

여기서 Virtual Size와 Size of Raw Data 를 주목합니다. Virtual size 실제로 메모리에 load 되었을 때 해당 섹션이

점유하는 공간의 크기입니다.  그러면 Size of Raw Data - Virtual Size 만큼의 공간은 실제로 사용하지 않는다는

의미입니다. 이 공간의 크기는 AA이고, 

injection 된 IDT 의 크기는 총 78h 일 것이므로, IDT 를 .rdata 의 말미에 삽입해도 넉넉할 것 같습니다.

 

000C7AA4 부터 64h 만큼이 IDT 였습니다. 이 HEX 를 복사해서 .rdata 아래로 데리고 오겠습니다

그림 1-2 의 .rdata 의 정보를 보고 .rdata 어느정도 아래가 좋을지 생각해봐야합니다. 

이정도 쯤에 넣으면 될 것 같습니다 . 113700 에 IDT 를 심겠습니다

RAW = 113500 - EF000 + A2000 = C6700

이렇게 IDT 를 복사해주고요. IDT 를 한 칸 확장할 것이므로 IDT 의 사이즈도 바꾸어줘야합니다.

위에서 IMPORT table  의 size 를 64 -> 78 로 바꾸어줘야 합니다. 

size 에 대한 정보는 184에 있다고하네요, 64 -> 78 로 바꿔주면 되겠습니다.

184 를 위와같이 64 -> 78 로 바꿉니다.

78로 바뀐걸 확인할 수 있습니다.

 

TextView 프로젝트를 컴파일하고 PE VIEW 로 열어주세요

이제 

이 형광펜친 주소를 .rdata 에 심어논 IDT 의 주소로 바꿔치기 해주면 됩니다.

아까 C6700 에 넣어놨으니깐 C6700이  RVA 로 어떻게 되는지 계산합니다

C6700 = RVA - EF000 + A2000 = 113700 이네요

180번지로 가서 1182A4 를 113700 으로 바꿉니다

RVA 가 001134F0 로 바뀝니다. 이제 TextView.exe 는 IDT 가 00113700 에 있다고 알고 있습니다.

이제 myhack3.dll 을 .rdata 에 있는 IDT 에 넣어줍니다

드래그한곳 까지가 실제로 존재하는 앞에 4개 KERNEL32,USER32,GDI32,SHELL32.dll 의 정보이고 그 아래줄부터

14byte 는 아까 말했던 null 요소입니다. 이 null 요소에 myhack3.dll 의 정보를 inject 해주면 되겠습니다.

생각해야될게 좀 있습니다. 

IIDT(IMAGE_IMPORT_DESCRIPTOR) 구조체는 

OriginalFirstThunk , TimeDateStamp , ForwarderChain , Name, FirstThunk  에 대한 정보가 필요합니다.

 OriginalFirstThunk 는 INT 의 RVA를

 TimeDateStamp , ForwarderChain 는 우선 0으로

 Name 은 dll 의 이름을 

 FirstThunk 의 이름의 문자열이 필요합니다

그래서 위와같이 hex 를 변경시켜주면 됩니다. 

자세한 설명은 책을 참고하세요(물론 위의 binary 는 정상작동합니다)

C6750 은 OriginalFirstThunk 인데요, 00113780 이라고 되어있습니다. 근데 실제 저 정보는 위의 사진자료에서

00C6780 에 적혀져 있습니다. 이 이유는 C6780 은 OFFSET 이고, 실제로 저 dll 을 참조할 때는 RVA 값을 통해서

얻어와야 합니다. 저는 처음에, 00113780 대신 C6780 을 적었더니 아래와 같은 오류를 받았습니다,

따라서, 반드시 RVA 로 변환한 후에 참조를 해주어야 합니다 

예를들어 C6780 을 참조하는 HEX 를 만들고 싶으면, C6780 를 RVA 값으로 바꾸어서 참조를 해야한다는 것이죠

이제 마지막 스텝으로, IAT 섹션의 Characteristics 를 쓰기속성인 C0000040 로 바꾸어줍니다.

 IAT 섹션의 Characteristics 를 쓰기속성으로 변경

그리고 저장하면

IMPORT Directory Table 이 .rdata 섹션으로 옮겨간 것을 볼 수 있습니다.

이제  실행보겠습니다.

성공입니다.

댓글