⏪
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
  • Branches (260 pts)
  • Description
  • Solution
  • Serial (390 pts)
  • Description
  • Solution
  • Box (623 pts)
  • Description
  • Solution
  • Standard (1000 pts)
  • Description
  • Solution
  1. Write Up
  2. 2024
  3. Intechfest

Reverse Engineering

PreviousIntechfestNextForensic

Last updated 5 months ago

Challenge
Link

Branches (260 pts) 🥇

Serial (390 pts) 🥇

Box (623 pts) 🥇

Standard (1000 pts) 🥇

Branches (260 pts)

Description

-

Solution

Diberikan file ELF. buka dengan IDA

Dari kode diatas diketahui bahwa input kita akan dimapping ke check_function. Check_function berisi shellcode karena akan dieksekusi/dipanggil nantinya. Jadi disini ada dua kemungkinan mengenai input kita, yang pertama adalah input kita akan digunakan sebagai instruksi atau yang kedua sebagai operand. Mari kita cek

Input pertama akan terletak pada 0x4066 (nilai setelah t). Lakukan disasm

Jika kita ganti nilai ff dengan nilai lain misal 00 maka bisa dilihat bahwa operand dari jz akan berubah

Jadi disini bisa kita simpulkan bahwa input kita berfungsi sebagai operand dari jz, kita tahu jz pasti akan dieksekusi dikarenakan cmp 0,0 pasti true. Langkah selanjutnya hanya menentukan dimana address yang valid untuk eksekusi selanjutnya. Cek input selanjutnya berada dimana

Input selanjutnya berada pada 0x40b4, lakukan disasm di instruksi sekitar 0x40b4. Dengan trial dan error bisa kita temukan bahwa instruksi valid berada pada 0x40b0.

Dari sini kita tahu bahwa nilai operand pada jz adalah 0x40b0. Jadi untuk mendapatkan operand yang valid kita bisa dengan melihat selisih dari kedua address tersebut. (target_address - address_after_jz). Contoh untuk input pertama adalah 0x40b0 - 0x4067

Asumsi kami disini semua bentuk assemblynya sama, jadi tinggal scripting letak ‘t’ lalu kurangi dengan letak ‘t’ selanjutnya dimana perlu ada padding sebesar 5 supaya menghasilkan seperti kasus manual diatas. Berikut solver yang kami gunakan

f = open("result.bin", "rb").read()
a = []
for i in range(len(f)):
	if f[i] == ord("t"):
		a.append(i)

flag = ""
for i in range(0, len(a) - 1):
	flag +=(chr(a[i + 1] - a[i] - 5))
print(flag)

Flag: INTECHFEST{Br4nch3s_As_Fl4g_Ch3ck3r_Wh0_W0uld_Hav3_Th0ught}

Serial (390 pts)

Description

-

Solution

Diberikan file PE .NET, buka dengan dnspy

Fungsi yang dibuat oleh probset tidak terlihat langsung, buka dengan IDA untuk melihat fungsi lebih jelas. Pada IDA fungsi terlihat lebih jelas

Lakukan decompile pada dnspy untuk fungsi decryptflag. Lakukan analyze pada fungsi decryptflag untuk mendpat xref.

Bisa dilihat bahwa fungsi DecryptFlag akan dipanggil jika username equal dengan Administrator dan serial untuk user Administrator valid. Jadi selanjutnya cek fungsi checkSerial. Fungsi checkSerial menerima dua argument yaitu username dan serial. Bisa dilihat bahwa username akan diproses pada kode berikut

Nilai akhir dari proses yang memanfaatkan username akan disimpan pada variable num6. Kemudian num6 akan disimpan pada vector _u0020

Selanjutnya vector tersebut akan digunakan untuk validasi terhadap serial. Sampai disini kita tahu bahwa nilai num6 bisa kita dapatkan dari program, selanjutnya tinggal mencari tahu bagaimana serial divadliasi berdasarkan num6.

