All Articles

CTFZone 2023 Writeup

This page has been machine-translated from the original page.

I participated in CTFZone, which started on 8/12.

image-20230818111048893

Unfortunately, I could barely solve anything this time, but as usual I’m writing this up as a review.

Table of Contents

strcmp(Rev)

You can solve easy tasks, but do you understand how functions work?

Running the PE file provided for the challenge launched a GUI application that prompted me to enter a string, as shown below.

If you enter an incorrect password here, a warning dialog is displayed.

image-20230812190715251

I first checked how the validation worked, and it turned out to be a simple implementation like this.

image-20230812190649465

As you can see from the decompiled output, it simply compares the input string with the value of param2 using lstrcmpA.

That made me think I could easily get the flag with dynamic analysis, so I attached a debugger and found a plausible-looking string in the argument memory area.

image-20230818182056429

However, no matter how many times I tried, the string above would not pass validation as the correct input.

So I decided to take a closer look at what lstrcmpA was actually calling.

It turned out that the table entries for the library function call had been tampered with, and when lstrcmpA was called it actually jumped to the function at offset 0x1003.

image-20230818185726355

You can also confirm in the debugger that execution really jumps to the function at this offset.

image-20230818190736774

After decompiling the function at offset 0x1003 in Ghidra, I found that it compares the input against hard-coded bytes after XORing them with 0x6c, as shown below.

int FUN_00401003(char *param_1,undefined4 param_2)
{
  int iVar1;
  int iVar2;
  undefined2 *puVar3;
  undefined2 local_1c;
  undefined4 local_1a;
  undefined local_16;
  undefined4 local_15;
  undefined local_11;
  undefined4 local_10;
  undefined4 local_c;
  undefined4 local_8;
  
  iVar2 = 0;
  local_c = 0x5c043329;
  local_1a = 0x580f3339;
  iVar1 = 0;
  local_15 = 0x25d2a33;
  local_8 = 0x1f075c;
  local_10 = 0x15c4833;
  local_11 = 0x28;
  local_1c = 0x335;
  local_16 = 0x22;
  do {
    *(byte *)((int)&local_1c + iVar1) = *(byte *)((int)&local_1c + iVar1) ^ 0x6c;
    iVar1 = iVar1 + 1;
  } while (iVar1 < 0x17);
  puVar3 = &local_1c;
  if (*param_1 == (char)local_1c) {
    do {
      if (0x16 < iVar2) break;
      puVar3 = (undefined2 *)((int)puVar3 + 1);
      iVar2 = iVar2 + 1;
    } while (param_1[iVar2] == *(char *)puVar3);
    if ((iVar2 == 0x17) && (*(char *)puVar3 == '\0')) {
      return 0;
    }
  }
  iVar1 = (*DAT_00451eb0)(param_1,param_2);
  if (iVar1 == 0) {
    iVar1 = -1;
  }
  return iVar1;
}

I could have written a solver, but I was too lazy, so I just set a breakpoint on the validation routine in the debugger and obtained the correct flag like this.

image-20230812190413085

Rans00kit(Forensic)

An international company has been attacked. One of the computers has been hacked with the BlueKeep exploit. The attacker was able to gain a foothold in the system using a ring0 rootkit and has encrypted several important files. Your target: Bypass the rootkit, write a decryptor and find the flag.

Password for windows account login: ctfzone

The challenge file was provided as an OVA file.

Booting it in VirtualBox gave me a Windows 7 machine with Russian set as the system language.

I spent some time exploring the machine while struggling with the Russian UI, but I could not find any files or traces that seemed related to the ring0 rootkit.

The event logs had also been cleared, which made the investigation difficult.

Because it was described as a ring0 rootkit, I thought it might be hiding itself inside the OS and considered attaching a debugger, but I gave up because enabling debug mode and rebooting prevented the OS from starting.

To find the rootkit, I converted the file to VHDX and mounted it locally with the following commands.

mv Ransookit.ova Ransookit.tar
tar -xvf Ransookit.tar
qemu-img convert -f vmdk -O vhdx Ransookit-disk1.vmdk out.vhdx

Reference: NahamCon 2023 Writeup - Frog’s Secret Base

