← writeups

Reverse · Medium · BeeCTF 2026 · Aug 22, 2026

Flux Capacitor

The Flux Capacitor in Dr. Brown's old car is acting up, leaving him stuck in the wrong timeline. Maybe the “data” inside it can help him get the DeLorean running again. Author: c0smic

  • REVERSE ENGINEERING
  • XOR

Flux Capacitor

The Flux Capacitor in Dr. Brown's old car is acting up, leaving him stuck in the wrong timeline. Maybe the “data” inside it can help him get the DeLorean running again. Author: c0smic

Flux Capacitor — figure 1


Di sini kita diberi file stripped elf

bash
~/ctf/beectf/rev/fluxcapacitor
❯ file chall                                                                                                                                                                     󰥔 09:53:34
chall: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=692d65dfc73cb3865f92959ec407ae58140231ac, for GNU/Linux 3.2.0, stripped

Nah aku langsung buka dogbolt.org untuk decompile ini secara online, karena aku males buka IDA.

Ini output decompilenya (banyak)

c
/* This file was generated by the Hex-Rays decompiler version 9.4.0.260714.
   Copyright (c) 2007-2025 Hex-Rays <info@hex-rays.com>

   Detected compiler: GNU C++
*/

#include <defs.h>

//-------------------------------------------------------------------------
// Function declarations

__int64 (**init_proc())(void);
void sub_1020();
// void free(void *ptr);
// int putchar(int c);
// char *strncpy(char *dest, const char *src, size_t n);
// __int64 __fastcall __isoc23_strtoull(_QWORD, _QWORD, _QWORD); weak
// int puts(const char *s);
// int printf(const char *format, ...);
// char *fgets(char *s, int n, FILE *stream);
// void *calloc(size_t nmemb, size_t size);
// __int64 ptrace(enum __ptrace_request request, ...);
// int setvbuf(FILE *stream, char *buf, int modes, size_t n);
// int atoi(const char *nptr);
// void __noreturn exit(int status);
// int _cxa_finalize(void *);
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)());
FILE **sub_1130();
__int64 sub_1160();
FILE **sub_11A0();
__int64 sub_11E0();
__int64 sub_11E9();
int __fastcall sub_121D(__int64 a1, unsigned __int64 a2);
unsigned __int64 __fastcall sub_12DD(_BYTE *a1);
void term_proc();
// int _libc_start_main(int (*main)(int, char **, char **), int argc, char **ubp_av, void (*init)(), void (*fini)(), void (*rtld_fini)(), void *stack_end);
// int __cxa_finalize(void *);
// __int64 ITM_deregisterTMCloneTable(void); weak
// __int64 _gmon_start__(void); weak
// __int64 ITM_registerTMCloneTable(void); weak

//-------------------------------------------------------------------------
// Data declarations

_UNKNOWN main;
_BYTE byte_2030[48] =
{
  26,
  89,
  4,
  13,
  89,
  4,
  53,
  58,
  31,
  4,
  51,
  94,
  53,
  14,
  89,
  6,
  90,
  24,
  89,
  94,
  4,
  53,
  91,
  83,
  82,
  95,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0
}; // weak
_BYTE byte_2060[56] =
{
  -77,
  -96,
  111,
  103,
  64,
  37,
  65,
  5,
  -99,
  -112,
  114,
  123,
  119,
  34,
  74,
  34,
  -110,
  -12,
  126,
  20,
  102,
  60,
  94,
  80,
  -110,
  -73,
  83,
  84,
  96,
  80,
  94,
  60,
  -126,
  -112,
  105,
  71,
  39,
  16,
  73,
  60,
  -107,
  -81,
  104,
  22,
  37,
  16,
  9,
  87,
  -126,
  -68,
  119,
  0,
  0,
  0,
  0,
  0
}; // weak
const char byte_2155 = '\0'; // idb
void *off_4068 = &off_4068; // idb
FILE *stdout; // idb
FILE *stdin; // idb
char byte_4088; // weak

