1 요람(CreateProcess)에서 무덤(ResumeThread)까지 Art Of Memory 보안분석팀 조효제 (kino)
4 Art Of Memory
• 현재 실행중인 프로세스의 메모리에 접근 – 실행중인 프로세스에 DLL Injection
– 실행중인 프로세스에 Thread Injection
• 새로운 프로세스를 생성해 메모리에 접근 – 새로운 프로세스를 생성해 DLL, Thread Injection
– 새로운 프로세스를 생성해 코드 영역 덮어 쓰기
– 새로운 프로세스를 생성해 메모리 재 매핑 후 실행
5 Art Of Memory
• 현재 실행중인 프로세스의 메모리에 접근 – 실행중인 프로세스에 DLL Injection
– 실행중인 프로세스에 Code Injection
explorer.exe
Heap
Malware explorer.exe
1. OpenProcess (PID)
PE Header
Code
2. VirtualAlloc Ex
Kernel32.dll
ntdll.dll WS32.dll
LoadLibrary(malware.dll) Allocated
Area
3. WriteProcessMemory
4. CreateRemoteThread
malware.dll malware.dll
6 Art Of Memory
• 새로운 프로세스를 생성해 메모리에 접근 – 새로운 프로세스를 생성해 DLL, Thread Injection
– 새로운 프로세스를 생성해 코드 영역 덮어 쓰기
– 새로운 프로세스를 생성해 메모리 재 매핑 후 실행
PE Header
Code
Malware notepad.exe
1. CreateProcess (notepad.exe)
PE Header
Code
2. WriteProcessMemory
Kernel32.dll
ntdll.dll WS32.dll
3. ResumeThread MalCode
7 Art Of Memory
• 새로운 프로세스를 생성해 메모리에 접근 – 새로운 프로세스를 생성해 DLL, Thread Injection
– 새로운 프로세스를 생성해 코드 영역 덮어 쓰기
– 새로운 프로세스를 생성해 메모리 재 매핑 후 실행
PE Header
Code
Malware notepad.exe
1. CreateProcess (notepad.exe)
PE Header
Code
2. UnMapViewOfSection
8 Art Of Memory
• 새로운 프로세스를 생성해 메모리에 접근 – 새로운 프로세스를 생성해 DLL, Thread Injection
– 새로운 프로세스를 생성해 코드 영역 덮어 쓰기
– 새로운 프로세스를 생성해 메모리 재 매핑 후 실행
Malware notepad.exe
PE Header
Code
5. ResumeThread
MalCode
MalPeHeader
Mal Area
3. VirtualAllocEx
4. WrtieProcessMemory
10 불편하다 불편해…
• 입사초기 평화롭게 월급 루팡질을 하고 있던 분석가 J씨
• 악성코드를 하나 받게 되는데….. – 매우 단순한 악성코드
– CreateProcessA(%temp%calc.exe, SUSPEND)
– WriteProcessMemory(pHandle,0x00401000);
– ResumeThread(pHandle); 후 악성행위 수행
• 일반적인 분석 프로세스에 따라 BP후 분석 수행 – 그런데… 새롭게 생성된 프로세스는 어떻게 분석을…?!?!?!
11 불편하다 불편해…
• 난감해 하던 분석가는 일단 문서를 찾는다. – 찾다 보면 누구나 보게 된다는 그 문서
• 0xCC를 EP에 박은 후 JIT(Just In Time Debugging)을 통해 디버거에 Attach 방법을 보고 신박하다고 생각한다. – Do It !!
12 불편하다 불편해…
• 기술적 관점
PE Header
Code
PE Header
Code
Malware Created Malware
1. CreateProcess(path, SUSPEND)
2. WriteProcessMemory( EP, 0xCC) 0x8B
EP
3. ResumeThread
Run!
Debugger
13 불편하다 불편해…
• 위 문서에 나온 방법을 응용해 디버거에 Attach를 시도했다. – 0xCC : BreakPoint에 사용되는 OPCode
– JIT : 프로세스에서 0xCC와 같은 BP 인터럽트 발생시 제어권을 디버거로 가져오는 옵션
• 시나리오 – CreateProcessA -> WriteProcessMemory시 PE헤더를 분석해 EP를 찾아낸 후 그곳에 0xCC
를 삽입
– 이후 ResumeThread를 수행하면 메인 쓰레드가 동작하면서 EP에서 인터럽트가 발생해 OllyDBG로 제어권이 넘어옴
– 손으로 직접…
OllyDBG로 디버깅 권한을 Get ~☆ 완벽한 시나리오 !
18 기존의 방식들론 왜…
• 첫 번째 시나리오 – 0xCC와 JIT를 통해 프로세스의 제어권을 디버거로 연결
– 디버거에 정상적으로 제어권이 넘어오지 않음
• 두 번째 시나리오 – 일단 ResumeThread를 통해 프로세스를 실행시킨 뒤 실행중인 프로세스를 PETools로 덤프
– 프로세스가 실행되는 도중 덤프가 떠지므로 코드(데이터)가 변하는 문제가 발생
– 빠르게 실행되고 종료되는 악성코드의 경우 PETools로 덤프를 뜨기 전에 이미 종료됨
– 코드를 처음부터 살펴볼 수 없음
20 Do It Yourself !!
• 어차피 기존의 방식으로 해서 되질 않는다. – 찾는 다고 방법이 나오는 것도 아니고…. 나온 방법이 되는 것도 아니고…
• 그냥 방법을 찾아서 만들어보자. – 만들어 두면 상세 분석 시 상당한 도움이 될 것 같음
• 기존 방식들의 문제점들을 먼저 파악 해 보자. – EP를 찾아 코드를 패치 : PE헤더를 분석해 EP를 찾는게 귀찮음
– 0xCC를 통해 디버거로 연결 : 왜 인지 모르지만 안됨
• 문제점을 어떻게 해결할 것인가 ? – EP를 찾아 코드 패치 : 자동으로 EP를 찾아주기
– 디버거로 제어권 넘겨 받기 : 고민을 해보자.
21 Do It Yourself !!
• 0xCC를 통한 디버거 연결 – 0xCC로 디버거로 연결되지 않는다
– 0xCC 이후 ResumeThread 후 Attach를 시도 해도 붙지 않는다
– 다른 방법이 필요 !
• 필요 조건 – 레지스터 및 스택의 값에 변화가 없어야 함
• 그럼 일단 동작을 시키면 되잖아 !! – 0xCC대신 다른걸 이용하자
– jmp self 를 사용 하는건 어떨까??
• jmp self – EP 가 0x00401000이라면 jmp 0x00401000 으로 !
22 Do It Yourself !!
• 종합해 보자면… – 자동으로 EP를 찾아 EP의 코드를 백업해 둔 뒤 0xEBFE ( jmp self)로 변경하고
ResumeThread 한 뒤 Attach 시키고 원본코드로 변경 !
– 스택 및 레지스터의 값 변화가 없으며 실제 프로세스가 실행중인 상태이므로 일반 프로세스 분석과 크게 다르지 않아 쉽게 접근 가능
PE Header
Code
push ebp (0x55) mov ebp,esp (0x8B,0xEC)
… …
EP
PE Header
Code
jmp self (0xEBFE) … … …
EP
0x00401000 : jmp 0x00401000
25 개발 !!
• 프로그램 동작
PE Header
Code
Malware Created Malware
1. CreateProcess(path, SUSPEND)
2. WriteProcessMemory(EP, MalCode)
Debugger
memory Breakpointer
3. Privilege Escalation
4. Get Process Base Information (From PEB)
5. Injection 0xEBFE
PE Header
Code
6. ResumeThread ( )
7. Attach & BP On EP & Run
8. Injection Backuped Original Code
26 개발 !!
• 필요 모듈 – Process Information Module : 프로세스의 정보를 받아올 수 있는
– Get Privilege Module : 프로세스에 접근하기 위한 권한 상승 모듈
– PE Header Module : PE 구조를 파싱해 EP를 찾아가기 위한 모듈
– Main Module : EP에 0xEBFE를 입력하기 위한 모듈
• Process Information Module – OpenProcess( )
– GetModuleHandle( )
– ZwQueryInformationProcess( )
– ReadProcessMemory( )
• Get Privilege Module – OpenProcessToken( )
– LookupPrivilegeValue( )
– AdjustTokenPrivileges( )
• Main Module – ReadProcessMemory( )
– WriteProcessMemory( )