Rating:

Optimizer

We were given the challenge text:

EU instance: 207.180.200.166 9660

US instance: 45.134.3.200 9660

author: pop_eax

Upon connecting to the socket using netcat, we got the message

you will be given a number of problems give me the least number of moves to solve them
level 1: tower of hanoi

followed by a list of numbers. This challenge was a bit hard to understand at first, but after a bit of trial and error I figured out what it wanted. According to Wikipedia, the miminum number of solves for a TOH is 2<sup>n</sup>-1., where n is the amount of disks, or in this instance, the length of the integer array. After connecting to the socket via Python and parsing the input, the answer was a simple oneliner current_answer = str(pow(2, len(arr))-1).encode()., where arr is the list we received as input.

After letting the script solve quite a few of these, it hit level 2.

level 2 : merge sort, give me the count of inversions

After trying to learn a bit, I decided to go the easy way instead. This website has copy-paste ready code for finding the inversion count of a merge sort. I copied this into a function, and it worked.

There were no more levels after this, and I received the flag: flag{g077a_0pt1m1ze_3m_@ll}

Since you had to solve a lot for each level, I created a Python script to interact with the socket. (I was expecting more than 2 levels, so it's a bit unnecessary long).

import ast
import re
import socket

current_answer = ''
level = 1

s = socket.socket()
s.connect(('207.180.200.166', 9660)) # connects to the web socket 

def level_1(arr):
    global current_answer
    current_answer = str(pow(2, len(arr))-1).encode() # returns the encoded answer for level 1, Tower of Hanoi 

def level_2(arr):
    global current_answer

    n = len(arr)
    inv_count = 0
    for i in range(n): 
        for j in range(i + 1, n): 
            if (arr[i] > arr[j]): 
                inv_count += 1

    current_answer = str(inv_count).encode() # returns the encoded answer for level 2, merge sort inversions

while True: # continouly read data from socket
    received = s.recv(2048).decode()
    print(received)

    if 'wrong' in received or 'flag' in received:
        quit()
    
    if 'level 1' in received:
        level = 1
    if 'level 2' in received:
        level = 2
        
    if level == 1:
        try:
            inp = re.findall(r'\[[0-9, ]+\]', received)[0] # regex to only get the list itself from the data
            inp = ast.literal_eval(inp) # converts the string list to an actual list
            level_1(inp)
        except IndexError:
            pass
    if level == 2:
        try:
            inp = re.findall(r'\[[0-9, ]+\]', received)[0]
            inp = ast.literal_eval(inp)
            level_2(inp)
        except IndexError:
            pass
    
    if '>' in received: # sends the answer to the socket
        print(current_answer.decode())
        s.send(current_answer)
Original writeup (https://github.com/WastefulNick/CTF-Writeups/tree/master/0x41414141/misc/optimizer).