서문
Elastic Security Labs는 위협 헌팅 파이프라인과 원격 분석 대기열을 통해 유입되는 다양한 멀웨어를 분석합니다. 최근 RHADAMANTHYS 인포스틸러와 함께 발견된 새로운 멀웨어 제품군인 DOUBLELOADER를 발견했습니다. 더블로더의 흥미로운 특성 중 하나는 2023년에 처음 출시된 오픈 소스 난독화기인 ALCATRAZ로 보호된다는 점입니다. 이 프로젝트는 게임 해킹 커뮤니티에 뿌리를 두고 있지만, 전자 범죄 분야에서도 관찰되고 있으며 표적 침입에 사용되기도 합니다.
이 게시물의 목적은 악성코드 분석가로서 알카트라즈가 사용하는 다양한 난독화 기법을 살펴보고 이러한 기법에 대응할 수 있는 방법을 강조하는 것입니다. 이러한 기술에는 제어 흐름 평탄화, 명령어 변이, 상수 전개, LEA 상수 숨김, 분해 방지 트릭 및 진입점 난독화 등이 있습니다.
핵심 사항
- 오픈 소스 난독화 도구인 알카트라즈는 라다만티스 감염과 함께 유포되는 새로운 멀웨어에서 발견되었습니다.
- 제어 흐름 평탄화와 같은 난독화 기술은 분석가에게 계속해서 장애물로 작용합니다.
- 난독화 기법과 이에 대응하는 방법을 이해함으로써 조직은 보호된 바이너리를 효과적으로 분류하고 분석하는 능력을 향상시킬 수 있습니다.
- 엘라스틱 보안 연구소에서 ALCATRAZ 보호 바이너리의 난독화를 해제하는 도구가 이 포스팅과 함께 릴리즈되었습니다.
더블로더
작년 12월부터 저희 팀은 일반적인 백도어 멀웨어와 라다만티스 스틸러 감염이 결합된 것을 관찰했습니다. PDB 경로를 기반으로 이 멀웨어는 스스로를 더블로더라고 설명합니다.
이 멀웨어는 Windows 데스크톱/파일 관리자(explorer.exe) 내에서 백업되지 않은 코드를 실행하는 NtOpenProcess, NtWriteVirtualMemory, NtCreateThreadEx 과 같은 시스템 호출을 활용합니다. 멀웨어는 호스트 정보를 수집하고, 자신의 업데이트된 버전을 요청하고, 바이너리에 저장된 하드코딩된 IP(185.147.125.81)로 비콘을 보내기 시작합니다.
더블로더 샘플에는 실행 권한이 있는 비표준 섹션(.0Dev)이 포함되어 있으며, 이는 바이너리 난독화 도구에 대한 작성자의 핸들에 따라 남겨진 툴마크입니다, ALCATRAZ.
알카트라즈와 같은 난독화 도구는 멀웨어를 선별할 때 복잡성을 증가시킵니다. 주요 목표는 제어 흐름을 숨기거나 디컴파일을 어렵게 만드는 등 다양한 기법을 통해 바이너리 분석 도구를 방해하고 리버스 엔지니어링 프로세스의 시간을 늘리는 것입니다. 아래는 더블로더 내부의 한 함수에 대한 난독화된 제어 흐름의 예시입니다.
이 글의 나머지 부분에서는 알카트라즈에서 사용하는 다양한 난독화 기술에 대해 집중적으로 다룰 예정입니다. 더블로더의 첫 번째 단계와 기본 코드 예제를 사용하여 ALCATRAZ의 기능을 강조하겠습니다.
알카트라즈
알카트라즈 개요
알카트라즈는 2023년 1월에 처음 출시된 오픈소스 난독화 프로그램입니다. 이 프로젝트는 게임 해킹 커뮤니티에서 난독화 기술을 배우기 위한 기본 도구로 인정받고 있지만, 전자 범죄 및 APT 그룹에서 악용하는 경우도 관찰되고 있습니다.
알카트라즈의 코드 베이스에는 표준 코드 난독화 기술을 중심으로 한 5 주요 기능과 함께 엔트리포인트 난독화를 위한 개선 사항이 포함되어 있습니다. 워크플로는 표준 bin2bin 형식을 따르며, 이는 사용자가 컴파일된 바이너리를 제공하면 변환 후 새로 컴파일된 바이너리를 받는다는 의미입니다. 이 접근 방식은 소스 코드 수준에서 최소한의 노력과 수정이 필요 없는 사용 편의성 때문에 게임 해커/멀웨어 개발자에게 특히 매력적입니다.
개발자는 전체 또는 특정 기능을 난독화하도록 선택할 수 있을 뿐만 아니라 각 기능에 적용할 난독화 기술을 선택할 수도 있습니다. 컴파일 후 파일 이름 끝에 문자열(obf)이 추가되어 파일이 생성됩니다.
ALCATRAZ의 난독화 기술
다음 섹션에서는 알카트라즈에서 구현하는 다양한 난독화 기법에 대해 설명합니다.
진입점 난독화
난독화된 진입 지점을 처리하는 것은 가족 여행을 시작할 때 타이어가 펑크 나는 것과 같습니다. 이 아이디어는 분석가에게 혼란을 주고 프로그램이 시작되는 위치가 명확하지 않은 이진 도구에 중점을 두고 있어 분석 프로세스를 시작할 때 혼란을 야기합니다.
다음은 IDA Pro 내에서 난독화되지 않은 프로그램의 깨끗한 엔트리포인트(0x140001368)의 보기입니다.
진입점 난독화를 활성화하면 ALCATRAZ는 진입점을 이동한 다음 프로그램의 새 진입점을 계산하는 알고리즘이 포함된 추가 코드를 포함합니다. 아래는 난독화된 진입점의 디컴파일된 보기의 일부입니다.
ALCATRAZ는 오픈 소스 난독화 도구이므로 사용자 정의 엔트리포인트 코드를 찾아 계산이 어떻게 수행되는지 확인하거나 자체 난독화된 예제를 역으로 확인할 수 있습니다. 디컴파일에서 알고리즘이 Size of the Stack Commit, Time Date Stamp 과 같은 PE 헤더의 몇 가지 필드와 .0dev 섹션의 처음 4바이트를 사용하는 것을 볼 수 있습니다. 이러한 필드는 구문 분석된 다음 오른쪽으로 회전(ROR) 및 배타적 또는(XOR)과 같은 비트 연산과 함께 사용되어 진입점을 계산합니다.
아래는 난독화되지 않은 샘플로 원래 시작점(0x140001368)을 확인하여 PE를 구문 분석하고 실제 진입점을 찾는 IDA Python 스크립트(부록 A)의 출력 예시입니다.
분해 방지
멀웨어 개발자와 난독화자는 정적 분석을 더 어렵게 만들기 위해 디스어셈블러를 혼란스럽게 하거나 깨뜨리는 디스어셈블리 방지 트릭을 사용합니다. 이러한 기법은 선형 스윕 및 재귀적 분해 중에 약점을 악용하여 분석가가 기본 명령어를 수동 또는 자동으로 수정해야 하는 깔끔한 코드 재구성을 방지합니다.
ALCATRAZ는 0xFF 바이트로 시작하는 명령어 앞에 짧은 점프 명령어( 0xEB)를 추가하여 이 기법의 한 가지 형태를 구현합니다. 0xFF 바이트는 스택에서 호출, 간접 점프, 푸시를 처리하는 여러 유효한 명령의 시작을 나타낼 수 있습니다. 앞에 짧은 점프 0xEB 를 추가하면 다음 바이트 0xFF 로 효과적으로 점프합니다. 복잡하지는 않지만 분해가 필요하고 어떤 종류의 개입이 필요한 손상입니다.
이 특정 기술을 수정하기 위해 0xEB 바이트의 각 발생을 NOP로 대체하여 파일을 패치할 수 있습니다. 패치 후 코드가 깨끗한 상태로 복원되어 다음 call 명령어를 사용하여 올바르게 디스어셈블할 수 있습니다.
명령어 변이
난독화자가 사용하는 일반적인 기술 중 하나는 명령어 변이인데, 명령어를 원래 동작은 유지하되 코드를 이해하기 어렵게 변형하는 방식입니다. 타이그리스나 페르세스와 같은 프레임워크는 명령어 변이에 대한 난독화 연구의 좋은 예입니다.
아래는 알카트라즈에서 구현한 이 기법의 예시로, 두 레지스터 사이의 덧셈은 변경되지만 의미적 동등성은 그대로 유지됩니다. 간단한 add 명령어는 5 다른 명령어(push, not, sub, pop, sub)로 변환됩니다.
이 문제를 해결하기 위해 패턴 매칭을 사용하여 5 명령어를 함께 찾고, 바이트를 분해하여 어떤 레지스터가 관련되어 있는지 찾은 다음 Keystone과 같은 어셈블러를 사용하여 올바른 해당 바이트를 생성할 수 있습니다.
끊임없는 전개
이 난독화 기법은 더블로더 샘플 전체에 널리 퍼져 있으며 다양한 형태의 멀웨어에서 널리 사용되는 방법입니다. 컴파일 시점에 알려진 계산을 최적화하는 대신 난독화기가 이러한 상수를 '펼쳐서' 디스어셈블과 디컴파일을 복잡하고 혼란스럽게 만드는 컴파일 프로세스의 반전에 초점을 맞춘 개념입니다. 아래는 알려진 상수(46)를 두 개의 수학 연산으로 나누는 이 기법의 간단한 예시입니다.
더블로더에서는 즉시 값을 레지스터로 옮길 때마다 이 기술이 사용됩니다. 이러한 즉각적인 값은 이러한 상수 값을 마스킹하는 여러 비트 연산으로 대체되므로 컨텍스트와 분석가의 흐름이 방해받게 됩니다. 예를 들어, 아래 왼쪽의 분해에서 주소 (0x18016CD93)에 EAX 값의 비교 명령어가 있습니다. 이전 지침을 검토해 보면, 여러 개의 모호한 비트 단위 계산으로 인해 EAX 값이 무엇인지 명확하지 않거나 명확하지 않습니다. 프로그램을 디버그하면 EAX 값이 0 로 설정되어 있는 것을 확인할 수 있습니다.
이 난독화 기술을 정리하기 위해 다음 소스 코드를 사용하여 변환이 어떻게 적용되는지 확인할 수 있는 자체 예제를 통해 그 동작을 확인할 수 있습니다.
#include <iostream>
int add(int a, int b)
{
return a + b;
}
int main()
{
int c;
c = add(1, 2);
printf("Meow %d",c);
return 0;
}
컴파일 후 왼쪽의 클린 버전에서 main 함수의 분해를 보면 이 두 상수(2,1)가 EDX 및 ECX 레지스터로 이동한 것을 확인할 수 있습니다. 오른쪽은 변환된 버전으로, 두 상수는 새로 추가된 명령어 사이에 숨겨져 있습니다.
패턴 매칭 기술을 사용하면 이러한 명령어 시퀀스를 찾고, 명령어를 에뮬레이션하여 다양한 계산을 수행하여 원래 값을 되찾은 다음, 나머지 바이트를 NOP로 패치하여 프로그램이 계속 실행되도록 할 수 있습니다.
LEA 난독화
앞서 설명한 기법과 유사하게 LEA(로드 유효 주소) 난독화는 LEA 명령과 관련된 즉각적인 값을 모호하게 만드는 데 중점을 둡니다. 뺄셈을 사용한 산술 계산은 원래 의도한 값을 계산하기 위해 LEA 명령어 바로 뒤에 따라옵니다. 이는 사소한 변경처럼 보일 수 있지만, 효과적인 이진 분석에 필수적인 문자열과 데이터에 대한 상호 참조를 끊는 데 큰 영향을 미칠 수 있습니다.
아래는 더블로더 내에서 이 기법의 예시로, 초기값(0x1F4DFCF4F)을 로드한 다음 빼기(0x74D983C7)를 통해 새로운 계산값(0x180064B88)을 제공하는 패턴을 통해 RAX 레지스터 값을 위장하는 것입니다.
샘플 내에서 해당 주소로 이동하면 읽기 전용 데이터 섹션으로 이동하여 참조된 문자열 bad array new length 을 찾을 수 있습니다.
이 기술을 수정하기 위해 패턴 매칭을 사용하여 이러한 특정 명령어를 찾아 계산을 수행한 다음 새 LEA 명령어를 다시 구성할 수 있습니다. 64비트 모드에서 LEA는 RIP 상대 주소 지정을 사용하므로 현재 명령 포인터(RIP)를 기준으로 주소가 계산됩니다. 궁극적으로 다음과 같은 새 인스트럭션이 생성됩니다: lea rax, [rip - 0xFF827].
다음은 이 최종 지침을 생성하는 단계입니다:
이 정보를 통해 IDA 파이썬을 사용하여 이러한 모든 패턴을 패치할 수 있으며, 아래는 고정 LEA 명령어의 예시입니다.
제어 흐름 난독화
제어 흐름 평탄화는 조건부 분기 및 루프와 같은 기존 구조를 제거하여 프로그램의 제어 흐름의 기존 구조를 파괴하는 강력한 난독화 기법입니다. 대신 상태 변수에 따라 실행할 다음 기본 블록을 결정하는 중앙 집중식 디스패처를 사용하여 실행을 재구성하므로 분석 및 디컴파일이 훨씬 더 어려워집니다. 아래는 플랫화되지 않은 제어 흐름과 플랫화된 제어 흐름의 차이점을 나타내는 간단한 다이어그램입니다.
저희 팀은 DOORME와 같은 다양한 멀웨어에서 이 기법을 관찰해왔으며, 이 경우 평탄화된 제어 흐름이 ALCATRAZ 난독화기의 주요 기능 중 하나라는 것은 놀라운 일이 아닐 것입니다. 평탄화 해소에 접근하기 위해 보안 연구원 보리스 바튜가 작성한 IDA 플러그인 D810을 사용하여 기존 툴링에 집중했습니다.
버퍼 오버플로우를 감지하는 데 사용되는 일반적인 _security_init_cookie 함수를 사용하는 이전 예제 프로그램부터 시작하겠습니다. 아래는 쿠키 초기화 함수의 제어 흐름도를 난독화되지 않은 형태로 나타낸 것입니다. 그래프를 보면 6개의 기본 블록과 2개의 조건부 브랜치가 있으며, 실행 흐름을 쉽게 따라갈 수 있습니다.
동일한 함수에 ALCATRAZ의 제어 흐름 평탄화 기능을 적용하면 22 기본 블록, 8 조건부 브랜치, 새로운 디스패처를 통해 프로그램의 제어 흐름이 크게 달라집니다. 아래 그림에서 색으로 채워진 블록은 난독화되지 않은 버전의 이전 기본 블록을 나타내고, 흰색으로 표시된 나머지 블록은 디스패치 및 실행 제어에 사용되는 추가된 난독화 코드를 나타냅니다.
디컴파일을 살펴보면, 이제 함수가 while 루프 내에서 여러 부분으로 나뉘어져 있고, 새로운 state 변수가 popf/pushf 명령어를 포함한 난독화 잔여물과 함께 프로그램을 안내하는 데 사용되는 것을 볼 수 있습니다.
이 기능을 정리하기 위해 D810은 마이크로코드 변환을 적용하여 디컴파일을 개선하는 두 가지 규칙(UnflattenerFakeJump, FixPredecessorOfConditionalJumpBlock)을 적용합니다.
2025-04-03 15:44:50,182 - D810 - INFO - Starting decompilation of function at 0x140025098
2025-04-03 15:44:50,334 - D810 - INFO - glbopt finished for function at 0x140025098
2025-04-03 15:44:50,334 - D810 - INFO - BlkRule 'UnflattenerFakeJump' has been used 1 times for a total of 3 patches
2025-04-03 15:44:50,334 - D810 - INFO - BlkRule 'FixPredecessorOfConditionalJumpBlock' has been used 1 times for a total of 2 patches
디컴파일러를 새로 고치면 제어 흐름 평탄화가 제거되고 의사 코드가 정리됩니다.
이는 좋은 예이지만, 제어 흐름 난독화를 수정하는 것은 종종 기능에 따라 수동적이고 시기적절한 프로세스가 될 수 있습니다. 다음 섹션에서는 우리가 배운 몇 가지 기술을 모아 더블로더에 적용해 보겠습니다.
더블로더 기능 청소하기
멀웨어의 난독화를 다룰 때 어려운 점 중 하나는 개별 난독화 기술이 아니라 기술이 계층화되어 있는 경우입니다. 또한 더블로더의 경우 코드의 상당 부분이 경계가 모호한 함수 청크에 배치되어 있어 분석하기가 어렵습니다. 이 섹션에서는 알카트라즈에서 보호하는 더블로더 기능의 청소 프로세스를 보여주는 실제 사례를 살펴봅니다.
Start 내보내기에서 시작하면 첫 번째 호출 중 하나가 loc_18016C6D9 으로 연결됩니다. 이것은 더 큰 함수에 대한 항목으로 보이지만 0x18016C8C1 에서 정의되지 않은 지침으로 인해 IDA가 함수를 제대로 만들 수 없습니다.
이 주소로 스크롤하면 앞서 블로그 게시물(EB FF)에서 살펴본 숏 점프 분해 방지 기술로 인해 첫 번째 중단이 발생하는 것을 확인할 수 있습니다.
6 같은 기법의 근처 발생을 수정한 후 시작 주소(0x18016C6D9)로 돌아가서 MakeFunction 기능을 사용할 수 있습니다. 이 함수는 디컴파일되지만 여전히 심하게 난독화되어 있어 분석에 적합하지 않습니다.
다시 분해로 돌아가서, 아래에서 이 함수에 사용된 LEA 난독화 기법을 보면 문자열 상수 ”Error” 가 이전 솔루션을 사용하여 복구된 것을 확인할 수 있습니다.
아래의 또 다른 예는 lpIconName 매개변수가 0x7f00 (IDI_APPLICATION)로 정리되는 LoadIcon 호출에 대한 난독화된 매개변수의 변환을 보여줍니다.
이제 디컴파일이 개선되었으므로 D810 플러그인을 사용하여 제어 흐름 난독화를 제거하여 정리를 마무리할 수 있습니다. 아래는 효과 전후를 보여주는 데모입니다.
이 섹션에서는 알카트라즈로 보호되는 악성 난독화 기능을 제거하는 실제 작업 시나리오를 다루었습니다. 멀웨어 분석 보고서에는 최종 결과가 표시되는 경우가 많지만, 제대로 분석할 수 있도록 난독화를 제거하고 바이너리를 수정하는 데 상당한 시간이 소요되는 경우가 많습니다.
IDA 파이썬 스크립트
저희 팀은 알카트라즈 난독화기에 의해 부과된 기본 난독화 기술을 처리하는 데 사용되는 일련의 개념 증명 IDA Python 스크립트를 공개하고 있습니다. 이는 이러한 기술을 다룰 때 기본적인 예시를 제공하기 위한 것으로, 연구 목적으로만 사용해야 합니다. 안타깝게도 난독화를 처리하는 데 있어 만병통치약은 없지만, 몇 가지 예시와 일반적인 전략은 향후 유사한 문제를 해결하는 데 유용할 수 있습니다.
YARA
Elastic Security는 이 활동을 식별하기 위해 YARA 규칙을 만들었습니다.
관찰
이 연구에서는 다음과 같은 관찰 가능성에 대해 논의했습니다.
| 관측 가능합니다. | 유형 | 이름 | 참조 |
|---|---|---|---|
3050c464360ba7004d60f3ea7ebdf85d9a778d931fbf1041fa5867b930e1f7fd | SHA256 | DoubleLo.dll | 더블로더 |
참고 자료
위의 조사에서 참조한 내용은 다음과 같습니다:
