0xNOP Posted January 12, 2016 Posted January 12, 2016 (edited) Difficulty : 2Language : PureBasic 5.40Platform : Windows (x86), Linux (x86)OS Version : Windows XP and AbovePacker / Protector : None Description: Simple CrackMe I've made using PureBasic, I have worked with PureBasic before but the more I work with it, the more I find it's a fascinating language and the more interest I grab towards it. The CrackMe has nothing so amazing, hence the difficulty, Made very basics CFlow-Obfuscations, Hope you have fun analyzing this! and Let the games begin! # Special Note: If you haven't tried PureBasic regardless your backdground, I encourage you to try it! it's a very nice language ## Additional Note (Optional): Please rate this CrackMe whenever you leave your solution. Note this is optional but it will greatly help me in further development. Rate this CrackMe: Boring Crap... Kinda Boring... Was Okay. Good! Awesome! Objective(s): Patch the program or Fish the correct password. Screenshot : PWD is CORRECT.7z PWD is CORRECT - CrackMe Source Code Edited April 2, 2017 by 0xNOP Added: CrackMe Source Code is now public
Solution lostit Posted January 13, 2016 Solution Posted January 13, 2016 Well I think a difficulty of 4 might be a little high for this one, maybe a 1 or 2 is more appropriate. But I did like your breakpoint message Hard not to get suspicious when you see a string like that. Password and other info inside the spoiler.... Spoiler So you start at the entrypoint and you see a few calls ... 00401000 <ModuleEntryPoi> $ 68 E0000000 PUSH 0xE0 ; /n = E0 (224.) 00401005 . 68 00000000 PUSH 0x0 ; |c = 00 0040100A . 68 10554000 PUSH PWD_is_C.00405510 ; |s = PWD_is_C.00405510 0040100F . E8 FC0F0000 CALL <JMP.&MSVCRT.memset> ; \memset 00401014 . 83C4 0C ADD ESP,0xC 00401017 . 68 00000000 PUSH 0x0 ; /pModule = NULL 0040101C . E8 F50F0000 CALL <JMP.&KERNEL32.GetModuleHandleW> ; \GetModuleHandleW 00401021 . A3 14554000 MOV DWORD PTR DS:[0x405514],EAX 00401026 . 68 00000000 PUSH 0x0 ; /MaximumSize = 0x0 0040102B . 68 00100000 PUSH 0x1000 ; |InitialSize = 1000 (4096.) 00401030 . 68 00000000 PUSH 0x0 ; |Flags = 0 00401035 . E8 E20F0000 CALL <JMP.&KERNEL32.HeapCreate> ; \HeapCreate 0040103A . A3 10554000 MOV DWORD PTR DS:[0x405510],EAX 0040103F . E8 1C1C0000 CALL PWD_is_C.00402C60 00401044 . E8 9E180000 CALL PWD_is_C.004028E7 00401049 . E8 6F000000 CALL PWD_is_C.004010BD 0040104E . E9 4B050000 JMP PWD_is_C.0040159E Pretty easy to guess that one of those 3 leads us to something so we follow them and look for anything interesting. 0040103F . E8 1C1C0000 CALL PWD_is_C.00402C60 <--- Heap stuff :( 00401044 . E8 9E180000 CALL PWD_is_C.004028E7 <--- Setup some function pointers? :| 00401049 . E8 6F000000 CALL PWD_is_C.004010BD <--- OooO run more code :) 0040104E . E9 4B050000 JMP PWD_is_C.0040159E So lets follow #3 and see what the code does. After a little scrolling it becomes pretty clear it likes to call a few functions a whole bunch of times, looking in to each you'll find a little info but in general we can skip it and look for anything else interesting. Finally we arrive at.... 00401406 . FF35 B8554000 PUSH DWORD PTR DS:[0x4055B8] 0040140C . 8B15 EC554000 MOV EDX,DWORD PTR DS:[0x4055EC] 00401412 . 59 POP ECX 00401413 . E8 180C0000 CALL PWD_is_C.00402030 00401418 . 75 38 JNZ SHORT PWD_is_C.00401452 0040141A . BA 3C504000 MOV EDX,PWD_is_C.0040503C ; UNICODE "PWD is CORRECT!" 0040141F . 8D0D D8554000 LEA ECX,DWORD PTR DS:[0x4055D8] 00401425 . E8 DE0B0000 CALL PWD_is_C.00402008 0040142A .^E9 24FCFFFF JMP PWD_is_C.00401053 Hrmm a conditional ... wonder what that call does before it ... 00402030 /$ 09D2 OR EDX,EDX 00402032 |. 75 05 JNZ SHORT PWD_is_C.00402039 00402034 |. BA 0A514000 MOV EDX,PWD_is_C.0040510A 00402039 |> 09C9 OR ECX,ECX 0040203B |. 75 05 JNZ SHORT PWD_is_C.00402042 0040203D |. B9 0A514000 MOV ECX,PWD_is_C.0040510A 00402042 |> 53 PUSH EBX 00402043 |> 66:8B02 /MOV AX,WORD PTR DS:[EDX] 00402046 |. 83C2 02 |ADD EDX,0x2 00402049 |. 66:8B19 |MOV BX,WORD PTR DS:[ECX] 0040204C |. 83C1 02 |ADD ECX,0x2 0040204F |. 66:39D8 |CMP AX,BX 00402052 |. 75 0E |JNZ SHORT PWD_is_C.00402062 00402054 |. 66:09C0 |OR AX,AX 00402057 |.^75 EA \JNZ SHORT PWD_is_C.00402043 00402059 |. 5B POP EBX 0040205A |. B8 01000000 MOV EAX,0x1 0040205F |. 85C0 TEST EAX,EAX 00402061 |. C3 RETN 00402062 |> 5B POP EBX 00402063 |. 31C0 XOR EAX,EAX 00402065 |. 85C0 TEST EAX,EAX 00402067 \. C3 RETN Not a lot going on, appears to compare 2 memory addresses ECX/EDX one word at a time. I'm suspicious that this might just be a unicode strcmp... hrmmmm So lets set a bp inside the loop and see if anything interesting pops up. MOV AX,WORD PTR DS:[EDX] <---- BP this line Run app, enter test password "forgreatjustice" Yay it breaks... and in ECX we have our password from the console, and EDX points to PWD Looks like this could be the magic stuff, its comparing our test pass against "PWD" Must be a play on the title of the crackme. 00401413 . E8 180C0000 CALL PWD_is_C.00402030 00401418 . 75 38 JNZ SHORT PWD_is_C.00401452 0040141A . BA 3C504000 MOV EDX,PWD_is_C.0040503C ; UNICODE "PWD is CORRECT!" 0040141F . 8D0D D8554000 LEA ECX,DWORD PTR DS:[0x4055D8] 00401425 . E8 DE0B0000 CALL PWD_is_C.00402008 0040142A .^E9 24FCFFFF JMP PWD_is_C.00401053 Back to the jump right after this call 00401418 . 75 38 JNZ SHORT PWD_is_C.00401452 Bad pass eax = 0, good pass eax = 1 So we can either nop the jump and always have a bad password or turn it in to a unconditional jmp and always have a good password. Or you can just enter the password "PWD" without quotes. 2
0xNOP Posted January 13, 2016 Author Posted January 13, 2016 25 minutes ago, lostit said: Well I think a difficulty of 4 might be a little high for this one, maybe a 1 or 2 is more appropriate. But I did like your breakpoint message Hard not to get suspicious when you see a string like that. Password and other info inside the spoiler.... Reveal hidden contents So you start at the entrypoint and you see a few calls ... 00401000 <ModuleEntryPoi> $ 68 E0000000 PUSH 0xE0 ; /n = E0 (224.) 00401005 . 68 00000000 PUSH 0x0 ; |c = 00 0040100A . 68 10554000 PUSH PWD_is_C.00405510 ; |s = PWD_is_C.00405510 0040100F . E8 FC0F0000 CALL <JMP.&MSVCRT.memset> ; \memset 00401014 . 83C4 0C ADD ESP,0xC 00401017 . 68 00000000 PUSH 0x0 ; /pModule = NULL 0040101C . E8 F50F0000 CALL <JMP.&KERNEL32.GetModuleHandleW> ; \GetModuleHandleW 00401021 . A3 14554000 MOV DWORD PTR DS:[0x405514],EAX 00401026 . 68 00000000 PUSH 0x0 ; /MaximumSize = 0x0 0040102B . 68 00100000 PUSH 0x1000 ; |InitialSize = 1000 (4096.) 00401030 . 68 00000000 PUSH 0x0 ; |Flags = 0 00401035 . E8 E20F0000 CALL <JMP.&KERNEL32.HeapCreate> ; \HeapCreate 0040103A . A3 10554000 MOV DWORD PTR DS:[0x405510],EAX 0040103F . E8 1C1C0000 CALL PWD_is_C.00402C60 00401044 . E8 9E180000 CALL PWD_is_C.004028E7 00401049 . E8 6F000000 CALL PWD_is_C.004010BD 0040104E . E9 4B050000 JMP PWD_is_C.0040159E Pretty easy to guess that one of those 3 leads us to something so we follow them and look for anything interesting. 0040103F . E8 1C1C0000 CALL PWD_is_C.00402C60 <--- Heap stuff :( 00401044 . E8 9E180000 CALL PWD_is_C.004028E7 <--- Setup some function pointers? :| 00401049 . E8 6F000000 CALL PWD_is_C.004010BD <--- OooO run more code :) 0040104E . E9 4B050000 JMP PWD_is_C.0040159E So lets follow #3 and see what the code does. After a little scrolling it becomes pretty clear it likes to call a few functions a whole bunch of times, looking in to each you'll find a little info but in general we can skip it and look for anything else interesting. Finally we arrive at.... 00401406 . FF35 B8554000 PUSH DWORD PTR DS:[0x4055B8] 0040140C . 8B15 EC554000 MOV EDX,DWORD PTR DS:[0x4055EC] 00401412 . 59 POP ECX 00401413 . E8 180C0000 CALL PWD_is_C.00402030 00401418 . 75 38 JNZ SHORT PWD_is_C.00401452 0040141A . BA 3C504000 MOV EDX,PWD_is_C.0040503C ; UNICODE "PWD is CORRECT!" 0040141F . 8D0D D8554000 LEA ECX,DWORD PTR DS:[0x4055D8] 00401425 . E8 DE0B0000 CALL PWD_is_C.00402008 0040142A .^E9 24FCFFFF JMP PWD_is_C.00401053 Hrmm a conditional ... wonder what that call does before it ... 00402030 /$ 09D2 OR EDX,EDX 00402032 |. 75 05 JNZ SHORT PWD_is_C.00402039 00402034 |. BA 0A514000 MOV EDX,PWD_is_C.0040510A 00402039 |> 09C9 OR ECX,ECX 0040203B |. 75 05 JNZ SHORT PWD_is_C.00402042 0040203D |. B9 0A514000 MOV ECX,PWD_is_C.0040510A 00402042 |> 53 PUSH EBX 00402043 |> 66:8B02 /MOV AX,WORD PTR DS:[EDX] 00402046 |. 83C2 02 |ADD EDX,0x2 00402049 |. 66:8B19 |MOV BX,WORD PTR DS:[ECX] 0040204C |. 83C1 02 |ADD ECX,0x2 0040204F |. 66:39D8 |CMP AX,BX 00402052 |. 75 0E |JNZ SHORT PWD_is_C.00402062 00402054 |. 66:09C0 |OR AX,AX 00402057 |.^75 EA \JNZ SHORT PWD_is_C.00402043 00402059 |. 5B POP EBX 0040205A |. B8 01000000 MOV EAX,0x1 0040205F |. 85C0 TEST EAX,EAX 00402061 |. C3 RETN 00402062 |> 5B POP EBX 00402063 |. 31C0 XOR EAX,EAX 00402065 |. 85C0 TEST EAX,EAX 00402067 \. C3 RETN Not a lot going on, appears to compare 2 memory addresses ECX/EDX one word at a time. I'm suspicious that this might just be a unicode strcmp... hrmmmm So lets set a bp inside the loop and see if anything interesting pops up. MOV AX,WORD PTR DS:[EDX] <---- BP this line Run app, enter test password "forgreatjustice" Yay it breaks... and in ECX we have our password from the console, and EDX points to PWD Looks like this could be the magic stuff, its comparing our test pass against "PWD" Must be a play on the title of the crackme. 00401413 . E8 180C0000 CALL PWD_is_C.00402030 00401418 . 75 38 JNZ SHORT PWD_is_C.00401452 0040141A . BA 3C504000 MOV EDX,PWD_is_C.0040503C ; UNICODE "PWD is CORRECT!" 0040141F . 8D0D D8554000 LEA ECX,DWORD PTR DS:[0x4055D8] 00401425 . E8 DE0B0000 CALL PWD_is_C.00402008 0040142A .^E9 24FCFFFF JMP PWD_is_C.00401053 Back to the jump right after this call 00401418 . 75 38 JNZ SHORT PWD_is_C.00401452 Bad pass eax = 0, good pass eax = 1 So we can either nop the jump and always have a bad password or turn it in to a unconditional jmp and always have a good password. Or you can just enter the password "PWD" without quotes. Thank you for your participation as always, your answer has been selected as the primary solution for this CrackMe Now let's see others approaches on this
Jasi2169 Posted January 13, 2016 Posted January 13, 2016 (edited) "Wow Correct Breakpoint! Congratulations! The PWD is: '0x90', Now go post the solution!" <= This is just wrong Spoiler real password is :- "PWD" solved Edited April 3, 2017 by Loki Added spoiler
0xNOP Posted January 13, 2016 Author Posted January 13, 2016 (edited) On 1/13/2016 at 12:27 AM, Jasi2169 said: "Wow Correct Breakpoint! Congratulations! The PWD is: '0x90', Now go post the solution!" <= This is just wrong Reveal hidden contents real password is :- "PWD" solved haha, gratz! P.S. Could you please enclose your solution in a spoiler tag, thanks! Edited January 28, 2018 by 0xNOP
0xNOP Posted April 2, 2017 Author Posted April 2, 2017 *Update* April.1.2017 - CrackMe Source Code is now public, Enjoy!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now