반응형

Section 02. 쉘코드 실전

* 하드코딩할 경우 

(1) Windows XP : 서비스팩과 언어만 동일하다면 값이 바뀌지 않으므로 가능

(2) Windows 7 : 부팅할 때마다 kernel32.dll의 상위 2바이트 주소값이 바뀌기 때문에 성공할 가능성 매우 희박

 => 프로세스 상에서 함수의 주소값을 동적으로 구해오는 Universal 쉘코드를 작성


1. Universal 쉘코드

 - 프로세스에서 함수의 주소값을 구하기 위해서는 dll의 시작 주소값dll 시작 주소부터 함수까지의 offset을 알아야 한다.

 - Universal 쉘코드의 목적 : 함수의 주소값을 실행 중에 스스로 구해 동적으로 입력


* 배경 지식들 - PEB, TEB, PE Header, Export Table, Export Name Table 등


1) TEB (Thread Environment Block)

 - TEB = 현재 실행되고 있는 쓰레드에 대한 정보를 담고 있는 구조체

 - 특수한 레지스터인 FS 레지스터에 TEB의 주소가 저장되어 있음 -> 프로세스 내부적으로 TEB에 접근하고자 할 때 FS 레지스터를 사용

 - PEB의 주소값을 정확히 알 수 있다. (TEB+0x30)


2) PEB (Process Environment Block)

 - PEB = 현재 실행 중인 프로세스에 대한 정보를 담아두는 구조체

 - 프로세스에 로드된 PE Image(EXE, DLL 등)들에 대한 정보들도 기록되어있음. -> 이를 이용

 - _PEB_LDR_DATA를 가리키는 포인터인 Ldr을 이용 (PEB+0xC)

 - InMemoryOrderModuleList (_PEB_LDR_DATA+0x14) = 프로세스의 PE Image들의 데이터가 저장된 LDR_DATA_TABLE_ENTRY 구조체의 더블링크드리스트 시작 주소가 저장

 - _LDR_DATA_TABLE_ENTRY 구조체 = 로드된 모듈에 대한 다양한 정보들을 저장, 모듈의 주소값인 DllBase가 저장되어 있음, 실행파일 그 자체에 대한 정보 (DllBase = 우리가 처음으로 필요로 한 dll의 시작 주소값)

 - InMomoryOrderLinks의 FLINK를 따라가면 첫 번째 로드된 라이브러리인 ntdll.dll 파일의 정보가 들어있는 LDR_DATA_TABLE_ENTRY 구조체를 만남

 - 한 번 더 FLINK를 따라가면 두 번째 로드된 라이브러리이며 우리가 원하는 kernel32.dll 파일의 정보가 들어있는 LDR_DATA_TABLE_ENTRY 구조체를 만남



* WinDBG = 윈도우 심볼 서버와 연동하여 다양한 심볼 정보를 쉽게 확인할 수 있다.

명령어 

설명 

사용 예시 

db 

byte 단위로 메모리를 표시 

>db [메모리주소]

>db 0x7ffd6000 

dd 

double word 단위로 메모리를 표시 

>dd [메모리주소]

>dd 0x7ffd6000 

dt 

type을 표시 (구조체 등)


type에 해당하는 실제 메모리값 확인 

>dt [구조체]

>dt _PEB


>dt [구조체] [메모리주소]

>dt _PEB 0x7ffd6000 


* <동적으로 모듈 주소 구하기> 실습 명령어 순서

1) !teb
2) dt _TEB [TEB주소]

3) dt _PEB [PEB주소]

4) dt _PEB_LDR_DATA [Ldr주소]

5) dt _LDR_DATA_TABLE_ENTRY [InMomoryOrderModuleList 의 FLINK값 -8]   = 로드된 파일 자기 자신 정보

6) dt _LDR_DATA_TABLE_ENTRY [InMomoryOrderLinks의 FLINK값 -8]            = ntdll.dll 정보

7) dt _LDR_DATA_TABLE_ENTRY [InMomoryOrderLinks의 FLINK값 -8]            = kernel.dll 정보


=> kernel32.dll의 DLLBase 값을 알 수 있다. 함수의 offset은 Windows 운영체제 버전과 서비스팩에 따라 달라질 수 있으므로 동적으로 구해보자!


3) IMAGE_EXPORT_DIRECTORY

 - DLL은 자신이 어떤 함수를 Export하고 있는지에 대한 정보를 PE헤더에 저장

 - 저장위치는 PE 헤더 IMAGE_OPTIONAL_HEADER32의 DataDirectory 배열의 첫 번째 구조체인 Export Directory

 - Export Directory는 IMAGE_EXPORT_DIRECTORY 구조체로 저장되어 있음.


