티스토리 뷰
[Reversing] Process Hollowing 기법
프로레스 할로잉 기법은 자식 프로세스를 이용하여 프로세스 자체를 인젝션하는 것으로 간략하게 말하자면 절차는 자식 프로레스를 서스펜드 상태로 만든 뒤 기존 악성 프로세스의 정보를 얻어 자식 프로세스의 각 위치에 매핑을 한다.
이후 메모리를 할당과 악성 데이터를 삽입한 후 서스펜드 상태를 풀어주게 되면 악성 행위를 하게된다..
source code
> https://github.com/theevilbit/injection/tree/master/ProcessHollowing
프로세스 생성(SUSPENDED)
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 – 참고 그림
PE Header 생성
PE Header을 선언한 뒤 IMAGE_DOS_HEADER 구조체에서 e_magic(2byte) 필드 값이 “MZ” 저장 유무를 확인하는 걸 확인 할 수 있다.
IMAGE_NT_HEADER의 시작 offset 값을 e_lfanew(4byte)이 가지고 있으며, Calc.exe.의 스레드 컨텍스트를 가져오는걸 확인 할 수 있다.
Image Base 주소
Image Base 주소를 기반으로 원본(notepad.exe) 바이너리를 메모리에 Unmap 하기 위해 필요하다. 해당 Image Base 주소는 PEB에 담겨있는 프로세스 정보를 통해 알 수 있다. 이전 GetThreadContext()을 이용하여 SUSPENDED로 생성된 프로세스 경우 Ebx 레지스터에는 PEB 주소가 있으며, PEB + 0x08에는 프로세스의 Image Base 주소가 들어가 있다. ReadProcessMemory()을 이용하여 프로세스 Image Base 주소를 구하는 걸 확인 할 수 있다.
Unmap 및 메모리 할당
Base relocation table의 값을 통해 ASLR 적용 유무를 확인 한 후, NtUnmapViewOfSection()을 이용하여 대상 프로세스(notepad.exe)의 핸들과 대상 프로세스의 Image Base 주소를 넣고 이를 통해 notepad.exe 파일은 Unmap 되는 걸 확인 할 수 있다.
Calc.exe의 Image Base 주소를 구한 후 그 주소에 맞게 Image Base 주소를 VirtualAllocEx()을 이용하여 메모리를 할당해준다.(읽기, 쓰기, 실행 권한)
빈 곳에 calc.exe 쓰기
WriteProcessMemory()을 이용하여 PE Header 및 나머지 섹션의 비어 있는 곳에 calc.exe.의 데이터를 쓰는 걸 확인 할 수 있다.
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 교체 |
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에 도달하여 실행이 된다
'Reversing > Reversing Tech' 카테고리의 다른 글
[Reversing] Self Creation, 디버깅 (0) | 2019.12.02 |
---|---|
[Reversing] Malwarebytes CrackMe: a step-by-step tutorial (0) | 2019.11.19 |
[Reversing] Inline Code Patch ② (0) | 2019.07.19 |
[Reversing] Inline Code Patch ① (0) | 2019.07.17 |
[Reversing] PE 파일 만들기④ (0) | 2019.06.25 |
- Total
- Today