The binary in this post is fictional. Use the structure to document your own analyses.
First look
Before opening a disassembler, gather basic information about the binary:
file crackme
strings -n 6 crackme | head
The program asks for a password and replies with Correct! or Wrong password.
Static analysis
In Ghidra, main reads the input and calls check. The simplified pseudocode is:
int check(char *input) {
char key[] = { 0x31, 0x26, 0x30, 0x37, 0x00 };
for (int i = 0; i < 4; i++) {
if ((input[i] ^ 0x42) != key[i]) return 0;
}
return 1;
}
Each input character is compared with the key after being XORed with 0x42.
Recovering the password
XOR is reversible, so applying the same operation to the key is enough:
key = [0x31, 0x26, 0x30, 0x37]
print("".join(chr(b ^ 0x42) for b in key))
Dynamic verification
Confirm the result by running the binary, or set a breakpoint on check in GDB to inspect its return value.
Conclusion
XOR with a fixed key protects nothing: the key lives inside the binary and the operation is trivially reversed.