* 가장 중요한 3개의 멤버

(1) AddressOfFunctions = 실제 함수의 시작 주소까지의 오프셋 배열을 가리킴(EAT)

(2) AddressOfNames = 함수 이름의 배열을 가리킴

(3) AddressOfNameOrdinals = 함수의 서수 배열을 가리킴


* 실제 함수의 주소값을 찾는 과정

1) 함수명 배열로 이동해서 원하는 함수의 이름과 해당 인덱스를 찾는다.

2) Ordinals 배열에서 인덱스에 해당하는 서수 인덱스 값을 찾는다.

3) EAT 배열에서 서수 인덱스에 해당하는 함수 offset을 확인한다.

4) DLL Base 주소와 offset을 더해서 함수의 실제 주소를 구한다.


* 주의사항 !

 - EAT, 함수명 배열 모두 직접 값이 들어있는 것이 아니라 RVA값(상대주소)의 배열이라는 것


* <동적으로 함수 주소 구하기> 실습 명령어 순서

1) !dlls     => 로드된 dll 목록 확인, base 주소 확인 가능

2) dt nt!_IMAGE_OPTIONAL_HEADER [dll base주소+0xf4+0x14] 

//Image_Optional_Header = Base + DOS_HEADER + IMAGE_FILE_HEADER

//IMAGE_OPTIONAL_HEADER 내용에서 IMAGE_DATA_DIRECTORY offset 확인

//nt!_의 의미는 NT 헤더에 있는 IMAGE_OPTIONAL_HEADER의 정보라는 의미

3) dd [IMAGE_OPTIONAL_HEADER 주소값 + 0x60]

  (IMAGE_OPTIONAL_HEADER 주소값 = Base + DOS_HEADER + IMAGE_FILE_HEADER + 0x60)

//IMAGE_EXPORT_DIRECTORY offset 확인

 = PEView로 c:\windows\system32\kernel32.dll 파일을 연 뒤 IMAGE_OPTIONAL_HEADER의 EXPORT Table 값과 동일

4) dd [dll base주소 + Export Table Offset]

 // IMAGE_EXPORT_DIRECTORY = BaseAddress + Export Table Offset]

 // 8번째 DWORD 부터 차례대로 함수주소배열, 함수명 배열, 서수배열의 주소값 확인 가능


* ActivateActCtx 함수의 주소를 구해보자!!

1) 함수명 배열에서 원하는 함수명의 인덱스 값을 찾는다.

 - EXPORT Name Table(ENT) = DLL Base + ENT Offset

 - 시작지점부터 4바이트마다 함수명의 offset이 저장 -> Base 주소에 각 offset 주소를 더해 확인 가능 ex) da 0x764f0000 + 0xb8c61



- IMAGE_EXPORT_DIRECTORY = BaseAddress + Export Table Offset

 - 노란색 형광펜은 순서대로 함수주소배열(EAT), 함수이름배열(ENT), 서수테이블(EOT)이다.

 - da 명령어 : 메모리를 ASCII 로 해석.

 - 3번째에 있는 함수명이 우리가 원하는 ActivateActCtx이므로 이에 해당하는 인덱스 값은 2이다. (인덱스는 0부터 시작)


2) 서수 테이블의 인덱스 2일 때의 값을 확인한다.

- 1)에서 찾는 인덱스로 바로 주소값을 확인하지 않고 서수 테이블을 거치는 이유는 함수명 테이블과 함수명 주소 테이블의 인덱스가 같지 않은 경우도 있기 때문


 - Export Ordinal Table(EOT) = DLL Base + EOT Offset

 - 바이트 단위로 저장되어 있으므로 db 명령어로 확인

 - 서수 테이블에서 인덱스 2일 때의 값은 4임을 확인


3) EAT에서 인덱스 4의 값을 확인

 - 인덱스 4의 값 = 5번째 주소 값(인덱스는 0부터 시작하므로) = 0x4556d



4) Base 주소에 함수의 offset을 더해서 최종 주소값을 구한다.

 - u 명령어 : 해당 주소 disassemble


반응형

'Hacking > System' 카테고리의 다른 글

PART3 쉘코드 원리와 작성  (0) 2016.12.21
16.12.19 공부일지  (0) 2016.12.20
16.12.17 공부  (0) 2016.12.18
블로그 이미지

rootable

,