Log in

View Full Version : From newbie to guru crackme


ZaiRoN
November 24th, 2005, 14:16
Hi.
Here is a new crackme by lord_Phoenix. It has some levels from easy to guru (!?!) level.
If you are a newbie this crackme is perfect for you, it uses some standard anti-debug tricks and the protection routines (for some levels) are designed for you.
If you are a guru... well, you might have some fun with the latest levels.

Who will solve them all???

Good luck,
ZaiRoN

danbradster
January 8th, 2006, 11:08
I can't even get it to work in ollydbg...after I open it in ollydbg, it automatically terminated itself before I can even press f9.

Bra!NSHiT
January 8th, 2006, 12:37
Quote:
it uses some standard anti-debug tricks
...

think about it danbradster ...

Fake51
January 8th, 2006, 13:54
Well, since it seems noone is really working on this one anyway, I figured there might be some idea in just making it a work in progress. My own reasons for doing this are:
- I don't have the time to actually delve into it
- I'm very rusty

Anyway, I'll leave it up to the mods whether or not this approach is acceptable, and up to everyone else whether or not they'll jump in.

A starter: dumping it.
First problem is obviously getting something usable out of the exe. A quick scan with a probably outdated version of PeID showed nothing. Then, opening in olly, a messagebox tells you that the code is likely compressed. Hence, don't bother with the analysis.
Now, at least in my version of olly, there's no problem singlestepping thru the code. So that's what to do. After a few short sections, some code that looks suspiciously like unpacking is reached. This starts at 00424988h. A cursory stepping through while keeping eyes open reveals that there's a popad at 00424abeh followed by a jump to another section. That would probably be a good place to break.
Once that's done, dump the process. I used LordPe. Then I opened ImpRec, fed it the OEP, then had it fix the exe by appending a new import section. Last thing to remember is obviously fixing the OEP with LordPe or whatever dump tool was used. This produced a fully working dump for me, that is ready for analyzis.

Fake

SiGiNT
January 8th, 2006, 16:00
It's Visual UPX .2 whatever the hell that is, an easy dump, Google doesn't do much good - started about an hour ago number 1 is easy - number 2 it detects Olly - even well hidden - and sends you off into neverland, hmm. I've got OllyShadow around here somewhere. BTW DeDe aint much help - neither is the fact that after you get the first number your message that the second number is wrong is another repeat congratz.

SiGiNT

bilbo
January 9th, 2006, 13:55
That's UPX!
4 little patches to restore it

(a) first section name (at offset 1F8): replace 4 nulls with UPX0
(b) UPX header magic at offset 3E0: replace 4 nulls with "UPX!" (without quotes)
(c) UPX version (the byte after, at 3E4) 0D->0C
(d) checksum (last byte of UPX header at 3FF) 7F->7E

Now you can run "upx -d crackme.exe"
Sorry, no time at the moment to tell more...

Regards, bilbo

Fake51
January 11th, 2006, 10:25
Yeah, the first serial is rather easy ...

1. Find the code-spot: looking at the dialogproc, it obviously checks for WM_COMMAND - and when it receives one compares it against four values, obviously matching the four buttons of the dialog. button 2 is the interesting one. When pressed, it leads to 41538fh, which is a call to 4149d4h - the serial routine. I like the anti-debug codes inserted - checking to see if messagebox and getdlgitemtext are replaced, but not getdlgitem, which is what the dialog uses.
2. After fetching data from the edits, it checks to see if a name is entered at all, if a serial is entered, and that the name is more than 2 chars long. If those checks pass, it starts calculating the correct serial from the name given.
3. First serial routine is simple: First, sum the hex values of every byte of the name (including spaces). Multiply that sum by 7d5h. Then xor it with 10h. Convert the sum to decimal and ascii. Then, grab the first three chars of the name. Append to this the converted sum reached before. Then append the name entered. Presto, serial done.
4. Cleartext comparison happens from a call at 414c24h. That would be a good place to fish a working serial

Fake

SiGiNT
January 11th, 2006, 21:48
Ahhh!

I found the 1st serial easily by setting a bp on GetWindowTextA, and tracing over and into - components pop-up here and there first the middle portion then the beginning and end and eventually the entire string - I'm almost convinced there is no second number and it must be patched - the success message is not conditional it's yep! and the "what the hell try another code", as though it's detected being patched then your 3rd number box opens up, that's as far as I got in the time I had- there is a few land mines - setting a bp on GetDlgItemTextA - will cause a fatal error - look in the code for "Greetz from Lord Phoenx" and "The Power of int 3" .

SiGiNT

xenakis
January 12th, 2006, 12:35
SiGiNT: I can confirm that there is a second serial to be fished, no need to patch. Now, on to the third challenge

xenakis

SiGiNT
January 12th, 2006, 13:45
Okay,

I need to dig a little deeper - actually at one point while I was fishing for #2, I found myself in the middle of a proceess that seemed to be showing me the serial, a byte at a time, - but I had no time to investigate, and trying to find that, spot is not going to be easy, interesting though, my typed number shows up in memory but does not get displayed while tracing, just the first successful one, hmmmmm. oh well Dr.'s appointment then work - maybe tonight.

SiGiNT

xenakis
January 12th, 2006, 13:49
Actually, now that you mention it, perhaps you may need a temporary patch to persuade it to yield the serial. I did it a few days ago, and as usual, all my projects fuse into one, fogging up my memory. Call it a melting pot in the brain
Will look into it and edit post...

xenakis

EDIT: Indeed, it does require a little persuation of the "double-clicking" variety. Fun crackme

SiGiNT
January 14th, 2006, 00:51
NOPE!

No patch required - just need to find it a little at a time - off to number 3 tomorrow, maybe, grandkids here all day!!

SiGiNT

xenakis
January 14th, 2006, 01:47
I didn't have to patch either, just changed the zero flag to gather the bits and pieces in one run

I am currently enjoying trying to fish the 3rd code, but so far I've only figured out how to crash the crackme, without patching!!

xenakis

SiGiNT
January 14th, 2006, 02:01
AHHHH!

We're in real time here - look for "the power" - you have to patch! - it pretty much tells you so.

SiGiNT

Hmmmm. Just told I have to "get a life" by my wife - break time!

Interesting - only that number of X's causes it to crash outside the debugger other letters won't either.

xenakis
January 14th, 2006, 12:17
Observation and small hint: Not just X's, and just the choice of the first character can crash it outside the debugger. Go down the alphabet and see when it starts crashing

xenakis

Funny, my wife keeps telling me the same, but she phrases it differently

Inv
January 15th, 2006, 14:22
I have 2 first pass,
first part of three pass==00414514 <- proc that get 2 part of key ?
But if i am patch 414514 proc (for second part key) i have acces violation :