Next, I ran a Defender scan on the mounted folder, and it detected the following two files.

  • C:\Program Files\VMware\VMware Tools\VMware VGAuth\agony.sys
  • C:\Program Files\VMware\VMware Tools\VMware VGAuth\VGAuthCGI.exe

image-20230818094924045

While exploring the machine, the modules under C:\Program Files\VMware\VMware Tools\VMware VGAuth\ had obviously looked suspicious to me (in my defense), but I ignored them because I thought they were normally signed by VMware.

Looking again, these two files were indeed the only ones marked as hidden and also unsigned.

image-20230818100900910

Running the binary showed that it was an old rootkit program called Agony rootkit.

image-20230818104447925

Decompiling it in Ghidra shows that it is malware that installs the bundled agony.sys on the system and can perform actions such as hiding processes and files.

Tracing the logic further, it gets a handle to the agony.sys driver installed on the system and sends commands to the driver via DeviceIoControl.

image-20230818165611086

These commands appear to make agony.sys hide files and processes.

However, the challenge description says that some malware encrypted important files, but even after examining agony.sys I could not find any code that actually performed file encryption, so I got a bit stuck.

My guess was that the encryption was done by malware hidden by this rootkit, so I searched the mounted disk for other files marked as hidden, just like agony.sys.

As a result, I found a file called aliasStore and VGAuth.sys.config, which looked like an encrypted file.

image-20230818172431665

aliasStore was a .NET binary, so I decompiled it with ILSpy.

Looking at the Main function, I found that it embeds a random key generated by the KEYGEN function into the INFO value under Software\Wow6432Node\Microsoft\Active Setup\Status.

image-20230818173417212

Next, in the ENCRYPTION function, it calls the CIPHER function using the SHA256 hash of the string received as GETCIPHERKEY, generating the Key and IV and performing AES encryption in CBC mode.

image-20230818173538270

In other words, by using the information collected from the registry, you can identify the Key and IV and decrypt the encrypted file.

Using the INFO string collected from the registry hive and the decompiled result from ILSpy as-is, I created the following solver script.

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Win32;

