HAH Trial CrackMe v2.0
Visual Basic Cracking
Written by Sphinx


Introduction


Well, after finishing my essay on HAH Trial CrackMe #1. I craved for another P-Coded app. And wouldn't you know
it? HAH Trial CrackMe #2 is also P-Coded :) So I set my hands on it. So I guess I could congratulate myself again for
this one. Nice work Sphinx! :) And I believe this CrackMe is still valid as of this writing - 05/16/2001. So if you have
plans of joining HAH, please (note: I'm begging!) do NOT read this. Don't cheat just crack! But if you do cheat, please
give credit where credit is due (heh!). Or better yet, wait for HAH Trial CrackMe #4, coz #3's NOT a Trial CrackMe :(
And besides, it's coded in Delphi ;)



Tools required


ExDec (I used the GUI version)

Target's URL

http://www.vinaplus.com/~tnhuan



Essay



Ok. As usual, as I start any of my cracking session, I snoop instead of running it immediately. Dunno why though.
I guess it's just me :) Ok. Ahhh, VB6-coded once again (ie. requiring MSVBVM60.DLL). But still, no SmartCheck
here and SoftICE wasn't used at all :) Only ExDec, a powerful tool for cracking P-Coded "programs". Anyway,
onward we go (as we should)...

- Run the CrackMe. Whooow! Nifty gfx :) Though I personally liked the first one ;) Hmmm... a name field and hey!
  Notice how it'll accept a serial. Yep, via four (4) (horizontal) scroll bars! Remember, I didn't use SoftICE here, so I
  entirely relied on ExDec and (a lot of) my own intuition :) Anyway, I entered Sphinx as name and made the bars read
  (ie. starting from the top) 1234. And wouldn't you know it? It's wrong! Then my egoistic personality suddenly kicked in :)
  I was focused on a goal. A goal that must be pursued by all means. A goal.... yeah, whatever. I just wanted to crack it :)
  So let's exit and start from scatch with ExDec.

- Run ExDec and disassemble the crackme, then exit. Now search for a [my.txt] in the dir where you've disassembled it.
  And NOTE! I won't present here the entire dasm listing, since it's too long. And some infos aren't really necessary for us.
  I'll just present here the important parts (and also, I've modified some lines and added some comments to make it more
  clear for you and (a lot for) me :)

 The (important) code snippet starts here: (hexcodes were ripped!)

 408F1A: FnLenStr ; get namelength
 408F1B: LitI4: 0x5 5 (....) ; the "to-be-compared to"
 408F20: LtI4
 408F21: BranchF: 408F4D ; jump to :408F4D (calc_routine) if length >= 5 chars.
 408F24: LitVar_Missing
 408F27: LitVar_Missing
 408F2A: LitVar_Missing
 408F2D: LitI4: 0x0 0 (....)
 408F32: LitVarStr: ( local_00AC ) Name must >=5 charecter
 408F37: FStVarCopyObj local_00BC
 408F3A: FLdRfVar local_00BC
 408F3D: ImpAdCallFPR4:
 408F42: FFreeVar
 See? We jumped OVER these routine if we passed the length check :)

Calculations begins... NOW!

 408F4D: LitI2_Byte: 0x1 1 (.) ; push 1 onto stack to be the initial_value of the "for" loop below.
 408F4F: FLdRfVar local_0086
 408F52: ILdRf local_0094
 408F55: FnLenStr; get namelength to be the the final_value
 408F56: CI2I4
 408F57: Lead3/63 ForI2: (when done) 408FAD ; Now it begins...
 Ok. The actual for loop starts from the above - ie. for Count := 1 to Length(Name)

 408F5D: LitVarI2: ( local_00BC ) 0x1 (1) ; push 1 for MID$()
 408F62: FLdI2 local_0086
 408F65: CI4UI1
 408F66: FLdRfVar local_0094
 408F69: CVarRef: ( local_00AC ) 4008
 408F6E: FLdRfVar local_00DC
 Maybe "FldRfVar" will load the variable for name, coz we're starting to get the chars of name here!

 408F71: ImpAdCallFPR4: rtcMidCharVar; yep, call MID$() to position the pointer on the name
 408F76: FLdRfVar local_00DC
 408F79: CStrVarTmp
 408F7A: FStStr local_008C
 408F7D: FFreeVar
 408F84: ILdRf local_008C
 408F87: ImpAdCallI2 rtcAnsiValueBstr yep, call ASC() to get the ASCII value of the name_char
 408F8C: FStI2 local_0088 ; "push" it here (?)
 408F8F: FLdI2 local_0088 ; "pop" it here (?)
 408F92: LitI2_Byte: 0x2 2 (.) ; save a 2 for...
 408F94: MulI2 ; multiplication
 408F95: LitI2_Byte: 0x68 104 (h) ; save a 0x68 for..
 408F97: AddI2 ; addition
 408F98: FStI2 local_0088
 408F9B: FLdI2 local_008E
 408F9E: FLdI2 local_0088
 408FA1: AddI2 ; note this! This acts as the "accumulator" for the above
 408FA2: FStI2 local_008E
 408FA5: FLdRfVar local_0086
 408FA8: NextI2: (continue) 408F5D ; yeah, get the next since we've not yet reached the final_value yet

