HOW TO CRACK VideoCraft Gif Animator (Win 3.1)
(magic numbers galore)
by Desert Eagle
Courtesy of Fravia's page of reverse engineering
~
A very interesting essay, this target calculates a different checksum based
on the BIOS of your PC!
I wrote this tutorial a couple weeks ago hoping to get it published on
your page. But unfortunately, I have been busy (lazy) lately so I just got
around to finishing (plus testing) it up yesterday.
Originally when I cracked this program, I modified -easily- certain registers
using Winice to accomplish the crack. Unfortunately again, for a cheap $30
program, this target has many layers of protection and knows if its executable has been
modified (thus the cracks only work through Winice). I don't think my tutorial
would make sense if it didn't solve this problem (at least not how Phrozen Crew
did it) so I decide to pass on what I wrote to you since you might find it
interesting. Anyway, along with the others that have learnt thru you guys
(+Orc & students), THANKS.
HOW TO CRACK VideoCraft Gif Animator (Win 3.1)
VGA, as the name suggests, is a gif animator with numerous video special
effects (overlay, morphing, warp, etc) but unfortunately you're limited to a
30 day trial period which is disabled as usual when you register.
In this tutorial I will explain the two different methods I used in order to
defeat this copy protection. Method two, is more a dead listings/softice approach
and surprising quick, it took about 5 minutes. However method one, although more
interesting, is pretty time consuming (you're getting the time saving version).
I still recommend trying it nevertheless, since it offers an alternative.
Method one is based on +RCG essay on Cuteftp... where he explains how to crack
programs, like VGA, which read a file to determine the user's registration status.
Like CuteFtp, VGA does this by manipulating and checking specific data in its
control file (vidcra.ctl) in order to determine if you are registered or not
(also checking your computer), along with other things.
Method 1
=========
Fire Winice
In Windows 3.1 there are two API functions used in order to read files :
_LREAD
_HREAD - files > 64 Kb
Therefore, BPX _LREAD and run our target VGA.
When the breakpoint is triggered you will be in the _LREAD call, therefore
exit the call (F11). You should see the following code:
PUSH WORD PTR [0592] file buffer segment -> DS
PUSH WORD PTR [0590] file buffer offset
PUSH 02A4 # of bytes to read (676 bytes, the exact length of vidcra.ctl)
CALL KERNEL!_LREAD
CMP AX, 02A4 check file length
JZ 324C jump if correct else sorry, your time limit has expired
Since we know the segment, offset and length of the file buffer we can BPR it
and observe what our target VGA does with it. So...
BPR DS:buffer_offset DS:buffer_offset+2A4 R
Your first stop will land you inside this code snippet:
0001.327D MOV BX, DI DI = buffer_offset
0001.327F MOV ES, [BP-04] BX = buffer_offset
0001.3282 MOV AL , ES [BX+SI] [BP-04] = buffer_segment
0001.3285 SUB BX, SI SI = 0
0001.3287 MOV [BP-01], AL
0001.328A MOV AL , ES [BX+02A3]
0001.328F LEA CX, [BX+02A3]
0001.3293 MOV BX, DI
0001.3295 MOV ES [BX+SI], AL
0001.3298 MOV BX, CX
0001.329A MOV AL , [BP-01]
0001.329D MOV ES [BX], AL
0001.32A0 INC SI
0001.32A1 INC SI
0001.32A2 CMP SI, 0150
0001.32A6 JB 327D
Examining the code, you'll see that our target VGA is switching every other byte
at the beginning of the buffer with every other byte from the end (hmmm).
Now if you BPR some more, then the fun really starts and we get into the
decryption of vidcra.ctl... look!
SI = 0 ES = buffer_segment DI = 0 key = dbfrsmftrtu
0001.1D37 LES BX, [BP+06] BX points to buffer_offset
0001.1D3A MOV AL , ES [BX+SI] move byte in AL for decryption
0001.1D3D LES BX, [BP+0A] BX points to decryption_key_offset
0001.1D40 MOV CX, AX
0001.1D42 MOV AX, [BP-04] [BP-04] = 40
0001.1D45 SUB AX, [BP-06] [BP-06] = 0xA = # of bytes to be decrypted
0001.1D48 ADD AX, SI
0001.1D4A DEC AX
0001.1D4B MOV DX, 00FE
0001.1D4E MOV [BP-0C], DX
0001.1D51 CWD prepare for division
0001.1D52 IDIV WORD PTR [BP-0C] divide AX by 0xFE and put remainder and
quotient in AX
0001.1D55 INC DX
0001.1D56 MOV [BP-04], DX
0001.1D59 XOR DL, ES [BX+DI] xor DL with decryption key then...
0001.1D5C XOR CL , DL xor result with CL (byte to be decrypted)
0001.1D5E JE 1D67
0001.1D60 LES BX, [BP+0E] BX points to offset where the decrypted
bytes are to be placed
0001.1D63 MOV AL , CL
0001.1D65 JMP 1D70
0001.1D67 LES BX, [BP+06] BX points to buffer_offset
0001.1D6A MOV AL , ES [BX+SI]
0001.1D6D LES BX, [BP+0E] BX points to offset where the decrypted
bytes are to be placed
0001.1D70 MOV ES [BX+SI], AL move decrypted bytes into their new home
0001.1D73 CMP [BP-08], DI [BP-08] = length of decryption key
0001.1D76 JG 1D7C if [BP-08] > DI...
0001.1D78 XOR DI, DI then zero DI (start at beginning of decrypt
ion key again) else
0001.1D7A JMP 1D7D
0001.1D7C INC DI
0001.1D7D INC SI
0001.1D7E CMP [BP-06], SI
0001.1D81 JG 1D37 loop until decryption is finished
This decrypts the first 10 bytes into 0000009531, which our target VGA checks,
in order to see if the file is indeed vidcra.ctl. There is also no need to
breakpoint this memory location. I think this also serves as an id. number for
the control file so that it can't be used with another program that North Coast
Software writes, which employs the same copy protection scheme.
If we continue breakpointing we eventually return to the same decryption code
again and again. Therefore, to make a long essay shorter, a bunch of shit is
decoded:
[BP-04] = 0xD8 (for all) key = jkebmbmfbdfmbm009531 (for all)
Beginning at
DS:buffer_offset + Decrypted message Comment
=============================================================================
0xD North Coast Software, Inc Thelma & Lewis employers
0x3E Thelma & Lewis bored programmers?
0xC5 Barrington guess what city N.S.C. is in
0xF3 NH now for the daily double, can
you name this state?
0xF7 03825 zip code
0x10F VideoCraft GIF Animator ?
0x13D 263726376237 Hmmm! (maybe different for u)
0x24C 07 04 CD 07 installation date (7/4/1997)
0x252 17 2E 3B I think it was the time
0x256 07 05 CD 07 expiration date
Knowing what most of the decrypted stuff is, the only important thing to us are
those suspicious numbers. The rest -excluding the time and dates-, if you check,
is only 'filler' to beef up the file, therefore our target VGA blindly recompiles
(encrypt it and shifts it around) back into vidcra.ctl without checking it. So...
BPR DS:decrypted_bytes_home DS:decrypted_bytes_home+C R
Before this new breakpoint get a chance to be triggered, our previous BPR comes
back into play and brings us here:
0001.35F5 MOV AL , ES [BX+025C]
0001.35FA MOV BX, 27A4
0001.35FD ADD AL, 24
0001.35FF MOV [BX+025C], AL --> Very important. BPMB DS:2A00 R. You could
0001.3603 LES SI, [0590] also BPR the entire memory location
0001.3607 MOV AL , ES [SI+025E] affected but it would prove to be a waste
0001.360C SUB AL, 15 of time
0001.360E MOV [BX+025E], AL
0001.3612 LES SI, [0590]
0001.3616 MOV AL , ES [SI+025F]
0001.361B SUB AL, 15
0001.361D MOV [BX+025F], AL
0001.3621 LES SI, [0590]
0001.3625 MOV AL , ES [SI+0260]
0001.362A SUB AL, 15
0001.362C MOV [BX+0260], AL
.
.
.
.
0001.367B LES SI, [0590]
0001.367F MOV AL , ES [SI+0266]
0001.3684 SUB AL, 15
0001.3686 MOV [BX+0266], AL
0001.368A LES SI, [0590]
0001.368E MOV AL , ES [SI+0267]
0001.3693 SUB AL, 15
After that, our old breakpoint, BPR DS:buffer_offset DS:buffer_offset+2A4 R,
will not be needed again. If you decide to keep it (and waste time) you'll only
see our target VGA recompiling the file (among other tedious things).
As expected our *NEW* breakpoint is now triggered and at the second instance
you'll land into another crucial part of the program:
0001.2294 CMP BYTE PTR [2A00], 44
0001.2299 JE 22BA
0001.229B CMP BYTE PTR [2A00], 45
0001.22A0 JE 22BA
0001.22A2 CMP BYTE PTR [2A00], 53
0001.22A7 JE 22BA
0001.22A9 CMP BYTE PTR [2A00], 50
0001.22AE JE 22BA
0001.22B0 CMP BYTE PTR [2A00], 4E
0001.22B5 JE 22BA
0001.22B7 MOV AL, 20
0001.22B9 RETF
0001.22BA MOV AL, [2A00]
0001.22BD RETF
As you can see, DS:[2A00] could have 5 different values and hence the target could
switch to 5 possible directions. In order to find the right path without wasting
time we need to use a process of elimination. Remember this piece of code that we
have seen earlier?
0001.35F5 MOV AL , ES [BX+025C]
0001.35FA MOV BX, 27A4
0001.35FD ADD AL, 24
0001.35FF MOV [BX+025C], AL
BPX on CS:35F5 and clear the remaining breakpoints. Restart VGA and edit the
memory location ES [BX+025C], BEFORE 0x24 is added, then enter the hex value
that, when 0x24 is added, equals one of the 5 values we have seen above.
Let VGA run and observe the results:
Hex ASCII Result
============================================================
0x53 S Normal - registration screen comes up
0x50 P Normal - registration screen comes up
0x45 E Trial time expired
0x4E N Registered but to a different machine - Bingo!
0x44 D Trial time expired
|_ Hmmm
Talk about luck. If changing the memory location didn't produce a visible
result, we would have had to set breakpoints and trace through the code for
each of the 5 hex values we saw
Now, you must know (or suspect) that 0x4E is the right value for a
registered VGA target and that the suspicious numbers are supposed to be
(or to be part of) the correct machine number needed.
I don't think I need to go into much detail about what needs to be done next
nor about how tp do it.
All you should need is a BPR on the suspicious numbers and the right hex value
(0x2A) in the correct memory location (as showed earlier).
The breakpoint will reveal that the numbers are copied to another location
(BPR it!) afterwhich they are copied oncemore from that location to another.
To save time, clear the original BPR once the numbers are copied to a new memory
location.
Eventually, you will land inside this code snippet... which proves to be quite
interesting:
0041.22F7 LODSB load first number
0041.22F8 CMP AL, 20
0041.22FA JE 22F7
0041.22FC CMP AL, 09
0041.22FE JE 22F7
0041.2300 PUSH AX save first number
0041.2301 CMP AL, 2D compare number to "-"
0041.2303 JE 2309
0041.2305 CMP AL, 2B compare number to "+"
0041.2307 JNE 230A
0041.2309 LODSB load number
0041.230A CMP AL, 39 \
0041.230C JA 232D |
0041.230E SUB AL, 30 |- if not between 0 & 9 jump to 232D
0041.2310 JB 232D /
0041.2312 SHL BX, 01 shift bits in BX to the left once (BX x 2)
0041.2314 RCL DX, 01 rotate bits in DX to the left once. DX becomes
(DX x 2) + 1 if CF set or (DX x 2) if CF not set
(or something like that :-)
0041.2316 MOV CX, BX
0041.2318 MOV DI, DX
0041.231A SHL BX, 01
0041.231C RCL DX, 01
0041.231E SHL BX, 01
0041.2320 RCL DX, 01
0041.2322 ADD BX, CX
0041.2324 ADC DX, DI add DI (+1 if CF set) to DX
0041.2326 ADD BX, AX
0041.2328 ADC DX, 0000 add 1 to DX if CF is set
0041.232B JMP 2309
0041.232D POP AX get first number
0041.232E CMP AL, 2D
0041.2330 XCHG AX,BX
0041.2331 JNE 233A
0041.2333 NEG AX
0041.2335 ADC DX, 0000
0041.2338 NEG DX
0041.233A POP SI
0041.233B POP DI
0041.233C POP BP
0041.233D RETF
Analysing the code you'll notice that the AX & DX registers will
eventually contain the results from the calculations performed. Now we
must single step through the code in order to see what happens next to
these registers. Once you exit the call and single step a little
you'll the see the following code snippet...
0040.04ED MOV SI, AX
0040.04EF MOV DI, DX
0040.04F1 CALL WARP.PP_COMPNO -> compute no.?
0040.04F6 CMP SI, AX
0040.04F8 JNE 04FE
0040.04FA CMP DI, DX
0040.04FC JE 0556
0040.04FE XOR AX, AX
0040.0500 PUSH AX
0040.0501 MOV CX, 1701
0040.0504 PUSH DS
0040.0505 PUSH CX
0040.0506 MOV CX, 16F8
0040.0509 PUSH DS
0040.050A PUSH CX
0040.050B MOV CX, 0010
0040.050E PUSH CX
0040.050F CALL USER.MESSAGEBOX
...and notice that our two magic numbers are moved into the SI & DI registers
Immediately after the next call, SI & DI (most likely ours), are compared
with AX & DX. Now notice that if the comparision fails a message will be
displayed.
You don't need a bigger sign than that to know we have reached the infamous
JE/JNZ/JNE/JZ crossroad, tipical of most copy protected programs. To test our
hunch, step over the call (F10) and edit the SI & DI registers, and enter the
right values.
R SI=AX
R DI=DX
Give control back to our target VGA and bingo!, we have finished our cracking
session. Well not quite, since VGA reads vicra.ctl every time it starts, even
when we're registered, we have to modify vidcraft.exe and add the following
changes:
0040.04F6 CMP SI, AX
0040.04F8 JNE 04FE becomes JE 04FE
0040.04FA CMP DI, DX
0040.04FC JE 0556 becomes JNE 0556
Since we already edited the file buffer and placed 0x2A in it, VGA will save a
new vidcra.ctl with this new value, so now we're really done.
If you were interested to know how VGA generates the correct machine number
VGA, in the PP_COMPNO call... it copies your BIOS into a new memory location
and using the code below calculates your PECULIAR machine number.
0001.394D PUSH SI
0001.394E SUB AX, AX zero ax
0001.3950 MOV [BP-02], AX zero [BP-02]
0001.3953 MOV [BP-04], AX zero [BP-04]
0001.3956 XOR SI, SI zero SI
0001.3958 MOV DI, [BP+06] move BIOS_offset into DI
0001.395B JMP 3972
0001.395D MOV ES, [BP+08] move BIOS_segment in ES
0001.3960 MOV BX, DI
0001.3962 ADD BX, SI increment BIOS_offset
0001.3964 SUB AH, AH
0001.3966 MOV AL , ES [BX] copy BIOS_byte into AL
0001.3969 SUB DX, DX
0001.396B ADD [BP-04], AX add new BIOS_byte to previous BIOS_byte
0001.396E ADC [BP-02], DX add DX (+1 if CF set) to [BP-02]
0001.3971 INC SI
0001.3972 CMP SI, 1FE0
0001.3976 JBE 395D
0001.3978 MOV AX, [BP-04] move correct_machine_number #1 into AX
0001.397B MOV DX, [BP-02] move correct_machine_number #2 into DX
0001.397E POP SI get vidcra.ctl_machine_number #1
0001.397F POP DI get vidcra.ctl_machine_number #2
0001.3980 LEAVE
0001.3981 RETF
BTW, the numbers are generated again later, in order to create your Product
Identification number.
Method 2
=========
In writing warp.dll, the silly programmers aptly named every function.
Of course this can be all revealed when you disassemble warp.dll with your
favourite disassembler and can as usual be used to our advantage. If you
examine the list of functions you can't help but notice the PP_UNLOCK function
and know that it must be there exactly for that... to unlock the software.
.
.
Addr:0001.147E Ord:0032d Type:FFh Name: PP_COMPNO {Exported}
Addr:0001.1092 Ord:0033d Type:FFh Name: PP_NEXECT {Exported}
Addr:0001.13F6 Ord:0034d Type:FFh Name: PP_UNLOCK {Exported}
You are deep inside fravia's page of reverse engineering,
choose your way out:
homepage
links
anonymity
+ORC
students' essays
tools cocktails
search_forms mailFraVia