

memcmp(input, "password")

python:
data = [0x28, 0x3F, 0x2C, 0x3F, 0x28, 0x29, 0x3F]
pwd = ''
for val in data:
pwd = f"{pwd}{chr(val ^ 0x5A)}"
print(pwd)
Enter Secret Key: reverse
[+] Access Granted! You solved it.
Some interesting strings in the binary:
> strings level10.exe -d
...
=============================
CRACKME LEVEL 10 (BOSS)
=============================
Enter Password:
[+] Correct! Decrypted flag:
(Garbage!)
[-] Access Denied. Decrypted output:
Press Enter to exit...
RSDSe
...
A quick Hex-Rays look at the final comparison:
if ( goal == 0x3D17141A )
{
v10 = sub_1400017A0(std::cout, "\n[+] Correct! Decrypted flag: ");
v11 = "\n";
}
else
{
v10 = sub_1400017A0(std::cout, "\n[-] Access Denied. Decrypted output: ");
v11 = " (Garbage!)\n";
}
Let's see what goal actually is.
goal is assigned here:
goal = dword_140006278;
...
}
goal = dword_140006278;
}
if ( goal == 0x3D17141A )
So goal is just *140006278.
Checking the write xref leads to this function:
int __fastcall sub_140001300(char *a1)
{
int v1; // ebx
char *v2; // r8
_QWORD *v3; // r9
char *v4; // rdx
char *v5; // rcx
int v6; // eax
v1 = 0;
if ( *(a1 + 3) <= 0xFui64 )
{
v4 = a1;
v3 = a1;
v2 = a1;
}
else
{
v2 = *a1;
v3 = *a1;
v4 = *a1;
}
v5 = v3 + *(a1 + 2);
if ( v2 != v5 )
{
do
{
v6 = *v4++;
v1 = v6 + 31 * v1;
}
while ( v4 != v5 );
}
if ( Mtx_lock(&unk_1400060C0) )
{
std::_Throw_Cpp_error(5);
__debugbreak();
}
if ( dword_14000610C == 0x7FFFFFFF )
{
dword_14000610C = 2147483646;
std::_Throw_Cpp_error(6);
__debugbreak();
}
dword_140006278 = v1; // here!
return Mtx_unlock(&unk_1400060C0);
}
This function is invoked via thread.join:
sub_1400017A0(std::cout, "Enter Password: ");
sub_140001970(std::cin, &v22);
sub_140001C10(&v21, v0, &v22);
sub_140001C10(&v21, v0, &v22);
// ↑
// v6[4] = func; // our above function ↓ this call func
// result = beginthreadex(0i64, 0, StartAddress, v6, 0, (a1 + 8)); here
if ( !v21._Id )
{
std::_Throw_Cpp_error(1);
__debugbreak();
}
if ( v21._Id == Thrd_id() )
{
std::_Throw_Cpp_error(5);
__debugbreak();
}
v17 = v21;
if ( Thrd_join(&v17, 0i64) )
{
std::_Throw_Cpp_error(2);
__debugbreak();
}
v21 = 0i64;
goal = dword_140006278;
...
The core logic is simple:
v5 = &v3[*(a1 + 2)];
if ( v2 != v5 )
{
do
{
v6 = *v4++; // next ptr
v1 = v6 + 31 * v1; // char * 31
}
while ( v4 != v5 ); // iterate input
}
Equivalent Python:
x = 0
pwd = "123"
for c in pwd:
x *= 31
x += ord(c)
print(hex(x))
So how do we find a valid input?
Let's figure out the length first.
The lowest printable ASCII character we can input is !.
Let's fill every position with it and see what x becomes:
goal is 3D17141A (8 digits)
3 len / !!! is 0x8001 (4 digits)
4 len / !!!! is 0xf8040 (5)
5 len / !!!!! is 0x1e087e1 (7)
6 len / !!!!!! is 0x3a307460 (8)
7 len / !!!!!!! is 0x70bde17c1 (9)
So length 6 is the right ballpark — length 7 already overshoots goal even in the best case (all !), and lengths ≤5 can't reach 8 hex digits at all.
To be sure length 5 truly can't reach it, test the highest printable character too, e.g. z:
5 len / zzzzz is 0x6f081fa
Still not enough. So length 6 is the only possible length.
Now we can find the input using binary search — since x = x*31 + byte, an earlier character in the password has a far larger effect on the final value than a later one (Horner's-method style weighting: 31^(len-1-i)). This means the value is monotonic with respect to each position, so each character can be pinned down independently with a binary search: fix a prefix, fill the rest with the minimum char, and binary-search the prefix's last character until the resulting value straddles goal. Repeat left to right.
answer = b'"6656=' hash=0x3D17141A target=0x3D17141A diff=0
Now feed it to binary:
=============================
CRACKME LEVEL 10 (BOSS)
=============================
Enter Password: "6656=
[+] Correct! Decrypted flag: Perfect!
First checked how input is handled: username → part1 → part2 → compared against something → invalid! on mismatch.
Threw it in a debugger, but hit multiple anti-debug checks stacked together (well-known methods). Patched all of them out to get a clean trace.
Still obfuscated, so instead of fighting the obfuscation directly, just traced execution step by step — watching how each input byte got consumed and transformed — and reimplemented the logic piece by piece as each operation was identified. Once everything was mapped out, wrote the keygen in Python.
The core generation logic is simple:
part1 = sum(username) * 31
part2 = (part1 ^ 0x1337) + 0x7B
Keygen worked — valid usernames now pass the check. But after the "valid" message, a second Message: field is decrypted based on the input, and that part came out garbled for arbitrary valid inputs.
Didn't reverse the message-decryption logic itself (The key from Level 10 was 1 byte, easy to bruteforce). So instead, just ran the keygen with a handful of guessable usernames (author's nickname, "admin", etc.) and checked whether the decrypted message came out meaningful.
"crackme" turned out to be the one that decrypts into a real message:
[+] Access Granted!
[+] Message: wOWYOUDIDIT