00414880 68 D0484100 PUSH OFFSET <CrackMe_.aNormal__inProg> ; ASCII "Normal..in progress"
00414885 68 E4484100 PUSH OFFSET <CrackMe_.aYouCanDoMore> ; ASCII "You can do more "
0041488A A1 48794100 MOV EAX,DWORD PTR DS:[417948]
0041488F 50 PUSH EAX
00414890 FF15 64794100 CALL NEAR DWORD PTR DS:[417964] <- exception
What i do wrong?

SiGiNT
January 15th, 2006, 15:04
I think even if the rules say patching is OK fishing out the serials without patching, (or even changing a jump context), is a lot more fun - this crackme is designed to crash - even if not patched - you're in the wrong spot for number 2 serial, that's the area for number 3 - which quite frankly is a brick wall - interesting though there is no separate congratulations for serial number 3, unless it returns to the "yep" dialogue - the big problem is the numbers are analyzed as you type them in on #3 if you don't get the first number correct - it sends you to "exception land".

SiGiNT

Inv
January 16th, 2006, 12:38
you're in the wrong spot for number 2 serial,
login: Inv
pass1: Inv603489Inv
pass2: 496E76
pass3: 0909491949591949 <- there 9999..etc second part key
OR
414514 proc Wrong ???

ZaiRoN
January 25th, 2006, 12:49
Seems like we are stalled so I decided to do a little sum up trying to make things a little bit clear.


Unpack
------
To unpack the crackme follows the post by Bilbo


Antidebug(s)
------------
Trying to run the program from Ollydbg you'll surely find out that something is wrong because the application crashes.
Looking at the string references produced by Ida we know that IsDebuggerPresent is called:
Code:

CODE:004141BA 014 push offset str->Isdebuggerpresent ; "IsDebuggerPresent"
CODE:004141BF 018 push edi
CODE:004141C0 01C call GetProcAddress_0 ; Get the address of IsDebuggerPresent
CODE:004141C5 01C mov ebp, eax
CODE:004141C7 01C mov esi, ebp
CODE:004141C9 01C test ebp, ebp
CODE:004141CB 01C jz short loc_4141D1
CODE:004141CD 01C call esi ; Call IsDebuggerPresent. Returns: al = 1 if under debugger, 0 otherwise
...
CODE:004151E1 024 test al, al ; al = value returned by IsDebuggerPresent function
CODE:004151E3 024 jz short loc_4151EF ;
CODE:004151E5 024 push 3039h ; Here if you are under the debugger
CODE:004151EA 028 call FatalExit ; Close everything
CODE:004151EF 024 push offset OutputString ; "s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"...
CODE:004151F4 028 call OutputDebugStringA
As you can it uses a simple trick, the good old IsDebuggerPresent function. This is not the only trick used by the crackme infact if you try to fool IsDebuggerPresent trick (patching it using an Olly plugin or simply invert the conditional jump at 4151E3) you'll find out the crackme still crashes. Does OutputDebugStringA tell you nothing? Yes, it's a well known Ollydbg vulnerability, I don't remember how it really works but a simple google search (like: ollydbg+OutputDebugString) will do the job. To avoid this trick it's easy and there are lot of ways, I changed the conditional jump at 4151E3.
Run the crackme again hoping to see the dialog but unfortunatly the crackme has another trick:
Code:
CODE:00415A1F xor eax, eax
CODE:00415A21 push ebp
CODE:00415A22 push offset loc_415A4E
CODE:00415A27 push dword ptr fs:[eax]
CODE:00415A2A mov fs:[eax], esp
CODE:00415A2D jmp short near ptr unk_415A3E -------------------
CODE:00415A2F str->Int3Power db 'int 3 power =)',0 |
CODE:00415A3E unk_415A3E db 0CCh ; CODE XREF: CODE:00415A2Dj <--
CODE:00415A3F db 0CCh <------ the debugger stops here
CODE:00415A40 db 0CCh
CODE:00415A41 db 0CCh
CODE:00415A42 db 0CCh
CODE:00415A43 db 0CCh
CODE:00415A44 xor eax, eax
CODE:00415A46 pop edx
CODE:00415A47 pop ecx
CODE:00415A48 pop ecx
CODE:00415A49 mov fs:[eax], edx
CODE:00415A4C jmp short loc_415A5F
...
CODE:00415A5F push offset unk_417928
CODE:00415A64 call TranslateMessage
CODE:00415A69 push offset unk_417928
CODE:00415A6E call DispatchMessageA
CODE:00415A73 push 0
CODE:00415A75 push 0
CODE:00415A77 push 0
CODE:00415A79 push offset unk_417928
CODE:00415A7E call GetMessageA
CODE:00415A83 test eax, eax
CODE:00415A85 jnz short loc_415A1F
It's easy to find out that this part of code is here for one reason only... stop our stepping session.
Ok, we have another trick to find out; I did find it in a second time looking at the disasm. The code is between address 415200 and 415316. I don't post the entire code but mainly it's the usual code used to retrieve if a particular process is running inside our system. The list of the processes is taken with the CreateToolhelp32Snapshot/Module32First/... functions and the check is made over Ollydbg process. The crackme checks for: "OllyDbg.EXE", "OllyDbg.exe", "ollydbg.EXE", "Ollydbg.EXE", "ollydbg.exe". Now you should know why I didn't notice this trick before, I named the file "OLLYDBG.EXE"

Ollydbg is nowadays almost the most used debugger by the masses, lot of programmers put all this tricks inside their applications/crackmes but it's really funny to see how softice won't get fouled by all these tricks

Ok, we can know start with the first level.


First level
-----------
From what I've read Fake51 did find the routine codes passing through the dialog proc while sigint33 used a breakpoint over GetWindowTextA (I really don't know how you did it indeed...). I'll use the usual approach looking at the string references. From all the visible strings this one seems to be what we are looking for: "Congratz! U improve ur newbie-level. Try next one..":
Code:
seg000:00414C1C mov edx, [ebp+var_14]
seg000:00414C1F mov eax, ds:dword_417958
seg000:00414C24 call @System@@LStrCmp$qqrv ; It's pretty obvious that our serial is compared with the right serial
seg000:00414C29 jnz short loc_414C70
seg000:00414C2B push 30h
seg000:00414C2D push offset aHNewbie ; "H! newbie"
seg000:00414C32 push offset aCongratzUImpro ; "Congratz!\rU improve ur newbie-level. Tr"...

