KOROMOON

착한 사마리아인이 되고 싶습니다.

9/14/2020

메모리 헌팅 (Hunting In Memory)


Elastic Security 사 블로그에 2019년 06월 14일에 올라온 "Hunting In Memory" 글을 한글 번역함.

링크 : 

https://www.elastic.co/kr/blog/hunting-memory




위협 분석가는 다양한 데이터의 방대한 소스를 검색하여 공격 라이프 사이클(lifecycle)의 모든 단계에서 적대적 활동을 정확히 찾아내는 어려운 작업을 담당함. 

성공하려면 분석가는 최신 공격자 기법 및 탐지 방법에 대한 주제 전문 지식을 지속적으로 연마해야 함.

다양한 형태로 나타나는 메모리 상주 악성코드는 10년 넘게 존재해온 공격자 기법임.

메모리 상주 악성코드의 인기는 시간이 지남에 따라 꾸준히 증가해 왔으며 이는 아마도 코드의 확산과 메모리 기법에 대한 지식 때문일 수 있음.

그 인기는 보안 제품 및 실무자의 탐지를 피하는 메모리 기반 기법의 성공을 반영함.

한때 고급 공격자에게만 제한되었던 메모리 상주 기법은 이제 모든 수준의 공격자의 정교함을 위해 일반적임.

이러한 메모리 기반 공격자 기법 중 가장 일반적인 방법을 검토하고 메모리에 숨어 있는 적을 찾기 위한 확장 가능하고 소음이 적은 접근 방식을 만드는 데 도움이 되는 Google 팀의 연구 자료를 살펴봄.




( 1 ) 공격자 기법


네트워크에서 적을 탐지하기 위한 메모리 헌팅(Memory Hunting) 방법을 다루기 전에 메모리 상주 악성코드의 일반적인 형태를 이해하는 것이 좋음.

이러한 기법에는 쉘코드 인젝션, 반사 DLL 인젝션, 메모리 모듈, 프로세스 및 메모리 Hollowing, Gargoyle(ROP/APC) 이 포함됨.




쉘코드 인젝션


쉘코드 인젝션은 가장 기본적인 메모리 기법이며 가장 오래된 기법임.

쉘코드 인젝션의 기본 동작은 4 단계 프로세스임.

1 단계 : 대상 프로세스 열기 (OpenProcess)

2 단계 : 프로세스에 메모리 덩어리(Chunk)을 할당 (VirtualAllocEx)

3 단계 : 새로 할당된 섹션에 쉘코드 페이로드를 작성 (WriteProcessMemory)

4 단계 : 원격 프로세스에 새 스레드를 생성하여 쉘코드를 실행 (CreateRemoteThread)

오래 이슈 된 Poison Ivy 악성코드는 이 기법을 사용했으며 수 년에 걸쳐 많은 APT 그룹에서도 이 기법을 사용함.


x64dbg 로 Poison Ivy 악성코드 샘플을 가져와 VirtualAllocEx 에 중단점을 설정하면 곧 인센션을 담당하는 코드 덩어리(Chunk)를 찾을 수 있음.


첫 번째 이미지에서 VirtualAllocEx 에 대한 호출 이전의 push 40 명령어는 PAGE_EXECUTE_READWRITE 의 페이지 액세스 보호값에 해당함.

Poison Ivy 악성코드의 메모리 레이아웃에 대한 ProcessHaker 툴의 다음 스크린샷에서 이러한 RWX 센션을 여러 개 할당하는 것을 볼 수 있음.

일반적인 코드 섹션은 이미지 유형이며 디스크 파일에 매핑됨.

그러나 이들은 Private 유형이며 디스크 파일에 매핑되지 않음.

따라서 백업되지 않은 실행 가능 섹션 또는 부동 코드(Floating Code)라고 함.

이러한 유형의 메모리 영역에서 시작하는 스레드는 비정상적이고 악의적인 활동의 좋은 지표임.

ProcessHacker 툴은 악성코드 스레드의 호출 스택도 보여줄 수 있음.

로드된 모듈과 관련된 메모리에 매핑되지 않는 호출 스택에 여러 함수가 있음.




반사 DLL 인젝션


원래 Steven Fewer 님이 개발한 반사 DLL 인젝션은 메모리 공격자 기법의 또 다른 유형임.