Sebelumnya ada validasi seperti input harus valid hexadecimal karakter. Selain itu terdapat validasi sebenarnya yaitu seperti pada (num20 << 4) | num21 != _u0020 & 255. Jadi tinggal reverse kode tersebut dan dapat serial yang valid. Berikut kode yang kami gunakan

num6 = 0xF8809629
num = 0x0000BFFD

vector = [0 for _ in range(8)]

vector[4] = num6 % 256
vector[5] = (num6 >> 8) % 256
vector[6] = (num6 >> 16) % 256
vector[7] = (num6 >> 24) % 256
vector[3] = 156

ptr7 = vector[5]
vector[2] = (num % 256) ^ ptr7

ptr7 = vector[7]
vector[1] = (num >> 8) ^ ptr7

ptr7 = vector[1]
vector[0] = ((vector[6] ^ ptr7 ^ 85) % 256) ^ 167

serial = ""
for i in range(0, len(vector), 2):
	serial += (hex(vector[i]))[2:] + hex(vector[i+1])[2:]
	serial += "-"
print(serial[:-1].upper())

Dapatkan num6 dari breakpoint pada line berikut

Selanjutnya tinggal masukkan user dan serial ke program dan dapat flag

Flag: INTECHFEST{did_you_know_that_this_serial_system_was_the_same_serial_system_for_010_editor?}

Box (623 pts)

Description

-

Solution

Diberikan file APK, decompile dengan apktool. Dari struktur direktori asset diketahui bahwa apk tersebut dibuat dengan unity

Selanjutnya gunakan script sesuai dengan tools yang digunakan untuk melakukan patch terhadap executable berdasarkan hasil extract dari global-metadata.dat. Disini saya menggunakan ida lalu melakukan load terhadap ida_py3.py dan pilih script.json. Selanjutnya kita fokus pada fungsi dengan awalan GameManager.

Lihat fungsi AddScore

Dapat diketahui bahwa AddScore pasti melakukan penambahan score. Penambahan score dilakukan sebanyak 1 kali, jadi bisa diketahui bahwa (v1+32) merupakan address untuk score. Dapat diketahui juga bahwa terdapat increment lain yaitu untuk v2 (v1 + 36) dimana nilainya didecrypt lalu ditambah dan diencrypt lagi. Jadi disini nilai score sebenarnya ada 2 yaitu pada v1 + 32 dan v1 + 36. Selanjutnya lihat fungsi Update

Pada bagian awal dari fungsi Update dapat diketahui bahwa terdapat decrypt process untuk +0x24 atau 36, hasil decrypt akan dibandingkan dengan plaintext score (+0x20). Jika berbeda akan menampilkan “CHEATER DETECTED!!!”

Selanjutnya dibawah ada pengecekan nilai plaintext score, jika lebih besar atau sama dengan 0xCC07C9 maka akan dilakukan decrypt. Asumsi disini decrypt adalah fungsi untuk menampilkan flag. Lanjut pengecekan ke fungsi decrypt

Fungsi decrypt menggunakan a1+0x24 yang mana nilai dari score yang terencrypt sebagai argument untuk md5. Dimana nilai md5 tersebut akan digunakan untuk melakukan decrypt flag. Sampai disini kita tahu bahwa kita harus melakukan update terhadap 2 nilai jika ingin melakukan cheat, yaitu 0x20 dan 0x24. Gunakan IDA untuk debug

Set breakpoint pada address 0xD7ADE4 dan 0xD7AE10. Pada 0xd7ade4 ubah nilai x8 menjadi 0xCC07C9

Selanjutnya pada 0xD7AE10 ubah nilai x0 menjadi 0xCC07C9

Selanjutnya tinggal continue saja dan jika ada error pilih pass to the app

Flag: INTECHFEST{Byp4ss1ng_Sh1tty_4nt1_Ch34t_S0_EZ}

Standard (1000 pts)

Description

-

Solution

