보안 솔루션의 차세대 AI 및 머신 러닝 구성 요소는 행동 기반 탐지 기능을 지속적으로 개선하고 있지만, 그 핵심은 여전히 시그니처 기반 탐지에 의존하고 있습니다. Cobalt Strike는 출시 이후 위협 행위자와 레드팀 모두가 사용하는 인기 있는 레드팀 지휘 및 통제(C2) 프레임워크로, 여전히 보안 솔루션의 집중적인 시그니처 탐지 대상입니다.
과거의 Cobalt Strikes 운영 사용을 계속하기 위해 IBM X-Force Red Adversary Simulation 팀은 상당한 연구 개발 노력을 투자하여 내부 툴로 Cobalt Strike를 맞춤화했습니다. 일부 Cobalt Strike 전용 내부 도구에는 'InlineExecute-Assembly', 'CredBandit', 'BokuLoader' 같은 공개 버전이 있습니다. 지난 2년간 Cobalt Strike에 대한 과도한 시그니처 탐지로 인해, 저희는 이를 덜 정교한 위협 행위자 시뮬레이션에만 사용하도록 제한하고, 보다 진보된 레드팀 훈련 수행 시에는 다른 제3자 및 자체 개발 C2를 활용합니다.
연구 개발 노력을 통해 저희는 다음과 같은 고급 레드 팀 훈련에서 더 나은 운영 성공을 거두었습니다.
그러나 여전히 많은 수의 위협 행위자가 Cobalt Strike의 해적판 사본을 악용하고 있으며, 이러한 위협 행위자를 시뮬레이션할 수 있는 능력은 여전히 중요합니다. 연구 및 개발 노력을 기울이려는 레드 팀의 경우 이러한 적들을 시뮬레이션하는 동시에 Cobalt Strike를 사용하여 운영상의 성공을 거둘 수 있습니다. 또한 Cobalt Strike는 훌륭한 학습 도구로, 초보자가 레드 팀 교육 과정을 통해 C2 프레임워크를 직접 사용해 볼 수 있는 데 활용할 수 있습니다.
C2 기능을 지속적으로 확장하면서, 특히 맞춤형 반사 로더를 개발하여 과거에 Cobalt Strike 프레임워크를 구축한 방법에 대한 인사이트를 공유하고자 합니다. 또한 방어자가 Cobalt Strike가 어떻게 작동하여 보다 강력한 탐지를 생성하는지 이해할 수 있도록 하기 위한 것입니다.
Think 뉴스레터를 통해 AI, 자동화, 데이터 등 가장 중요하고 흥미로운 업계 동향에 대한 최신 소식을 받아보세요. IBM 개인정보 보호정책을 참조하세요.
이 블로그 게시물은 Cobalt Strike 반사 로더 개발의 기본 사항을 다루는 입문서 역할을 하는 시리즈의 첫 번째 게시물입니다. 이 시리즈를 진행하면서 이 기반을 바탕으로 이 게시물을 참조할 것입니다.
이 시리즈가 끝날 무렵에는 Cobalt Strike의 기존 회피 기능과 통합되고 현재 도구에 없는 고급 기술로 이를 개선하는 반사 로더를 만드는 것을 목표로 하고 있습니다. 향후 게시물에서는 특정 회피 기능의 개발과 이를 Cobalt Strike 반사 로더에 구현하는 방법에 대해 더 자세히 알아볼 것입니다.
시작하기에 앞서 이 게시물이 다루는 내용은 다음과 같습니다.
공격형 보안 도구 개발자의 관점에서 Cobalt Strike의 반사 로딩을 살펴보며 탐지 및 회피 기회를 중점적으로 살펴보겠습니다. 일부 개발 측면은 생략되거나 간소화되므로 기존 반사 로더 프로젝트를 디버깅하거나, 처음부터 다시 빌드하거나, 교육을 통해 격차를 메우는 것이 좋습니다.
Cobalt Strike C2 임플란트인 비콘은 Windows 동적 링크 라이브러리(DLL)이며, Cobalt Strike에서 자체 DLL 로더를 사용하는 모듈식 기능은 사용자 정의 반사 로더(UDRL) 로 알려져 있습니다.
일반적으로 기본 제공 Windows DLL 로더는 DLL을 프로세스의 가상 메모리 공간에 로드하는 역할을 합니다. Windows DLL 로더는 주로 사용자 공간 내에 존재하지만, 디스크에서 DLL을 매핑할 때 커널 공간으로 넘어가기도 합니다.
Windows DLL 로더를 사용하면 적대적 시뮬레이션 중에 사용할 때 다음과 같은 몇 가지 단점이 있습니다.
따라서 Windows DLL 로더를 사용하여 비콘 DLL을 로드하는 것은 이상적인 해결책이 아닙니다. 이러한 문제를 극복하기 위해 저희는 반사 로더를 사용하여 메모리에서 Beacon DLL을 로드합니다.
반사 로딩이 회피하는 세 가지 주요 탐지 지점은 다음과 같습니다.
반사 로딩은 파일 시스템에서 DLL을 로드하는 것과는 달리 메모리에서 직접 DLL을 로드하는 것으로 생각할 수 있습니다.
반사 로딩과 Windows에 내장된 DLL 로더는 모두 원시 파일 형식에서 프로세스의 가상 메모리 공간으로 DLL을 로드하는 동일한 목적을 수행합니다. 하지만 반사 로딩은 Windows DLL 로더에 비해 DLL 파일이 파일 시스템에 존재할 필요가 없다는 중요한 장점을 가지고 있습니다. 이 인메모리 로딩을 통해 C2 임플란트 DLL이 프로세스 메모리 내의 암호화 및 인코딩 계층 내에 숨겨질 수 있으므로 체인 로딩 단계를 무제한으로 수행할 수 있습니다.
DLL을 로드할 때 이해해야 할 핵심 개념은 DLL이 디스크에서 포맷될 때와 인메모리에서 포맷될 때 다르게 포맷된다는 점입니다. 원시 파일 형식의 DLL과 가상 주소 형식의 주요 차이점은 다음과 같습니다.
원본 파일 형식:
가상 주소 형식:
Aleksandra Doniec의 PE-Bear 도구에서 HTTP 비콘 DLL을 살펴봄으로써 DLL의 각 섹션에 대한 원시 주소와 가상 주소의 차이점을 확인할 수 있습니다.
Beacon DLL의 각 섹션에 대한 원시 주소와 가상 주소를 나열한 테이블.
이 HTTP/S 비콘 DLL은 프로세스의 가상 메모리 공간에 로드될 때 크기가
PE-Bear는 원시 파일 형식과 가상 주소 공간 형식으로 존재하는 비콘 DLL의 시각적 표현을 제공합니다.
비콘 DLL의 원시 형식(왼쪽)과 가상 형식(오른쪽)의 시각적 표현
적대적 시뮬레이션 중에 수행하는 것이 가장 현명한 방법은 아니지만, 난독화가 없는 원시 비콘 DLL을 디스크에 배치하고 Windows DLL 로더로 로드하는 것은 비콘과 DLL 로딩을 모두 이해할 수 있는 좋은 방법입니다. 본질적으로 비콘은 그냥 DLL일 뿐입니다. Windows DLL 로더와 반사 로더는 DLL을 프로세스에 로드하기만 하면 됩니다.
Windows DLL 로더를 사용하여 비콘 DLL을 로드하려면 다음 단계를 수행합니다.
LoadLibrary
API를 사용합니다.먼저, Windows DLL 로더에서 비콘 DLL을 불러올 수 없게 하는 모든 Malleable PE 옵션을 비활성화합니다. 이를 위해 Malleable C2 프로파일을 수정하고 스테이지 블록에 있는 Malleable PE 회피 옵션을 비활성화합니다.
Cobalt Strike 회피 기능을 비활성화하도록 수정된 Malleable C2 프로파일 스테이지 블록.
프로파일을 수정한 후 Cobalt Strike Team Server를 다시 시작하여
Cobalt Strike 클라이언트를 사용하여 Team Server에 연결합니다. 그런 다음, 아웃풋 옵션으로
Cobalt Strike Client에서 '원시 스테이지리스(raw stageless)' 비콘 DLL을 생성하는 스크린샷
아래 코드를 사용하여
Windows DLL 로더를 사용하여 디스크에서 비콘 DLL을 로드하는 Windows C 코드입니다.
저희는
로딩 프로세스의 일부로, Windows DLL 로더는 비콘 DLL의 진입점을 호출합니다. 이때
Windows DLL 로더가 비콘 DLL을 프로세스의 가상 메모리 공간에 로드하고 초기화한 후에는 다음 인수를 사용하여 가상 비콘 DLL의 진입점을 다시 호출해야 합니다.
저희 프로그램은 가상 비콘 DLL을 실행하기 위해 가상 비콘 DLL의 진입점을 알아야 합니다. 이는 진입점 상대 가상 주소(RVA)에 대한 가상 비콘 DLL의 헤더를 구문 분석하여 프로그램 내에서 동적으로 수행하거나, 정의를 빠르게 살펴보고 값을 하드코딩할 수 있습니다.
개념 증명을 위해 저희는 비콘 DLL의 진입점 RVA를 수동으로 발견하고 프로그램에 하드코딩합니다. PE-Bear를 사용하여 RVA에서 비콘으로의 진입점은 다음과 같다는 것을 발견했습니다.
PE-Bear를 사용하여 비콘 DLL 진입점 RVA를 찾는 스크린샷
그리고
코드가 준비되면 C 프로그램을 Windows 실행 파일로 컴파일합니다.
프로그램을 컴파일하는 데 사용되는 명령.
비콘 DLL과 실행 가능한 비콘 로더 프로그램을 동일한 디렉토리에 배치함으로써 Windows DLL 로더는 로딩 루틴을 수행할 때 DLL을 검색할 수 있습니다.
저희는
비콘 DLL과 로더 프로그램은 같은 디렉터리에 배치되어 있습니다.
Windows 바탕 화면에서 loadBeaconDLL.exe 프로그램을 두 번 클릭하고 저희 팀 서버에 활성 비콘 연결을 설정합니다.
Windows DLL 로더를 사용하여 로드된 비콘 DLL에서 C2 Team Server에 성공적으로 연결되었습니다.
Cobalt Strike는 Stephen Fewer의 Reflective Loader 프로젝트를 수정하여 사용합니다. 이 전설적인 인메모리 DLL 로더는 10년이 넘었으며 Metasploit 및 기타 유명한 공격용 보안 도구에 사용되었습니다.
수년에 걸쳐 Cobalt Strike 반사 로더는 Cobalt Strike가 제공하는 모든 Malleable PE 회피 기능을 처리하도록 개선되었습니다. 사용자 정의 사용자 정의 반사 로더(UDRL)를 사용할 때의 가장 큰 단점은 Malleable PE 회피 기능이 즉시 지원되거나 지원되지 않을 수 있다는 것입니다.
일부 회피 기능은 UDRL을 사용할 때 완전히 구현되며, 비콘 페이로드 생성 시 Cobalt Strikes Malleable PE 엔진에 의해 비콘 DLL에 패치됩니다. 그러나 현재 같은 기능을 UDRL에서 처리해야 하지만, 및 같은 다른 기능들은 적절한 UDRL 통합을 통해 비콘에서 처리할 수 있습니다.
원래 반사 로더 프로젝트는
그러면 다른 프로젝트가 다음 단계를 담당합니다.
가상 메모리에 DLL을 로드하는 원본 반사 로더의 다이어그램.
다른 방법은 DLL에 반사 로더를 미리 추가하는 것입니다. 이렇게 하면 관리되지 않는 모든 DLL을 로드할 수 있으며 소스 코드에서 DLL을 컴파일할 필요가 없습니다. 이는 강력한 반사 로딩 방식으로, 모든 PE 파일(EXE 또는 DLL)을 로드할 수 있습니다.
DLL에 추가된 반사형 로더가 가상 메모리에 DLL을 로드하는 다이어그램.
Cobalt Strike의 반사 로딩 구현은 위의 두 가지 방법을 혼합하여 사용합니다. 이 반사 로딩 방법은 Metasploit의 Meterpreter가 반사 로딩을 수행하는 방법에 대한 지식이 있는 사람들에게 익숙할 수 있습니다.
원래 반사 로더 방식과 마찬가지로,
UDRL이 Cobalt Strike에 로드되고 운영자가 Cobalt Strike 클라이언트에서 비콘 페이로드를 생성하면, Cobalt Strike의 Malleable PE 엔진은 다음의 원시 파일 오프셋에 있는 반사 로더 셸코드에서 패치를 진행합니다:
Malleable PE 엔진이 원시 비콘 DLL의 패치를 완료하면, 원시 비콘 DLL은 실행 가능한 셸코드와 유사한 형식으로 운영자에게 제공됩니다.
비콘 DLL을 가상 메모리에 로드하는 Cobalt Strike 반사 로더의 다이어그램.
PE-Bear 디스어셈블러의 초기 바이트를 살펴보면 비콘 DLL 자체가 실행 가능하다는 것을 알 수 있습니다.
실행 가능한 어셈블리 작업 코드로 표시되는 호출 반사 로더 스텁.
초기 바이트
선택적으로 앞에 추가된
원시 파일 오프셋(
PE-bear를 사용하여 ReflectiveLoader 내보내기의 원시 파일 오프셋을 결정하는 스크린샷.
내보내기 디렉터리 내에 존재하므로 다음에 대한 주소는
원시 파일 오프셋(
가상 및 원시 주소(
비콘 DLL의 .text 섹션의 원시 및 가상 주소.
이 둘의 차이점은
이를 PE-Bear에서
요약하자면, Cobalt Strike 반사 로딩 프로세스 흐름은 다음과 같습니다.
Cobalt Strike가 비콘 DLL의 반사 로딩을 수행하는 방법의 주요 단계를 보여주는 다이어그램입니다.
반사 로더는 비콘 DLL이 로드되기 전에 실행되므로 반사 로더 코드는 순수한 셸코드여야 합니다.
복잡한 셸 코드를 만드는 가장 쉬운 방법은 외부 종속성 없이 C로 작성하는 것입니다. 그런 다음 C 파일이 오브젝트 파일로 컴파일됩니다. 모든 것이 반드시 개체 파일의 섹션에 포함되어야 합니다. 마지막으로, 저희는 다음을 제거합니다:.text
Cobalt Strike의 Malleable PE 엔진은 반사 로더 오브젝트 파일에서 셸코드를 가져와서 원시 파일 오프셋의 원시 비콘 DLL에 패치하는 작업을 처리합니다.
Cobalt Strike를 활용하여 반사 로더 셸코드를 원시 비콘 DLL에 삽입하는 공격자 스크립트.
UDRL Aggressor 스크립트는 다음 단계를 수행하여 Cobalt Strike가 반사 로더 셸코드를 작성하도록 합니다.
<a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#extract_reflective_loader">extract_reflective_loader</a>Cobalt Strike Aggressor 함수가 UDRL 개체 파일을
<a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#setup_reflective_loader">setup_reflective_loader</a>Cobalt Strike Aggressor 함수는 Malleable PE 엔진을 사용하여
Cobalt Strike는 반사적 로더 개체 파일에서 .text 섹션을 추출하고, 반사적 로더 셸코드를 패치하고, 비콘 DLL 헤더에 위치한 반사적 로더 스텁을 호출하여 반사적 로더를 실행하는 작업을 대신 수행해 주었습니다.
다음은 비콘을 반사적으로 로드하기 위해 개발해야 하는 단계입니다.
메모리에서 원시 비콘 DLL의 주소를 찾는 데 사용할 수 있는 방법은 여러 가지가 있습니다. 몇 가지 방법은 다음과 같습니다.
역방향으로 추적하는 메서드를 사용할 때는 먼저 스레드의 명령어 포인터(
Intel x64 어셈블리 코드를 사용하여 RDI 레지스터에서 원시 비콘 DLL 기본 주소를 가져옵니다.
원래의 반사 로더 프로젝트는 MZ 및 PE 헤더를 역방향으로 추적합니다. 이러한 헤더는 탐지 지점이 됩니다. 이를 극복하기 위해 Cobalt Strike는
The Cobalt Strike 문서 에는
다음을 구성 시
이 바이트들은 어느 정도 고유해야 합니다. 그렇지 않으면 반사 로더가 해당 바이트를 찾을 수 없습니다. 또한 MZ 헤더의 바이트는 무작동 및 실행 가능 바이트여야 합니다. 다음과 같은 값은 사용할 수 없습니다.
이 잠재적 탐지 지점을 발견한 후 저는 원시 비콘 DLL의 기본 주소를 찾는 다르지만 유사한 방법을 개발했습니다. 이 방법은 다음에서 역방향으로 탐색할 수 있는 에그 헌터를 사용합니다:
주소
Java Malleable PE 엔진에 쉽게 액세스할 수 없기 때문에
원시 비콘 DLL에 에그를 작성하고 Cobalt Strike 스크립트 콘솔에 변경 사항을 표시하는 Aggressor 스크립트입니다.
UDRL 코드는 UDRL 스크립트에 의해 원시 비콘 DLL에 기록된 에그 값을 알고 있어야 합니다. 에그가 알려진 상태에서 에그 헌터는 아래 코드와 같이 에그의 두 인스턴스를 역방향으로 검색합니다.
64비트 에그의 두 인스턴스를 거꾸로 검색하는 에그 헌터를 위한 Intel x64 어셈블리 코드입니다.
이제 MZ 및 PE 헤더가 더 이상 사용되지 않으므로 UDRL Aggressor 스크립트에서 이를 제거할 수 있습니다.
원시 비콘 DLL의 헤더에 있는 DOS 배너의 MZ, PE 및 사용되지 않는 바이트를 마스킹하는 공격자 스크립트입니다.
원시 비콘 DLL의 기본 주소를 검색하는 또 다른 Cobalt Strike 전용 방법도 있습니다. 위에서 살펴본 바와 같이, 호출 반사 로더 스텁의 초기 바이트는 원시 비콘 DLL의 기본 주소를
디버거에서 이를 더 자세히 살펴보기 위해 비콘을 생성하고 중단점(
반사 로더를 호출하기 전에 원시 비콘 DLL 기본 주소가 RDI 레지스터에 저장되어 있는지 확인하기 위해 호출 반사 로더 스텁을 단계별로 실행하는 스크린샷.
다음은 호출 반사 로더 스텁에서 원시 비콘 DLL의 기본 주소를 가져오는 방법을 보여주는 작동 예시입니다.
RDI 레지스터에서 원시 비콘 DLL 기본 주소를 가져오기 위한 인라인 어셈블리 C 코드입니다.
원시 비콘 DLL의 기본 주소를 사용하면 이제 비콘을 프로세스의 가상 주소 공간에 로드하는 데 필요한 값을 가져올 수 있습니다.
아래 표에는 원시 비콘 DLL의 헤더에서 필요한 값, 찾을 위치 및 유형이 나열되어 있습니다.
비콘 DLL을 로드하는 데 유용한 원시 비콘 DLL 헤더의 값을 나열하는 테이블.
비콘 DLL을 로드하는 데 헤더의 모든 내용이 필요한 것은 아닙니다. 필수 값은 재포장하거나 난독화할 수 있습니다. 필요하지 않은 값은 제거하거나 무작위로 지정할 수 있습니다.
원시 비콘 DLL의 헤더에서SizeOfImagef
가상 비콘 DLL의 메모리를 할당하는 데 다양한 방법을 사용할 수 있습니다. 방법에 따라 다양한 유형의 메모리를 사용합니다. Cobalt Strike의 기본 반사 로더가 지원하는 다양한 방법은 다음과 같습니다.
가상 비콘 DLL에 대한 Cobalt Strike 메모리 할당 옵션을 보여주는 테이블.
이는 UDRL을 통해 한 걸음 더 나아갈 수 있습니다. 대신 이러한 함수의 NTAPI 버전을 사용할 수 있습니다. 또한 NTAPI 함수는 직간접적인 시스템 호출을 통해 호출될 수 있으며, 이는 회피 기능을 강화하는 데 도움이 될 수도 있고 도움이 되지 않을 수도 있습니다.
Cobalt Strike Malleable C2 프로파일에서 할당자 메서드가
프로세스에서 시스템 호출을 검색하는 방법을 보여주는 BokuLoader 프로젝트의 코드 샘플입니다.
이제 가상 비콘 DLL에 대한 메모리를 할당했으므로 원시 비콘 DLL에 있는 비콘의 섹션을 원시 파일 오프셋에서 상대적 가상 오프셋에 있는 할당된 메모리로 복사해야 합니다.
다음을 사용하여 메모리를 할당하면READWRITE의 주소와 해당 크기를 추적해야 합니다. 가상 비콘 DLL의 진입점을 호출하기 전에 섹션의 메모리 보호를 실행 가능으로 변경해야 합니다.
또한 로 메모리를 할당하면 반사 로딩 프로세스가 간소화되지만, 보안 솔루션의 탐지 가능성이 높아집니다.
다음은 BokuLoader 프로젝트의 간소화된 코드 예시로, 이를 보여줍니다.
원시 비콘 DLL에서 가상 비콘 DLL로 복사된 섹션을 보여주는 BokuLoader 프로젝트의 코드 샘플.
로딩 섹션과 관련된 몇 가지 회피 기능은 다음과 같습니다.
공개 BokuLoader 프로젝트에서 비콘 DLL의 헤더는 원시 비콘 DLL에서 가상 비콘 DLL로 복사되지 않습니다. 현재 가상 비콘 DLL의 첫 번째
또 다른 회피 기회는 UDRL Aggressor 스크립트가 섹션을 암호화하도록 하는 것입니다. 섹션은 UDRL과 UDRL Aggressor 스크립트 간에 공유되는 키를 사용하여 UDRL에 의해 메모리에서 해독될 수 있습니다.
x64 HTTP/S 비콘이 제대로 작동하려면 4개의 DLL이 필요합니다. 이러한 DLL이 현재 프로세스에 로드되지 않은 경우 반사 로더가 이를 로드해야 합니다.
네 개의 DLL은 HTTP/S 비콘 DLL의 가져오기 디렉터리에 나열됩니다.
비콘 DLL의 가져오기 디렉터리에 있는 DLL을 나열하는 PE-Bear의 스크린샷.
내장된 Cobalt Strike 반사 로더는 DLL 로딩을 위해 kernel32.LoadLibraryA API를 사용합니다.
DLL 로딩은 다양한 운영 보안 고려 사항과 함께 다양한 방법으로 달성할 수 있습니다. 몇 가지 방법은 다음과 같습니다.
프로세스에 DLL이 이미 있는 경우에도 위의 Windows API를 사용하여 DLL 기본 주소를 가져올 수 있지만, 이로 인해 원치 않는 탐지 경고가 트리거될 수 있습니다.
또는 PEB는
<a title="https://learn.microsoft.com/kr-ko/windows/win32/api/winternl/ns-winternl-peb_ldr_data" href="https://learn.microsoft.com/kr-ko/windows/win32/api/winternl/ns-winternl-peb_ldr_data">_PEB_LDR_DATA</a>
구조체에 대한 포인터를 가집니다. 내부에는 프로세스에 로드된 모든 DLL과 그 관련 정보의 연결된 목록이 있습니다(
). BokuLoader는 이를 활용하여 DLL 정보를 검색하여 불필요한 API 호출을 피할 수 있습니다.
DLL이
중첩된 반사 로딩은 반사 로더가 일반적으로 DLL을 프로세스에 등록하지 않기 때문에 DLL 종속성을 로드하는 데 쉽게 사용할 수 없습니다. DLL 외부의 코드는 반사적으로 로드된 DLL을 제대로 사용할 수 없습니다. DarkLoadLibrary 프로젝트는 커널 이미지 로드 이벤트를 트리거하지 않고 DLL을 메모리에 제대로 로드할 수 있을 수 있습니다.
InMemoryOrderModuleList를 탐색하여 로드된 DLL의 기본 주소를 확인하는 방법을 보여주는 BokuLoader 프로젝트의 코드 샘플.
필요한 DLL이 프로세스에 로드되면 가져오기 디렉터리에 나열된 API를 확인해야 합니다. 그런 다음, API 주소를 가상 비콘 DLL의 IAT(주소 가져오기 테이블)에 기록해야 합니다. 이렇게 하면 비콘이 다음과 같은 API를 호출해야 할 때 어떤 주소로 이동할지 알 수 있습니다.
가져오기 항목은 서수 또는 이름 문자열을 통해 확인해야 합니다.
아래 이미지에서 Cobalt Strike 비콘 DLL이 가져오기 항목에 서수와 이름 문자열의 조합을 사용하는 것을 볼 수 있습니다.
비콘 DLL에 대한 일부 가져오기 항목을 보여주는 PE 베어의 스크린샷은 서수로 해결해야 합니다.
내장된 Cobalt Strike 반사 로더는
API 주소를 확인하는 몇 가지 회피 방법은 다음과 같습니다.
GetProcAddress
NTDLL.LdrGetProcedureAddress
BokuLoader는GetProcAddress
그리고 는 이름 문자열과 서수를 모두 처리할 수 있습니다. 가져오기 항목에 대해 반환된 주소가 다른 DLL에 대한 전달자인 경우 BokuLoader는 로 기본 설정되어 전달자를 확인합니다.
IAT를 작성할 때 의도한 API 가상 주소가 아닌 구현한 후크 함수의 가상 주소를 작성하여 후킹을 구현할 수 있습니다. IAT의 주소가 호출될 때 예상 출력이 비콘으로 반환되는 한, 비콘으로 돌아오기 전에 추가 코드를 실행할 수 있습니다. 미래 게시물과 공개 BokuLoader 릴리스에서는 고급 회피 기능을 위해 IAT 후킹을 활용하는 방법을 보여줍니다.
최근 릴리스를 통해 공개 BokuLoader 프로젝트는 사용자 정의 구현이 있는 Cobalt Strike C2 프로파일의 Malleable PE 기능을 지원합니다. 다음에 위치한 마스킹 키를 수정함으로써BokuLoader.cna
운영 보안과 관련하여 패턴 매칭 엔진이 싱글바이트 XOR 마스크를 무차별 대입할 수 있다는 점을 아는 것이 중요합니다. 향후 게시물에서는 패턴 매칭을 극복하기 위해 비콘을 난독화하는 Cobalt Strikes Aggressor 스크립팅 기능을 사용하여 자체적인 Malleable PE 엔진을 만드는 방법을 보여줄 것입니다.
비콘 DLL에는 실행 전에 해결하고 가상 비콘 DLL의 기본 재배치 테이블에 기록해야 하는 많은 재배치 정보가 있습니다.
PE-Bear에서 볼 수 있듯이, 비콘 DLL은 기본적으로 다음과 같은 이미지 기본 주소를 가집니다:
비콘 DLL의 이미지 기본 주소를 보여주는 PE-Bear의 스크린샷.
재배치를 작성하기 전에, 가상 비콘 DLL의 기본 주소와 하드코딩된 기본 주소 간의 델타를 계산해야 합니다.
예를 들어 가상 비콘 DLL의 기본 주소가
다음으로, 기본 재배치 테이블의 각 재배치 항목에 대한 가상 주소를 결정하기 위해 하드코딩된 재배치 항목 주소에 기본 주소 델타를 추가하여 가상 비콘 DLL 내의 재배치를 결정합니다.
아래 이미지에서 비콘 재배치 항목이 리틀 엔디안 형식으로 거꾸로 작성된 것을 볼 수 있습니다.
일부 재배치 항목이 리틀 엔디안 형식으로 존재함을 보여주는 PE-bear의 스크린샷.
이 재배치 항목의 하드코딩된 주소는 다음과 같습니다:
이 주소를 기본 주소 델타에 추가하여 가상 비콘 DLL에 존재하는 재배치를 위한 다음의 가상 주소를 얻습니다.
각 재배치 항목에 대해 유형이 다음인지 확인해야 합니다
<a title="https://learn.microsoft.com/kr-ko/windows/win32/debug/pe-format" href= " https://learn.microsoft.com/kr-ko/windows/win32/debug/pe-format" > IMAGE_REL_BASED_DIR64 (0xA)</a>
. false인 경우 재배치 작성을 건너뜁니다.
가상 비콘 DLL 내에 존재하는 재배치의 가상 주소를 결정한 후에는 이를 하드코딩된 재배치 항목 주소가 있는 메모리 공간에 기록합니다.
PE 재배치 방법에 대해 자세히 알아보려면 공개 BokuLoader 프로젝트의 doRelocations 함수 코드를 확인하세요. 이 블로그 게시물을 공개하기 전에 기술적인 세부 사항을 알고 싶어하는 다른 사람들을 돕기 위해 어셈블리 코드였던 재배치 코드를 사람이 읽기 쉬운 C 코드로 변경했습니다.
비콘 실행은 세 단계로 나눌 수 있습니다.
가상 비콘 DLL에 할당한 메모리가
가상 비콘 메모리를 실행 불가능으로 할당한 경우 (
공개 BokuLoader 프로젝트에서 메모리 보호 변경은
가상 비콘 DLL의 .text 섹션을 실행 가능으로 변경하는 것을 보여주는 BokuLoader의 코드 샘플.
이러한
가상 비콘 DLL이 제대로 작동하려면 먼저 가상 비콘 DLL의 진입 지점을 호출하여 초기화해야 합니다. 첫 번째 인수는 가상 비콘 DLL의 기본 주소입니다. 두 번째 인수는
가상 비콘 DLL을 초기화하는 BokuLoader 프로젝트의 코드 샘플.
가상 비콘 DLL을 초기화한 후 가상 비콘의 진입점을 호출 반사 로더 스텁으로 반환하거나 다음을 사용하여 UDRL에서 가상 비콘 DLL의 진입점을 호출할 수 있습니다. 이때
일반적인 DLL(
<a href="https://learn.microsoft.com/kr-ko/windows/win32/dlls/dllmain">DLLMAIN</a>
에 대한 첫 번째 인수가 가상 DLL의 기본 주소임)과 달리, 비콘은 원시 비콘 DLL의 기본 주소를 기대합니다. 이 기본 주소가 제공되지 않으면 일부 Malleable PE 회피 기능이 작동하지 않을 수 있습니다.
가상 비콘 DLL을 실행하는 두 가지 방법을 보여주는 BokuLoader 프로젝트의 코드 샘플입니다.
이 블로그 게시물이 레드팀과 블루팀 모두 Cobalt Strike와 반사 로딩 프로세스를 더 잘 이해하는 데 도움이 되기를 바랍니다. 반사적 로딩을 통해 활용할 수 있는 회피 기회는 여전히 많이 있습니다. 이러한 개념에 대한 더 깊은 이해로 조직은 사이버 위협에 대한 성공적인 방어를 위해 더 잘 준비할 수 있습니다.
이 시리즈의 향후 게시물에서는 UDRL을 현재 Cobalt Strike 회피 기능과 통합하고, 공개 BokuLoader에 이미 존재하는 문서화되지 않은 회피 기능 및 아직 대중에게 공개되지 않은 고급 기능에 대해 자세히 설명합니다. UDRL 개발을 통해 Cobalt Strike 게임을 한 단계 끌어올리는 방법을 배울 수 있는 더 자세한 정보와 기술을 기대해주세요!