⏪
CTFs
TwitterGithub
  • 👋Introduction
  • 📚Write Up
    • 2024
      • 📖1337UP LIVE CTF
        • Reverse Engineering
        • Mobile
        • Forensic
        • Misc
      • 📖HKCERT CTF Quals
        • Reverse Engineering
        • Binary Exploitation
      • 📖Flare-On 11
        • Challenge #1 - frog
      • 📖Intechfest
        • Reverse Engineering
        • Forensic
        • Cryptography
        • Mobile
      • 📖Cyber Breaker Competition (1v1)
        • Reverse Engineering
        • Web Exploitation
        • Cryptography
        • Binary Exploitation
      • 📖Cyber Breaker Competition Quals
        • Reverse Engineering
        • Web Exploitation
        • Cryptography
      • 📖BlackHat MEA Quals
        • Reverse Engineering
        • Forensic
      • 📖TFC CTF
        • Reverse Engineering
        • Forensic
        • Misc
      • 📖DeadSec CTF
        • Reverse Engineering
        • Web Exploitation
      • 📖Aptos - Code Collision CTF
        • Reverse Engineering
        • Misc
      • 📖DownUnder CTF
        • Reverse Engineering
      • 📖JustCTF
        • Reverse Engineering
        • Forensic
        • Misc
      • 📖Akasec CTF
        • Reverse Engineering
        • Forensic
      • 📖Codegate CTF Preliminary
        • Reverse Engineering
      • 📖NahamCon CTF
        • Cryptography
        • Reverse Engineering
        • Malware
        • Misc
        • Mobile
        • Scripting
        • Web Exploitation
        • Forensic
      • 📖SAS CTF Quals
        • Reverse Engineering
      • 📖SwampCTF
        • Reverse Engineering
        • Misc
        • Cryptography
      • 📖UNbreakable International
        • Reverse Engineering
        • Network
        • Cryptography
      • 📖ACSC
        • Reverse Engineering
        • Hardware
        • Web Exploitation
      • 📖0xL4ugh
        • Mobile
    • 2023
      • 📖BlackHat MEA Final
        • Reverse Engineering
        • Web Exploitation
      • 📖Flare-On 10
        • Challenge #1 - X
        • Challenge #2 - ItsOnFire
        • Challenge #3 - mypassion
        • Challenge #4 - aimbot
        • Challenge #5 - where_am_i
        • Challenge #6 - FlareSay
        • Challenge #7 - flake
        • Challenge #8 - AmongRust
        • Challenge #9 - mbransom
        • Challenge #10 - kupo
        • Challenge #11 - over_the_rainbow
        • Challenge #12 - HVM
        • Challenge #13 - y0da
      • 📖LakeCTF Quals
        • Reverse Engineering
        • Cryptography
      • 📖TSG CTF
        • Reverse Engineering
        • Cryptography
      • 📖ISITDTU Quals
        • Web Exploitation
        • Misc
        • Reverse Engineering
      • 📖BlackHat MEA Quals
        • Reverse Engineering
      • 📖ASCIS Final
        • Reverse Engineering
        • Web Exploitation
        • Cryptography
      • 📖ASCIS Quals
        • Reverse Engineering
        • Forensic
        • Cryptography
      • 📖IFest
        • Reverse Engineering
        • Cryptography
        • Misc
      • 📖Cyber Jawara International
        • Reverse Engineering
        • Forensic
        • Cryptography
        • Web Exploitation
      • 📖Intechfest
        • Reverse Engineering
        • Forensic
        • Cryptography
        • Mobile
      • 📖CSAW Quals
        • Reverse Engineering
      • 📖SECCON Quals
        • Reverse Engineering
      • 📖CTFZone Quals
        • Reverse Engineering
      • 📖Securinets Quals
        • Reverse Engineering
      • 📖Compfest Final (Attack Defense)
        • Web Exploitation
        • Cryptography
      • 📖Compfest Quals
        • Reverse Engineering
        • Cryptography
        • Forensic
        • Misc
      • 📖Tenable
        • Reverse Engineering
        • Cryptography
        • Steganography
      • 📖ASCWG Quals
        • Reverse Engineering
        • Cryptography
      • 📖Gemastik Quals
        • Reverse Engineering
      • 📖BSides Indore
        • Reverse Engineering
        • Cryptography
      • 📖NahamCon CTF
        • Cryptography
      • 📖HSCTF
        • Reverse Engineering
        • Cryptography
        • Web Exploitation
        • Misc
      • 📖ACSC
        • Reverse Engineering
      • 📖HackTM Quals
        • Reverse Engineering
    • 2022
      • 📖Intechfest
        • Reverse Engineering
        • Mobile
        • Cryptography
      • 📖NCW Final
        • Reverse Engineering
      • 📖NCW Quals
        • Reverse Engineering
        • Misc
        • Cryptography
      • 📖Compfest Final
        • Reverse Engineering
        • Forensic
      • 📖Compfest Quals
        • Reverse Engineering
        • Cryptography
      • 📖IFest
        • Reverse Engineering
        • Cryptography
        • Forensic
    • 2021
      • 📖Cyber Jawara Final
        • Reverse Engineering
      • 📖Cyber Jawara Quals
        • Reverse Engineering
        • Cryptography
      • 📖DarkCon CTF
        • Reverse Engineering
      • 📖Wreck IT Quals
        • Mobile
      • 📖MDT4.0 Final
        • Reverse Engineering
        • Cryptography
        • Forensic
      • 📖MDT4.0 Quals
        • Reverse Engineering
        • Cryptography
      • 📖IFest
        • Reverse Engineering
        • Cryptography
      • 📖Compfest Final
        • Reverse Engineering
      • 📖Compfest Quals
        • Reverse Engineering
        • Cryptography
    • 2020
      • 📖Deep CTF
        • Reverse Engineering
  • 🚩Lifetime CTF
    • 📖Hack The Box
      • Reverse Engineering
        • TBU