Now that we know where the check is placed we can use our debugger and put a breakpoint directly before the LStrCmp call. You can sniff the right serial or you can study the algo. Do you remember what Fake51 said?:
Quote:
First serial routine is simple: First, sum the hex values of every byte of the name (including spaces). Multiply that sum by 7d5h. Then xor it with 10h. Convert the sum to decimal and ascii. Then, grab the first three chars of the name. Append to this the converted sum reached before. Then append the name entered. Presto, serial done.
Let's go to see the instructions used to perform such an algo:
Code:
CODE:00414B71 0A4 mov edx, ds:dword_417954 <-- edx points to the name
CODE:00414B77 0A4 movzx edx, byte ptr [edx+esi-1] <-- take a char from a name
CODE:00414B7C 0A4 add ebx, edx <-- "sum the hex values of every byte of the name"
CODE:00414B7E 0A4 inc esi
CODE:00414B7F 0A4 dec eax
CODE:00414B80 0A4 jnz short loc_414B71
...
CODE:00414BE0 0A4 mov cl, 3
CODE:00414BE2 0A4 call @@PStrNCat <-- "grab the first three chars of the name"
...
CODE:00414BF8 0A8 imul eax, ebx, 7D5h <-- "Multiply that sum by 7d5h"
CODE:00414BFE 0A8 xor eax, 10h <-- "Then xor it with 10h"
CODE:00414C01 0A8 call sub_406BFC <-- " Convert the sum to decimal and ascii"
...
CODE:00414C17 0B0 call sub_403E9C <-- "Append to this (first 3 chars of the name) the converted sum reached before. Then append the name entered"


Easy
A little thing before level_2.
This part of the crackme contains a breakpoint check, it checks for bpx over MessageBox and GetDlgItemText function. The check is a standard check over the first byte of the function. Let's an example for one of the function:
Code:
CODE:00414A0B 094 push offset str->Messageboxa <-- "MessageBoxA"
CODE:00414A10 098 push offset LibFileName <-- "user32.dll"
CODE:00414A15 09C call LoadLibraryA
CODE:00414A1A 098 push eax
CODE:00414A1B 09C call GetProcAddress_0
CODE:00414A20 09C mov [ebp+var_4], eax <-- eax points to the first byte of MessageBoxA function
CODE:00414A23 09C mov eax, [ebp+var_4]
CODE:00414A26 09C mov ebx, [eax] <-- take the dword pointed by eax
CODE:00414A28 09C cmp bl, 0CCh <-- compare the value of the first byte with 0xCC
CODE:00414A2B 09C jz short loc_414A37 <-- it means: Do you put a 'bpx MessageBoxA'?
CODE:00414A2D 09C add eax, 7 <-- eax points to the second instruction of the function
CODE:00414A30 09C mov ebx, [eax] <-- take the dword pointed by eax
CODE:00414A32 09C cmp bl, 0CCh <-- Do you put a breakpoint over the second instruction?
CODE:00414A35 09C jnz short loc_414A5C
CODE:00414A37 09C push 29Ah
CODE:00414A3C 0A0 call FatalExit <-- Exit if there is a breakpoint
CODE:00414A41 09C jmp short loc_414A5C

This is the classical check but as you can see there is another check for a second breakpoint. To fool -or to prevent- checks like the first one I used to put breakpoint directly inside the code of the function, not exactly on the first byte of it (To reach the function you can do a simple 'u MessageBoxA' under softice or a go-to 'User32.MessageBoxA' under Ollydbg). The aim of the second check used by the crackme is to block this kind of *smart* breakpoint.


Second level
------------
Even at this level you can sniff the serial -byte per byte this time- and you don't have to patch anything. My approach is always the same: "Congratz!\rU fully improve ur newbie-lev".
Code:
seg000:00414CC4 lea eax, [ebp+var_34]
seg000:00414CC7 push eax
seg000:00414CC8 mov ecx, 2 <-- a parameter for the next call
seg000:00414CCD mov edx, esi
seg000:00414CCF mov eax, ds:dword_417958 <-- our serial
seg000:00414CD4 call @System@@LStrCopy$qqrv <-- copy 2 chars from our serial into another buffer
seg000:00414CD9 mov eax, [ebp+var_34] <-- eax points to the 2 chars
seg000:00414CDC push eax
seg000:00414CDD mov eax, ds:dword_417954 <-- eax points to our name
seg000:00414CE2 movzx eax, byte ptr [eax+ebx-1] <-- takes a char from the name
seg000:00414CE7 lea ecx, [ebp+var_38]
seg000:00414CEA mov edx, 2
seg000:00414CEF call sub_406D10 <-- convert the char into two byte (i.e. 'Z'=0x5A becomes "5A"
seg000:00414CF4 mov edx, [ebp+var_38]
seg000:00414CF7 pop eax
seg000:00414CF8 call @System@@LStrCmp$qqrv <-- compare between the first two chars of the serial with the bytes
obtained by the name
seg000:00414CFD jnz loc_414F38 <-- they have to be equal
seg000:00414D03 add esi, 2
seg000:00414D06 inc ebx
seg000:00414D07 mov eax, ds:dword_417954
seg000:00414D0C call @System@_16823
seg000:00414D11 cmp ebx, eax
seg000:00414D13 jnz short loc_414CC4 <-- jump up and check the other bytes
seg000:00414D15 push 30h
seg000:00414D17 push offset aCoolNewbie ; "Cool, newbie"
seg000:00414D1C push offset aCongratzUFully ; "Congratz!\rU fully improve ur newbie-lev"...
Do you understand the algo? Pretty easy, even more than level 1. The serial is obtained by the ascii value of the name. sigint33, you were right saying it's possible to sniff the serial byte a byte
Nothing more to say.


Third level
-----------
New level and new string references: "Normal..NOT FOUND!" and "Normal..in progress"
The first string doesn't help me too much:
Code:
CODE:00414ED9 000 call @StrToInt
CODE:00414EDE 000 mov ds:dword_417944, eax <-- eax is an integer value. We don't know anything else at the moment
CODE:00414EE3 000 xor eax, eax
CODE:00414EE5 000 push ebp
CODE:00414EE6 004 push offset loc_414F02 <-- seh: handler exception
CODE:00414EEB 008 push dword ptr fs:[eax] <-- seh
CODE:00414EEE 00C mov fs:[eax], esp <-- seh
CODE:00414EF1 00C mov eax, ds:dword_417944
CODE:00414EF6 00C call eax <-- the integer should be an address of a function...
CODE:00414EF8 00C xor eax, eax
CODE:00414EFA 00C pop edx
CODE:00414EFB 008 pop ecx
CODE:00414EFC 004 pop ecx
CODE:00414EFD 000 mov fs:[eax], edx
CODE:00414F00 000 jmp short loc_414F38
CODE:00414F02 loc_414F02: ; DATA XREF: sub_4149D4+512o
CODE:00414F07 000 push 30h
CODE:00414F09 000 push offset str->Normal__notFound ; "Normal..NOT FOUND!"
CODE:00414F0E 004 push offset str->UNeedSomeBrainzOrLuck ; "U need some brainz or luck"
CODE:00414F13 008 mov eax, ds:hDlg
CODE:00414F18 008 push eax
CODE:00414F19 00C call [ebp+var_4]
CODE:00414F1C 00C call @@DoneExcept
CODE:00414F21 00C jmp short loc_414F38
The string is showed by a message box but unfortunatly Ida is not able to understand from where it's called. By the way, this piece of code it's not so friendly, the 'call @@DoneExcept' suggests me that seh is used and the instructions between 414ED9 and 414EF6 represent the proof; the crackme calls a function pointed by a value inside eax which is filled at runtime. The use of seh is necessary because from the call you can go everywhere . The question is: where is the right function to call? And, how is the address abtained?
Let's see... the initial part of the routine (which starts at 414D42, after level_2 routine) checks the length of the serial -16 characters- and takes some chars from our fake serial. These chars are the ones in postion 1,3,5,7,9,11,13,15; they are putted all together into a string which is converted to integer (For example: serial = 1234567890abcdef --> eax=13579ACE).
The integer value represents the address to call, the address of a function inside the crackme. We don't know where the function is located at but we can locate it using the second string "Normal..in progress". Doing some backtrace from the second string we arrive at the beginning of an unreferenced function, which starts at 414514 (Inv, I think you were right
about the first part of the serial ). It's almost obvious that we surely reach this piece of code (otherwise how can we reach the "Normal..in progress" message?); now we know where we'll jump from the 'call eax' at 414EF6.

