Jump to content
Tuts 4 You

0x90 "PWD is CORRECT!" - 2016


0xNOP
Go to solution Solved by lostit,

Recommended Posts

Difficulty : 2
Language : PureBasic 5.40
Platform : Windows (x86), Linux (x86)
OS Version : Windows XP and Above
Packer / 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 :D

## 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 :

M6Un7MR.png

PWD is CORRECT.7z

PWD is CORRECT - CrackMe Source Code

 

Edited by 0xNOP
Added: CrackMe Source Code is now public
Link to comment
Share on other sites

  • Solution

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.

 

 

  • Like 2
Link to comment
Share on other sites

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 :D

Now let's see others approaches on this :D

Link to comment
Share on other sites

 "Wow Correct Breakpoint! Congratulations! The PWD is: '0x90', Now go post the solution!"    <= This is just wrong

Spoiler


real password is :- "PWD"

 

solved :P

 

Edited by Loki
Added spoiler
Link to comment
Share on other sites

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 :P

 

haha, gratz! :D

P.S. Could you please enclose your solution in a spoiler tag, thanks!

Edited by 0xNOP
Link to comment
Share on other sites

  • 9 months later...
  • 1 month later...
  • 3 months later...

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...