Powered by GitBook
On this page
  • baby-asm (100 pts)
  • Description
  • Solution
  • baby-vm (100 pts)
  • Description
  • Solution
  • baby-crack (100 pts)
  • Description
  • Solution
  1. Write Up
  2. 2024
  3. Cyber Breaker Competition (1v1)

Reverse Engineering

Challenge
Link

baby-asm (100 pts)

baby-vm (100 pts)

baby-crack (100 pts)

baby-asm (100 pts)

Description

-

Solution

Given ELF 64 bit file, open it using IDA

int __fastcall main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbx
  __int64 v4; // rbx
  __int64 v5; // rbx
  __int64 v6; // rbx
  __int64 v7; // rbx
  __int64 v8; // rbx
  __int64 v9; // rbx
  __int64 v10; // rbx
  __int64 v11; // rbx
  __int64 v12; // rbx
  __int64 v13; // rbx
  __int64 v14; // rbx
  __int64 v15; // rbx
  __int64 v16; // rbx
  __int64 v17; // rbx
  __int64 v18; // rbx
  _QWORD *v20; // [rsp+8h] [rbp-128h]
  char s[8]; // [rsp+10h] [rbp-120h] BYREF
  __int64 v22; // [rsp+18h] [rbp-118h]
  __int64 v23; // [rsp+20h] [rbp-110h]
  __int64 v24; // [rsp+28h] [rbp-108h]
  __int64 v25; // [rsp+30h] [rbp-100h]
  __int64 v26; // [rsp+38h] [rbp-F8h]
  __int64 v27; // [rsp+40h] [rbp-F0h]
  __int64 v28; // [rsp+48h] [rbp-E8h]
  __int64 v29; // [rsp+50h] [rbp-E0h]
  __int64 v30; // [rsp+58h] [rbp-D8h]
  __int64 v31; // [rsp+60h] [rbp-D0h]
  __int64 v32; // [rsp+68h] [rbp-C8h]
  __int64 v33; // [rsp+70h] [rbp-C0h]
  __int64 v34; // [rsp+78h] [rbp-B8h]
  __int64 v35; // [rsp+80h] [rbp-B0h]
  __int64 v36; // [rsp+88h] [rbp-A8h]
  __int64 v37; // [rsp+90h] [rbp-A0h]
  __int64 v38; // [rsp+98h] [rbp-98h]
  __int64 v39; // [rsp+A0h] [rbp-90h]
  __int64 v40; // [rsp+A8h] [rbp-88h]
  __int64 v41; // [rsp+B0h] [rbp-80h]
  __int64 v42; // [rsp+B8h] [rbp-78h]
  __int64 v43; // [rsp+C0h] [rbp-70h]
  __int64 v44; // [rsp+C8h] [rbp-68h]
  __int64 v45; // [rsp+D0h] [rbp-60h]
  __int64 v46; // [rsp+D8h] [rbp-58h]
  __int64 v47; // [rsp+E0h] [rbp-50h]
  __int64 v48; // [rsp+E8h] [rbp-48h]
  __int64 v49; // [rsp+F0h] [rbp-40h]
  __int64 v50; // [rsp+F8h] [rbp-38h]
  __int64 v51; // [rsp+100h] [rbp-30h]
  __int64 v52; // [rsp+108h] [rbp-28h]
  unsigned __int64 v53; // [rsp+118h] [rbp-18h]

  v53 = __readfsqword(0x28u);
  v20 = mmap(0LL, 0x1000uLL, 7, 34, 0, 0LL);
  if ( v20 == (_QWORD *)-1LL )
  {
    perror("mmap");
    exit(1);
  }
  *v20 = code;
  v20[1] = 0xC7480000002D358DLL;
  v20[2] = 0xC0314800000029C2LL;
  v20[3] = 0x1375063A1834078ALL;
  v20[4] = 0xFF48C6FF48C7FF48LL;
  v20[5] = 0x2021C0C748ED75CALL;
  v20[6] = 0x2020C0C748C30000LL;
  v20[7] = 0x282A5B5A5BC30000LL;
  qmemcpy(v20 + 8, "*,c +y~~+.,.!)/ }}*yy{/~.{*}| !/}z*e", 36);
  printf("Enter your flag: ");
  fgets(s, 256, _bss_start);
  v3 = v22;
  *(_QWORD *)((char *)v20 + 100) = *(_QWORD *)s;
  *(_QWORD *)((char *)v20 + 108) = v3;
  v4 = v24;
  *(_QWORD *)((char *)v20 + 116) = v23;
  *(_QWORD *)((char *)v20 + 124) = v4;
  v5 = v26;
  *(_QWORD *)((char *)v20 + 132) = v25;
  *(_QWORD *)((char *)v20 + 140) = v5;
  v6 = v28;
  *(_QWORD *)((char *)v20 + 148) = v27;
  *(_QWORD *)((char *)v20 + 156) = v6;
  v7 = v30;
  *(_QWORD *)((char *)v20 + 164) = v29;
  *(_QWORD *)((char *)v20 + 172) = v7;
  v8 = v32;
  *(_QWORD *)((char *)v20 + 180) = v31;
  *(_QWORD *)((char *)v20 + 188) = v8;
  v9 = v34;
  *(_QWORD *)((char *)v20 + 196) = v33;
  *(_QWORD *)((char *)v20 + 204) = v9;
  v10 = v36;
  *(_QWORD *)((char *)v20 + 212) = v35;
  *(_QWORD *)((char *)v20 + 220) = v10;
  v11 = v38;
  *(_QWORD *)((char *)v20 + 228) = v37;
  *(_QWORD *)((char *)v20 + 236) = v11;
  v12 = v40;
  *(_QWORD *)((char *)v20 + 244) = v39;
  *(_QWORD *)((char *)v20 + 252) = v12;
  v13 = v42;
  *(_QWORD *)((char *)v20 + 260) = v41;
  *(_QWORD *)((char *)v20 + 268) = v13;
  v14 = v44;
  *(_QWORD *)((char *)v20 + 276) = v43;
  *(_QWORD *)((char *)v20 + 284) = v14;
  v15 = v46;
  *(_QWORD *)((char *)v20 + 292) = v45;
  *(_QWORD *)((char *)v20 + 300) = v15;
  v16 = v48;
  *(_QWORD *)((char *)v20 + 308) = v47;
  *(_QWORD *)((char *)v20 + 316) = v16;
  v17 = v50;
  *(_QWORD *)((char *)v20 + 324) = v49;
  *(_QWORD *)((char *)v20 + 332) = v17;
  v18 = v52;
  *(_QWORD *)((char *)v20 + 340) = v51;
  *(_QWORD *)((char *)v20 + 348) = v18;
  if ( ((unsigned int (*)(void))v20)() == 8225 )
    puts("Congrats, this app successfully cracked!");
  else
    puts("Sorry, try again!");
  return 0;
}

From code above we can see that there is mmap function called at initial of main function. The third argument of mmap function is 7, it means that the we allowed to read, write, and execute memory. We can see that the static values and our input (s) are stored also in v20 and at the end there is a call to v20. So basically v20 contains shellcode that will process our input and static values. To know the instructions executed, we can debug it by stepping instruction on v20 call.

pie b 0x14B6
pie run

Input some random value then send "si" to step instruction.

So rdi is our input and rsi is static values. our input (rdi) will be moved each byte to al and then will be xored with 0x18. After that it will be compared with 1 byte value of rsi (static values). From that information we can get the valid value of input by xoring the static values with 0x18. Below is the script to solve the challenge

a = b"[Z[*(*,c +y~~+.,.!)/ }}*yy{/~.{*}| !/}z*e"
flag = b""
for i in a:
	flag += bytes([i ^ 0x18])
print(flag)

Flag: CBC2024{83aff36469178ee2aac7f6c2ed897eb2}

baby-vm (100 pts)

Description

-

Solution

Given ELF 64 bit, open it using IDA

int __fastcall main(int argc, const char **argv, const char **envp)
{
  FILE *stream; // [rsp+8h] [rbp-18h]
  __int64 size; // [rsp+10h] [rbp-10h]
  void *ptr; // [rsp+18h] [rbp-8h]

  stream = fopen("code.bin", "rb");
  if ( !stream )
  {
    puts("Failed to open code.bin");
    exit(1);
  }
  fseek(stream, 0LL, 2);
  size = ftell(stream);
  fseek(stream, 0LL, 0);
  ptr = malloc(size);
  fread(ptr, size, 1uLL, stream);
  fclose(stream);
  if ( (unsigned int)vm_exec(ptr, (unsigned int)size) )
    puts("Congrats, you own the flag!");
  else
    puts("Oops, wrong flag!");
  return 0;
}

