commit e341625a66343be78e72fddf42aeb030e4514658 Author: Jack Bond-Preston Date: Mon Feb 13 15:42:53 2023 +0000 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b883f1f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.exe diff --git a/1/README.md b/1/README.md new file mode 100644 index 0000000..c664eb8 --- /dev/null +++ b/1/README.md @@ -0,0 +1,33 @@ +# CrackMeOne + +## Steps + +- Launch x32dbg and open the exe + +- Run up until `EntryPoint` + +- Open the strings view + +- Find + + > Congratulations, you found the secret password + + This must be our code path on success. Double click to find it in the assembly view. + +- Insert some breakpoints before and play around with entering password (anything is fine) and stepping through code, observing registers etc. + +- Observe that there is a loop iterating through bytes at `*eax` and `*ecx` and comparing them. + eax points to our entered password, ecx points to `j5%9lk`. + +- Clearly we are checking for equality between these two strings, thus this is the password. + +- If we complete the loop, we jump straight to the `test eax, eax` that gates the success path. If we don't, we jump a few instrs before, where `eax` is set to a value that is always non-zero (thus we take the branch, which we don't want to). + `eax` will be zero in the success path due to the final equality check being performed on the null-byte string terminator.## Solution + + + +## Solution + +Password: `j5%9lk`. + + diff --git a/1b/README.md b/1b/README.md new file mode 100644 index 0000000..af184dc --- /dev/null +++ b/1b/README.md @@ -0,0 +1,36 @@ +# CrackMeTwo + +- Same idea as one, just with anti-debugger measures. + +- Uses [NtQueryInformationProcess](https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess) to check debugger state. Note the linked documentation doesn't cover the `ProcessInfoClass` option it uses. [Full enumeration is available here](https://www.pinvoke.net/default.aspx/ntdll/PROCESSINFOCLASS.html). + +- Debugger stepping can confirm we are calling this function with `0x1F` (`ProcessDebugFlags`). This anti-debug method is documented [here](https://anti-debug.checkpoint.com/techniques/debug-flags.html#using-win32-api-ntqueryinformationprocess-processdebugflags). + +- Basically just need to make this function return anything but zero. Bunch of ways to do this (edit eax in breakpoint, modify instructions to mov something in, etc.). + A patch is a bit cleaner, we can patch the `call ebx` instruction (the call to `NtQueryInformationProcess`) with `mov eax,ebp` or any other instructions with the same length that will give us a non-zero `eax`: + + ```patch + >crackmeoneb.exe + 00001169:FF->89 + 0000116A:D3->E8 + ``` + +- Now we've patched this, we can get to the input dialog. However, trying to enter anything and hit ok gives us another exception. + +- Inspecting the exception seems we are dividing by zero on purpose, unconditionally, which throws an exception. + +- Looking at the instructions above, we can see calls to `UnhandledExceptionFilter()`. This means we are encountering [another anti-debug technique, documented here](https://anti-debug.checkpoint.com/techniques/exceptions.html#unhandledexceptionfilter). + +- We can inspect the exception handler that would be registered if not debugging, and see that it is adding 2 to the `eip` and returning `EXCEPTION_CONTINUE_EXECUTION`. This just skips the `div` instruction. + +- Just fill the `div` instruction with `nop`s and everything works great under the debugger again. + +- Use the same method as CrackMeOne to find the password + +## + +## Solution + +Password: `zoq98m` + + diff --git a/1b/patch.1337 b/1b/patch.1337 new file mode 100644 index 0000000..77f8d97 --- /dev/null +++ b/1b/patch.1337 @@ -0,0 +1,5 @@ +>crackmeoneb.exe +00001169:FF->89 +0000116A:D3->E8 +00001247:F7->90 +00001248:F0->90 \ No newline at end of file diff --git a/3/keygen.py b/3/keygen.py new file mode 100644 index 0000000..ced7535 --- /dev/null +++ b/3/keygen.py @@ -0,0 +1,14 @@ +import hashlib + +username = input("Enter your username: ") + +print(f"\nUsername: {username}") + +hash = int(hashlib.sha256(bytes(username, encoding="ascii")).hexdigest()[-8:], base=16) +print(f"SHA256-derived bytes: {hex(hash)}") + +target = hash ^ 0x2faecb0d +print(f"Target bytes: {hex(target)}") + +password = target ^ 0xa2f99eae +print(f"Your password: {hex(password)[2:]}") \ No newline at end of file diff --git a/3/patch.1337 b/3/patch.1337 new file mode 100644 index 0000000..b1c5a9d --- /dev/null +++ b/3/patch.1337 @@ -0,0 +1,9 @@ +>crackmethree.exe +0000116C:C0->F6 +00001239:C0->F6 +000013D1:50->90 +000013D2:33->90 +000013D3:C0->90 +000013D4:F7->90 +000013D5:F0->90 +000013D6:58->90 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0a76f4b --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# CrackMes + +Crackmes and solutions, from [GitHub - ripxorip/crackmes: A set of "CrackMe"s intended for beginners who wants to learn more about x86 assembly and reverse engineering](https://github.com/ripxorip/crackmes). Solutions my own, may not be optimal or anything, just for learning. + + + +- [CrackMeOne](./1/) + +- [CrackMeOneB](./1b/) + +- [CrackMeTwo](./2/) - Not completed yet. + +- [CrackMeThree](./3/) - Not written up yet. + +