Ok, it's enough for the moment. Are you able to find out the second part of the serial?

Ciao,
ZaiRoN

SiGiNT
January 25th, 2006, 18:19
Zairon,

You are absolutely correct - I lied , it wont break on GetWindowTextA, thats one of the first I usually try - probably what I used was plain old GetDlgItem - that's the one that usually works even when the tried and true BP's don't work - as for the second I simply followed the routine in the dead listing, found a likely spot, placed a BP and traced from there - eventually I found a spot that if I placed a BP it would spit-out my number 2 ascii characters at every break - I did notice that this spot would have worked for the first number also and I was hoping for the third also - but of course it not that easy as you've described.

SiGiNT

BTW - I have the first 2 numbers for Woodmann - if he'd like to give it a go.

Zairon,

I went back and read your post a little more carefully, I noticed that in the second routine "LStrCmp" is called, I've never been able to get any serial routine to break on that - why is that? Just curious.

Kayaker
January 25th, 2006, 18:51
Quote:
[Originally Posted by sigint33]BTW - I have the first 2 numbers for Woodmann - if he'd like to give it a go.


Hey, what's this, Giving the OBC some hints?
Aww c'mon, we gotta have a little bit of faith in him don't we?

Woodmann
January 25th, 2006, 19:26
Howdy,

I didnt know I was working on this .
I guess I will start now.

Woodmann

SiGiNT
January 25th, 2006, 20:23
"HINT" take Inv's lead and use a short "name" makes for less work on the first 2.

SiGiNT

Woodmann
January 26th, 2006, 00:42
Howdy,

I have already discovered the "short" route .
This third part is a bitch. Remember, I am old and not as smart as I was in my youth .

No hints unless others ask for them.
414514 is giving me a hard time. I am not sure that this is the way to follow.

Woodmann

ZaiRoN
January 26th, 2006, 07:24
Quote:
I noticed that in the second routine "LStrCmp" is called, I've never been able to get any serial routine to break on that - why is that?
It isn't the kernel32 function, you can't put a direct breakpoint on it. The name @@LStrCmp is added by Ida when I applied the Delphi signature, it's a Delphi specific function.

Kayaker
January 26th, 2006, 21:09
Interesting crackme. It looks like the 2nd half of the 3rd SN needs a little bruteforcing. The tricky part seems to be to pull out the algorithm from all the Delphi crap. Luckily tracing Delphi does have its merits, there are certain patterns repeated as well as some default procedures which can be eliminated from in depth tracing. Someone experienced in Delphi coding could probably identify a familiar syntax.

There's always a basic pattern one quickly picks up, something like

lea edx, [ebp-xx]
lea eax, [ebp-xx]
Call -----

For a first run through anyway one can do a quick trace, jumping from Call to Call and checking the memory in and *around* edx and eax before and after the call. You can often "see" what's going on this way.

And I'm sure everyone knows string comparisons are almost always based on values in ESI and EDI, usually a recognizable loop going on there.


I suppose if you used DeDe one could identify some of the common Delphi procs and clarify the disassembly a bit. Zairon just mentioned the IDA sigs which could be used even better. Any sigs exist for Olly?


One thing I didn't understand was this, as Zairon pointed out there is a second check for opcode 0xCC in the MessageBoxA breakpoint test. *7 bytes* after the normal check of the first byte. The thing is, the 7th byte is in the middle of the 4th instruction, it's checking for a CC in a nonsensical place! Very strange. A 6 byte difference could mean a trampoline, but there's still no sense in checking it. Maybe it was meant for no reason, there needn't be rules in crackmes..

Code:

:77E38098 MessageBoxA proc near
...
:77E38098 55 push ebp
:77E38099 8B EC mov ebp, esp
:77E3809B 51 push ecx
:77E3809C 83 3D 38 92 E6 77 00 cmp dword_77E69238, 0
// dword_77E69238 == Symbol [_gfEMIEnable]


:00414A1B 09C call GetProcAddress_0
:00414A20 09C mov [ebp+var_4], eax <-- eax points to the first byte of MessageBoxA function
:00414A23 09C mov eax, [ebp+var_4]
:00414A26 09C mov ebx, [eax] <-- take the dword pointed by eax
:00414A28 09C cmp bl, 0CCh <-- compare the value of the first byte with 0xCC
:00414A2B 09C jz short loc_414A37 <-- it means: Do you put a 'bpx MessageBoxA'?
:00414A2D 09C add eax, 7 <-- eax points to the second instruction of the function
:00414A30 09C mov ebx, [eax] <-- take the dword pointed by eax
:00414A32 09C cmp bl, 0CCh <-- Do you put a breakpoint over the second instruction?


There are a couple of other interesting bits, a "missing" API which could be fixed, though ultimately it doesn't appear to affect the overall algo patterns. And there's at least one other "orphaned" procedure you can direct that 3rd SN to and another part of the crackme.

I haven't tried the 4th SN yet, but damn it looks the size of a keyfile!

Kayaker

SiGiNT
January 27th, 2006, 03:13
Kayaker,

When I first started playing with this I tried DeDe - and nothing usefull there - must be some anti-DeDe stuff or my copy of DeDe has gone sour, which is possible since the last couple of times I used it it did not show any Forms data.

SiGiNT

