엔지니어링

메모리 시그니처를 이용한 코발트 스트라이크 탐지

Elastic Security에서 우리는 다양한 방법으로 위협 탐지 과제에 접근합니다. 전통적으로, 우리는 머신 러닝 모델과 행동에 초점을 맞춰왔습니다. 이 두 가지 방법은 이전에는 볼 수 없었던 Malware를 탐지할 수 있기 때문에 강력합니다. 역사적으로, 우리는 시그니처가 너무 쉽게 회피된다고 느껴왔지만, 또한 회피의 용이성이 고려해야 할 많은 요소들 중 하나일 뿐이라는 것도 인식하고 있습니다. 성능과 오탐율도 탐지 기술의 효과를 측정하는 데 중요합니다.

알 수 없는 Malware를 탐지할 수는 없지만 시그니처는 0에 근접하는 오탐율을 가지고 있으며 경보 기능의 우선 순위를 지정하는 데 도움이 되는 관련 레이블을 가지고 있습니다. 예를 들어, TrickBot 또는 REvil 랜섬웨어에 대한 경보 기능에는 잠재적으로 원하지 않는 애드웨어 변형 유형보다 더욱 즉각적인 조치가 필요합니다. 가설적으로 우리가 시그니처를 통해 알려진 Malware의 절반만 잡을 수 있다고 하더라도, 다른 이점을 고려하면, 다른 보호 장치와 계층화했을 때 이것은 여전히 큰 성공입니다. 현실적으로 우리는 훨씬 더 잘할 수 있습니다.

장기적인 가치를 제공하는 시그니처를 만드는 데 있어 한 가지 장애물은 패커와 임시 Malware 로더의 광범위한 사용입니다. 이러한 구성 요소는 시그니처 탐지를 회피하기 위해 빠르게 진화하지만 최종 Malware 페이로드가 결국 암호 해독되어 메모리에서 실행됩니다.

패커 및 로더 문제를 해결하기 위해, 인메모리 콘텐츠에 시그니처 탐지 전략을 집중할 수 있습니다. 따라서 시그니처의 저장 수명이 일 단위에서 월 단위로 연장됩니다. 이 포스팅에서는 코발트 스트라이크(Cobalt Strike)를 메모리 내 시그니처를 활용하는 예로 사용할 것입니다. 

코발트 스트라이크 시그니처

코발트 스트라이크는 레드 팀의 공격 평가 및 공격자들의 공격 시뮬레이션을 수행하는 데 널리 사용되는 프레임워크입니다. 아마도 사용 편의성, 안정성, 스텔스 기능 때문에, 훨씬 더 비열한 의도를 가진 나쁜 행위자들이 가장 좋아하는 도구이기도 합니다. 코발트 스트라이크의 엔드포인트 페이로드인 비컨(Beacon)을 탐지하는 다양한 기술이 있어왔습니다. 여기에는 백업되지 않은 스레드 및 최근에는 기본으로 내장된 명명된 파이프를 찾는 작업이 포함됩니다. 그러나 비컨의 구성성 수준 때문에 일반적으로 공개 탐지 전략을 피하는 방법이 있습니다. 여기서는 메모리 시그니처를 대체 탐지 전략으로 사용하려고 합니다.

비컨은 일반적으로 메모리에 반사적으로 로드되며 절대 직접 시그니처가 가능한 형태로 디스크에 닿지 않습니다. 또한, 비컨은 다양한 인메모리 난독화 옵션으로 구성하여 페이로드를 숨길 수 있습니다. 예를 들어, 난독화 및 절전 옵션은 특히 시그니처 기반 메모리 스캔을 피하기 위해 콜백 사이에 비컨 페이로드의 일부를 마스킹하려고 시도합니다. 시그니처를 개발할 때는 이 옵션을 고려해야 하지만, 이러한 고급 스텔스 기능으로도 비컨에 서명하는 것은 여전히 쉽습니다.

본격적으로 시작해 볼까요?

먼저 sleep_mask 옵션이 활성화되고 최신 릴리즈(참조 섹션의 해시)가 비활성화된 비컨 페이로드를 몇 개 구하는 것으로 시작합니다. sleep_mask가 비활성화된 샘플부터 시작하여 디토네이션 후 백업되지 않은 영역에서 SleepEx를 호출하는 스레드를 찾아 프로세스 해커와 함께 비컨을 메모리에서 찾을 수 있습니다.

여기에서, 분석을 위해 관련 메모리 영역을 디스크에 저장할 수 있습니다.

가장 쉬운 성공 방법은 이 영역에서 몇 개의 고유한 스트링을 선택하여 시그니처로 사용하는 것입니다. 이를 직접 보여드리기 위해 여기서는 산업 표준 도구인 yara로 시그니처를 작성할 예정입니다.

rule cobaltstrike_beacon_strings
{
meta:
    author = "Elastic"
    description = "Identifies strings used in Cobalt Strike Beacon DLL."
strings:
    $a = "%02d/%02d/%02d %02d:%02d:%02d"
    $b = "Started service %s on %s"
    $c = "%s as %s\\%s: %d"
condition:
    2 of them
}

