← Back to projectsLINUX / CRACKME / PYTHON

good-girl — Solving a Lookup-Table Validation CrackMe

Translating decompiled integer-validation logic into a mathematical constraint and finding valid command-line arguments.

August 13, 2025LinuxCompleted CrackMe
This case study documents my analysis of a standalone reverse-engineering challenge. The code, recovered conditions, and solution are included for educational reproducibility.

Objective

The good-girl CrackMe prints either good girl! or bad girl!. The challenge was to determine the accepted argument format and find inputs that trigger the positive result.

Reconstructing the input model

Ghidra analysis showed that the executable requires exactly eight integer arguments (so argc == 9 when counting the program name). The eight numbers form four pairs of coordinates. Each coordinate is within the range 0 through 3 and selects an integer from a 4×4 lookup table.

for each (x, y) pair:
    sum += table[x * 4 + y]

if sum == 0:
    print("good girl!")
else:
    print("bad girl!")

Recovered lookup table

x \ y0123
0111323-7
1-27107-5341
267-51253-143
3-119101401-391

Manual solution

I selected four coordinate pairs whose table entries sum to zero: (0,0), (0,2), (0,3), and (1,0). Their values satisfy:

11 + 23 - 7 - 27 = 0

The command-line test documented in the report was:

chmod +x good-girl
./good-girl 0 0 0 2 0 3 1 0
# good girl!

Automating solution discovery

With the constraint reconstructed, I wrote a Python utility to enumerate coordinate combinations, calculate the four selected table values, and report inputs for which the total equals zero. Its command-line interface supported checking a candidate and printing multiple valid solutions. The report documents a run displaying twenty example solutions.

from itertools import product

table = [11, 13, 23, -7,
         -27, 107, -53, 41,
         67, -51, 253, -143,
         -119, 101, 401, -391]

for coords in product(range(4), repeat=8):
    total = sum(table[coords[i] * 4 + coords[i+1]]
                for i in range(0, 8, 2))
    if total == 0:
        print(*coords)
        break

Outcome and takeaways

The binary's acceptance rule was a deterministic zero-sum check over a fixed lookup table; no cryptographic key or remote dependency was involved. Reconstructing the validation algorithm made it possible to derive correct inputs manually and automate further searches without patching the executable.

Scope: standalone CrackMe analysis. This is a constraint-solving exercise, not evidence of a vulnerability in an unrelated product.

Technical toolkit

GhidraPython 3.11Linux shellCombinatorial search