The opcode are stored in code.bin and the function that will execute the opcode in vm_exec, so let's check vm_exec.

__int64 __fastcall vm_exec(__int64 a1, int a2)
{
  int v3; // ecx
  int v4; // eax
  char v5; // [rsp+1Eh] [rbp-122h] BYREF
  unsigned __int8 v6; // [rsp+1Fh] [rbp-121h]
  int v7; // [rsp+20h] [rbp-120h]
  int v8; // [rsp+24h] [rbp-11Ch]
  _QWORD v9[35]; // [rsp+28h] [rbp-118h]

  v9[34] = __readfsqword(0x28u);
  v7 = 0;
  v9[0] = 0LL;
  v8 = 0;
  while ( 2 )
  {
    if ( v7 < a2 )
    {
      v6 = *(_BYTE *)(v7 + a1);
      switch ( v6 )
      {
        case 0u:
          return LOBYTE(v9[0]);
        case 1u:
          *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 1LL + a1)) = *(_BYTE *)(a1 + v7 + 2LL);
          v7 += 3;
          continue;
        case 2u:
          v3 = *(unsigned __int8 *)(v7 + 1LL + a1);
          v4 = v8++;
          *((_BYTE *)&v9[1] + v4) = *((_BYTE *)v9 + v3);
          v7 += 2;
          continue;
        case 3u:
          *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 1LL + a1)) += *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 2LL + a1));
          v7 += 3;
          continue;
        case 4u:
          *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 1LL + a1)) -= *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 2LL + a1));
          v7 += 3;
          continue;
        case 7u:
          if ( *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 1LL + a1)) == *((_BYTE *)v9
                                                                       + *(unsigned __int8 *)(v7 + 2LL + a1)) )
            v7 += 4;
          else
            v7 = *(unsigned __int8 *)(v7 + 3LL + a1);
          continue;
        case 8u:
          __isoc99_scanf(&unk_2004, &v5);
          *((_BYTE *)v9 + *(unsigned __int8 *)(v7 + 1LL + a1)) = v5;
          v7 += 2;
          continue;
        case 9u:
          v7 = *(unsigned __int8 *)(v7 + 1LL + a1);
          continue;
        default:
          printf("Invalid opcode: %d\n", v6);
          exit(1);
      }
    }
    return LOBYTE(v9[0]);
  }
}

We can see that the instruction is not much and the operation available only addition and substraction. So basically at the end our input only will be added or subtracted although there are many operation of substraction or addition. With assumption that our input will be processed individually (each byte and independent) so lets set breakpoint at compare instruction (opcode 7).

pie b 0x1516
pie run

Lets do scripting and use 2 different input to check the values compared.

#!/usr/bin/python3
import string

def write_payload(data):
    f = open("payload.txt", "wb")
    f.write(bytes(data))
    f.close()

class SolverEquation(gdb.Command):
    def __init__ (self):
        super (SolverEquation, self).__init__ ("solve-equation",gdb.COMMAND_OBSCURE)

    def invoke (self, arg, from_tty):
        dict = {}
        for i in string.printable[:2]:
            list_al = []
            list_dl = []
            tmp = [ord(i)] * 45
            write_payload(tmp)
            gdb.execute("pie b 0x1516")
            gdb.execute("pie run < payload.txt")
            for _ in range(45):
                al = addr2num(gdb.selected_frame().read_register("al"))
                dl = addr2num(gdb.selected_frame().read_register("dl"))
                gdb.execute("set $al=$dl")
                gdb.execute("c")
                list_al.append(al & 0xff)
                list_dl.append(dl & 0xff)
            dict[i] = list_dl
        print(dict)
        print(list_al)
        gdb.execute("pie del")