이렇게 하면 적용 범위가 넓어지지만 sleep_mask가 활성화된 샘플을 보면 더 나은 결과를 얻을 수 있습니다. 일반적으로 MZ/PE 헤더를 찾을 수 있는 메모리를 살펴보면 다음과 같이 난독화되어 있습니다.

빠르게 살펴보니, 반복 바이트가 많이 있습니다(이 경우 0x80). 여기서 실제로 null 바이트가 기대됩니다. 이것은 비컨이 단순한 1바이트 XOR 난독화를 사용하고 있음을 나타내는 것일 수 있습니다. 확인하기 위해 CyberChef를 사용할 수 있습니다.

보시는 것처럼, 디코딩 후 "This program cannot be run in DOS mode(이 프로그램은 DOS 모드에서 실행할 수 없습니다)" 스트링이 나타나 우리의 이론을 확인해줍니다. 단일 바이트 XOR은 케케묵은 트릭 중 하나이기 때문에, yara는 실제로 xor 변경자로 네이티브 탐지를 지원합니다.

rule cobaltstrike_beacon_xor_strings
{
meta:
    author = "Elastic"
    description = "Identifies XOR'd strings used in Cobalt Strike Beacon DLL."
strings:
    $a = "%02d/%02d/%02d %02d:%02d:%02d" xor(0x01-0xff)
    $b = "Started service %s on %s" xor(0x01-0xff)
    $c = "%s as %s\\%s: %d" xor(0x01-0xff)
condition:
    2 of them
}

스캔 중 PID를 제공하여 지금까지의 yara 규칙에 대한 탐지를 확인할 수 있습니다.

하지만, 아직 끝나지 않았습니다. 비컨의 최신 버전(본 문서 기준으로 4.2)으로 샘플에서 이 시그니처를 테스트한 후 난독화 루틴이 개선되었습니다. 이 루틴은 앞서 표시된 것처럼 콜 스택에 따라 찾을 수 있습니다. 이제 다음 IDA Pro 코드 조각에 표시된 것처럼 13바이트 XOR 키를 사용합니다.


다행히 비컨의 난독화 및 절전 옵션은 스트링과 데이터만 난독화하므로 전체 코드 섹션은 시그니처를 위해 충분히 준비된 상태가 됩니다. 코드 섹션에서 어느 기능에 대해 시그니처를 개발해야 하는가라는 문제가 있지만, 이것은 이 내용만을 위한 단독 블로그 포스팅에서 다루는 게 더 좋을 것 같습니다. 현재로서는, 단지 난독화 절차에 대한 시그니처를 만들 수 있습니다. 잘 작동해야겠죠.

rule cobaltstrike_beacon_4_2_decrypt
{
meta:
    author = "Elastic"
    description = "Identifies deobfuscation routine used in Cobalt Strike Beacon DLL version 4.2."
strings:
    $a_x64 = {4C 8B 53 08 45 8B 0A 45 8B 5A 04 4D 8D 52 08 45 85 C9 75 05 45 85 DB 74 33 45 3B CB 73 E6 49 8B F9 4C 8B 03}
    $a_x86 = {8B 46 04 8B 08 8B 50 04 83 C0 08 89 55 08 89 45 0C 85 C9 75 04 85 D2 74 23 3B CA 73 E6 8B 06 8D 3C 08 33 D2}
condition:
     any of them
}

비컨이 스텔스 절전 상태(32비트 및 64비트 변형 모두)일 때에도 비컨을 탐지할 수 있는지 검증할 수 있습니다.

이를 보다 강력한 탐지로 구축하기 위해 시스템(또는 전체 엔터프라이즈)의 모든 프로세스를 정기적으로 스킨할 수 있습니다. 이 작업은 다음과 같이 파워셸 원 라이너로 수행할 수 있습니다.

powershell -command "Get-Process | ForEach-Object {c:\yara64.exe my_rules.yar $_.ID}"

결론

시그니처 기반 탐지는 종종 무시되지만 특히 인메모리 스캔을 고려할 때 중요한 탐지 전략입니다. 소수의 시그니처만으로, 0의 유효 오탐율로 활성화된 구성 또는 스텔스 기능에 관계없이 코발트 스트라이크(Cobalt Strike)를 탐지할 수 있습니다.

참조 해시

7d2c09a06d731a56bca7af2f5d3badef53624f025d77ababe6a14be28540a17a
277c2a0a18d7dc04993b6dc7ce873a086ab267391a9acbbc4a140e9c4658372a
A0788b85266fedd64dab834cb605a31b81fd11a3439dc3a6370bb34e512220e2
2db56e74f43b1a826beff9b577933135791ee44d8e66fa111b9b2af32948235c
3d65d80b1eb8626cf327c046db0c20ba4ed1b588b8c2f1286bc09b8f4da204f2

Elastic Security에 대해 자세히 알아보기

(아직 하지 않으셨다면) Elastic Agent의 강력한 보호, 탐지 및 응답 기능을 숙지해 보세요. 14일 무료 체험판을 시작하거나(신용 카드 필요 없음) 또는 무료로 제품을 다운로드하여 온프레미스로 배포하세요. 또한 빠른 시작 교육을 활용하여 성공을 위한 준비를 하세요.