//----- (0000000000001000) ----------------------------------------------------
__int64 (**init_proc())(void)
{
  __int64 (**result)(void); // rax

  result = &_gmon_start__;
  if ( &_gmon_start__ != nullptr )
    return (__int64 (**)(void))_gmon_start__();
  return result;
}
// 4108: using guessed type __int64 _gmon_start__(void);

//----- (0000000000001020) ----------------------------------------------------
void sub_1020()
{
  JUMPOUT(0);
}
// 1026: control flows out of bounds to 0

//----- (0000000000001100) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)())
{
  __int64 v3; // rax
  int v4; // esi
  __int64 v5; // [rsp-8h] [rbp-8h] BYREF
  char *retaddr; // [rsp+0h] [rbp+0h] BYREF

  v4 = v5;
  v5 = v3;
  _libc_start_main((int (*)(int, char **, char **))main, v4, &retaddr, nullptr, nullptr, a3, &v5);
  __halt();
}
// 1106: positive sp value 8 has been found
// 110D: variable 'v3' is possibly undefined

//----- (0000000000001130) ----------------------------------------------------
FILE **sub_1130()
{
  return &stdout;
}
// 4100: using guessed type __int64 ITM_deregisterTMCloneTable(void);

//----- (0000000000001160) ----------------------------------------------------
__int64 sub_1160()
{
  return 0;
}
// 4110: using guessed type __int64 ITM_registerTMCloneTable(void);

//----- (00000000000011A0) ----------------------------------------------------
FILE **sub_11A0()
{
  FILE **result; // rax

  if ( byte_4088 == 0 )
  {
    if ( &__cxa_finalize != nullptr )
      _cxa_finalize(off_4068);
    result = sub_1130();
    byte_4088 = 1;
  }
  return result;
}
// 4088: using guessed type char byte_4088;

//----- (00000000000011E0) ----------------------------------------------------
// attributes: thunk
__int64 sub_11E0()
{
  return sub_1160();
}

//----- (00000000000011E9) ----------------------------------------------------
__int64 sub_11E9()
{
  __int64 result; // rax

  result = ptrace(PTRACE_TRACEME, 0, 1, 0);
  if ( result < 0 )
    exit(1);
  return result;
}

//----- (000000000000121D) ----------------------------------------------------
int __fastcall sub_121D(__int64 a1, unsigned __int64 a2)
{
  __int64 v5; // [rsp+18h] [rbp-18h]
  int i; // [rsp+2Ch] [rbp-4h]

  for ( i = 0; i < a2; ++i )
  {
    v5 = *(char *)(i + a1);
    if ( i <= 189 || i > 217 )
      printf("%llu, ", v5);
    else
      printf("%llu, ", v5 ^ (i % 7 + 55));
  }
  return putchar(10);
}

//----- (00000000000012DD) ----------------------------------------------------
unsigned __int64 __fastcall sub_12DD(_BYTE *a1)
{
  _BYTE *v1; // rax
  __int64 i; // [rsp+18h] [rbp-10h]
  unsigned __int64 v5; // [rsp+20h] [rbp-8h]

  v5 = 5381;
  for ( i = 0; ; ++i )
  {
    v1 = a1++;
    if ( *v1 == 0 )
      break;
    v5 = (0x9E3779B97F4A7C15LL * i) ^ ((33 * v5 + (unsigned __int8)*v1) >> 13) ^ (33 * v5 + (unsigned __int8)*v1);
  }
  return v5;
}

