Projects Vulnerabilities Challenges Write-ups
← Back to challenges
AlpacaHack Rev EASY Solved

Leaked Flag Checker

26.04.2026
Write-up

Challenge Description

Leaked Flag Checker is an Easy Reverse challenge from AlpacaHack. We are given the binary and, in this case, the source code as well. The checker is very small, but it exposes a useful property: every input character is XORed with 7 before being compared against a constant string stored in the binary.

Leaked Flag Checker challenge page

Source Code Analysis

The source code already tells us almost everything. The program reads our input, checks the length, and then compares each character using input[i] ^ 7.

// gcc -o challenge challenge.c
#include <stdio.h>
#include <string.h>

int main(void) {
    char input[32];
    const char xor_flag[] = "REDACTED";
    size_t flag_len = strlen(xor_flag);

    printf("Enter flag: ");
    fflush(stdout);
    scanf("%31s", input);

    if(strlen(input) != flag_len) {
        printf("Wrong length\n");
        return 1;
    }
    for(size_t i = 0; i < flag_len; i++) {
        if((input[i] ^ 7) != xor_flag[i]) {
            printf("Wrong at index %zu\n", i);
            return 1;
        }
    }
    printf("Correct\n");
    return 0;
}

This immediately gives us two useful observations:

1. the flag length is equal to the length of xor_flag
2. the real flag can be recovered by applying XOR with 7 one more time

Solution 1 - DogBolt + XOR

The first solution is the fastest one and, in my opinion, probably unintended. We upload the binary to DogBolt and immediately notice a constant string copied into a local buffer:

DogBolt decompilation view
__builtin_strcpy(&var_46, "Fkwfdf|krdl~z");

We also see the comparison logic very clearly:

char rax_7 = var_38[var_58_1] ^ 7;
if (rax_7 != *(var_58_1 + &var_46)) {
    printf("Wrong at index %zu\n", var_58_1);
}

At this point we use the main XOR property:

XOR explanation
(x ^ 7) ^ 7 = x

So if the stored string is Fkwfdf|krdl~z, we only need to XOR every character with 7 again to recover the original flag.

Script used:

XORED = "Fkwfdf|krdl~z"

for i in XORED:
    print(chr(ord(i) ^ 7), end="")

Run

$ python3 solve.py
Alpaca{lucky}

Solution 2 - Brute Force via the Checker

The second solution relies only on the checker behavior and does not need the constant to be read from decompilation. The program tells us either Wrong length or Wrong at index X, which makes it a very convenient oracle for brute force.

The idea is straightforward:

1. find the correct length by trying A, AA, AAA, ...
2. for each position, brute force printable ASCII characters
3. when the answer is no longer Wrong at index i, that character is correct
4. repeat until the full flag is recovered

Script used:

from pwn import *

elf = ELF("./challenge")

LenghtPayload = "A"

context.log_level = "error"

for i in range(1000):
    p = elf.process()
    p.sendline(LenghtPayload.encode())
    Response = p.recvline(timeout=5)
    p.close()
    if "Wrong length".encode() not in Response:
        break
    LenghtPayload += 'A'

print(f"Length : {len(LenghtPayload)}")

GenerativePayload = ["A"] * len(LenghtPayload)
for i in range(len(LenghtPayload)):
    for ascii_code in range(32, 127):
        p = elf.process()
        GenerativePayload[i] = chr(ascii_code)
        p.sendline(''.join(GenerativePayload).encode())
        Response = p.recvline(timeout=5)
        p.close()
        if f'Enter flag: Wrong at index {i}'.encode() not in Response and "Wrong length".encode() not in Response:
            break

print(''.join(GenerativePayload))

Run

$ python3 solve2.py
Length : 13
Alpaca{lucky}

Flag

Alpaca{lucky}
~/EnesBasmaci/Challenges