> ## Content Index
> Fetch the complete content index at: https://taiwanding.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# crackmes.one "Sexy 1337" Writeup: Ghidra Decompilation and XOR Reversing
- URL: https://taiwanding.com/en/crackmes-one-sexy-1337-writeup/
- Published: 2025-09-22T06:20:27.000Z
- Updated: 2026-07-15T02:49:51.000Z
- Author: Kevin Chen
- Tags: #en, #en-ctf

Challenge link: [https://crackmes.one/crackme/6715466c9b533b4c22bd18bb](https://crackmes.one/crackme/6715466c9b533b4c22bd18bb?ref=taiwanding.com)

## 1) Start with `main`: pick the two functions to chase

From `main` we can grab three key facts at once:

- `generate_password(local_48, "sexy1337")`  
⇒ there's a step that "generates the password from a fixed seed"
- `encrypt_decrypt(local_48, 0xffffffaa)` and `encrypt_decrypt(local_88, 0xffffffaa)`  
⇒ the **same key** (0xAA) is applied to both the "correct password" and the "user input"
- `strcmp(local_88, local_48)`  
⇒ the final comparison happens **after both have been encrypted (XORed)**.

Conclusion: first look at "how the password is generated" → `generate_password`; then come back to verify "the effect of a same-key XOR" → `encrypt_decrypt`.

## 2) Chase `generate_password`: work out the "password plaintext"

```c
for (i = 0; i < strlen(seed); i++) {
  dst[i] = seed[i] + 3;
}
dst[len] = '\0';

```

- The seed is a fixed string: `"sexy1337"`
- Each character is shifted **+3** (an ASCII Caesar shift)

Working it out by hand:

- s→v, e→h, x→{, y→|, 1→4, 3→6, 3→6, 7→:
- giving the password plaintext: `vh{|466:`

At this point we already know the "**un-XORed version** of the correct password."

## 3) Look at `encrypt_decrypt`: confirm the "same-key XOR" equivalence

```c
for (...) {
  buf[i] ^= 0xAA;   // 0xffffffaa truncated to its low 8 bits is 0xAA
}

```

`main` applies `^ 0xAA` to **both sides** before the `strcmp`.  
Property of XOR: `a == b ⇔ (a ^ k) == (b ^ k)`.  
So "XORing both sides with the same key" is equivalent to **comparing the originals directly**.

Inference: all we need is to type the **plaintext** we just computed (`vh{|466:`) into the input box, and it will match the "generated-and-then-XORed password" after XOR.

## 4) Back to `main`: converge on the final input

The remaining details in `main` are just reading the string, stripping the newline, then `strcmp`.  
Since the comparison is equivalent to comparing the originals, our **final input** is simply:

**`vh{|466:`**

## Summary

- From `main` we spotted the flow: "generate the password first, XOR both sides with the same key, then strcmp"
- Went into `generate_password` and computed the plaintext password `vh{|466:`
- Used the "same-key XOR is equivalent to comparing the originals" reasoning in `encrypt_decrypt` to confirm the logic
- Returned to `main` and drew the conclusion: just enter `vh{|466:` to beat the challenge

## Lessons learned

The code shown above is Ghidra-decompiled code, so we solved this challenge by analyzing the decompiled output!