//----- (000000000000135D) ----------------------------------------------------
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char v4[32]; // [rsp+0h] [rbp-B0h] BYREF
  char nptr[16]; // [rsp+20h] [rbp-90h] BYREF
  char s[79]; // [rsp+30h] [rbp-80h] BYREF
  unsigned __int8 v7; // [rsp+7Fh] [rbp-31h]
  unsigned __int64 v8; // [rsp+80h] [rbp-30h]
  unsigned __int64 v9; // [rsp+88h] [rbp-28h]
  int v10; // [rsp+94h] [rbp-1Ch]
  char *dest; // [rsp+98h] [rbp-18h]
  __int64 j; // [rsp+A0h] [rbp-10h]
  __int64 i; // [rsp+A8h] [rbp-8h]

  sub_11E9();
  setvbuf(stdout, nullptr, 2, 0);
  dest = (char *)calloc(0xFAu, 1u);
  if ( dest == nullptr )
    return 1;
  for ( i = 0; byte_2030[i] != 0; ++i )
    dest[i + 190] = byte_2030[i] ^ 0x6A;
  puts("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]");
  puts("[][]                                                    [][]");
  puts("[][]  FLUX CAPACITOR TEMPORAL CALIBRATION SYSTEM v1.21  [][]");
  puts("[][]                                                    [][]");
  puts("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]");
  puts(&byte_2155);
  puts("Enter your calibration note:");
  if ( fgets(s, 64, stdin) == nullptr )
    return 1;
  if ( s[0] == 10 )
  {
    puts("Critical Error");
    return 0;
  }
  else
  {
    strncpy(dest, s, 0x30u);
    puts("How many bytes of memory state do you want to inspect?");
    if ( fgets(nptr, 16, stdin) != nullptr )
    {
      if ( nptr[0] == 10 )
      {
        puts("Critical Error");
        return 0;
      }
      else
      {
        v10 = atoi(nptr);
        printf("Inspecting %d bytes from Flux Memory:\n", v10);
        sub_121D((__int64)dest, v10);
        puts("\nEnter the 64-bit Flux Hash to initiate Time Travel:");
        if ( fgets(v4, 32, stdin) != nullptr )
        {
          if ( v4[0] == 10 )
          {
            puts("Critical Error");
            return 0;
          }
          else
          {
            v9 = __isoc23_strtoull(v4, 0, 10);
            v8 = sub_12DD(dest + 190);
            if ( v9 == v8 && v9 != 0 )
            {
              puts("\n1.21 GIGAWATTS ACHIEVED!");
              puts("Temporal Displacement Initialized! Great Scott!");
              for ( j = 0; byte_2060[j] != 0; ++j )
              {
                v7 = v9 >> (8 * ((unsigned __int8)j & 7u));
                putchar(v7 ^ byte_2060[j]);
              }
              putchar(10);
            }
            else
            {
              puts("\nTemporal Hash Mismatch! You are stuck in 1955!");
            }
            free(dest);
            return 0;
          }
        }
        else
        {
          return 1;
        }
      }
    }
    else
    {
      return 1;
    }
  }
}
// 1060: using guessed type __int64 __fastcall __isoc23_strtoull(_QWORD, _QWORD, _QWORD);
// 2030: using guessed type _BYTE byte_2030[48];
// 2060: using guessed type _BYTE byte_2060[56];

//----- (00000000000016B8) ----------------------------------------------------
void term_proc()
{
  ;
}

// nfuncs=42 queued=12 decompiled=12 lumina nreq=0 worse=0 better=0
// ALL OK, 12 function(s) have been successfully decompiled

Setelah kita baca function mainnya, dapat kita simpulkan kalau byte_2060 itu isinya adalah flag asli.