public class Solver
{
    public static void Main()
    {
        string INFO = "HF48K!SP%hHudfQrk?*wvYvn*F-$DrooyKUdie0ZcY82OR%bW6$Mbk15hR?E@bLZ/q(TL!IGTmTXm/ZtKtqU0bNNfl(RgwjAMj9uWyQjy7)*QeTo/b)T8+wnc4*x+$wuCTKDF1XjcHs/iY&ASeYF2PPV9WSo9qr7KV9?UPjOEg+0V3ED7!fkpr+!E@Q6i5w8m84Nm=3C(KBVYl=GRO3=LHSqd-)e-z2V7FNj-+o8Hcpfqtlp$KpUCxxfqO6nFYDSe3lTXmHZx%/6p9A7kbo!KiSJe5)6HA25YWA!HSRaCPtH5+@3O=D16PH(kb*ptXSxPJhS8NzSJN8(@Lbn)MsI?B-IOFZ2dz41&&/vgt%AW7rseMGZAXvg2K0NKZD3!&*hgG-/S2HWRs8Mgd0C-A2FDY=9T1lHpONZ&KMYONGUQYPKYn34vB4!R6dHHLwoR=3DeiQWQc*7)i*1J@l2?3jogZIN3EQCopCRsM2$XhoSN&)5%y-Rx%qlnPtFZCpLL8TbguJ?KvenPQbjgZSFF=cu=n1cpxnU+cGb0oZXoBHBmCWW*Kv=7kFMgwc/)4ekIJw9K=6+A(nE/aH&ReofBnkdX%(DMhd7uu)dcjM*a3=*?BUFpfxlQ=isvSmQE22po2hVg1q5SzEUnvgVw$l37/ruLY4K?&7vBhXRr=v**+Tn%OEA9QqOR-4wL9JI&g8V+gSFYP1xRx//vDz?T3Y3dtdDzxF5@n+fG?wl(-ztl/&rG@AIJM*PIE/UCPdxJ&715k9xeOCVE1Rkx9?!x?v0zyWCEbj2sBkpHS8tCZ0(JqKe9fuPSq=MXHCGN7tD2W0CQzceBb7XU0qJn/Pw3TjBBYRAQ1fS3xQ!@INKCPO+5z/un)qVs&Wi!yA/hcOW(pqtk3Tf1FtnFsSZgujXLKx7a4AOHVzxB+&QJVJ7wKqmZ6dSfyj!/+L8+6T23EYgc&mNvCQLkzxArKhqb46g8@4J2LZZBdDs9JKdUPtdiYZQRKR4Z0b-V/unOchk0$JGvEOh=DWLLc?kmn/s%rAYCFW%luO/4I0rOSsM&64VdP9/%KAyj@qI$8Ep4T(c*deDzdWT(2vK!2%9SdAbtnf/or1dODez!bgA86Qn!324QgUK$SWbTr5Y-mlHy)F/X&WiV%AjNjo$7yyIWqm(3DfTsICWUI*%x!gUJ9@&R!N7C/nW!d8IeKLUnC@N+1PFuuP&Se-k1p1)$vQ0s2i$X3mnzL3H&yEmuHMfzqEgeXd@gSd/8MsMTY5+HzUGx+oCkOV6i8BByBj=ZxGg5*V7G/TWYVY=V?5n5bcS?ugALqlR@5ogs*Y9t4(r%-hNjB30S&R-V*iKfUvneChp3+ehw&)Bf7X-NSnK98-)oqL3cNeYIfN/o+hstWDWCPqlok?M3l0tDoBN3xEips/=tfhV8(nn4z$Y=xP/QRrt1r*=$T*&Rr4gXq+ICza7-N*bxzNFhMSXBWVBqhfoGrVM(hBg5H@o+6un3kZOG6lEYhfAU@psT91e+ygPx3WaX1gRy4VFHQiXFR*kBAL/oTUEFQwEEJnZjL4tANZnrjkCbdZx!(Nwse8DhbMiIRA-0I*%jRj*yvYF6R0y+-QJ($4FZ0LwB+fZimZSpeNtiZ-&F3UQxkrJA+C9a5r5F!97Q-tT+hJj8uys/7=tg(=oXVZrkm/6!eounO3GKAZPaHYdPg%p5?ZK!Vk%wB6bpZvdFDF1D)jft7NP?(cEsZA@Fe7R19hIR?xBj%XMaQl@l)oDHU&0w26PY5XyT!=RjaNvKM2DuQ0c!LbL@3Jg$3jmOhz0tv)mQUdL3/)(p)GgBdbNeM8m0qa2$yhzkCg-WNMq4Pf?!O+?xDk7FlVh!d8w)xUEiQimjHJ!R8fO3*zmzdF!Nxu-3-L)bmwH(amt2bkq%wpTGG0-1W?nsh+7tk5k(Pj2MYTcYF6X)m/nHa/xUNOFoImlj1ASs=u1N9G5!XwwmxuFob0SsIP4BdOD94)uFo1)+NZUTJ!?npq+lg&IB4xk6$07vD(FeCr-(1NaBf-iVSRi!Wpc78tX+RJBkpwQ";
        byte[] array = null;
        byte[] salt = new byte[1648]
        {
            180, 0, 176, 3, 205, 16, 180, 11, 183, 0,
            179, 4, 205, 16, 235, 0, 190, 102, 0, 232,
            60, 0, 190, 185, 0, 232, 54, 0, 190, 2,
            1, 232, 48, 0, 190, 85, 1, 232, 42, 0,
            235, 0, 190, 72, 3, 232, 34, 0, 191, 132,
            3, 180, 0, 205, 22, 180, 14, 60, 13, 116,
            7, 205, 16, 136, 5, 71, 235, 239, 198, 5,
            0, 160, 132, 3, 190, 100, 3, 232, 2, 0,
            235, 216, 180, 14, 183, 0, 179, 7, 138, 4,
            60, 0, 116, 7, 205, 16, 131, 198, 1, 235,
            243, 195, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 10, 13, 0, 32, 32, 32, 32, 32,
            32, 32, 32, 79, 111, 111, 111, 111, 112, 115,
            33, 32, 89, 111, 117, 114, 32, 115, 121, 115,
            116, 101, 109, 32, 104, 97, 118, 101, 32, 98,
            101, 101, 110, 32, 101, 110, 99, 114, 121, 112,
            116, 101, 100, 32, 98, 121, 32, 67, 82, 89,
            76, 73, 78, 69, 32, 82, 65, 78, 83, 79,
            77, 87, 65, 82, 69, 10, 13, 0, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
            45, 45, 45, 45, 45, 45, 45, 45, 10, 13,
            0, 32, 84, 104, 101, 32, 104, 97, 114, 100,
            32, 100, 114, 105, 118, 101, 32, 111, 102, 32,
            121, 111, 117, 114, 32, 99, 111, 109, 112, 117,
            116, 101, 114, 32, 104, 97, 118, 101, 32, 98,
            101, 101, 110, 32, 101, 110, 99, 114, 121, 112,
            116, 101, 100, 32, 119, 105, 116, 104, 32, 97,
            110, 32, 109, 105, 108, 105, 116, 97, 114, 121,
            32, 103, 114, 97, 100, 101, 10, 13, 32, 101,
            110, 99, 114, 121, 112, 116, 105, 111, 110, 32,
            97, 108, 103, 111, 114, 105, 116, 104, 109, 46,
            32, 84, 104, 101, 114, 101, 32, 105, 115, 32,
            110, 111, 32, 119, 97, 121, 32, 116, 111, 32,
            114, 101, 115, 116, 111, 114, 101, 32, 121, 111,
            117, 114, 32, 100, 97, 116, 97, 32, 119, 105,
            116, 104, 111, 117, 116, 32, 97, 32, 115, 112,
            101, 99, 105, 97, 108, 10, 13, 32, 101, 110,
            99, 114, 121, 112, 116, 105, 111, 110, 32, 107,
            101, 121, 33, 32, 89, 111, 117, 32, 99, 97,
            110, 32, 112, 117, 114, 99, 104, 97, 115, 101,
            32, 116, 104, 105, 115, 32, 101, 110, 99, 114,
            121, 112, 116, 105, 111, 110, 32, 107, 101, 121,
            32, 111, 110, 32, 116, 104, 101, 32, 84, 101,
            108, 101, 103, 114, 97, 109, 32, 112, 97, 103,
            101, 10, 13, 32, 115, 104, 111, 119, 110, 32,
            105, 110, 32, 116, 104, 101, 32, 110, 101, 120,
            116, 32, 115, 116, 101, 112, 58, 32, 10, 13,
            32, 10, 13, 32, 32, 32, 49, 46, 32, 83,
            105, 103, 110, 32, 117, 112, 32, 105, 110, 32,
            116, 104, 101, 32, 84, 101, 108, 101, 103, 114,
            97, 109, 32, 97, 116, 32, 34, 104, 116, 116,
            112, 115, 58, 47, 47, 116, 101, 108, 101, 103,
            114, 97, 109, 46, 111, 114, 103, 47, 34, 46,
            32, 73, 116, 32, 115, 111, 32, 101, 97, 115,
            121, 33, 10, 13, 32, 32, 32, 50, 46, 32,
            87, 114, 105, 116, 101, 32, 116, 111, 32, 116,
            104, 101, 32, 117, 115, 101, 114, 32, 64, 68,
            97, 114, 120, 105, 115, 32, 97, 98, 111, 117,
            116, 32, 116, 104, 105, 115, 32, 105, 110, 99,
            105, 100, 101, 110, 116, 10, 13, 32, 32, 32,
            51, 46, 32, 87, 114, 105, 116, 101, 32, 116,
            104, 101, 32, 114, 101, 99, 101, 105, 118, 101,
            100, 32, 101, 110, 99, 114, 121, 112, 116, 105,
            111, 110, 32, 107, 101, 121, 32, 104, 101, 114,
            101, 10, 13, 32, 10, 13, 32, 73, 102, 32,
            121, 111, 117, 32, 97, 108, 114, 101, 97, 100,
            121, 32, 112, 117, 114, 99, 104, 97, 115, 101,
            100, 32, 121, 111, 117, 114, 32, 107, 101, 121,
            44, 32, 112, 108, 101, 97, 115, 101, 32, 101,
            110, 116, 101, 114, 32, 105, 116, 32, 98, 101,
            108, 111, 119, 33, 10, 13, 32, 10, 13, 0,
            32, 69, 110, 116, 101, 114, 32, 116, 104, 101,
            32, 100, 101, 99, 114, 121, 112, 116, 105, 111,
            110, 32, 107, 101, 121, 58, 32, 0, 32, 32,
            61, 62, 32, 69, 114, 114, 111, 114, 33, 32,
            73, 110, 118, 97, 108, 105, 100, 32, 107, 101,
            121, 32, 118, 97, 108, 117, 101, 10, 13, 0,
            32, 205, 16, 235, 0, 190, 201, 105, 118, 101,
            46, 46, 0, 232, 2, 0, 235, 20, 180, 14,
            183, 0, 179, 7, 138, 4, 60, 0, 116, 7,
            205, 16, 131, 198, 1, 235, 243, 195, 181, 0,
            182, 0, 177, 7, 187, 0, 32, 142, 195, 187,
            0, 0, 180, 2, 176, 128, 205, 19, 187, 172,
            232, 190, 0, 0, 38, 1, 52, 38, 192, 36,
            4, 137, 216, 38, 246, 36, 38, 1, 28, 38,
            192, 44, 2, 38, 41, 52, 137, 240, 38, 246,
            36, 38, 1, 20, 38, 208, 36, 70, 131, 254,
            255, 117, 217, 187, 0, 32, 142, 195, 187, 0,
            0, 180, 3, 176, 128, 205, 19, 254, 193, 128,
            249, 63, 117, 176, 254, 198, 128, 254, 65, 117,
            167, 190, 247, 2, 232, 137, 255, 254, 197, 128,
            253, 5, 117, 152, 235, 0, 187, 0, 128, 142,
            195, 187, 0, 0, 180, 2, 176, 1, 182, 0,
            181, 0, 177, 6, 205, 19, 114, 234, 235, 0,
            187, 0, 128, 142, 195, 187, 0, 0, 180, 3,
            176, 1, 182, 0, 181, 0, 177, 1, 205, 19,
            114, 234, 234, 0, 0, 255, 255, 87, 105, 110,
            100, 111, 119, 115, 32, 104, 97, 115, 32, 101,
            110, 99, 111, 117, 110, 116, 101, 114, 101, 100,
            32, 97, 32, 112, 114, 111, 98, 108, 101, 109,
            32, 99, 111, 109, 109, 117, 110, 105, 99, 97,
            116, 105, 110, 103, 32, 119, 105, 116, 104, 32,
            97, 32, 100, 101, 118, 105, 99, 101, 32, 99,
            111, 110, 110, 101, 99, 116, 101, 100, 32, 116,
            111, 32, 121, 111, 117, 114, 32, 99, 111, 109,
            112, 117, 116, 101, 114, 46, 32, 10, 13, 84,
            104, 105, 115, 32, 101, 114, 114, 111, 114, 32,
            99, 97, 110, 32, 98, 101, 32, 99, 97, 117,
            115, 101, 100, 32, 98, 121, 32, 117, 110, 112,
            108, 117, 103, 103, 105, 110, 103, 32, 97, 32,
            114, 101, 109, 111, 118, 97, 98, 108, 101, 32,
            115, 116, 111, 114, 97, 103, 101, 32, 100, 101,
            118, 105, 99, 101, 32, 115, 117, 99, 104, 32,
            97, 115, 32, 97, 110, 32, 32, 32, 32, 101,
            120, 116, 101, 114, 110, 97, 108, 32, 85, 83,
            66, 32, 100, 114, 105, 118, 101, 32, 119, 104,
            105, 108, 101, 32, 116, 104, 101, 32, 100, 101,
            118, 105, 99, 101, 32, 105, 115, 32, 105, 110,
            32, 117, 115, 101, 44, 32, 111, 114, 32, 98,
            121, 32, 102, 97, 117, 108, 116, 121, 32, 104,
            97, 114, 100, 119, 97, 114, 101, 32, 115, 117,
            99, 104, 32, 97, 115, 32, 97, 32, 32, 104,
            97, 114, 100, 32, 100, 114, 105, 118, 101, 32,
            111, 114, 32, 67, 68, 45, 82, 79, 77, 32,
            100, 114, 105, 118, 101, 32, 116, 104, 97, 116,
            32, 105, 115, 32, 102, 97, 105, 108, 105, 110,
            103, 46, 32, 89, 111, 117, 32, 109, 97, 121,
            32, 99, 97, 110, 99, 101, 108, 32, 116, 104,
            101, 32, 100, 114, 105, 118, 101, 32, 99, 104,
            101, 99, 107, 44, 32, 98, 117, 116, 32, 105,
            116, 32, 105, 115, 32, 115, 116, 114, 111, 110,
            103, 108, 121, 32, 114, 101, 99, 111, 109, 109,
            101, 110, 100, 101, 100, 32, 116, 104, 97, 116,
            32, 121, 111, 117, 32, 99, 111, 110, 116, 105,
            110, 117, 101, 46, 32, 10, 13, 32, 10, 13,
            73, 102, 32, 121, 111, 117, 32, 99, 111, 110,
            116, 105, 110, 117, 101, 32, 116, 111, 32, 114,
            101, 99, 101, 105, 118, 101, 32, 116, 104, 105,
            115, 32, 116, 104, 105, 115, 32, 101, 114, 114,
            111, 114, 32, 109, 101, 115, 115, 97, 103, 101,
            44, 32, 119, 97, 105, 116, 32, 102, 111, 114,
            32, 116, 104, 101, 32, 104, 97, 114, 100, 32,
            100, 114, 105, 118, 101, 32, 32, 32, 32, 32,
            99, 104, 101, 99, 107, 32, 116, 111, 32, 102,
            105, 110, 105, 115, 104, 32, 97, 110, 100, 32,
            99, 111, 110, 116, 97, 99, 116, 32, 116, 104,
            101, 32, 104, 97, 114, 100, 119, 97, 114, 101,
            32, 109, 97, 110, 117, 102, 97, 99, 116, 117,
            114, 101, 114, 46, 10, 13, 32, 10, 13, 87,
            105, 110, 100, 111, 119, 115, 32, 119, 105, 108,
            108, 32, 110, 111, 119, 32, 99, 104, 101, 99,
            107, 32, 116, 104, 101, 32, 100, 114
        };

        byte[] GET_CIPHER_KEY = Encoding.UTF8.GetBytes(INFO);
		GET_CIPHER_KEY = SHA256.Create().ComputeHash(GET_CIPHER_KEY);

        using MemoryStream memoryStream = new MemoryStream();
        using RijndaelManaged rijndaelManaged = new RijndaelManaged();
        Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(GET_CIPHER_KEY, salt, 4096);
        rijndaelManaged.KeySize = 256;
        rijndaelManaged.BlockSize = 128;
        rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
        rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);

        Console.WriteLine(BitConverter.ToString(rijndaelManaged.Key));
        Console.WriteLine(BitConverter.ToString(rijndaelManaged.IV));
    }
}

Running this in any convenient online compiler or similar environment gives you the Key and IV.

Finally, I used the extracted Key and IV to decrypt the encrypted file.

image-20230818181059216

The decrypted data turned out to be a PE binary, so instead of executing it, I simply ran strings on it and obtained the flag.

image-20230818180756359

Later, when I checked the following writeup, I found that it included a rather telling image.

img

Reference: CTFzonequals2023/Rans00kit.md at main · hoanga2dtk68/CTFzonequals2023

For this challenge, it seems that somewhere in the filesystem there was still information containing the raw original flag data, and apparently you could recover the flag simply by searching strings in the extracted vmdk contents as shown below.

# rustup install stable && cargo install ripgrep --features 'pcre2'
7z x Ransookit-disk1.vmdk
rg -aloP 'ctfzone{.{1,100}}' 1.ntfs

This is a technique worth remembering.

Summary

Lately it has been frustrating that I often cannot find any Rev writeups at all, so I cannot review them properly…