---
# System prepended metadata

title: amatuersCTF 2024

---

# amatuersCTF 2024
Reverse challenges in this events are fun so i want to keep some of them on my blog.

![image](https://hackmd.io/_uploads/r1kpHI9xC.png)

## typo
> 166 solves / 243 points
> can you make sure i didn't make a typo?
> Downloads
:::spoiler `mian.py`
```python=
import random as RrRrRrrrRrRRrrRRrRRrrRr
RrRrRrrrRrRRrrRRrRRrRrr = int('1665663c', 20)
RrRrRrrrRrRRrrRRrRRrrRr.seed(RrRrRrrrRrRRrrRRrRRrRrr)
arRRrrRRrRRrRRRrRrRRrRr = bytearray(open('flag.txt', 'rb').read())
arRRrrRrrRRrRRRrRrRRrRr = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
arRRrrRRrRRrRrRrRrRRrRr = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]
arRRRrRRrRRrRRRrRrRRrRr = lambda aRrRrRrrrRrRRrrRRrRrrRr: bytearray([arRrrrRRrRRrRRRrRrRrrRr + 1 for arRrrrRRrRRrRRRrRrRrrRr in aRrRrRrrrRrRRrrRRrRrrRr])
arRRrrRRrRRrRRRrRrRrrRr = lambda aRrRrRrrrRrRRrrRRrRrrRr: bytearray([arRrrrRRrRRrRRRrRrRrrRr - 1 for arRrrrRRrRRrRRRrRrRrrRr in aRrRrRrrrRrRRrrRRrRrrRr])
def arRRrrRRrRRrRrRRrRrrRrRr(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex
arRRRRRRrRRrRRRrRrRrrRr = [arRRrrRRrRRrRrRRrRrrRrRr, arRRRrRRrRRrRRRrRrRRrRr, arRRrrRRrRRrRRRrRrRrrRr]
arRRRRRRrRRrRRRrRrRrrRr = [RrRrRrrrRrRRrrRRrRRrrRr.choice(arRRRRRRrRRrRRRrRrRrrRr) for arRrrrRRrRRrRRRrRrRrrRr in range(128)]
def RrRrRrrrRrRRrrRRrRRrrRr(arr, ar):
    for r in ar:
        arr = arRRRRRRrRRrRRRrRrRrrRr[r](arr)
    return arr
def arRRrrRRrRRrRrRRrRrrRrRr(arr, ar):
    ar = int(ar.hex(), 17)
    for r in arr:
        ar += int(r, 35)
    return bytes.fromhex(hex(ar)[2:])
arrRRrrrrRRrRRRrRrRRRRr = RrRrRrrrRrRRrrRRrRRrrRr(arRRrrRRrRRrRRRrRrRRrRr, arRRrrRrrRRrRRRrRrRRrRr.encode())
arrRRrrrrRRrRRRrRrRRRRr = arRRrrRRrRRrRrRRrRrrRrRr(arRRrrRRrRRrRrRrRrRRrRr, arrRRrrrrRRrRRRrRrRRRRr)
print(arrRRrrrrRRrRRRrRrRRRRr.hex())

# output: 5915f8ba06db0a50aa2f3eee4baef82e70be1a9ac80cb59e5b9cb15a15a7f7246604a5e456ad5324167411480f893f97e3
```
:::

This challenge is just simply obfuscate the code so we can deobfuscate by hand and test each function until it's correct. This is my friend's([s1gm4](https://s19ma.github.io/)) script:

```python=
import random as Random_Module
Random_Seed = int('1665663c', 20)
Random_Module.seed(Random_Seed)
Random_part1 = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
Random_part2 = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]
inv_funcion1 = lambda something: bytearray([val - 1 for val in something])
inv_funcion2 = lambda something: bytearray([val + 1 for val in something])

def funcion3(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex

def inv_funcion3(hex):
    for list in range(1, len(hex) - 1, 2):
        hex[list+1], hex[list] = hex[list], hex[list+1]
    for id in range(0, len(hex) - 1, 2):
        hex[id+1], hex[id] = hex[id], hex[id+1]

    return hex

list_func_inv = [inv_funcion3, inv_funcion1, inv_funcion2]
list_func_inv = [Random_Module.choice(list_func_inv) for val in range(128)]

def Random_Module_choice(arr, ar):
    for r in ar:
        arr = list_func_inv[r](arr)
        print(arr)
    return arr

def inv_function3_(arr, ar):
    ar = int(ar, 16)
    for r in arr:
        ar -= int(r, 35)

    return ar

flag_enc = "5915f8ba06db0a50aa2f3eee4baef82e70be1a9ac80cb59e5b9cb15a15a7f7246604a5e456ad5324167411480f893f97e3"
flagg = inv_function3_(Random_part2, flag_enc) 
flaggg = "486f67686960685561685568552559536660375b3a5d28625353275d676753595c6029275a712858536067602b646167" 
fl = bytearray(bytes.fromhex(flaggg))
flag_enc = Random_Module_choice(fl, Random_part1.encode())
print(flag_enc)
```
Flag: ***amateursCTF{4t_l3ast_th15_fl4g_isn7_misspelll3d}***

## cplusplus
> 37 solves / 386 points
> idk why everyone keeps telling me to use c++? c is just as good.

Actually, when I read the title of this challenge, I recognize it is a meme on [reddit](https://www.reddit.com/r/programminghorror/comments/18x7vk9/why_does_everyone_keep_telling_me_to_use_c/). Maybe the challenge is related to that meme? Download the file and open it with IDA, this is a few things we can see.

```C=
unsigned __int64 __fastcall stage_1(unsigned __int64 a1, unsigned __int64 a2)
{
  unsigned __int64 i; // [rsp+18h] [rbp-8h]

  for ( i = 0LL; i < a2; i = s1(i) )
    a1 = s1(a1);
  return a1 % qword_4010;
}
__int64 __fastcall stage_2(__int64 a1, __int64 a2)
{
  return s2(a1, a2, 0LL, stage_1);
}
__int64 __fastcall stage_3(__int64 a1, __int64 a2)
{
  return s2(a1, a2, 1LL, stage_2);
}
unsigned __int64 __fastcall s2(
        unsigned __int64 a1,
        unsigned __int64 a2,
        unsigned __int64 a3,
        __int64 (__fastcall *a4)(unsigned __int64, unsigned __int64))
{
  while ( a2 )
  {
    if ( (a2 & 1) != 0 )
      a3 = a4(a3, a1) % (unsigned __int64)qword_4010;
    a1 = a4(a1, a1) % (unsigned __int64)qword_4010;
    a2 >>= 1;
  }
  return a3;
}
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 v3; // rax
  __int64 v4; // rax
  unsigned __int64 v6; // [rsp+0h] [rbp-70h]
  __int64 i; // [rsp+8h] [rbp-68h]
  FILE *stream; // [rsp+10h] [rbp-60h]
  char ptr[2]; // [rsp+1Eh] [rbp-52h] BYREF
  char s[72]; // [rsp+20h] [rbp-50h] BYREF
  unsigned __int64 v11; // [rsp+68h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  fgets(s, 64, stdin);
  stream = fopen("/dev/urandom", "r");
  fread(ptr, 1uLL, 2uLL, stream);
  fclose(stream);
  v6 = 0LL;
  for ( i = 0LL; s[i]; ++i )
  {
    v3 = stage_1(v6, s[i]);
    v4 = stage_2(v3, (unsigned __int8)ptr[0]);
    v6 = stage_3(v4, (unsigned __int8)ptr[1]);
    if ( i )
      printf(", ");
    printf("%zu", v6);
  }
  putchar(10);
  return 0LL;
}
```

As you can see, the program simply takes 2 bytes randomly and then transforms your input through 3 stages and then prints. But the problem is this program is not optimized so it runs slow as fuck. Because of that, we need to optimize to get the flag. After debugging and reading the code, I know that ``stage_1`` is just adding two parameters and ``stage_2`` is multiplying two parameters 💀. This is enough to run so I don't change stage_3 anymore. Optimizing is done but one more important thing is we need to know 2 bytes randomly in order to generate the right number. Bruteforcing and we get this ``0xed, 0x29``. My final optimized code and solution:

```C=
#include <stdio.h>

size_t stage_2(size_t stage1, size_t random, size_t a3) {
    return (stage1 * random) % 0x3B9ACA07;
}
size_t stage3(size_t stage2, size_t random, size_t a3) {
    while (random) {
        if (random & 1)
            a3 = stage_2(a3, stage2, 0) % 0x3B9ACA07;
        stage2 = stage_2(stage2, stage2, 0) % 0x3B9ACA07;
        random >>= 1;
    }
    return a3;
}

int main() {
size_t flag[] = {816696039, 862511530, 897431439, 341060728, 173157153, 31974957, 491987052, 513290022, 463763452, 949994705, 910803499, 303483511, 378099927, 773435663, 305463445, 656532801, 655150297, 28357806, 69914739, 213536453, 962912446, 458779691, 598643891, 94970179, 732507398, 792930123, 216371336, 680163935, 397010125, 693248832, 926462193, 419350956, 594922380, 944019434, 93600641, 116339550, 373995190, 558908218, 700841647, 703877327, 665247438, 690373754, 35138387, 389900716, 625740467, 682452898, 894528752, 603308386, 442640217, 15961938, 573068354};
printf("a");
for (int i = 1; i < sizeof(flag);i++){
    for (int j = 32; j < 126; j++){
        size_t tmp = 0;
        size_t v3 = stage_2(j + flag[i-1], 0xed, 0);
        tmp += stage3(v3, 0x29, 1);
        if (tmp == flag[i]){
            printf("%c",j);
            break;
            }
        }
    }
}
```

Flag: ***amateursCTF{r/programminghorror/comments/18x7vk9/}***


## revtale-1
> 23 solves / 419 points
> Once upon a time...there was a binary with a flag.

At first, I tried to reverse MiniTale.exe with IDA but that's a dumb way, I got nothing. After that, I noticed the data.win file, it seems not normal so I decided to research about that. After scrolling on the Internet for hours, I finally found that it is a database file of GameMaker, it contains script, audio, and many things. So the first thing is finding some tools that support us opening this kind of file and I found this works [UndertaleModTool](https://github.com/UnderminersTeam/UndertaleModTool). This is the ``src_check_flag`` function

```gml=
funcs = [color_get_hue, color_get_green]
function scr_check_flag(argument0) //gml_Script_scr_check_flag
{
    l = string_lower(argument0)
    if ((string_pos("gaster", l) != 0))
    {
        window_set_caption("redacted")
        game_end(1)
    }
    if ((string_pos("frisk", l) != 0))
    {
        window_set_caption("don't make this hard")
        game_end(1)
    }
    if string_starts_with(argument0, "amateursCTF{")
    {
        if ((string_length(argument0) > 15))
        {
            a = scr_a(argument0)
            if ((a[12] == "{"))
            {
                window_set_caption("no")
                return 0;
            }
            for (i = 0; i < array_length(a); i++)
            {
            }
            aa = (ord(a[12]) & 4095)
            ab = (ord(a[13]) & 2047)
            ac = (ord(a[14]) & 1023)
            ad = (ord(a[15]) & 511)
            arr_op = array_reverse
            color_check = color_get_saturation
            if ((a[12] == a[13]) && (a[12] != a[14]))
            {
                if ((ac == (aa - 2)))
                {
                    if (((ab + 152) == self.color_check(16711935)) && ((ad + 133) == self.color_check(128)))
                    {
                        if (((obj_input_field.pk[0] ^ ord(a[16])) == 0))
                        {
                            if (((obj_input_field.pk[1] ^ ord(a[17])) == 0))
                            {
                                if (((obj_input_field.pk[2] ^ ord(a[18])) == 0))
                                {
                                    if ((ord(a[19]) == (power(2, 6) | 31)))
                                    {
                                        r = self.arr_op(["%", "3", "v", "0", "l", "_"], 0, 6)
                                        c = 0
                                        if ((a[19] == r[0]))
                                            c += 1
                                        if ((a[20] == r[1]))
                                            c += 2
                                        if ((a[21] == r[2]))
                                            c += 3
                                        if ((a[22] == r[3]))
                                            c += 4
                                        if ((a[23] == r[4]))
                                            c += 5
                                        if ((a[20] == a[21]))
                                            c += 5
                                        if ((c == 15))
                                        {
                                            if ((string_pos(file_text_read_string(file_text_open_read("f.txt")), argument0) != 0))
                                                return ((45887 == scr_c((((string_char_at(argument0, 29) + string_char_at(argument0, 30)) + string_char_at(argument0, 31)) + string_char_at(argument0, 32)))) && (ord(a[32]) == 125));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return 0;
        }
        else
            return 0;
    }
    else
        show_message(("flag wrapper missing... you entered " + argument0))
    return 0;
}

```

Now it is clear, that the flow is easy to reverse, i will put that flag only without any explanations.

Flag: ***amateursCTF{ggez_w3_l0v3_vm_b33f}***


## dill-with-it
> 20 solves / 427 points
> Crisp green Larry lies Bathes, brining in vinegar Dill pickle delight
:::spoiler `main.py`
```python=
# Python 3.10.12
n
```
:::

This is pickle - flag checker challenge. So at first, I tried to decode it into human-readable python but it was not that easy. After research, I figured out that pickle files could be disassembled by [pickletools](https://docs.python.org/3/library/pickletools.html)

```python=
0: \x80 PROTO      4
    2: c    GLOBAL     'types FunctionType'
   22: (    MARK
   23: c        GLOBAL     'types CodeType'
   39: (        MARK
   40: I            INT        1
   43: I            INT        0
   46: I            INT        0
   49: I            INT        4
   52: I            INT        8
   55: I            INT        67
   59: C            SHORT_BINBYTES b't\x00\xa0\x01|\x00d\x01\xa1\x02}\x01t\x02|\x01\x83\x01d\x00d\x00d\x02\x85\x03\x19\x00d\x00d\x03\x85\x02\x19\x00}\x00d\x04}\x02t\x03d\x05t\x04|\x00\x83\x01d\x06\x83\x03D\x00]\x11}\x03|\x02t\x05t\x00|\x00|\x03|\x03d\x06\x17\x00\x85\x02\x19\x00d\x07\x83\x02\x83\x017\x00}\x02q\x1d|\x02S\x00'
  159: (            MARK
  160: N                NONE
  161: V                UNICODE    'big'
  166: I                INT        -1
  170: I                INT        -3
  174: V                UNICODE    ''
  176: I                INT        0
  179: I                INT        8
  182: I                INT        2
  185: t                TUPLE      (MARK at 159)
  186: (            MARK
  187: V                UNICODE    'int'
  192: V                UNICODE    'from_bytes'
  204: V                UNICODE    'bin'
  209: V                UNICODE    'range'
  216: V                UNICODE    'len'
  221: V                UNICODE    'chr'
  226: t                TUPLE      (MARK at 186)
  227: (            MARK
  228: \x8c             SHORT_BINUNICODE '🔥'
  234: \x8c             SHORT_BINUNICODE '🤫'
  240: \x8c             SHORT_BINUNICODE '🧏'
  246: \x8c             SHORT_BINUNICODE '🎵'
  252: t                TUPLE      (MARK at 227)
  253: V            UNICODE    'dill-with-it'
  267: \x8c         SHORT_BINUNICODE '📮'
  273: I            INT        0
  276: C            SHORT_BINBYTES b'\x00\x01\x0c\x01\x1a\x01\x04\x01\x14\x01 \x01'
  290: )            EMPTY_TUPLE
  291: )            EMPTY_TUPLE
  292: t            TUPLE      (MARK at 39)
  293: \x81     NEWOBJ
  294: c        GLOBAL     'builtins globals'
  312: )        EMPTY_TUPLE
  313: R        REDUCE
  314: \x8c     SHORT_BINUNICODE '📮'
  320: t        TUPLE      (MARK at 22)
  321: \x81 NEWOBJ
  322: \x94 MEMOIZE    (as 0)
  323: 0    POP
  324: g    GET        0
  327: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  338: \x85 TUPLE1
  339: R    REDUCE
  340: g    GET        0
  343: C    SHORT_BINBYTES b'\x01.\xce\x966'
  350: \x85 TUPLE1
  351: R    REDUCE
  352: \x93 STACK_GLOBAL
  353: g    GET        0
  356: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  367: \x85 TUPLE1
  368: R    REDUCE
  369: g    GET        0
  372: C    SHORT_BINBYTES b'\x01\xa6&\xf6\xc6v\xa6tN.\xce'
  385: \x85 TUPLE1
  386: R    REDUCE
  387: \x93 STACK_GLOBAL
  388: g    GET        0
  391: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  402: \x85 TUPLE1
  403: R    REDUCE
  404: g    GET        0
  407: C    SHORT_BINBYTES b'\x01.v\x96N\x0e'
  415: \x85 TUPLE1
  416: R    REDUCE
  417: \x93 STACK_GLOBAL
  418: V    UNICODE    "What's the flag? "
  437: \x85 TUPLE1
  438: R    REDUCE
  439: 0    POP
  440: g    GET        0
  443: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  454: \x85 TUPLE1
  455: R    REDUCE
  456: g    GET        0
  459: C    SHORT_BINBYTES b'\x01.\xae\x0ev\x96'
  467: \x85 TUPLE1
  468: R    REDUCE
  469: \x93 STACK_GLOBAL
  470: V    UNICODE    '> '
  474: \x85 TUPLE1
  475: R    REDUCE
  476: \x85 TUPLE1
  477: R    REDUCE
  478: \x85 TUPLE1
  479: R    REDUCE
  480: \x94 MEMOIZE    (as 1)
  481: 0    POP
  482: g    GET        0
  485: C    SHORT_BINBYTES b'\x01\xb6\xf6&v\x86N'
  494: \x85 TUPLE1
  495: R    REDUCE
  496: g    GET        0
  499: C    SHORT_BINBYTES b'\x01&\xa6\xa6\xce'
  506: \x85 TUPLE1
  507: R    REDUCE
  508: \x93 STACK_GLOBAL
  509: V    UNICODE    'five nights as freddy'
  532: \x85 TUPLE1
  533: R    REDUCE
  534: 0    POP
  535: g    GET        0
  538: C    SHORT_BINBYTES b'\x01\xb6\xf6&v\x86N'
  547: \x85 TUPLE1
  548: R    REDUCE
  549: g    GET        0
  552: C    SHORT_BINBYTES b'\x01\xa66ff\xae\x16\xce'
  562: \x85 TUPLE1
  563: R    REDUCE
  564: \x93 STACK_GLOBAL
  565: g    GET        1
  568: \x85 TUPLE1
  569: R    REDUCE
  570: 0    POP
  571: g    GET        0
  574: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  585: \x85 TUPLE1
  586: R    REDUCE
  587: g    GET        0
  590: C    SHORT_BINBYTES b'\x01.\xce\x966'
  597: \x85 TUPLE1
  598: R    REDUCE
  599: \x93 STACK_GLOBAL
  600: g    GET        0
  603: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  614: \x85 TUPLE1
  615: R    REDUCE
  616: g    GET        0
  619: C    SHORT_BINBYTES b'\x01\x0e\x86\xb6'
  625: \x85 TUPLE1
  626: R    REDUCE
  627: \x93 STACK_GLOBAL
  628: g    GET        0
  631: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  642: \x85 TUPLE1
  643: R    REDUCE
  644: g    GET        0
  647: C    SHORT_BINBYTES b'\x01\xfa\xfaN\xf6\x1e\xfa\xfat.v\x96'
  661: \x85 TUPLE1
  662: R    REDUCE
  663: \x93 STACK_GLOBAL
  664: g    GET        0
  667: C    SHORT_BINBYTES b'\x01\xb6\xf6&v\x86N'
  676: \x85 TUPLE1
  677: R    REDUCE
  678: g    GET        0
  681: C    SHORT_BINBYTES b'\x01\xce\xa6.\x9eF&v\x86N'
  693: \x85 TUPLE1
  694: R    REDUCE
  695: \x93 STACK_GLOBAL
  696: g    GET        0
  699: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  710: \x85 TUPLE1
  711: R    REDUCE
  712: g    GET        0
  715: C    SHORT_BINBYTES b'\x01v\xa66'
  721: \x85 TUPLE1
  722: R    REDUCE
  723: \x93 STACK_GLOBAL
  724: g    GET        1
  727: \x85 TUPLE1
  728: R    REDUCE
  729: \x85 TUPLE1
  730: R    REDUCE
  731: g    GET        1
  734: \x87 TUPLE3
  735: R    REDUCE
  736: \x85 TUPLE1
  737: R    REDUCE
  738: \x94 MEMOIZE    (as 2)
  739: 0    POP
  740: g    GET        0
  743: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  754: \x85 TUPLE1
  755: R    REDUCE
  756: g    GET        0
  759: C    SHORT_BINBYTES b'\x01\x9ev\x86'
  765: \x85 TUPLE1
  766: R    REDUCE
  767: \x93 STACK_GLOBAL
  768: g    GET        0
  771: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  782: \x85 TUPLE1
  783: R    REDUCE
  784: g    GET        0
  787: C    SHORT_BINBYTES b'\x01\x0e\x86\xb6'
  793: \x85 TUPLE1
  794: R    REDUCE
  795: \x93 STACK_GLOBAL
  796: g    GET        0
  799: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
  810: \x85 TUPLE1
  811: R    REDUCE
  812: g    GET        0
  815: C    SHORT_BINBYTES b'\x01\xfa\xfaN\xf6\x1e\xfa\xfat.v\x96'
  829: \x85 TUPLE1
  830: R    REDUCE
  831: \x93 STACK_GLOBAL
  832: (    MARK
  833: I        INT        138
  838: I        INT        13
  842: I        INT        157
  847: I        INT        66
  851: I        INT        68
  855: I        INT        12
  859: I        INT        223
  864: I        INT        147
  869: I        INT        198
  874: I        INT        223
  879: I        INT        92
  883: I        INT        172
  888: I        INT        59
  892: I        INT        56
  896: I        INT        27
  900: I        INT        117
  905: I        INT        173
  910: I        INT        21
  914: I        INT        190
  919: I        INT        210
  924: I        INT        44
  928: I        INT        194
  933: I        INT        23
  937: I        INT        169
  942: I        INT        57
  946: I        INT        136
  951: I        INT        5
  954: I        INT        120
  959: I        INT        106
  964: I        INT        255
  969: I        INT        192
  974: I        INT        98
  978: I        INT        64
  982: I        INT        124
  987: I        INT        59
  991: I        INT        18
  995: I        INT        124
 1000: I        INT        97
 1004: I        INT        62
 1008: I        INT        168
 1013: I        INT        181
 1018: I        INT        61
 1022: I        INT        164
 1027: I        INT        22
 1031: I        INT        187
 1036: I        INT        251
 1041: I        INT        110
 1046: I        INT        214
 1051: I        INT        250
 1056: I        INT        218
 1061: I        INT        213
 1066: I        INT        71
 1070: I        INT        206
 1075: I        INT        159
 1080: I        INT        212
 1085: I        INT        169
 1090: I        INT        208
 1095: I        INT        21
 1099: I        INT        236
 1104: l        LIST       (MARK at 832)
 1105: g    GET        2
 1108: \x87 TUPLE3
 1109: R    REDUCE
 1110: \x85 TUPLE1
 1111: R    REDUCE
 1112: \x94 MEMOIZE    (as 3)
 1113: 0    POP
 1114: g    GET        0
 1117: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
 1128: \x85 TUPLE1
 1129: R    REDUCE
 1130: g    GET        0
 1133: C    SHORT_BINBYTES b'\x01\xfa\xfaN\xf6\xfa\xfat.v\x96'
 1146: \x85 TUPLE1
 1147: R    REDUCE
 1148: \x93 STACK_GLOBAL
 1149: g    GET        3
 1152: g    GET        0
 1155: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
 1166: \x85 TUPLE1
 1167: R    REDUCE
 1168: g    GET        0
 1171: C    SHORT_BINBYTES b'\x01\xfa\xfa\xa6v\xfa\xfat.v\x96'
 1184: \x85 TUPLE1
 1185: R    REDUCE
 1186: \x93 STACK_GLOBAL
 1187: g    GET        0
 1190: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
 1201: \x85 TUPLE1
 1202: R    REDUCE
 1203: g    GET        0
 1206: C    SHORT_BINBYTES b'\x01v\xa66'
 1212: \x85 TUPLE1
 1213: R    REDUCE
 1214: \x93 STACK_GLOBAL
 1215: g    GET        2
 1218: \x85 TUPLE1
 1219: R    REDUCE
 1220: I    INT        59
 1224: \x86 TUPLE2
 1225: R    REDUCE
 1226: \x86 TUPLE2
 1227: R    REDUCE
 1228: \x94 MEMOIZE    (as 4)
 1229: 0    POP
 1230: g    GET        0
 1233: C    SHORT_BINBYTES b'\x01\xcev\x96.6\x96\xaeF'
 1244: \x85 TUPLE1
 1245: R    REDUCE
 1246: g    GET        0
 1249: C    SHORT_BINBYTES b'\x01\xfa\xfa\xb6\xa6.\x96.\xa6\xe6\xfa\xfat.\xce\x966'
 1268: \x85 TUPLE1
 1269: R    REDUCE
 1270: \x93 STACK_GLOBAL
 1271: (    MARK
 1272: V        UNICODE    'Looks like you got it!'
 1296: V        UNICODE    'Nah, try again.'
 1313: l        LIST       (MARK at 1271)
 1314: g    GET        4
 1317: \x86 TUPLE2
 1318: R    REDUCE
 1319: .    STOP
highest protocol among opcodes = 4
```

As you can see, it is so difficult to understand, so that I researched more about some tools can debug pickle and luckily we got that [pickledbg](https://github.com/Legoclones/pickledbg). Now our jobs will be easier... or not?  🤣

First, it will receive out input and convert to int and save in memo 

![image](https://hackmd.io/_uploads/BkvKKjfxC.png)

After that, it will call ``five nights as freddy`` function, and do some random shuffle and save it again in memo.

![image](https://hackmd.io/_uploads/rJcjYiMl0.png)

Next, it will xor the shuffled array with these bytes 
> \xd5d\xf0x0?\x86\xfc\xb6\xab\x03\x96RY*)\xca`\xda\xb7\x01\xb9j\xc8\\\xe7bH\x0f\x8c\xb4=2#HsO\x0ea\xc9\xdbO\xc8d\xf7\x96\r\x90\xae\x99\xbe\x18\xbd\xcd\xa0\xdd\xe4J\x84

![image](https://hackmd.io/_uploads/BJGZqiMx0.png)

Finally, it will compare with array in stack.

![image](https://hackmd.io/_uploads/HysM5izl0.png)

Now it is easy to reverse. My final script:

```python=
from pwn import *
flag_shuf = [138, 13, 157, 66, 68, 12, 223, 147, 198, 223, 92, 172, 59, 56, 27, 117, 173, 21, 190, 210, 44, 194, 23, 169, 57, 136, 5, 120, 106, 255, 192, 98, 64, 124, 59, 18, 124, 97, 62, 168, 181, 61, 164, 22, 187, 251, 110, 214, 250, 218, 213, 71, 206, 159, 212, 169, 208, 21, 236]
xor_key = b'\xd5d\xf0x0?\x86\xfc\xb6\xab\x03\x96RY*)\xca`\xda\xb7\x01\xb9j\xc8\\\xe7bH\x0f\x8c\xb4=2#HsO\x0ea\xc9\xdbO\xc8d\xf7\x96\r\x90\xae\x99\xbe\x18\xbd\xcd\xa0\xdd\xe4J\x84'
unshuf_flag = xor(flag_shuf,xor_key)
orin_inndex = [48, 19, 44, 50, 33, 17, 39, 52, 12, 54, 29, 55, 41, 2, 13, 49, 30, 5, 57, 28, 18, 11, 58, 0, 56, 31, 51, 45, 4, 42, 3, 25, 37, 43, 20, 32, 47, 23, 34, 53, 22, 38, 35, 6, 16, 1, 14, 10, 9, 8, 15, 40, 7, 46, 24, 26, 36, 21, 27]
for i in range(len(orin_inndex)):
    c = orin_inndex.index(i)
    print(chr(unshuf_flag[c]),end="")
```

Flag: ***amateursCTF{p1ckL3-is_not_the_goat_l4rrY_is_m0R3_\:goat:ed}***


## gogogaga
> 17 solves / 436 points
> "wow its my favorite language to rev" - nobody

First time, I could solve golang reverse challenge. Btw, this challenge makes me so crazy. It tooks me nearly 12 hours to solve (~~because of my skill issue~~). Download binary and try to run it, it simple takes key and if it is correct, we will get flag.

Open bin with IDA and start analyzing, golang is so shit when it is decompiled :+1:. At first, it will take our input into ``main_checkKey`` function. In that function has more 5 ``main_checkKey_func1`` to ``main_checkKey_func5`` 💀. The nightmare has come, but we need to do this.

```C=
// main.checkKey
bool __golang main_checkKey(string key)
{
  __int64 v1; // r14
  __int64 v2; // rcx
  __int64 v4; // rdx
  __int64 v5; // rcx
  unsigned __int64 j; // rbx
  runtime_funcval *v7; // rax
  __int64 v8; // rcx
  runtime_hchan *v9; // rdx
  _QWORD *v10; // r11
  runtime_funcval *v11; // rax
  __int64 v12; // rcx
  runtime_hchan *v13; // rdx
  _QWORD *v14; // r11
  runtime_funcval *v15; // rax
  __int64 v16; // rcx
  runtime_hchan *v17; // rdx
  _QWORD *v18; // r11
  runtime_funcval *v19; // rax
  __int64 v20; // rcx
  runtime_hchan *v21; // rdx
  _QWORD *v22; // r11
  runtime_funcval *v23; // rax
  __int64 v24; // rcx
  runtime_hchan *v25; // rdx
  _QWORD *v26; // r11
  __int64 i; // rax
  uint8 v28; // si
  uint8 v29; // si
  bool elem; // [rsp+1h] [rbp-31h] BYREF
  __int64 v31; // [rsp+2h] [rbp-30h]
  uintptr v32; // [rsp+Ah] [rbp-28h]
  __int64 *array; // [rsp+12h] [rbp-20h]
  runtime_hchan *c; // [rsp+1Ah] [rbp-18h]
  __int64 v35; // [rsp+22h] [rbp-10h]
  void *retaddr; // [rsp+32h] [rbp+0h] BYREF
  string v37; // 0:rcx.8,8:rdi.8
  _slice_string v38; // 0:rax.8,8:rbx.8,16:rcx.8

  if ( (unsigned __int64)&retaddr <= *(_QWORD *)(v1 + 16) )
  {
    runtime_morestack_noctxt();
    JUMPOUT(0x495FC5LL);
  }
  v37.str = (uint8 *)&runtime_gcbits__ptr_;
  v37.len = 1LL;
  v38 = strings_genSplit(key, v37, 0LL, -1LL);
  if ( v38.len != 5 )
    return 0;
  v2 = 0LL;
LABEL_6:
  if ( v2 >= 5 )
  {
    array = (__int64 *)v38.array;
    c = runtime_makechan((internal_abi_ChanType *)&RTYPE_chan_bool_0, 5LL);
    v32 = array[1];
    v35 = *array;
    v7 = (runtime_funcval *)runtime_newobject((internal_abi_Type *)&stru_4A7560);
    v7->fn = (uintptr)main_checkKey_func1;
    v7[2].fn = v32;
    if ( *(_DWORD *)&runtime_writeBarrier.enabled )
    {
      runtime_gcWriteBarrier2();
      v8 = v35;
      *v10 = v35;
      v9 = c;
      v10[1] = c;
    }
    else
    {
      v8 = v35;
      v9 = c;
    }
    v7[1].fn = v8;
    v7[3].fn = (uintptr)v9;
    runtime_newproc(v7);
    v32 = array[3];
    v35 = array[2];
    v11 = (runtime_funcval *)runtime_newobject((internal_abi_Type *)&stru_4A7600);
    v11->fn = (uintptr)main_checkKey_func2;
    v11[2].fn = v32;
    if ( *(_DWORD *)&runtime_writeBarrier.enabled )
    {
      runtime_gcWriteBarrier2();
      v12 = v35;
      *v14 = v35;
      v13 = c;
      v14[1] = c;
    }
    else
    {
      v12 = v35;
      v13 = c;
    }
    v11[1].fn = v12;
    v11[3].fn = (uintptr)v13;
    runtime_newproc(v11);
    v32 = array[5];
    v35 = array[4];
    v15 = (runtime_funcval *)runtime_newobject((internal_abi_Type *)&stru_4A76A0);
    v15->fn = (uintptr)main_checkKey_func3;
    v15[2].fn = v32;
    if ( *(_DWORD *)&runtime_writeBarrier.enabled )
    {
      runtime_gcWriteBarrier2();
      v16 = v35;
      *v18 = v35;
      v17 = c;
      v18[1] = c;
    }
    else
    {
      v16 = v35;
      v17 = c;
    }
    v15[1].fn = v16;
    v15[3].fn = (uintptr)v17;
    runtime_newproc(v15);
    v32 = array[7];
    v35 = array[6];
    v19 = (runtime_funcval *)runtime_newobject((internal_abi_Type *)&stru_4A7740);
    v19->fn = (uintptr)main_checkKey_func4;
    v19[2].fn = v32;
    if ( *(_DWORD *)&runtime_writeBarrier.enabled )
    {
      runtime_gcWriteBarrier2();
      v20 = v35;
      *v22 = v35;
      v21 = c;
      v22[1] = c;
    }
    else
    {
      v20 = v35;
      v21 = c;
    }
    v19[1].fn = v20;
    v19[3].fn = (uintptr)v21;
    runtime_newproc(v19);
    v32 = array[9];
    v35 = array[8];
    v23 = (runtime_funcval *)runtime_newobject((internal_abi_Type *)&stru_4A77E0);
    v23->fn = (uintptr)main_checkKey_func5;
    v23[2].fn = v32;
    if ( *(_DWORD *)&runtime_writeBarrier.enabled )
    {
      runtime_gcWriteBarrier2();
      v24 = v35;
      *v26 = v35;
      v25 = c;
      v26[1] = c;
    }
    else
    {
      v24 = v35;
      v25 = c;
    }
    v23[1].fn = v24;
    v23[3].fn = (uintptr)v25;
    runtime_newproc(v23);
    for ( i = 0LL; i < 5; i = v31 + 1 )
    {
      v31 = i;
      elem = 0;
      runtime_chanrecv1(c, &elem);
      if ( !elem )
        return 0;
    }
    return 1;
  }
  else
  {
    v4 = v2;
    v5 = v2;
    if ( v38.array[v5].len == 5 )
    {
      for ( j = 0LL; ; ++j )
      {
        if ( (__int64)j >= 5 )
        {
          v2 = v4 + 1;
          goto LABEL_6;
        }
        if ( j >= v38.array[v5].len )
          runtime_panicIndex();
        v28 = v38.array[v5].str[j];
        elem = v28 < 0x41u;
        if ( v28 >= 0x41u )
        {
          if ( j >= v38.array[v5].len )
            runtime_panicIndex();
          elem = v38.array[v5].str[j] > 0x5Au;
        }
        if ( elem )
        {
          if ( j >= v38.array[v5].len )
            runtime_panicIndex();
          v29 = v38.array[v5].str[j];
          elem = v29 < 0x30u;
          if ( v29 >= 0x30u )
          {
            if ( j >= v38.array[v5].len )
              runtime_panicIndex();
            elem = v38.array[v5].str[j] > 0x39u;
          }
          if ( elem )
            break;
        }
      }
      return 0;
    }
    else
    {
      return 0;
    }
  }
}
```

Before talking about 5 check functions, the most important things we need to concern is ``strings_genSplit``. During the contest, i didn't noticed this so it took a long time to solve. About that function, it simply count how many **-** in our string and separate it into 5 part corresponding to 5 check functions. So we need 4 **-** in our string, and after that it will go down and checking each input characters if them are in range ``0->9`` and ``A-Z``. If two conditions are correct, it will go to the main func check.

```C=
v38 = strings_genSplit(key, v37, 0LL, -1LL);
if ( v38.len != 5 )
return 0;
v2 = 0LL;
LABEL_6:

...

else
  {
    v4 = v2;
    v5 = v2;
    if ( v38.array[v5].len == 5 )
    {
      for ( j = 0LL; ; ++j )
      {
        if ( (__int64)j >= 5 )
        {
          v2 = v4 + 1;
          goto LABEL_6;
        }
        if ( j >= v38.array[v5].len )
          runtime_panicIndex();
        v28 = v38.array[v5].str[j];
        elem = v28 < 0x41u;
        if ( v28 >= 0x41u )
        {
          if ( j >= v38.array[v5].len )
            runtime_panicIndex();
          elem = v38.array[v5].str[j] > 0x5Au;
        }
        if ( elem )
        {
          if ( j >= v38.array[v5].len )
            runtime_panicIndex();
          v29 = v38.array[v5].str[j];
          elem = v29 < 0x30u;
          if ( v29 >= 0x30u )
          {
            if ( j >= v38.array[v5].len )
              runtime_panicIndex();
            elem = v38.array[v5].str[j] > 0x39u;
          }
          if ( elem )
            break;
        }
      }
      return 0;
    }
    else
    {
      return 0;
    }
  }
```
``main_checkKey_func1`` is just compare the string with base64 encoding, we can easily get the first string is **LARRY**


```C=
c = (runtime_hchan *)check;
  len = key.len;
  v10.str = key.str;
  v10.len = len;
  v11 = runtime_stringtoslicebyte((runtime_tmpBuf *)&elem[1], v10);
  cap = v11.cap;
  v11.cap = v11.len;
  v11.len = (int)v11.array;
  v5 = encoding_base64__ptr_Encoding_EncodeToString(encoding_base64_StdEncoding, *(_slice_uint8 *)&v11.len);
  v6 = v5.len == 8 && *(_QWORD *)v5.str == 0x3D6B6C5553464554LL;
  elem[0] = v6;
  runtime_chansend1(c, elem);
```

``main_checkKey_func2`` will check if our input is in range ``0->9`` and does basic compare.

```C=
while ( v3 < 5 )
{
if ( key.len <= (unsigned __int64)v3 )
  runtime_panicIndex();
v6 = key.str[v3];
elem[0] = v6 < '0';
if ( v6 >= '0' )
  elem[0] = key.str[v3] > '9';
if ( elem[0] )
{
  runtime_chansend1((runtime_hchan *)check, &runtime_egcbss);
  return;
}
v5 = (unsigned __int8)(key.str[v3++] - 48);
v4 += v5;
}
elem[0] = v4 == 35;
runtime_chansend1((runtime_hchan *)check, elem);
```

Part 2:

```C=
#include <stdio.h>
int main(){
    for (int i = 48; i < 58; i++){
        for (int j = 48; j < 58; j++){
            for (int x = 48; x < 58; x++){
                for (int y = 48; y < 58; y++){
                    for (int z = 48; z < 58; z++){
                    int tmp = (i - 48) + (j - 48) + (x - 48) + (y - 48) + (z - 48);
                    if (tmp == 35){
                        printf("%c%c%c%c%c :%d\n",i,j,x,y,z,tmp);
                }
              }
            }
        }
      }
    }
}
```
I will take **77777** for part 2. Next will be ``main_checkKey_func3``, this function is similar with part 2 but the most different is we need to find a string that each character is different from each one. This is because of ``runtime_mapassign()``

```C=
while ( v6 < 5 )
  {
    if ( len <= v6 )
      runtime_panicIndex();
    v7 = v5[v6];
    if ( (unsigned __int8)v7 < 0x41u
      || (unsigned __int8)v7 > 0x5Au
      || (v10 = v6, v9 = v7, *(_BYTE *)runtime_mapaccess1((internal_abi_MapType *)&RTYPE_map_uint8_bool_0, &h, &v9)) )
    {
      runtime_chansend1(c, &runtime_egcbss);
      return;
    }
    v9 = keya[v10];
    *(_BYTE *)runtime_mapassign((internal_abi_MapType *)&RTYPE_map_uint8_bool_0, &h, &v9) = 1;
    v6 = v10 + 1;
    len = key.len;
    v5 = keya;
  }
  v18.str = v5;
  v18.len = len;
  v19 = runtime_stringtoslicebyte((runtime_tmpBuf *)buf, v18);
  for ( i = 0LL; i < 5; ++i )
  {
    if ( v19.len <= (unsigned __int64)i )
      runtime_panicIndex();
    v19.array[i] ^= 0x60;
  }
  v17 = runtime_slicebytetostring((runtime_tmpBuf *)v12, v19.array, v19.len);
  main_Tuesday(v17, (chan_bool)c);
```

Part 3:

```C=
#include <stdio.h>

int check_diff(int i, int j, int x, int y, int z) {
    int values[5] = {i, j, x, y, z};
    for (int idx1 = 0; idx1 < 5; idx1++) {
        for (int idx2 = idx1 + 1; idx2 < 5; idx2++) {
            if (values[idx1] == values[idx2]) {
                return 0;
            }
        }
    }
    return 1;
}
int main(){
    for (int i = 80; i < 90; i++){
        for (int j = 80; j < 90; j++){
            for (int x = 80; x < 90; x++){
                for (int y = 80; y < 90; y++){
                    for (int z = 80; z < 90; z++){
                    int tmp = ((i ^ 0x60) - 48) + ((j ^ 0x60) - 48) + ((x ^ 0x60) - 48) + ((y ^ 0x60) - 48) + ((z ^ 0x60) - 48);
                    if (tmp == 35 && check_diff(i,j,x,y,z)){
                        printf("%c%c%c%c%c :%d\n",i,j,x,y,z,tmp);
                    }
              }
            }
        }
      }
    }
}
```
I will choose **WVYUX**. ``main_checkKey_func4`` is the tricky one, if you just read the pseudocode, you will not be able to solve this. This is the 
pseudocode:

```C=
v4 = 0LL;
  v5 = 0LL;
  v6 = 0LL;
  while ( v4 < 5 )
  {
    if ( v15.len <= (unsigned __int64)v4 )
      runtime_panicIndex();
    for ( i = v15.array[v4]; (_BYTE)i; i = v10 )
    {
      v8 = v5-- + 1;
      v9 = v6-- + 1;
      v10 = i;
      if ( (i & 1) != 0 )
        v5 = v8;
      if ( (i & 2) != 0 )
        v6 = v9;
      LOBYTE(v10) = (unsigned __int8)i >> 2;
    }
    ++v4;
  }
  elem[0] = v5 == 5;
  if ( v5 == 5 )
    elem[0] = v6 == 3;
  runtime_chansend1(c, elem);
}
```
Look easy right? You are wrong 🤣. If you just copy and paste that code, im sure you will not get any correct solution. 

![image](https://hackmd.io/_uploads/HJ_nOFXlR.png)

This the correct what this function does. We can implement this easily and got suitable value.

```python=
def sus(i1, i2, i3, i4, i5):

    rdx = 0
    rsi = 0

    input = i1
    while input:
        r8 = rdx + 1
        rdx -= 1
        r9 = rsi + 1
        rsi -= 1

        if input & 1 != 0:
            rdx = r8
        if input & 2 != 0:
            rsi = r9
        input >>=2

    input = i2
    while input:
        r8 = rdx + 1
        rdx -= 1
        r9 = rsi + 1
        rsi -= 1

        if input & 1 != 0:
            rdx = r8
        if input & 2 != 0:
            rsi = r9
        input >>=2

    input = i3
    while input:
        r8 = rdx + 1
        rdx -= 1
        r9 = rsi + 1
        rsi -= 1

        if input & 1 != 0:
            rdx = r8
        if input & 2 != 0:
            rsi = r9
        input >>=2
       

    input = i4
    while input:
        r8 = rdx + 1
        rdx -= 1
        r9 = rsi + 1
        rsi -= 1

        if input & 1 != 0:
            rdx = r8
        if input & 2 != 0:
            rsi = r9
        input >>=2
    
    input = i5
    while input:
        r8 = rdx + 1
        rdx -= 1
        r9 = rsi + 1
        rsi -= 1

        if input & 1 != 0:
            rdx = r8
        if input & 2 != 0:
            rsi = r9
        input >>=2

    
    if rdx == 5 and rsi == 3:
        print(chr(i1) + chr(i2) + chr(i3) + chr(i4) +chr(i5))


for i in range(48, 58):
    for j in range(48, 58):
        for x in range(48, 58):
            for y in range(48, 58):
                for z in range(48, 58):
                    sus(i,j,x,y,z)
```

So fourth part will be **99994**. Combine 4 parts, now we have **LARRY-77777-WVYUX-99994-**. The hardest part is comming up next, the ``main_checkKey_func5``

```C=
key_8 = key.len;
keya = (char *)key.str;
v23 = check;
qmemcpy(v21, "UNL0CK", sizeof(v21));
v3 = (char *)((__int64 (__fastcall *)(_BYTE *))loc_45E299)(v19);
v5 = 0LL;
while ( v5 < 6 )
{
v22 = v5;
v6 = runtime_makeslice((internal_abi_Type *)&RTYPE_uint_0, 7LL, 7LL);
v7 = v22;
v8 = 3 * v22;
v25[v8] = 7LL;
v25[v8 + 1] = 7LL;
v25[v8 - 1] = (__int64)v6;
v5 = v7 + 1;
v3 = keya;
v4 = (runtime_hchan *)v23;
key.len = key_8;
}
for ( i = 0LL; i < 6; ++i )
{
if ( !v25[3 * i] )
  runtime_panicIndex();
*(_QWORD *)v25[3 * i - 1] = i;
}
for ( j = 0LL; j < 7; ++j )
{
if ( (unsigned __int64)j >= v25[0] )
  runtime_panicIndex();
*(_QWORD *)(v24 + 8 * j) = j;
}
for ( k = 1LL; k < 6; ++k )
{
for ( m = 1LL; (__int64)m < 7; ++m )
{
  if ( key.len <= (unsigned __int64)(k - 1) )
    runtime_panicIndex();
  v13 = m - 1;
  if ( v21[m - 1] == v3[k - 1] ) // Check each input with each string v21
  {
    if ( *(&v22 + 3 * k) <= v13 )
      runtime_panicIndex();
    if ( m >= v25[3 * k] )
      runtime_panicIndex();
    *(_QWORD *)(v25[3 * k - 1] + 8 * m) = *(_QWORD *)(*(_QWORD *)&v19[24 * k + 24] + 8 * m - 8); // doing A stuff
  }
  else
  {
    v14 = *(char **)&v19[24 * k + 24]; // doing B stuffs
    if ( m >= *(&v22 + 3 * k) )
      runtime_panicIndex();
    v15 = v25[3 * k];
    v16 = *(_QWORD *)&v14[8 * m];
    v17 = (char *)v25[3 * k - 1];
    if ( v15 <= v13 )
      runtime_panicIndex();
    v18 = *(_QWORD *)&v14[8 * m - 8];
    if ( *(_QWORD *)&v17[8 * m - 8] < v16 )
      v16 = *(_QWORD *)&v17[8 * m - 8];
    if ( v18 < v16 )
      v16 = v18;
    if ( m >= v15 )
      runtime_panicIndex();
    *(_QWORD *)&v17[8 * m] = v16 + 1; 
  }
}
}
```

After debugging and reading code, i didn't completely understand what this function does :crying_cat_face:. But to summerizing, each input's character will be compared with v21 string, if it is the same, it will do A stuffs, if not will do B stuffs. So my solution will be brutefoce... with the input must be combination of ``UNL0CK`` with some characters. After bruteforcing, if you use combination from this string ``UNL0CK1``, you will have the final answer. First i use ``crunch`` to automatic generate combinations for me by ``crunch 5 5 UNL0CK1 > tmp.txt``. And using this script to brutefoce.


```python=
from pwn import *

flag = "LARRY-77777-WVYUX-99994-"
def send_combinations(file_name):
    with open(file_name, 'r') as file:
        for line in file:
            combination = line.strip()  # 
            payload = flag + combination
            p = process("./main") 
            p.recvuntil('> ')
            p.sendline(payload)
            l = p.recvall()
            if b"again" not in l:
                print(l)
                print(combination)
                p.interactive()
            else:
                p.close()
            
send_combinations("tmp.txt")
```

Nice the final part is **UUUCK**. So the key will be **LARRY-99935-WVYUX-99994-UUUCK**

![image](https://hackmd.io/_uploads/HkPWpY7eA.png)

Flag: ***amateursCTF{c4nt_b3liev3_g0_ogl3_r30p3ned_CTF_sp0n50rs}***