Metasploit 프레임워크의 Meterperter 페이로드 기능은 이 기법을 완전히 무기화하기 위한 최초의 시도 중 하나였지만 오늘날 많은 악성코드 계열이 이를 사용함.

반사 DLL 인젝션은 윈도우 로더(Window's Loader)에 의존하는 대신 실행될 때 자체적으로 메모리에 매핑되는 DLL 을 생성하여 작동함.

인젝션 프로세스는 쉘코드가 자체 매핑 DLL 로 대체된다는 점을 제외하고는 쉘코드 인젝션과 동일함.

DLL 에 추가된 자체 매핑 구성 요소는 가져오기 주소(Import Address) 확인, 재배치 수정 및 DllMain 함수 호출을 담당함.

공격자는 어셈블리 대신 C/C++ 와 같은 상위 수준 언어로 코딩할 수 있는 능력을 활용함.


Meterperter 페이로드 기능에서 사용하는 것과 같은 고전적인 반사 DLL 인젝션은 분석가가 쉽게 찾을 수 있음.

Meterperter 페이로드 세션이 닫혀있어도 프로세스에 큰 RWX 메모리 섹션이 남음.

이러한 백업되지 않은 실행 가능 메모리 섹션의 시작 부분에는 아래 이미지와 같이 전체 PE 헤더가 포함됨.

그러나 다른 반사 DLL 인젝션 구현은 헤더를 지우고 메모리 누수를 수정할 수 있음.


메모리에 로드된 DLL 은 ReflectiveLoader() 라는 자체 설명 함수를 편리하게 내보냄.




메모리 모듈


메모리 모듈은 도 다른 메모리 상주 공격자 기법임.

인젝터(Injector) 또는 로더(Loader)가 DLL 매핑 자체 대신 대상 DLL 을 메모리에 매핑한다는 점을 제외하면 반사 DLL 인젝션과 유사함.

기본적으로 메모리 모듈 로더는 LoadLibrary 함수를 다수 구현하지만 디스크의 파일 대신 메모리 버퍼에서 작동함.

원래 구현은 현재 프로세스의 매핑을 위해 설계되었지만 업데이트된 기법은 모듈을 원격 프로세스에 매핑할 수 있음.

대부분의 구현은 대상 DLL 의 섹션 권한을 존중하며 시끄러운(avoid) RWX 접근 방식을 피함.


NetTraveler 악성코드는 메모리 모듈 스타일 기법을 사용하는 악성코드 제품군임.

NetTraveler 악성코드가 시작되면 핵심 기능의 압축을 풀고 이를 메모리에 매핑함.

페이지 권한은 합법적인 DLL 과 더 비슷하지만 메모리 영역은 이미지와 달리 여전히 비공개임.

활성 스레드에는 이러한 Private 영역에서 시작 주소가 있음.

콜스택(Callstack)은 또한 이러한 악성 섹션을 드러냄.

Winnti 악성코드는 메모리 모듈 기법을 사용하는 또 다른 악성코드 샘플임.

아래 스크린샷에서 볼 수 있듯이 첫 페이지의 섹션 오류에 약간의 어긋남(slip)이 있음.

그러나 Winnti 악성코드 샘플은 DLL 파일의 MZ/PE 헤더가 지워져 탐지가 더 어렵게 만드므로 주목할 만함.




Process Hollowing (일명 프로세스 교체 및 실행)


Process Hollowing 는 공격자가 보안 제품 및 분석가가 악성코드를 탐지하는 것을 방지하기 위해 사용하는 또 다른 기법임.

여기에는 일시 중단된 프로세스 생성, 프로세스에서 원래 실행 파일 매핑 해제(비우기), 프로세스에 새 페이로드 할당 및 쓰기, SetThreadContext 를 사용하여 원래 스레드 실행을 새 페이로드로 리다이렉팅(redirecting), 마지막으로 ResumeThread 호출이 포함됨.

더 많은 은밀한 변형은 Create/Map 섹션 API 를 사용하여 WriteProcessMemory 를 방지함.

다른 방안으로 SetThreadContext 를 사용하는 대신 진입점(Entry Point)를 점프하여 수정할 수 있음.


DarkComet 악성코드는 Process Hollowing 기법을 사용하는 여러 악성코드 중 하나임.

여러 아티팩트(artifact)를 사용하여 Process Hollowing 기법을 감지할 수 있음.

아래 스크린샷에서 볼 수 있듯이 DarkComet 악성코드 샘플은 CREATE_SUSPENDED 플래그로 생성되는 프로세스임.




모듈 덮어쓰기 (Module Overwriting)


지금까지 논의된 모든 기법은 이미지 기반이 아닌 코드 실행으로 이어졌으므로 감지하기가 매우 간단함.

반면에 모듈 덮어쓰기는 이러한 요구 사항을 방지하므로 감지하기가 휠씬 더 어려워짐.

이 기법은 사용하지 않는 모듈을 대상 프로세스에 매핑한 다음 자체 페이로드로 모듈을 덮어 쓰는 것으로 구성됨.

Flame 악성코드는 이 기법을 사용한 최초의 악성코드임.

최근에는 Careto 및 Odinaff 악성코드에서도 모듈 덮어쓰기 기법을 사용했음.

메모리를 디스크의 관련 데이터와 비교하는 것이 포함되어 모듈 덮어쓰기 기법을 안정적으로(reliably) 감지하기 위해 다양한 기법을 사용할 수 있음.




가고일 (Gargoyle)


가고일 기법은 많은 보안 제품의 탐지를 피할 수 있는 메모리 상주 악성코드에 대한 개념 증명 기법임.

읽기 전용 페이지 보호를 사용하여 휴면 상태를 유지함으로써 이 기능을 수행함.

그런 다음 비동기 프로시저 호출을 사용하여 주기적으로 깨어나 ROP 체인을 실행하여 페이로드로 이동하기 전에 실행 가능한 것으로 표시함.

페이로드 실행이 완료되면 Gargoyle 은 페이지 권한을 다시 마스크(mask)하고 절전 모드로 돌아감.

이 기법을 탐지하는 한 가지 방법은 ROP 체인의 증거에 대한 스레드와 사용자 APC 를 검사하는 것임.




( 2 ) 메모리 내 공격 탐지


이러한 기법의 확산과 접근성을 감안할 때 보안 담당자는 메모리 기반 공격자 기법을 경계하고 네트워크에서 사전에 이를 찾아야 함.

그러나 대부분의 제품은 대규로로 인한 메모리 공격을 일반적으로 감지할 수 없으므로 방어자는 이러한 공격으로부터 보호할 수 있는 능력에 상당한 차이가 있음.

Endgame 사는 위에서 언급한 각 방법에 대해 저잡음 감지 기능(Low-Noise Detection)을 제품에 도입하기 위해 상당한 연구를 수행했음.


이 탐지 격차의 엄청난 크기와 영향을 감안할 때 고객 뿐만 아니라 모든 보트(boat)를 높이는 것이 중용함.

이러한 이유로 우리는 메모리 위협을 탐지하는 비교적 저잡음 방법(Low-Noise Method)을 구현하는 Get-InjectionThreads 라는 파워쉘 도구에 대해 Jared Atkinson 사와 협력했음.

의심스러운 시작 주소에 대해 시스템의 활성 스레드를 스캔함.

분석가는 이를 활용하여 네트워크 호스트를 스캔하고 많은 메모리 상주 악성코드 기법을 신속하게 식별함.

스크립트는 NtQueryInformationThread 함수로 각 활성 스레드를 쿼리하여 시작 주소를 검색하는 방식으로 작동함.

그런 다음 VirtualQueryEx 함수로 시작 주소를 쿼리하여 연결된 섹션 속성을 결정함.

스레드가 시작된 메모리 영역에 백업 해제되고 실행 가능(예 : 이미지 유형이 아니고 실행 비트가 설정되어 있음)하면 스레드가 인젠셕되는 것으로 간주됨.

다음 스크린샷은 9002 RAT 악성코드 샘플에 감염된 시스템에서 실행될 때 감지된 샘플을 보여줌.


이 스크립트는 쉘코드 삽입, 반사 DLL, 메모리 모듈 및 일부 Process Hollowing 기법을 활용한 다양한 악성코드를 탐지함.

그러나 Endgame 사와 같은 인 메모리 공격(In-Memory Attack)을 포괄적으로 방지하는 보안 제품을 대체할 수 없음.




( 3 ) 대규모 엔터프라이즈 인 메모리(In-Memory) 탐지


Endgame 사는 이러한 각 기법(그 이상)에 대한 탐지 기능을 엔터프라이즈 보안 플랫품에 구축하여 인 메모리 위협(In-Memory Threat)을 찾을 수 있는 업계 최고의 기능을 제공함.

우리는 프로세스 인젠션을 위해 잘 알려진 시스템 호출 시퀀스를 모니터링하는 것과 같은 순진한 접근 방식에 의존하는 것이 아니라 메모리를 효율적으로 분석하여 알려진 모든 회피 기능을 찾음.

이를 통해 사용자는 삽입된 코드에 대한 스레드 수준 가시성을 제공할 뿐만 아니라 삽입된 코드를 검사하고 악의적으로 삽입된 스레드만 일시 중단하여 위협을 해결하는 등의 정교한 후속 조치를 제공함.

우리의 플랫폼은 실시간으로 발생하기 때문에 인젝션을 중지하고 메모리에 이미 상주하는 적을 찾아내고 수 만개의 호스트에서 위협을 몇 초만에 찾아내는 데 효과적임.


다른 시그니처없는 탐지 기법과 마찬가지로 오탐(FP)도 중요한 고려 사항임.

위에서 설명한 각 공격자의 기법에 대한 기법 기반 예방을 연구하고 구현하면서 처음에는 모든 단계에서 오탐(FP)을 확인함.

당사 제품에서 이를 올바르게 취급하는 것이 가장 중요함.


대부분의 오탐(FP)은 보안 소프트웨어, JIT(Just-In-Time) 컴파일된 코드 또는 DRM 으로 보호/패킹된 어플리케이션과 관련이 있음.

보안 제품은 행동 감지 기능을 향상시키기 위해 시스템의 일부 또는 모든 프로세스에 코드를 삽입하는 경우가 있음.

단점은 제품의 방법이 엉성한(sloppy) 경우 실제로 시스템 보안에 해를 끼치고 실제 메모리 위협을 찾기가 더 어려워질 수 있다는 것임.

오탐의 또 다른 잠재적 영역인 JIT 코드는 런타임 시 백업되지 않거나 부동 메모리 영역에 있는 어셈블리 코드를 생성함.

.NET 또는 Java 어플리케이션은 JIT 기법을 사용하는 몇 가지 예임.

다행히 이러한 유형의 코드는 악성(rogue) 보안 제품보다 식별 및 필터링이 더 쉬움.

마지막으로 DRM(디지털 권한 관리) 체제로 포장되거나 보호되는 응용 프로그램을 염두에 두어야 함.

이러한 어플리케이션은 디버깅 및 리버스 엔지니어링을 방지하기 위해 메모리의 핵심 기능을 복호화하거나 난독화할 수 있음.

그러나 악성코드는 동일한 기법을 사용하여 탐지를 회피하고 보안 전문가의 분석을 차단함.


신중한 설계 결정과 광범위한 테스트를 통해 매우 낮은 오탐률을 달성하여 Endgame 사의 고객이 메모리 위협을 빠르게 근절할 수 있도록 함.




( 4 ) 결론


공격자는 탐지를 피하고 목표를 달성하기 위해 계속해서 새로운 기법을 혁신할 것임.

메모리 상주 기법도 예외는 아니며 10년 이상 Endgame 사의 보안 제품에서 이슈가 되어 왔음.

다행히도 최신 기법을 이해함으로써 우리는 이 지식을 바탕으로 새로운 고탐지 방법을 개발할 수 있음.

Endgame 사에서는 이러한 공격에 대한 포괄적인 접근 방식을 통해 파일없는 공격 탐지 분야(다른 주요 기법에 추가)에서 시장을 선도하는 위치에 올랐음.

인 메모리 공격(In-Memory Attacks)에 대한 자세한 내용은 SANS Threat Hunting 및 IR Summit 프리젠테이션 슬라이드를 확인 바람.

프리젠테이션 슬라이드 링크 : 

https://www.slideshare.net/JoeDesimone4/taking-hunting-to-the-next-level-hunting-in-memory


댓글 없음:

댓글 쓰기