LLXX
January 27th, 2006, 03:59
Quote:
[Originally Posted by sigint33]Kayaker,

When I first started playing with this I tried DeDe - and nothing usefull there - must be some anti-DeDe stuff or my copy of DeDe has gone sour, which is possible since the last couple of times I used it it did not show any Forms data.

SiGiNT
It wasn't coded in pure Delphi

(I started working on this two days ago... currently working on lvl. 5)

ZaiRoN
January 27th, 2006, 07:02
Quote:
One thing I didn't understand was this, as Zairon pointed out there is a second check for opcode 0xCC in the MessageBoxA breakpoint test
Depends on the dll version you have, in your case W2k.
Code:
XP-Sp1 MessageBoxA:
.text:77D3ADD7 MessageBoxA proc near
...
.text:77D3ADD7 83 3D C4 D3 D6 77 00 cmp dword_77D6D3C4, 0
.text:77D3ADDE 0F 85 37 7E 01 00 jnz loc_77D52C1B

XP-Sp2 MessageBoxA:
.text:77D504EA MessageBoxA proc near
...
.text:77D504EA 8B FF mov edi, edi
.text:77D504EC 55 push ebp
.text:77D504ED 8B EC mov ebp, esp
.text:77D504EF 83 3D BC 04 D7 77 00 cmp dword_77D704BC, 0
.text:77D504F6 74 24 jz short loc_77D5051C
Quote:
A 6 byte difference could mean a trampoline, but there's still no sense in checking it
Or he's using xp-sp1

Knight
January 27th, 2006, 11:32
Quote:
[Originally Posted by Kayaker]Any sigs exist for Olly?

With GODUP you can apply IDA signatures, or you can export map file from IDA and load it to Olly using some plugin. I prefer map way, since then you can get rid of demangled names, which are very annoying in delphi programs.

Regards,
Knight

Kayaker
January 27th, 2006, 14:08
Quote:
[Originally Posted by ZaiRoN]Depends on the dll version you have, in your case W2k. Or he's using xp-sp1


Aha. I had used xp-sp2 as well as win2K and the 'problem' existed with both MessageBoxA's. Funny how xp-sp1 is so different.

LLXX
January 28th, 2006, 00:44
I'm actually still working on the *third* code... when I mentioned I was on lvl. 5 I meant I was trying to enable the 5th editbox. This level seems to be rather more difficult than the previous ones. The code is 16 digits long and the even-numbered positions contain the hex address of the function to call to check the odd-numbered positions... although the most probable address is 00414514 (code is of the form 0X0X4X1X4X5X1X4X) I must not forget that there might be other possibilities. However, entering the code mentioned does *not* result in the "NOT FOUND" message, it does nothing at all. As well, replacing the X's with 0s *does* lead to "NOT FOUND". The only assumption I can make is that 00414514 does get called, but then causes an exception that either causes the function to just return or transfer to the "NOT FOUND" message.

At 414514 the code is stripped of its even-numbered characters and then converted to an integer but then it seems the result is discarded completely by restoration of SEH:
Code:
00414694 call StrToInt
00414699 xor eax, eax ; return value ignored
0041469B pop edx
0041469C pop ecx
0041469D pop ecx
0041469E mov fs:[eax], edx
Then follows some rather "demonic" calculations, all with no strange flow-transfers, which end here:
Code:
00414868 imul eax, 666
0041486E imul edx, ebx, 373737
00414874 imul edx, 666 ; as I said...
0041487A cmp eax, edx
0041487C jz short loc_0_414898 ; critical jump
0041487E push 30h
00414880 push offset aNormal__inProg ; "Normal..in progress"
00414885 push offset aYouCanDoMore ; "You can do more "
0041488A mov eax, ds:hDlg
0041488F push eax
00414890 call ds:dword_0_417964 ; this must be MessageBoxA...
00414896 jmp short loc_0_41489D
The other concern is the dword_0_417964 which is supposedly the address of a MessageBoxA, but IDA can't find where it gets initialised. Most likely via an indirect offset like [eax+4].

Woodmann
January 28th, 2006, 01:53
Howdy,

The level 3 password is beyond me. All I know is that the code at 414514 has me stumped. After reading your comments I dont feel so bad .

I will take a few days to look at this but, I do not think I will be able to solve it given my VERY limited skills.

You see back in the old days...............

Regards, Woodmann

Kayaker
January 28th, 2006, 04:28
Yeah, I'm still working on that too. It's a crazy algo and I still haven't figured out the logic of the final compare.

One thing I noted is that there seems to be a "covert" check of a previously set debugger flag. If a debugger was detected, the algo of the 2nd half of that 3rd SN starts with a slightly different sequence.. Follow the wrong algo and you'll never get it right.


The DebuggerFlag seems to be set under 2 conditions -
1. it's set ON by default at program start, and
2. it can be set if manual tracing is detected through the main DialogFunc

Code:

_DebuggerFlag is initialized on program start:
:004159F0 start:
...
:00415A11 mov ds:_DebuggerFlag, 1


_DebuggerFlag can also be set here if the procedure is manually traced:

:00415322 call GetTickCount
:00415327 sub eax, 3E8h
...
:0041534E mov ds:_DebuggerFlag, 1


The _DebuggerFlag is *cleared* in a clever little TranslateMessage / DispatchMessageA loop that continually returns to the "Int3Power" trick that Zairon previously mentioned. A breakpoint in this loop will regularly break if set.
The way I interpret it is that this is a loop that runs whenever the Windows dispatcher decides to handle TranslateMessage. The GetMessageA call continually returns to the embedded 0CCh - the trap exception that occurs should be picked up by the default SEH if no debugger is attached and the code redirected to run the proper instruction.

Code:

:00415A1F loc_415A1F: ; CODE XREF: :00415A85
:00415A1F xor eax, eax
:00415A21 push ebp
:00415A22 push offset loc_415A4E // @ThreadSEH
:00415A27 push dword ptr fs:[eax]
:00415A2A mov fs:[eax], esp
:00415A2D jmp short near ptr unk_415A3E
:00415A2D ; ---------------------------------------------------------------------------
:00415A2F aInt3Power db 'int 3 power =)',0

// You land here. If a debugger is attached (or I3HERE ON in SoftIce),
// and you trace over the Int3's you will *miss* the instruction
// :00415A53 mov ds:_DebuggerFlag, 0

// If a debugger is NOT attached, the Int3 will be handled immediately
// by the thread SEH. Since it's detecting no debugger, the SEH handler
// returns to instruction 00415A53