Ahhh, BIG code snippet isn't it? But we're NOT over yet! Oh no! The most important parts are yet to come. But to
sum up the above, here it is: (again, in Pascal code coz this is one of my faves, beside ASM :)

for Count := 1 to Length(Name) do
begin
   x := ord(Name[Count]);
   x := x * 2;
   x := x + $68;
   y := y + x;
end;

Anyway, these routine resulted for my nick 1892 (already in decimal). Then continuing to examine the dasm, I was
kinda sure that the next (not shown) just converts the serial to a fully qualified integer (ie. the entered 1234 would REALLY be 1234). Anyway, we'll skip these and goto the second part of the calculation, where I relied on my intuition to the fullest :) Note: I'll be calling usercode as our input and realcode as, well... the REAL code! But NOT YET the final realcode, but that 1892 above which resulted from the initial for-loop. Oh yeah, the usercode is the fully qualified integer, btw.

 4090AD: FStR4 local_0128 ; "push" usercode
 4090B0: ILdRf local_0128 ; "pop" usercode
 4090B3: LitI4: 0x4d2 1234 (....) ; save a 0x4D2 then...
 4090B8: Lead0/11 XorI2 ; xor usercode with it!
 4090BA: FStR4 local_0128 ; "push" usercode here
 4090BD: FLdI2 local_008E ; "pop" realcode here
 4090C0: LitI2: 0x8b9 2233 (..) ; save a 0x8B9 then...
 4090C3: Lead0/11 XorI2 ; xor realcode with it!
 4090C5: FStI2 local_008E ; "push" realcode here
 4090C8: FLdI2 local_008E ; "pop" realcode here
 4090CB: CI4UI1 ; dunno :)
 4090CC: ILdRf local_0128 ; "pop" usercode here
 4090CF: EqI4 ; compare them here
 4090D0: BranchF: 409135 ; yep, jump to :409135 if <>, else...
 4090D3: LitI4: 0xd 13 (....)
 4090D8: FLdRfVar local_00BC
 4090DB: ImpAdCallFPR4:
 4090E0: LitVar_Missing
 4090E3: LitVar_Missing
 4090E6: LitVarStr: ( local_00EC ) Congratulation
 4090EB: FStVarCopyObj local_011C
 4090EE: FLdRfVar local_011C
 4090F1: LitI4 0x40 64 (...@)
 4090F6: LitVarStr: ( local_00AC ) Great, Good work.Now, you can become a HAH member
 4090FB: FLdRfVar local_00BC
 4090FE: Lead0/94 AddVar local_00DC
 409102: LitVarStr: ( local_00CC ) I you want to join us, please send to me: serial+name+tutorial or a keygen
 409107: Lead0/94 AddVar local_00FC
 Ahhh, our target message, which is my "goal", btw :)

Ok. This is my explanation of the algo: (numbers with the "0x" prefixes are hex (as in C standard), the rest are in decimal)

- 1234 (usercode) xor 0x4D2 = 0
- 1892 (initial) xor 0x8B9 = 4061 (final realcode)

But since 0 is not equal with 4061, we're the bad_boys! So how are we going to reversed this algo? Simple. It's just a
simple algebra. Ok. We know that 4061 is our (well, my) final realcode noh? So what we do is this:

- 4061 (final) xor 0x4D2 = 2831 (usercode)

Let's check:

- 2831 (usercode) xor 0x4D2 = 4061
- 1892 (initial) xor 0x8B9 = 4061 (final realcode)

So that's it! The serial is sniffed (heh!). So if I entered 2831 by moving the topmost bar to 2, the 2nd to 8, the 3rd to 3
and the 4th to 1. Then hit "Check", it'll register! But we don't just want a serial right? Anyway, here's my keygen in JavaScript. Note: The could be some problems though, just imagine. We could only enter 4 numbers, but what if
the result was >= 4 numbers. I never encountered this myself though, but what if? Oh yeah, if the output for a name
resulted to only 3 numbers, you could bet that the 1st bar should be 0, then just continue on with the rest.

The Keygen



Enter thy name:  



Serial Number:  



Yep, that would be it for me, later.

Sphinx [sphinxter@edsamail.com.ph]

Final Notes



My Greetz Goes to:



TRES2000 (for the chance)
SpeedRipper (for being homey :)
tnHuAn (for ALWAYS "pressuring" me ;)
(sir) josephCo (for creating ExDec)
Andrea (for just being you) *sigh*




When ever there is a door,
there is an entrance.
And behind an entrance can no secret hide,
when a cracker takes his knowledge for a ride
                                                                               McCodEMaN



ObDuh

The information in this essay is for educational purpose only!
You are only allow to crack, reverse engineer, modify code and debugg programs that you legaly bought and then for personal use only!!
To ignore this warning is a criminell act and can result in lawful actions!

So please note!
I take no responebility for how you use the information in this essay, i take NO responebility for what might happen to you or your computer!
You use this information on your own risk!!









Essay written by Sphinx ŠTRES2000. All Rights Reserved.