티스토리 뷰

[Reversing] Process Hollowing 기법


-https://github.com/theevilbit/injection/tree/master/ProcessHollowing ] : source code


  1. 프로세스 생성(SUSPENDED)  


  2.  BOOL CreateProcessA(

      LPCSTR                lpApplicationName,

      LPSTR                 lpCommandLine,

      LPSECURITY_ATTRIBUTES lpProcessAttributes,

      LPSECURITY_ATTRIBUTES lpThreadAttributes,

      BOOL                  bInheritHandles,

      DWORD                 dwCreationFlags,

      LPVOID                lpEnvironment,

      LPCSTR                lpCurrentDirectory,

      LPSTARTUPINFOA        lpStartupInfo,

      LPPROCESS_INFORMATION lpProcessInformation

    );


CreateProcess()을 이용하여 argv[1] 대상을 CREATE_SUSPEND(0x00000004) dwCreate 플래그로 사용는 걸 확인 할 수 있다. Argv[1] 대상은 notepad.exe로 진행  것이며, 새로운 프로세스의 초기 스레드가 SUSPENDED 상태로 생성한 걸 확인 할 수 있다. 

내부 함수를 이용할 경우도 있다.

“[processshollwing.exe] [target binary] [to be run binary]”

Argv[1] 대상은 notepad.exe로 설정, 

Argv[2] 대상은 calc.exe로 설정.


 

그림 1 – 참고 그림 


  1. PE Header 생성 

PE Header을 선언한 뒤 IMAGE_DOS_HEADER 구조체에서 e_magic(2byte) 필드 값이 “MZ” 저장 유무를 확인하는 걸 확인 할 수 있다. 

IMAGE_NT_HEADER의 시작 offset 값을 e_lfanew(4byte)이 가지고 있으며, Calc.exe.의 스레드 컨텍스트를 가져오는걸 확인 할 수 있다. 


  1. Image Base 주소 

Image Base 주소를 기반으로 원본(notepad.exe) 바이너리를 메모리에 Unmap 하기 위해 필요하다. 해당 Image Base 주소는 PEB에 담겨있는 프로세스 정보를 통해 알 수 있다. 이전 GetThreadContext()을 이용하여 SUSPENDED로 생된 프로세스 경우 Ebx 레지스터에 PEB 주소가 있으며, PEB + 0x08에는 프로세스의 Image Base 주소가 들어가 있다. ReadProcessMemory()을 이용하여 프로세스 Image Base 주소를 구하는 걸 확인 할 수 있다.


  1. Unmap 및 메모리 할당 

Base relocation table의 값을 통해 ASLR 적용 유무를 확인 한 후, NtUnmapViewOfSection()을 이용하여 대상 프로세스(notepad.exe)의 핸들과 대상 프로세스의 Image Base 주소를 넣고 이를 통해 notepad.exe 파일은 Unmap 되는 걸 확인 할 수 있다. 

Calc.exe의 Image Base 주소를 구한 후 그 주소에 맞게 Image Base 주소를 VirtualAllocEx()을 이용하여 메모리를 할당해준다.(읽기, 쓰기, 실행 권한) 


  1. 빈 곳에 calc.exe 쓰기 

WriteProcessMemory()을 이용하여 PE Header 및 나머지 섹션의 비어 있는 곳에 calc.exe.의 데이터를 쓰는 걸 확인 할 수 있다. 


  1. Context 수정 및 실행 

notepad.exe.의 Entry Point 및 ImageBase 수정하는데 GetThreadContext()로 구한 Context에서의 EAX(EP) 수정한 후 SetThreadContext()로 설정하는 걸 확인 할 수 있다. Entry Point 수정하는 방식은 여러 종류가 있다고 한다. Resume Thread()을 이용하여 실행하게 되는 걸 확인 할 수 있다. Resume Thread()는 Thread 실행하는 역할을 하는데 이전 실습 때 Resume Thread()을 실행 했을 때 변경한 EP로 실행이 되는 걸 확인 한 적이 있다.(Import Table 복구 실행) 



Notepad Suspend 모드로 실행

Calc.exe PE 구조 매핑(MZ, PE, NT, section)

Relocation(ASLR) on/off

virtualAllocEX() notepad 할당

GetThreadContext() notepad PEB정보 Get

WriteProcessMemory() 데이터 삽입

PEB 정보 → calc ImageBase 교체

SetThreadContext()

ResumeThread API를 이용하여 Suspend 상태였던 프로세스를 실행

(교체된 PE가 실행됨)

1 – ProcessHollowing 단계


CreateProcess()을 이용하며 CREATE_SUSPENDED를 플래그로 사용한다. Notepad.exe 프로세스를 SUSPENDED 모드로 실행한다 ResumThread()가 호출될 때 까지 실행하지 않는다.. SUSPENDED로 생성된 프로세스의 경우 GetThreadContext()을 이용하여 정보를 얻어와 EBX값을 이용해 PEB 주소를 얻는다. 이후 IMAGEBASE값을 알 수 있다. 

VirtualAllocEx()을 이용하여 notepad.exe 프로세스 내 새로운 메모리 영역을 할당한다. 할당된 메모리는 읽기/쓰기/실행이 모두 가능한 영역이 추후 해당 주소에 새로운 PE 바이너리가 저장된 것을 확인 할 수 있다. 

WriteProcessMemory()을 이용하여 할당받은 메모리에 PE binary로 교체한다. 

notepad.exe EntryPoint까지 EIP가 도달하지 는데 이유는 현재 Suspend 상태이기 때문이다.( EntryPoint는 SetThreadContext()을 이용) 

ResumeThread() 실행하게 되면 New EntryPoint에 도달하여 실행이 된다 


댓글
공지사항
«   2020/02   »
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
Total
138,729
Today
2