:00415A3E unk_415A3E db 0CCh ; ¦ ; CODE XREF: :00415A2
// Exception occurs - who is going to handle it
// The crackme SEH or an external debugger?
:00415A3F db 0CCh ; ¦
:00415A40 db 0CCh ; ¦
:00415A41 db 0CCh ; ¦
:00415A42 db 0CCh ; ¦
:00415A43 db 0CCh ; ¦
:00415A44 ; ---------------------------------------------------------------------------
:00415A44 xor eax, eax // BadBoy code
:00415A46 pop edx
:00415A47 pop ecx
:00415A48 pop ecx
:00415A49 mov fs:[eax], edx
:00415A4C jmp short loc_415A5F // end BadBoy, @Continue
:00415A4E ; ---------------------------------------------------------------------------

:00415A4E
:00415A4E @ThreadSEH: ; DATA XREF: :00415A22
:00415A4E jmp loc_4032B4 // SEH handler

// SEH handler - I haven't traced it but it must return to the
// following instruction (as a jmp ebx), to continue the loop

:00415A53 ; ---------------------------------------------------------------------------

:00415A53 mov ds:_DebuggerFlag, 0 // GoodBoy code
:00415A5A call @@DoneExcept

// @Continue...

:00415A5F
:00415A5F loc_415A5F: ; CODE XREF: :00415A4Cj
:00415A5F push offset unk_417928
:00415A64 call TranslateMessage
:00415A69 push offset unk_417928
:00415A6E call DispatchMessageA
:00415A73
:00415A73 loc_415A73: ; CODE XREF: :00415A1Dj
:00415A73 push 0
:00415A75 push 0
:00415A77 push 0
:00415A79 push offset unk_417928
:00415A7E call GetMessageA
:00415A83 test eax, eax
:00415A85 jnz short loc_415A1F // let's go 'round again..
...



Meanwhile back in SN3...

At the very start of the 2nd half of the SN3 algo check proper, is a test for the _DebuggerFlag

Code:

:004146C3 loc_4146C3: ; CODE XREF: SN3_Part2
:004146C3 xor ebx, ebx
:004146C5 mov eax, ds:_Name // Original 'Name'
:004146CA call GetStringLength
// Delphi format = byte length followed by string literal

:004146CF mov edi, eax
:004146D1 test edi, edi
:004146D3 jle short loc_4146EA
:004146D5 mov esi, 1
:004146DA
:004146DA @SUMCharsOfName:
:004146DA mov eax, ds:_Name
:004146DF movzx eax, byte ptr [eax+esi-1]
:004146E4 add ebx, eax
:004146E6 inc esi
:004146E7 dec edi
:004146E8 jnz short @SUMCharsOfName
:004146EA
:004146EA loc_4146EA:
:004146EA cmp ds:_DebuggerFlag, 0
:004146F1 jz short @Goodboy

:004146F3 imul eax, ebx, 7D5h // BadBoy
:004146F9 mov ebx, eax
:004146FB jmp short @Continue

:004146FD ; ---------------------------------------------------------------------------
:004146FD
:004146FD @Goodboy:
:004146FD imul eax, ebx, 29Ah // GoodBoy
:00414703 mov ebx, eax

:00414705 @Continue:
:00414705 mov eax, 7Bh
...


The rest of the algo is rather ugly frankly. I can see the 'what' just not the 'why'.


0X0X4X1X4X5X1X4X
If one of the X's is a character, rather than an integer, the StrToInt function bugchecks to RaiseException, but with no MsgBox one way or another. In that case you never get to the rest of the algo itself.
'12345678' is a good alternative.

As for the missing API at 417964, I just hardcoded in the offset of MessageBoxA for running it. I assumed it was left blank on purpose since it's not critical, if not filled in an SEH handles the error and generates a MsgBox anyway.

Cheers,
Kayaker

LLXX
January 28th, 2006, 06:25
Thanks Kayaker! I thought that _DebuggerFlag was somehow related to the next level and that it was the same algo but modified slightly. Clever use of SEH there. lord_Phoenix certainly knows what he was doing when he wrote this one.

