개요
비교적 최근 있었던 샘플을 분석하며 정리한 내용입니다. 고객사로 부터 악성코드가 접수됐는데, 실행이 시간이 너무 오래 걸려, 자동분석 한계시간을 초과해 분석되지 않는 이슈가 있는 샘플이었습니다. 샘플은 THOR 랜섬웨어, Locky 랜섬웨어의 변종이고 출시된진 수개월이 지났지만 여전히 활발히 활동하는 랜섬웨어 중 하나입니다. Malwares.com 보고서 에서 이번 분석에 사용한 샘플의 해쉬 및 기타 정보를 확인할 수 있습니다.
이런 종류의 대응업무는 대게 분석시간이 빠듯합니다. 보통 세시간, 늦어도 당일 내에 만족할만한 결과를 뱉어내야하죠. 하다보니 느는건 꼼수라고, 샘플을 받으면 의심가는 API 에 대충 BP부터걸고 시작합니다.
하지만 샘플들이 어디 호락호락한가요, 이 샘플은 kernel32.dll 의 어떤 외부함수에도 BP가 적중하지 않았습니다. 조금 자세히 살펴보니 INT 2E 를 활용해 Native API를 바로 호출하더군요. 이번엔 이 악성코드에서 사용한 Native API 호출방법에 대해 알아보겠습니다.
분석 과정
어떤 샘플이든 분석 범위를 좁히고 출발하는게 좋습니다. 대충의 행위를 알아둬야 살펴봐야 할 대상도 좁힐 수 있기 떄문입니다. 이 샘플은 자식프로세스를 생성하고 자식에 이미지스위칭을 통해 악성 행위를 수행합니다.
일반적으로 프로세스 생성하면 CreateProcessInternalW()
가 떠오릅니다. CreateProcessA()
든 CreateProcessW()
든 종국에는 이 함수를 호출하기에 프로세스를 생성하는 악성코드를 분석할때 BP 걸기 좋은 API입니다.
일반적으로 자식프로세스 생성을 통한 이미지스위칭은 다음의 절차를 거칩니다.
- 프로세스 생성(SUSPENDED)
- 컨텍스트 백업
- 원본 메모리 영역 해제
- 스위칭 메모리영역 할당
- 쉘코드 기록
- 컨텍스트 수정
- 프로세스 재개
따라서 프로세스 생성을 잡으면 근처에서 쉘코드 기록하는 부분을 쉽게 찾을 수 있고, 쉘코드 기록부분을 잡으면, 변수값을 통해 파일오프셋으로 존재하는 원본 이미지를 쉽게 덤프 뜰 수 있습니다.
이 과정에서 사용할 법한 API를 나열해보면 VirtualAllocEx() GetThreadContext() SetTHreadContext() WriteProcessMemroy() ResumeThread()
등이 떠오릅니다. 하지만 여기에 BP걸고 잘 분석했으면 이 글을 쓰지 않았겠죠…
조금 더
분석에 시간을 잡아먹다가 아래와 같은 형태 INT 2E 명령어를 확인했습니다. 익숙하지 않은 사람에겐 CALL 도 아니고 API로 JMP 하는것도 아닌데 뭐가 중요하냐고 할 수 있지만, 이 부분은 Interrupt 를 일으켜 커널모드로 진입하는 코드입니다.
API를 Trace Into 로 끝없이 따라가다보면, ntdll.dll 같은 모듈에서 SYSENTER 가 호출되고, 더 이상 Trace Into 되지 않은 경험. 한번쯤 있으셨을 겁니다. 그와 비슷한 역할이라 생각하시면 됩니다. 실제로 ntdll!NtWriteVirtualMemory
의 코드를 확인해 보면 아래와 같은 명령어를 볼 수 있습니다.
EAX 에 0x115 를 대입하고, EDX 에 ESP 를 대입한 후 SYSENTER 를 호출하는 것이 보입니다. 여기서 EAX 는 어떤 Native API 를 호출하는지, 찾을 때 쓰이고, EDX 는 해당 API 가 호출될 때 사용될 스택프레임 포인터로 쓰입니다. 여기서 검색해보면 실제로 EAX=0x115 일때 어떤 함수를 호출하는지 쉽게 검색할 수 있습니다.
다시 한번 정리하자면, INT 2E 가 실행 될 때 EAX 와 EDX 를 통해 어떤 Native API를 호출하는지 알 수 있다 고 하겠습니다.
Native API 검색
NtWriteVirtualMemroy()
호출 부분을 찾았으나, 아직 무슨 역할의 함수인지 명확히 구분되지 않습니다. ntdll.dll 의 함수는 Undocumented 인 상태도 많아 MSDN 검색이 안될 수도 있습니다. 이름으로 충분히 유추할 수 있긴 하지만, 정확한게 좋으니까요.
Process Hacker 에 각종 헤더파일이 잘 문서화 되어있습니다. 분석 뿐 아니라 프로그래밍에도 요긴하게 쓰입니다. 직접 문서 페이지에 접속하는 것 보단, 원하는 API명 혹은 헤더파일명과 process hacker 를 키워드로, 같이 구글링하면 더 쉽게 접근할 수 있습니다.
아니면 IDA 로 ntoskrnl.exe 를 열면 됩니다. ntoskrnl.exe 는 실제 커널함수가 구현돼있는 파일입니다. IDA 가 알아서 심볼서버를 긁어와서 보기도 쉬울 뿐더러, 변수가 실제로 어떤식으로 사용되는지도 파악할 수 있습니다.
결론
이렇게 찾은 NtWriteVirtualMemory()
함수는 원격프로세스 메모리에 데이터를 기록하는 것은 맞지만, 이 악성코드는 PE 이미지가 아닌 PEB 를 조금 수정하는데 사용했습니다. 실제로 이미지를 쓸 땐 WriteProcessMemory()
도, NtWriteVirtualMemory()
도 아닌 또 다른 방법을 사용했습니다. 기회가 된다면 이 방법에 대해서도 포스트를 작성토록 하겠습니다.
이번에도 누군가에겐 도움이 되었길 바라며, 피드백은 언제나 환영합니다.
1 Comment