def addr2num(addr):
    try:
        return int(addr)
    except:
        return long(addr)

SolverEquation()
dict = {'0': [255, 16, 17, 12, 225, 34, 20, 122, 189, 6, 64, 215, 66, 169, 239, 181, 189, 255, 98, 171, 202, 8, 148, 254, 101, 68, 160, 161, 23, 9, 71, 138, 58, 115, 9, 208, 2, 157, 34, 159, 32, 220, 41, 254, 203], '1': [0, 17, 18, 13, 226, 35, 21, 123, 190, 7, 65, 216, 67, 170, 240, 182, 190, 0, 99, 172, 203, 9, 149, 255, 102, 69, 161, 162, 24, 10, 72, 139, 59, 116, 10, 209, 3, 158, 35, 160, 33, 221, 42, 255, 204]}
cmp_val = [18, 34, 36, 14, 225, 36, 24, 197, 189, 78, 64, 215, 113, 219, 32, 231, 6, 46, 168, 232, 249, 71, 214, 45, 151, 117, 210, 234, 70, 61, 74, 199, 58, 177, 56, 22, 63, 204, 35, 208, 41, 18, 50, 49, 24]


for i in dict:
	arr = []
	for j in dict[i]:
		arr.append((ord(i) - j) & 0xff)
	print(arr)

We can see from image above that the different is same, so lets decode it by adding the known diff with the ciphertext.

dict = {'0': [255, 16, 17, 12, 225, 34, 20, 122, 189, 6, 64, 215, 66, 169, 239, 181, 189, 255, 98, 171, 202, 8, 148, 254, 101, 68, 160, 161, 23, 9, 71, 138, 58, 115, 9, 208, 2, 157, 34, 159, 32, 220, 41, 254, 203], '1': [0, 17, 18, 13, 226, 35, 21, 123, 190, 7, 65, 216, 67, 170, 240, 182, 190, 0, 99, 172, 203, 9, 149, 255, 102, 69, 161, 162, 24, 10, 72, 139, 59, 116, 10, 209, 3, 158, 35, 160, 33, 221, 42, 255, 204]}
cmp_val = [18, 34, 36, 14, 225, 36, 24, 197, 189, 78, 64, 215, 113, 219, 32, 231, 6, 46, 168, 232, 249, 71, 214, 45, 151, 117, 210, 234, 70, 61, 74, 199, 58, 177, 56, 22, 63, 204, 35, 208, 41, 18, 50, 49, 24]


for i in dict:
	arr = []
	for j in dict[i]:
		arr.append((ord(i) - j) & 0xff)

flag = b""
for i in range(len(cmp_val)):
	flag += bytes([(cmp_val[i] + arr[i]) & 0xff])
print(flag)

Flag: CBC2024{0x00_baby_vm_or_baby_d3m0n_vm_1a9f9c}

baby-crack (100 pts)

Description

-

Solution

-- filename: @main.lua
-- version: lua54
-- line: [0, 0] id: 0
encrypt = function(r0_1)
  -- line: [1, 9] id: 1
  local r1_1 = ""
  for r5_1 = 1, #r0_1, 1 do
    r1_1 = r1_1 .. string.char((string.byte(r0_1:sub(r5_1, r5_1)) ~ r5_1))
  end
  return r1_1
end
io.write("Validate ur flag: ")
if encrypt(io.read()) == "B@@6543s1ij>=j8$u%\'p\'/ {+\"#)*(.B\u{17}\u{1a}@A\u{16}EDMT" then
  print("Yeah, that\'s the correct flag!")
else
  print("Whoops, that\'s not the correct flag!")
end

We know that it does xor operation to our input and compare it with static values. So the easy way to solve is by calling the same function again.

encrypt = function(r0_1)
  -- line: [1, 9] id: 1
  local r1_1 = ""
  for r5_1 = 1, #r0_1, 1 do
    r1_1 = r1_1 .. string.char((string.byte(r0_1:sub(r5_1, r5_1)) ~ r5_1))
  end
  return r1_1
end

tmp ="B@@6543s1ij>=j8$u%\'p\'/ {+\"#)*(.B\u{17}\u{1a}@A\u{16}EDMT" 

print(encrypt(tmp))

Flag: CBC2024{8ca20d74d74d297c2885761b68ce3cce}

PreviousCyber Breaker Competition (1v1)NextWeb Exploitation

Last updated 7 months ago

Given luac file, it should be compiled lua. At first i tried to clone the repo but it takes long time so i try to find online decompiler and found . Upload the .luac file and we got decompiled version of it.

📚
📖
https://luadec.metaworm.site/
Here
Here
Here