Quote:
[Originally Posted by Kayaker]If one of the X's is a character, rather than an integer, the StrToInt function bugchecks to RaiseException, but with no MsgBox one way or another. In that case you never get to the rest of the algo itself.
Assumptions can be misleading... in this case I assumed that StrToInt would just return if it encountered a non-numerical character, as my previous experience with functions of that sort do (e.g. C's atoi() does not raise an exception if it encounters letters in its input, it just returns). That was responsible for making me overlook the now-obvious surrounding of the call with an SEH - a most clever way of checking for non-numerical characters in strings!
Code:
00414681 xor eax, eax
00414683 push ebp
00414684 push offset loc_0_4146A3 ; <- SEH!
00414689 push dword ptr fs:[eax]
0041468C mov fs:[eax], esp
0041468F mov eax, ds:CODESTRING
00414694 call toInteger
00414699 xor eax, eax ; <- it may not return here; my false assumption!
0041469B pop edx
0041469C pop ecx
0041469D pop ecx
0041469E mov fs:[eax], edx
004146A1 jmp short loc_0_4146C3
004146A3 ; ---------------------------------------------------------------------
004146A3 ; SEH handler. It simply RETNs at the end and doesn't jump back
004146A3 loc_0_4146A3:
004146A3 jmp loc_0_4033E0

Quote:
[Originally Posted by Kayaker]As for the missing API at 417964, I just hardcoded in the offset of MessageBoxA for running it. I assumed it was left blank on purpose since it's not critical, if not filled in an SEH handles the error and generates a MsgBox anyway.
Using SEH to call the MessageBox! I never thought of that. However, SEH which is setup on entrance to 414514:
Code:
0041452E xor eax, eax
00414530 push ebp
00414531 push offset loc_0_4148C0 ; <-- SEH
00414536 push dword ptr fs:[eax]
00414539 mov fs:[eax], esp
does not call MessageBoxA in any way; it just goes to @System@@HandleFinally$qqrv and then to another short routine that frees the memory of the strings and returns. I'm still wondering how the "U need some brainz or luck" message gets displayed even if you enter 00414514 and pass the StrToInt with no exception. My suspicion is that either way, it never reaches the final comparison unless the code is exactly right. If the comparison is unequal, you get the "You can do more " and if it is equal, execution flows through a long and twisted path starting at 41450C until it gets to what looks like the next level algo at 41422C.

Either there is one aspect of SEH that I'm not quite understanding, or something else is causing the flow to deviate from its intended path.

Kayaker
January 28th, 2006, 09:37
Hi,

I hadn't looked into that handler specifically, but it takes a pretty convoluted path. We know the thread specific SEH is set to be 4148C0, and it must call the "U need some brainz" MsgBox proc at 414F07 at some point. If you set a BP on the SEH at 4148C0 and step over the "missing" API at 414890 (what should be a MessageBoxA call but is 0), an exception is generated and the BP will break on the SEH at 4148C0.

If you continue tracing from 4148C0 it jumps to @@HandleFinally at 403568. After passing through this proc (it doesn't actually execute the middle calls but jz's immediately to the RET. What's interesting is where the RET goes to - it returns to ntdll!ExecuteHandler

Code:

:004148C0 jmp @@HandleFinally // SEH


:00403568 @@HandleFinally:
:00403568 mov eax, [esp-4+arg_0]
:0040356C mov edx, [esp-4+arg_4]
:00403570 test dword ptr [eax+4], 6
:00403577 jz short loc_403598
...
:00403598 mov eax, 1
:0040359D retn // returns to ntdll!ExecuteHandler


From ntdll!ExecuteHandler it passes again through RtlDispatchException -> RtlpExecuteHandlerForException -> ExecuteHandler, which finally calls the handler proc at 414F02. This one jumps to a further handler (4032B4) which in turn calls
004032E7 call edx ; 40a5c0

Eventually an exception handler "Unwind" occurs, NtContinue is called and the "U need brainz" MsgBox is finally displayed.

I'd like to see the original code to see how these exception handlers are set up. I'm not sure *exactly* where the "U need some brainz" handler is specified. It's confusing, but in Softice anyway you can single step through everything and eliminate what is "handler" code in the disassembly at least.


It does seem kind of silly that the Delphi StrToInt function will raise an exception if it receives an ascii character, but single stepping confirms that. You really would think such a function should return an error to the caller function instead.


You're right that if the final comparison on SN3 is correct it just continues on to the next level and SN4. At least it looks that way, but if that's the case then you don't get a "success" message for SN3?

(Btw, using a Delphi SIG *really* helps )

Kayaker

SiGiNT
January 28th, 2006, 17:22
Kayaker,

I mentioned the lack of congratulatory messages past level 2 - some days ago, my speculation was that it returned to "yep", but since that isn't the case, it kind of brings up the spectre of "what's the point?", if you do get the third, fourth and fifth numbers you are rewarded with the fact that it simply doesn't crash? - how do you even prove that you've done it - other than submitting your numbers to the author - hmmmmm, frustrating, almost like a crippled demo.

SiGiNT

Kayaker
January 28th, 2006, 23:14
Well here's my solution for the second part of crackme #3. As I wrote these notes it started to come together, so I'll leave in the rambling thoughts that led to the conclusion.

There's something strange about this crackme..

There are 6 regular edit boxes, all initially disabled except the first two. There are a total of 5 crackme levels. Edit box 1 and 2 are for input of Name and SN1. When solved, edit box 1 (Name) gets disabled and edit box 3 (SN2) gets enabled. When SN2 is solved, edit box 4 (SN3) gets enabled.

Now it gets funky. SN3 has this strange algo which may or may not be solvable. After the algo is a simple jz check. It *appears* that if you "get" it you will jump directly to the SN4 routine. However, after 'getting' SN3 there is no 'success' message, and most importantly the edit box for SN4 DOES NOT GET ENABLED. Whoah, what's going on here?

If you search for every instance of GetDlgItem, it is only used with EnableWindow 3 times and WM_GETTEXT 5 times. But this doesn't account for Enabling edit boxes for SN4 or SN5. Nor does it account for getting the text with WM_GETTEXT for SN5. Might there be a hidden EnableWindow call in the form of a SendMessage call? Well there are no extra SendMessage calls unaccounted for either, or any obvious decryption routines.

Code:

:00414C65 call GetDlgItem ; Name - used with EnableWindow (disables)
:00414AAE call GetDlgItem ; Name - used with WM_GETTEXT
:00414AD3 call GetDlgItem ; SN1 - used with WM_GETTEXT
:00414C4D call GetDlgItem ; SN2 - used with EnableWinow (enables)
:00414C7B call GetDlgItem ; SN2 - used with WM_GETTEXT
:00414D37 call GetDlgItem ; SN3 - used with EnableWindow (enables)
:00414D4D call GetDlgItem ; SN3 - used with WM_GETTEXT
:0041425C call GetDlgItem ; SN4 - used with WM_GETTEXT


Well, we really don't know what this crackme is *supposed* to do. We're *assuming* from appearances that there are actually 5 levels all based on a serial number input. From the first few at least the edit box input is important - the Name is used for SN1, the result of SN1 is used with SN2, the Name is again used with SN3, etc.


So now what? Let's take another look at where SN3 leads. The algo is seemingly complex and it's not entirely clear, to me at least, the logic behind it. Let's call it a red herring for arguments sake. If we let the code execute naturally it will call a MessageBoxA function with a "missing" import. The code is protected by an SEH handler which will call the "U need brainz" message discussed in the previous posts.

Code:

:00414514 SN3_Part2 proc near
:0041487C jz short loc_414898
...
...
:0041487E push 30h
:00414880 push offset aNormal__inProg ; "Normal..in progress"
:00414885 push offset aYouCanDoMore ; "You can do more "
:0041488A mov eax, ds:hDlg
:0041488F push eax
:00414890 call ds:[00417964] ; MSGBOXA
// points to an empty memory variable


So what have we got here? - instructions that naturally lead to a code cave from 417964 - 418000!
And all conveniently protected by an SEH in case we screw up..
Wasn't that nice of lord_Phoenix?

With 20-20 hindsight it seems apparent we need to inject some code which will Enable the edit box for SN4 so we can continue. And basically ignore the demonic algo calculations that don't make any sense, just pass the basic requirements for the SN3 that have already been mentioned.

Here are the Code Snippet Creator (Iczelion) settings and code I used to do that. We've already had a few projects which make use of this tool.

Snippet VA - Specify the desired virtual address that the snippet will be relocated to - 417964
Patch into Existing Section
Redirect Control From Code Section - 414890
Return to Program - 414898 - this leads to SN4

Project ini file:
Code:

[OPTIONS]
SNIPPET_VA=417964
PATCHOPTION=2
REDIRECT=2
REDIRECT_VA=414890
RETURN=1
RETURN_VA=414898
RESTORE=1
TARGET=C:\SnippetCreator\Projects\Crackme\crackme.exe
MODEL=.386


Code snippet:
Code:

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.DATA?

hDlg HANDLE ?

.CONST

; ControlId for edit box used with SN4
IDC_EDIT_PROFI equ 5555


.CODE ; This is injected at 417964

; int 1 ; for debugging with Softice

; Get rid of the 4 pushes from the calling function (fake MessageBoxA)

pop eax
mov hDlg, eax ; 1st parameter on the stack is Dialog handle

pop eax
pop eax
pop eax

; Enable the control

invoke GetDlgItem, hDlg, IDC_EDIT_PROFI
invoke EnableWindow, eax, TRUE



Now this isn't really all of it. The first thing you notice is that SN4 requires a string input of length 28h. The problem is that the default size of the edit box won't take that many characters, so a little more work is needed in resizing the window. I don't know if this was premeditated or just an accident, but again there are no rules in crackmes.

All I can say is I'm glad to be done with that ugly SN3 algo (for the moment at least....)

Kayaker

LLXX
January 29th, 2006, 07:02
An interesting analysis by Kayaker, once again!

* The messages "Normal..in progress" and "You can do more " are never shown, even if SN3 is correct. That was intended to be a distractor along with the seemingly authentic call to a "missing" MessageBoxA. It lead me to think that somehow 417964 would've been filled with the MessageBoxA address, via SEH or other convoluted means if SN3 was correct.

* Injecting your own code into a crackme or otherwise modifying it... I had the impression that you weren't allowed to do that, as it says:
Quote:
Rules:
1. Full newbiez - try to patch.
2. Normalz - find some serialz.
3. Other - make full keygen.
Solution=keygen(or punch of serialz
"make full keygen" was what I had in mind.

* The end of lvl. 4 contains this interesting part:
Code:
00414381 pusha
00414382 call $+5
00414387 pop edx
00414388 add edx, 22h ; edx = 004143A9 = pointer
0041438B xor ebx, ebx
loc_0_41438D:
0041438D mov [ebp-4], ebx ; loop counter
00414390 mov eax, [ebp-4]
00414393 mov eax, [ebp+eax*4-1Ch] ; ebp-1c, ebp-18, ebp-14, ebp-10, ebp-0c
00414397 mov [ebp-8], eax
0041439A mov ecx, [ebp-8]
0041439D mov [edx], ecx
0041439F inc ebx ; loop counter +1
004143A0 add edx, 4 ; next dord
004143A3 cmp ebx, 5 ; done 5?
004143A6 jnz short loc_0_41438D
004143A8 popa
004143A9 ; 20 bytes go here
From looking at the functioning of the code before this, [ebp-1c] to [ebp-0c] are taken from SN4. I.e. SN4 is 40 bytes, and each word in hex is 8 bytes, so there are exactly 5 words in SN4, and those are actually going to be executed as code! The problem is, what does this code have to do? There aren't that many things you can do in 20 bytes...

ZaiRoN
January 31st, 2006, 09:50
Hi.
I'm perfectly agree with your analysis Kayaker, normal_level is definitly bugged!

There aren't hidden procedures, hidden tricks... I spent lot of time trying to find something without luck.
I think the *ugly* serial calculation is fake, it's here just to fool us (It appears to me it's not even solvable but we should bruteforce it, just to be sure). The normal_code level should be only a sort of trampoline between newbie and profi level. No congratulations box. A working serial is obtained by 8 insignificant chars and 8 chars representing the address (the trampoline) to the beginning of the profi routine (with the call to enablewindow...), nothing more. I don't understand how is possible to forget to add such part of code, he didn't check it. I'll mail him, just to be sure we are not totally stupid missing something important from the crackme.

Ok, level_4 now

ZaiRoN
January 31st, 2006, 10:50
Hi again Kayaker.
I was looking at your CSC project's settings, in particular:
RESTORE=1
It's not a good choice to restore the original instructions, don't you think?

Kayaker
January 31st, 2006, 13:45
Quote:
[Originally Posted by ZaiRoN]It's not a good choice to restore the original instructions, don't you think?


Only if you want it to crash...

Like he said...

SiGiNT
January 31st, 2006, 19:04
SiGiNT's ultimate CRaCKMe!

1. Short executable displays an empty TextBox - no matter what you type in it displays "LOSER", (mis-spelled "LOOSER".

2. Solution:

1. Write a "crackme"
2. Provide a solution along with a keygen.
3. Submit to the author.

3. I will supply you with the details on how to delete my crackme.

Just a little mean spirited humor!

Ok! inappropriate but I couldn't resist!

In going over the dead listing again - I noticed that there appears to be no "obvious, (at least to me),code", that will enable text boxes 5 & 6 - they can be enabled using an external tool, I can even fake it so it looks like I solved it, but in the crackme itself there is an instruction to push 15B3h (ID: 5555), but it appears to be locked out because it is not preceeded by push -1h (enable), or anything that would pass for that - then on to push 1A0Ah (ID: 6666), remember the demonic code in the second part of number 3?, It doesn't exist. (sorry Kayaker you already noticed this!)

Is it possible that we're dealing with a bad compilation?

Also found this while going through a hex listing of the file - my logic being that possibly the first half of number 3 could be fished but the second half was sitting in plain sight in the hex code - Not Yet Implemented at 0x00013834.

Unfinished release?

Just a thought!

SiGiNT (that smile is supposed to be a semicolon)

ZaiRoN
February 1st, 2006, 10:26
I got a little reply from Lord_Phoenix about level_3:
"u need to enable level_4 editbox by ur hands, and to check level_4 code using some little "exploit" in level_3"
Nothing more... Now, we should understand what level_4 wants.

SiGiNT
February 1st, 2006, 19:32
In other words totally ignore his "rules" -

Rules:
1. Full newbiez - try to patch.
2. Normalz - find some serialz.
3. Other - make full keygen.
Solution=keygen(or punch of serialz

In which case then I've solved it - I can send a screen if anyone wants to see.

Maybe my "inappropriate humor" wasn't in apprpriate.

SiGiNT

book
April 5th, 2006, 09:09
Hey there. This post contains a few details about the crackem. That's ok right?

Firstly: I got through the first weak protection section, and dumped the file. Would it have been to my advantage to have understood anything which was going on up to that point, such as the decryption method used? I basically just followed through without really understanding that much of it. Realistically, is that going to work very often? Obviously the bit I have got through is the extreme newbie one.

Secondly: While I was doing this it appeared that the crackme piggybacks part of something called wbsys.dll for some of its api calls. wtf is with that?

SiGiNT
April 5th, 2006, 11:51
Have fun working on this but I believe if you read prior posts, the general consensus is that this crackme is incomplete and the last part is up to you to code, fake, fool, whatever - not a good example of a crackme.

IMHO

SiGiNT

LLXX
April 5th, 2006, 21:43
Quote:
[Originally Posted by book]Firstly: I got through the first weak protection section, and dumped the file. Would it have been to my advantage to have understood anything which was going on up to that point, such as the decryption method used? I basically just followed through without really understanding that much of it. Realistically, is that going to work very often? Obviously the bit I have got through is the extreme newbie one.
Decryption method? You mean the packer? That's just UPX... no, you don't need to understand how the packer works besides knowing how to get to OEP and how to dump it.
Quote:
[Originally Posted by book]Secondly: While I was doing this it appeared that the crackme piggybacks part of something called wbsys.dll for some of its api calls. wtf is with that?
That is just the hook DLL for WindowBlinds. Disable it if you don't want the API calls to go through there.