are_you_serialz - Writeup by palkeo

Challenge :

We are proud of our new cyber enterprise business software which is at the premium price of only 8000 cyber bitcoins (version 8.0). To protect our software we hired a highly trained cyber serial security expert who implemented a serial number check. No cyberspace hackers will ever break it, so open your wallets and give us your cyber cash!

-- ░█▀▀░█░░░█▀█░█▀▀░▀▀█░█▀▀░█▀▀░█▀█ --
-- ░█▀▀░█░░░█▀█░█░█░░▀░░█░█░█▀▀░█░█ --
-- ░▀░░░▀▀▀░▀░▀░▀▀▀░░▀░░▀▀▀░▀▀▀░▀░▀ --
Welcome to FLAG?GEN!
Please enter your Name: palkeo
Now please enter your Product Key: 0006526322287485444096076662182
Thank you for purchasing FLAG?GEN!

My friend would also like to enjoy this software...
Can you give him a serial?
His name: vqogcquxcmrn
Now please enter his Product Key: 


Given the name and the challenge and what happen when we execute it, we quickly see that it generates a key from a username. The goal is to find an username/key that works.

However, after you do that, the program will give you a random username and ask you for the key. If it's correct, it will display the flag (which is not included in the binary you can download).

To get the flag, you have to connect to a distant server and interact with the program. However, if it takes more than 10 seconds, the program closes. So, we will have to automate the calculation of the key from a random user.

Looking at the file in IDA, we see that there is a function (at 0x400AAC) taking a user and a key, and returning if it's correct or not. I ran this function in angr, searching for the key that would makes the function returns 0 (success) for a given username.

It takes 8 seconds on my machine, which means we are in the time limit :) We just have to compute a first valid key for an arbitrary username before connecting.

import angr
import simuvex
import claripy
import pexpect
import sys
project = angr.Project('./serialz')
def solve(name):
    name = name.strip() + '\n\x00'
    initial_state = project.factory.call_state(0x400AAC, 0x10, 0x80)
    key = claripy.BVS('key', 31*8)
    for i in key.chop(8):
        initial_state.add_constraints(i >= '0')
        initial_state.add_constraints(i <= '9'), name), key)
    initial_path = project.factory.path(initial_state)
    path_group = project.factory.path_group(initial_state)
    def success(path):
        state = path.state
        return[state.ip == 0x400CC4, state.regs.eax == 0])
    return path_group.found[0]
first_user = 'palkeo'
first_key = solve(first_user)
print('first key: %s' % first_key)
child = pexpect.spawn('nc 4242', timeout=None)
child.logfile_read = sys.stdout
child.expect('His name: (\w+)')
name =
key = solve(name)
while True: