티스토리 뷰

[Reversing] Process Hollowing 기법


프로레스 할로잉 기법은 자식 프로세스를 이용하여 프로세스 자체를 인젝션하는 것으로 간략하게 말하자면 절차는 자식 프로레스를 서스펜드 상태로 만든  기존 악성 프로세스의 정보를 얻어 자식 프로세스의   매핑을 한다. 

 메모리를 할당과 악성 데이터를 삽입한  서스펜드 상태를 풀어주게 되면 악성 행위를 하게된다.. 


source code

https://github.com/theevilbit/injection/tree/master/ProcessHollowing


  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/09   »
    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 30      
Total
156,825
Today
19