text
          else
          {
            v9 = __isoc23_strtoull(v4, 0, 10);
            v8 = sub_12DD(dest + 190);
            if ( v9 == v8 && v9 != 0 )
            {
              puts("\n1.21 GIGAWATTS ACHIEVED!");
              puts("Temporal Displacement Initialized! Great Scott!");
              for ( j = 0; byte_2060[j] != 0; ++j )
              {
                v7 = v9 >> (8 * ((unsigned __int8)j & 7u));
                putchar(v7 ^ byte_2060[j]);
              }
              putchar(10);
            }

Nah, di sini itu merupakan target string kita. Jadi kita harus tau apa hasil dari ini agar kita bisa mendapatkan hash untuk mendapatkan flagnya. Jadi dia mengambil byte_2030 sebagai value yang nanti akan di XOR yang nanti hasilnya adalah ciphertext asli.

text
  for ( i = 0; byte_2030[i] != 0; ++i )
    dest[i + 190] = byte_2030[i] ^ 0x6A;

Flux Capacitor — figure 2

Di sini si AI sudah membuatkan script biar aku gak usah repot repot ngerakit script sendiri. Tapi output si AI ini salah. Seharusnya outputnya adalah p3ng3n_PunY4_d3l0r34n_1985

text
>>> byte_2030 = [
...     26, 89, 4, 13, 89, 4, 53, 58, 31, 4, 51, 94, 53, 14, 89, 6,
...     90, 24, 89, 94, 4, 53, 91, 83, 82, 95, 0, 0, 0, 0, 0, 0,
...     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
... ]
...
... target_string = ''.join(chr(x ^ 0x6A) for x in byte_2030 if x != 0)
... print(target_string)
...
p3ng3n_PunY4_d3l0r34n_1985

Sekarang kita lihat kembali isi dari snippet biar masuk ke win.

text
      else
      {
        v9 = __isoc23_strtoull(v4, 0, 10);
        v8 = sub_12DD(dest + 190);
        if ( v9 == v8 && v9 != 0 )
        {
          puts("\n1.21 GIGAWATTS ACHIEVED!");
          puts("Temporal Displacement Initialized! Great Scott!");
          for ( j = 0; byte_2060[j] != 0; ++j )
          {
            v7 = v9 >> (8 * ((unsigned __int8)j & 7u));
            putchar(v7 ^ byte_2060[j]);
          }
          putchar(10);
        }

Bisa dilihat kalau ada sub_12DD untuk compute si hashnya ini. Isi function tersebut adalah

text
//----- (00000000000012DD) ----------------------------------------------------
unsigned __int64 __fastcall sub_12DD(_BYTE *a1)
{
  _BYTE *v1; // rax
  __int64 i; // [rsp+18h] [rbp-10h]
  unsigned __int64 v5; // [rsp+20h] [rbp-8h]

  v5 = 5381;
  for ( i = 0; ; ++i )
  {
    v1 = a1++;
    if ( *v1 == 0 )
      break;
    v5 = (0x9E3779B97F4A7C15LL * i) ^ ((33 * v5 + (unsigned __int8)*v1) >> 13) ^ (33 * v5 + (unsigned __int8)*v1);
  }
  return v5;
}

Jadi tinggal ngereverse function hash ini dengan target string yang benar tadi. Aku pakai script yang dibuat sama AI tapi scriptnya dia itu salah dari key dan caranya. Karena outputnya itu melebihi 64 bits, kata si AI the Python implementation has a problem with the arithmetic.

Flux Capacitor — figure 3

bash
~/ctf/beectf/rev/fluxcapacitor
❯ cat hash.py                                                                                                                                                                    󰥔 10:33:48
def compute_hash(s):
    v5 = 5381
    MASK = (1 << 64) - 1  # 64-bit mask

    for i, ch in enumerate(s):
        # All operations need to be 64-bit
        term1 = (0x9E3779B97F4A7C15 * i) & MASK
        term2 = (33 * v5 + ord(ch)) & MASK
        v5 = term1 ^ ((term2 >> 13) & MASK) ^ term2
        v5 &= MASK  # Keep it 64-bit

    return v5

target = "p3ng3n_PunY4_d3l0r34n_1985"
hash_value = compute_hash(target)
print(hash_value)
bash
~/ctf/beectf/rev/fluxcapacitor
❯ python3 hash.py                                                                                                                                                                󰥔 10:34:02
7150136296559265265

Aku mengambil inspirasi snippet solver AI deepseek yang sudah jadi sama dia.

Karena kita sudah tau target key dan hashnya, kita bisa run terus masukkin valuenya.

bash
~/ctf/beectf/rev/fluxcapacitor 42s
❯ ./chall                                                                                                                                                                        󰥔 10:11:29
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[][]                                                    [][]
[][]  FLUX CAPACITOR TEMPORAL CALIBRATION SYSTEM v1.21  [][]
[][]                                                    [][]
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

Enter your calibration note:
p3ng3n_PunY4_d3l0r34n_1985
How many bytes of memory state do you want to inspect?
64
Inspecting 64 bytes from Flux Memory:
112, 51, 110, 103, 51, 110, 95, 80, 117, 110, 89, 52, 95, 100, 51, 108, 48, 114, 51, 52, 110, 95, 49, 57, 56, 53, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

Enter the 64-bit Flux Hash to initiate Time Travel:
7150136296559265265

1.21 GIGAWATTS ACHIEVED!
Temporal Displacement Initialized! Great Scott!
BeeCTF{flUx_cApAc1t0r_d3crYpt3d_sUcc3ss_djb21s34sy}

Sebenarnya di sini aku ada 2 cara untuk ngesolve. Karena si AI ini tiba tiba ngasih solver lengkap AI ini sekalian ngeextract flagnya juga. Seperti ini:

python
#!/usr/bin/env python3

byte_2030 = [
    26, 89, 4, 13, 89, 4, 53, 58, 31, 4, 51, 94, 53, 14, 89, 6,
    90, 24, 89, 94, 4, 53, 91, 83, 82, 95, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]

byte_2060 = [
    -77, -96, 111, 103, 64, 37, 65, 5,
    -99, -112, 114, 123, 119, 34, 74, 34,
    -110, -12, 126, 20, 102, 60, 94, 80,
    -110, -73, 83, 84, 96, 80, 94, 60,
    -126, -112, 105, 71, 39, 16, 73, 60,
    -107, -81, 104, 22, 37, 16, 9, 87,
    -126, -68, 119, 0, 0, 0, 0, 0
]

def compute_hash(s):
    v5 = 5381
    MASK = (1 << 64) - 1  # 64-bit mask
    
    for i, ch in enumerate(s):
        # All operations need to be 64-bit
        term1 = (0x9E3779B97F4A7C15 * i) & MASK
        term2 = (33 * v5 + ord(ch)) & MASK
        v5 = term1 ^ ((term2 >> 13) & MASK) ^ term2
        v5 &= MASK  # Keep it 64-bit
    
    return v5

# Get the target string
target = ''.join(chr(x ^ 0x6A) for x in byte_2030 if x != 0)
print(f"Target string: {target}")

# Compute the hash
hash_val = compute_hash(target)
print(f"Hash value: {hash_val} (0x{hash_val:016x})")

# Decrypt the flag
flag = ""
for i, val in enumerate(byte_2060):
    if val == 0:
        break
    if val < 0:
        val += 256
    v7 = (hash_val >> (8 * (i & 7))) & 0xFF
    flag += chr(v7 ^ val)

print(f"Flag: {flag}")

output:

bash
~/ctf/beectf/rev/fluxcapacitor
❯ python3 solve.py                                                                                                                                                               󰥔 10:34:07
Target string: p3ng3n_PunY4_d3l0r34n_1985
Hash value: 7150136296559265265 (0x633a6314240ac5f1)
Flag: BeeCTF{flUx_cApAc1t0r_d3crYpt3d_sUcc3ss_djb21s34sy}

https://chat.deepseek.com/share/npk5i25vkqjhwh617u

flag

export & files

all writeups →

0x06 / contact

Say hi.

CTF team invites, collabs, or a challenge you think I can't pwn. I read everything.

Elang Dimas Syadewa

available · Malang

    Open email

    Your email app will open with a draft. Review it and press Send there.