Diberikan file ELF 64 bit, decompile dengan IDA. Terlihat bahwa program dibuat dengan c++.

Pada awal program dilakukan penerimaan input lalu pengecekan format flag dan membagi input berdasarkan dengan _ sebagai separator. Pada line 114 dilakukan pengecekan nilai dari vector (hasil split) jika panjangnya 4 maka valid lanjut ke line 121 untuk looping pengecekan setiap nilainya. Jadi total ada 4 nilai yang dicek.

Masuk ke fungsi std::for_each<__gnu_cxx::__normal_iterator<std::string *,std::vector<std::string>>,main::{lambda(std::string&)#1}.

Input kita akan diproses pada fungsi main::{lambda(std::string &)#1}::operator()((__int64)&v5, v3);. Pada fungsi tersebut akan dilakukan pengecekan untuk keempat nilai, berikut untuk gambaran besar flownya

  • Pengecekan terhadap karakter yang menyusun nilai tersebut/charset (step 1)

    • Contoh fungsi

      • std::all_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#1}

    • Semisal pengecekan apakah 1 block tersebut terdiri dari angka semua, huruf, dkk

    • Jika semua pengecekan menghasilkan nilai true maka lanjut ke pengecekan nilai setiap indexnya (step 2)

    • Jika tidak, lanjut ke pengecekan terhadap karakter yang menyusun nilai tersebut tetapi berbeda pengecekan (misal yang awalnya cek untuk huruf besar dan angka jika salah lanjut ke pengecekan huruf kecil dan angka)

  • Pengecekan nilai setiap index(step 2)

    • Contoh fungsi

      • std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#3}>

    • Setiap index akan dilakukan pengecekan dengan pemanggilan fungsi yang sama beberapa kali

    • Tidak ada pengecekan urutan setiap block, jadi kita tentukan sendiri (step 3)

    • 1 yang pasti adalah pengecekan terhadap nilai 0xDEA47FED merupakan pengecekan terakhir karena diakhir akan ditambahkan }

    • Pengecekan terhadap

Total ada 4 block, jadi total ada 4 block pengecekan. Kita tahu nilai dari masing-masing block jika valid akan digabung dengan _ , jadi kita bisa memberi tanda bahwa setiap penambahan _ akhir dari block pengecekan (diluar penambahan }). Untuk mengetahui nilai yang dicek, kita bisa decompile fungsi secara berulang jika ada fungsi didalamnya, hal tersebut saya ketahui dari debugging. Contoh

  • …or<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#3}>

    • …__ops::_Iter_pred<main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#3}>>

      • …_Iter_pred<main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#3}>>

        • …const(std::string &)::{lambda(char)#3}>::operator()<__gnu_cxx::__normal_iterator<char *,std::string>>

          • …:operator() const(std::string &)::{lambda(char)#3}::operator()(a1, *v2

            • return a2 == 84;

Jadi selanjutnya tinggal cek semua fungsi dan dapat flag. Berikut komen pada hasil decompile yang saya simpan

__int64 __fastcall main::{lambda(std::string &)#1}::operator()(__int64 a1, __int64 input)
{
  __int64 v2; // rbx
  __int64 v3; // rax
  __int64 v4; // rbx
  __int64 v5; // rax
  __int64 v7; // rbx
  __int64 v8; // rax
  __int64 v9; // rdx
  __int64 v10; // rbx
  __int64 v11; // rax
  __int64 v12; // rbx
  __int64 v13; // rax
  __int64 v14; // rax
  __int64 result; // rax
  __int64 v16; // rax
  __int64 v17; // rbx
  __int64 v18; // rax
  __int64 v19; // rbx
  __int64 v20; // rax
  char *v22; // rax
  __int64 v23; // rdx
  __int64 v24; // rbx
  __int64 v25; // rax
  __int64 v26; // rdx
  __int64 v27; // rbx
  __int64 v28; // rax
  __int64 v29; // rdx
  __int64 v30; // rbx
  __int64 v31; // rax
  __int64 v33; // rax
  __int64 v34; // rax
  __int64 v35; // rax
  __int64 v36; // rbx
  __int64 v37; // rax
  __int64 v38; // rbx
  __int64 v39; // rax
  __int64 v40; // rbx
  __int64 v41; // rax
  char *v43; // rax
  __int64 v44; // rax
  char *v45; // rax
  __int64 v47; // rbx
  __int64 v48; // rax
  __int64 v49; // rbx
  __int64 v50; // rax
  __int64 v51; // rdx
  __int64 v52; // rbx
  __int64 v53; // rax
  __int64 v54; // rbx
  __int64 v55; // rax
  char check_var; // al
  __int64 v57; // rax
  __int64 v58; // rax
  __int64 v59; // rbx
  __int64 v60; // rax
  __int64 v61; // rbx
  __int64 v62; // rax
  __int64 v63; // rdx
  __int64 v64; // rax
  __int64 v65; // rax
  __int64 v66; // rax
  __int64 v67; // rax
  __int64 v68; // [rsp+18h] [rbp-E8h] BYREF
  __int64 v69; // [rsp+20h] [rbp-E0h] BYREF
  __int64 v70; // [rsp+28h] [rbp-D8h] BYREF
  __int64 v71; // [rsp+30h] [rbp-D0h] BYREF
  __int64 v72; // [rsp+38h] [rbp-C8h] BYREF
  __int64 v73; // [rsp+40h] [rbp-C0h] BYREF
  __int64 v74; // [rsp+48h] [rbp-B8h] BYREF
  __int64 v75; // [rsp+50h] [rbp-B0h] BYREF
  __int64 v76; // [rsp+58h] [rbp-A8h] BYREF
  __int64 v77; // [rsp+60h] [rbp-A0h] BYREF
  __int64 v78; // [rsp+68h] [rbp-98h] BYREF
  __int64 v79; // [rsp+70h] [rbp-90h] BYREF
  __int64 v80; // [rsp+78h] [rbp-88h] BYREF
  __int64 v81; // [rsp+80h] [rbp-80h] BYREF
  __int64 v82; // [rsp+88h] [rbp-78h] BYREF
  __int64 v83; // [rsp+90h] [rbp-70h] BYREF
  __int64 v84; // [rsp+98h] [rbp-68h] BYREF
  __int64 v85; // [rsp+A0h] [rbp-60h] BYREF
  __int64 v86; // [rsp+A8h] [rbp-58h] BYREF
  __int64 v87; // [rsp+B0h] [rbp-50h] BYREF
  __int64 v88; // [rsp+B8h] [rbp-48h] BYREF
  __int64 v89; // [rsp+C0h] [rbp-40h] BYREF
  __int64 v90; // [rsp+C8h] [rbp-38h] BYREF
  __int64 v91; // [rsp+D0h] [rbp-30h] BYREF
  __int64 v92; // [rsp+D8h] [rbp-28h] BYREF
  __int64 v93; // [rsp+E0h] [rbp-20h] BYREF

  v2 = std::string::end(input);
  v3 = std::string::begin(input);
  if ( std::all_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#1}>(
         v3,
         v2) )                                  // isalpha
  {
    v4 = std::string::end(input);
    v5 = std::string::begin(input);
    if ( !std::all_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#2}>(
            v5,
            v4) )                               // isxdigit, if non hex digit continue
    {
      v69 = std::string::begin(input);
      v7 = std::string::end(input);
      v8 = std::string::begin(input);
      v70 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#3}>(
              v8,
              v7);
      if ( !__gnu_cxx::operator==<char *,std::string>((__int64)&v70, (__int64)&v69) )// check T
        goto INVALID_FLAG_1;
      v72 = std::string::begin(input);
      v71 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v72, 1LL);
      v10 = std::string::end(input);
      v11 = std::string::begin(input);
      v73 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#4}>(
              v11,
              v10);                             // check h
      if ( !__gnu_cxx::operator==<char *,std::string>((__int64)&v73, (__int64)&v71) )
        goto INVALID_FLAG_1;
      v75 = std::string::begin(input);
      v74 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v75, 2LL);
      v12 = std::string::end(input);
      v13 = std::string::begin(input);
      v76 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#5}>(
              v13,
              v12);                             // check e
      if ( __gnu_cxx::operator==<char *,std::string>((__int64)&v76, (__int64)&v74) )
      {
        v14 = std::operator<<<char>(&_bss_start, input);
        return std::operator<<<std::char_traits<char>>(v14, '_');// VALID_FLAG_1
      }
      else
      {
INVALID_FLAG_1:
        v16 = std::operator<<<std::char_traits<char>>(&_bss_start, "Invalid flag!", v9);
        return std::ostream::operator<<(v16, &MEMORY[0x7EFEAA151910]);
      }
    }
  }
  v17 = std::string::end(input);
  v18 = std::string::begin(input);
  if ( (unsigned __int8)std::any_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#6}>(
                          v18,
                          v17) )                // isalpha
  {
    v19 = std::string::end(input);
    v20 = std::string::begin(input);
    if ( (unsigned __int8)std::any_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#7}>(
                            v20,
                            v19) )              // isalnum
    {
      v22 = (char *)std::string::operator[](input, 0LL);
      if ( isalpha(*v22) )
      {
        v77 = std::string::begin(input);
        v24 = std::string::end(input);
        v25 = std::string::begin(input);
        v78 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#8}>(
                v25,
                v24);                           // C val
        if ( __gnu_cxx::operator==<char *,std::string>((__int64)&v78, (__int64)&v77) )
        {
          v27 = std::string::end(input);
          v28 = std::string::begin(input);
          v68 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#9}>(
                  v28,
                  v27);                         // + val
          v79 = std::string::end(input);
          if ( (unsigned __int8)__gnu_cxx::operator!=<char *,std::string>(&v68, &v79)
            && (v80 = std::string::end(input),
                v30 = std::string::end(input),
                v31 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(
                        &v68,
                        1LL),                   // + val
                v81 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#10}>(
                        v31,
                        v30),
                (unsigned __int8)__gnu_cxx::operator!=<char *,std::string>(&v81, &v80)) )
          {
            v33 = std::operator<<<char>(&_bss_start, input);
            return std::operator<<<std::char_traits<char>>(v33, 95LL);// VALID_FLAG_2
          }
          else
          {
            v34 = std::operator<<<std::char_traits<char>>(&_bss_start, "Invalid flag!", v29);
            return std::ostream::operator<<(v34, &MEMORY[0x7EFEAA151910]);
          }
        }
        else
        {
          v35 = std::operator<<<std::char_traits<char>>(&_bss_start, "Invalid flag!", v26);
          return std::ostream::operator<<(v35, &MEMORY[0x7EFEAA151910]);
        }
      }
INVALID_FLAG_3:
      v67 = std::operator<<<std::char_traits<char>>(&_bss_start, "Invalid flag!", v23);
      return std::ostream::operator<<(v67, &MEMORY[0x7EFEAA151910]);
    }
  }
  v36 = std::string::end(input);
  v37 = std::string::begin(input);
  if ( !(unsigned __int8)std::any_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#11}>(
                           v37,
                           v36)
    || (v38 = std::string::end(input),
        v39 = std::string::begin(input),
        !(unsigned __int8)std::any_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#12}>(
                            v39,
                            v38))
    || (v40 = std::string::end(input),
        v41 = std::string::begin(input),
        (unsigned __int8)std::all_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#13}>(
                           v41,
                           v40) == 1) )
  {
    v59 = std::string::end(input);
    v60 = std::string::begin(input);
    if ( (unsigned __int8)std::all_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#18}>(
                            v60,
                            v59) )
    {
      v61 = std::string::end(input);
      v62 = std::string::begin(input);
      if ( (unsigned int)std::accumulate<__gnu_cxx::__normal_iterator<char *,std::string>,int,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(int,char)#1}>(
                           v62,
                           v61,
                           0) == 0xDEA47FED )
      {
        v64 = std::operator<<<char>(&_bss_start, input);
        v65 = std::operator<<<std::char_traits<char>>(v64, 125LL);// VALID_FLAG_4
        v66 = std::operator<<<std::char_traits<char>>(v65, " is the correct flag!", v65);
      }
      else
      {
        v66 = std::operator<<<std::char_traits<char>>(&_bss_start, "Invalid flag!", v63);
      }
      return std::ostream::operator<<(v66, &MEMORY[0x7EFEAA151910]);
    }
    goto INVALID_FLAG_3;
  }
  v43 = (char *)std::string::operator[](input, 0LL);
  if ( !isalpha(*v43) )
    goto INVALID_FLAG_3;
  v44 = std::string::size(input);
  v45 = (char *)std::string::operator[](input, v44 - 1);
  if ( !isalpha(*v45) )
    goto INVALID_FLAG_3;
  v82 = std::string::end(input);
  v47 = __gnu_cxx::__normal_iterator<char *,std::string>::operator-(&v82, 1LL);
  v83 = std::string::begin(input);
  v48 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v83, 1LL);
  result = std::all_of<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#14}>(
             v48,                               // check digit
             v47);
  if ( (_BYTE)result )
  {
    v85 = std::string::begin(input);
    v84 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v85, 1LL);
    v87 = std::string::end(input);
    v49 = __gnu_cxx::__normal_iterator<char *,std::string>::operator-(&v87, 1LL);
    v88 = std::string::begin(input);
    v50 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v88, 1LL);
    v86 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#15}>(
            v50,                                // 0 val
            v49);
    if ( !__gnu_cxx::operator==<char *,std::string>((__int64)&v86, (__int64)&v84) )
      goto INVALID_FLAG_2;
    v89 = std::string::begin(input);
    v52 = std::string::end(input);
    v53 = std::string::begin(input);
    v90 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#16}>(
            v53,
            v52);                               // G val
    if ( !__gnu_cxx::operator==<char *,std::string>((__int64)&v90, (__int64)&v89) )
      goto INVALID_FLAG_4;
    v92 = std::string::end(input);
    v91 = __gnu_cxx::__normal_iterator<char *,std::string>::operator-(&v92, 1LL);
    v54 = std::string::end(input);
    v55 = std::string::begin(input);
    v93 = std::find_if<__gnu_cxx::__normal_iterator<char *,std::string>,main::{lambda(std::string&)#1}::operator() const(std::string&)::{lambda(char)#17}>(
            v55,                                // d val
            v54);
    if ( __gnu_cxx::operator==<char *,std::string>((__int64)&v93, (__int64)&v91) )
      check_var = 1;
    else
INVALID_FLAG_4:
      check_var = 0;
    if ( check_var )
    {
      v57 = std::operator<<<char>(&_bss_start, input);
      return std::operator<<<std::char_traits<char>>(v57, '_');// VALID_FLAG_3
    }
    else
    {
INVALID_FLAG_2:
      v58 = std::operator<<<std::char_traits<char>>(&_bss_start, "Invalid flag!", v51);
      return std::ostream::operator<<(v58, &MEMORY[0x7EFEAA151910]);
    }
  }
  return result;
}

Flag: INTECHFEST{The_C++_G0d_dea47fed}

Karena tidak ada Assembly-CSharp.dll pada assets maka kita perlu melakukan reverse engineering terhadap libil2cpp.so yang ada pada lib direktori. Disini kita bisa memanfaatkan global-metadata.dat untuk melakukan recover terhadap beberapa informasi pada libil2cpp.so seperti nama fungsi. Gunakan il2cppdumper untuk mendapatkan datanya .

📚
📖
https://github.com/Perfare/Il2CppDumper
Here
Here
Here
Here