643 lines
31 KiB
Plaintext
643 lines
31 KiB
Plaintext
|
|
CRACKING 101 - 1990 edition
|
|
|
|
Lesson 2
|
|
|
|
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ DOC CHECK PRIMER ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
|
|
by Buckaroo Banzai
|
|
|
|
|
|
Ok, in this textfile, I will start talking about
|
|
removing doc check protection schemes. I find, the doc check
|
|
scheme to be slightly more difficult to work on than normal
|
|
INT 13 schemes.
|
|
|
|
What is a doc check. Usually, a doc check when a
|
|
program ask the user to enter a phrase or code supplied with
|
|
the manual. Now, one might think that "Shit, we can just
|
|
type all the codes in to a textfile and upload it with the
|
|
DOCS", but that way of thinking breaks down on programs such
|
|
as Future Classics where there are 6 pages with about 200
|
|
codes per page. So it is just better to remove the check
|
|
completely.
|
|
|
|
In this primer, I will get in to the theory of removing
|
|
a doc check, then start with a simple example (Electronic
|
|
Art's ESCAPE FROM HELL). Then in the next file, I will take
|
|
you deeper in to the world of doc checks and work with more
|
|
difficult examples. But for now, lets get started.
|
|
|
|
A doc check, in basic theory works much like normal
|
|
INT 13 copy protection. Somewhere in the beginning of the
|
|
program before it really starts, the check is made. If the
|
|
result is ok (ie the user enters the correct word or phrase)
|
|
then the program continues. If not, then the program simply
|
|
exits to dos.
|
|
|
|
Simple right, well not really. Usually, the input
|
|
routine is part of the standard input routine of the program
|
|
so you just can't go about modify the call to INT 16h (the
|
|
keyboard interrupt) like you could with INT 13h. So, where
|
|
do we start. If you think back to cracking the old INT 13
|
|
protection schemes, you would use a program like PCWATCH or
|
|
TRAP13 to get a rough idea of where the call resides. With
|
|
doc checks, this is really not the best way to do it.
|
|
|
|
I suggest that you try to break in to the program well
|
|
before the protection is checked. Remember, we must remove
|
|
the check without messing with the actual input routine so we
|
|
want to come in highest level.
|
|
|
|
So, how do we break in. By using a good debugger. I
|
|
suggest Periscope. I find it is the best and easiest to use.
|
|
Once we are in, all the is left is to trace through the
|
|
program until we find the topmost call to the doc check. Now
|
|
we're moving.
|
|
|
|
So let's say we have broken in to the program and found
|
|
the topmost call to the doc check. What next. We must try
|
|
to figure out what the program does. There are 2
|
|
possibilities. First, the program could simply check the
|
|
inputed string against a value in memory, and if they don't
|
|
match simply exit to dos and if they do, just continue with
|
|
the program; or if the input matches it can set a flag in
|
|
memory that is checked by some routine later.
|
|
|
|
So, on to the example. NOTE! All address might be
|
|
different. This is how it looked when I cracked it. ALSO
|
|
NOTE, you should be cracking without any memory resident
|
|
programs. Make sure MEMORY is clear, and that you load the
|
|
system the same way each time. Remember, if you load
|
|
everything the same, everything will be in the same memory
|
|
location.
|
|
|
|
So, what is our first step. Well, I suggest picking out
|
|
the right tools to do the job. In this case, You will only
|
|
need PERISCOPE (and the addin program that comes with it
|
|
called PSKEY) and a good file editor (when I say good I mean
|
|
it can edit and search in hex). So let's get started.
|
|
|
|
First, we load PERISCOPE (PS from now on). This is
|
|
gonna be the debugger we use. Next, we need a quick way in
|
|
to the debugger. Since ESCAPE FROM HELL (EFH from now on) is
|
|
not all the picky about how it keeps a crackest out, PSKEY
|
|
will do just fine but not without using a little trick.
|
|
|
|
Normally, when using PSKEY (for those of you who do not
|
|
know what PSKEY does, it allows up to break in to PS usings a
|
|
TSR hotkey) and you hit the hotkey, PSKEY does an INT 2h
|
|
(NMI). This then brings up PS and you are set. But, EFH
|
|
revectors INT 2h (NMI) to simply an IRET so this method does
|
|
not work. How do we get around this, well, INT 2h is the
|
|
default used with PSKEY but not the only way to work it. You
|
|
can also use INT 3h (Breakpoint interrupt) or INT 15h
|
|
(Extended services interrrupt) to activate PS. In this case
|
|
we will use INT 3h; so when we invoke PSKEY we add the
|
|
command line parameter "3" (ie: "PSKEY 3CAL" invokes PSKEY
|
|
using INT 3h setting the hotkey to CTRL-ALT-LEFT_SHIFT).
|
|
|
|
So, now that we have a way in to EFH, where do we want
|
|
to break out. Well boys (and Girls, and BTW: if there are
|
|
any Fems reading this, give me a ring, I'd like to hear from
|
|
ya) I don't have any formula to give, but remember, I suggest
|
|
that we try to break in to the outermost loop. So,
|
|
experiance (and a good fucking guess) tells me to break out
|
|
in the title screen before the music begins.
|
|
|
|
It just so happens that this time I was right (And noone
|
|
had to get nail to anything -D.A.) Right after the title
|
|
picture comes up, press your hotkey (oooh). The PS debugging
|
|
screen should come up and you should see the follow section
|
|
of code..
|
|
|
|
2309:019C CF IRET
|
|
2309:019D 3D0085 CMP AX,8500
|
|
etc.
|
|
|
|
This is the exit code from PSKEY. By usings the J(ump)
|
|
command, and executing the IRET, you will be put back right
|
|
to the spot where you pressed the hotkey (boy I'm getting
|
|
excited). I would love to give you a code fragment here, but
|
|
each time you press the hotkey you will end up at a different
|
|
point.
|
|
|
|
So what do we do next. Well, we will just have to keep
|
|
executing code until we find some reference point. Remember
|
|
how I said we wanted to break out before we reached to music
|
|
at the title screen. Well, you can bet that we are in the
|
|
outermost loop since the music comes before the doc check and
|
|
we haven't reached the call to the music routine yet. So we
|
|
start executing code.
|
|
|
|
Then all of the sudden BOOM! you execute a CALL
|
|
instruction and music bursts through the speaker. AHa, a
|
|
reference point. We know we are on the right track.
|
|
|
|
Press <ESC> during the music so that we can skip the
|
|
stupid intro for now. After pressing <ESC> you should regain
|
|
control at the instruction after the call to the music
|
|
routine.
|
|
|
|
From here on out, we want to procede rather slowly.
|
|
Each time you reach a CALL instruction you want to write down
|
|
the address where it is located. Sooner or later you will
|
|
execute a CALL instruction and EFH will jump in to it's doc
|
|
check routine. But damn, you have the address of the that
|
|
call WRITTEN DOWN right. So simply reboot and reload
|
|
everything.
|
|
|
|
Break out in to PS at the title picture. Now,
|
|
unassemble the address you wrote down. You should see
|
|
something like this
|
|
|
|
21DD:3EA4 9AA5368132 CALL 3281:36A5 (current line)
|
|
21DD:3EA4 9A522F8132 CALL 3281:2F52
|
|
21DD:3EA4 C706BB070000 MOV WORD PTR [07BB],0000
|
|
21DD:3EA4 8BE5 MOV SP,BP
|
|
21DD:3EA4 5D POP BP
|
|
21DD:3EA4 CB RETF
|
|
|
|
The first call, is the call to the doc check, therefore
|
|
it can for now be assumed that the second call is to the
|
|
actual game (remember, most programmers follow good
|
|
programming practice and will exit the routine that does the
|
|
doc check to finish the game). Please NOTE, from here on
|
|
out, if I say go back to STEP 1, reboot the machine, reload
|
|
and get to this point. Ok.
|
|
|
|
Our first though in seeing code like this is shit maybe
|
|
they just check the keyword and exit to dos if it's bad; if
|
|
it it's good, then they just exit that subroutine and start
|
|
the game. So having lots of time on our hands, we try just
|
|
executing the second CALL and bypass the first (you can do
|
|
that by setting the IP (instruction pointer) register to the
|
|
offset of the second call [In our case 3EA9]). When you do
|
|
this, the screen clears, and you see the character (Richard)
|
|
on the screen. But just as you think it worked, it switches
|
|
back to text mode and prints the message "Hell is HOT". Shit
|
|
I hate it when that happens.
|
|
|
|
So now we know that somewhere in the doc check routine,
|
|
EFH sets a flag in memory. We must figure out where this
|
|
flag is and figure out a way to fake it. So go back to step
|
|
1, this time, let's trace (using the T command) in to the doc
|
|
check routine.
|
|
|
|
I have included the entire outerloop of the doc check
|
|
routine here. The small subroutines are not of any
|
|
importants and infact when I first crack EFH, I never traced
|
|
in to any of them. It wasn't until I was out getting this
|
|
information that I took a look to see what they did.
|
|
|
|
Here is the dos check code. I have place some basic
|
|
instructions that should help you as you go along. Although
|
|
you address might be different than mine, I will use mine for
|
|
reference. Also, I have noted some special subroutines along
|
|
the way.
|
|
|
|
( - Unassembled DOC CHECK for ESCAPE FROM HELL [outer loop] )
|
|
|
|
First, we start off with some initialization routines.
|
|
You don't need to be all to concerned with them.
|
|
|
|
3281:36A5 55 PUSH BP
|
|
3281:36A6 8BEC MOV BP,SP
|
|
3281:36A8 83EC2A SUB SP,+2A
|
|
3281:36AB C746DE0000 MOV WORD PTR [BP-22],0000
|
|
3281:36B0 B80600 MOV AX,0006
|
|
3281:36B3 50 PUSH AX
|
|
3281:36B4 9AE3169900 CALL 0099:16E3
|
|
3281:36B9 59 POP CX
|
|
3281:36BA 48 DEC AX
|
|
3281:36BB 8946DA MOV [BP-26],AX
|
|
3281:36BE B80F00 MOV AX,000F
|
|
3281:36C1 50 PUSH AX
|
|
3281:36C2 9AE3169900 CALL 0099:16E3
|
|
3281:36C7 59 POP CX
|
|
3281:36C8 48 DEC AX
|
|
3281:36C9 8946DC MOV [BP-24],AX
|
|
3281:36CC C706CB070E00 MOV WORD PTR [07CB],000E
|
|
3281:36D2 C746D60000 MOV WORD PTR [BP-2A],0000
|
|
3281:36D7 E9C002 JMP 399A
|
|
3281:36DA C746D80000 MOV WORD PTR [BP-28],0000
|
|
3281:36DF E92501 JMP 3807
|
|
3281:36E2 9A9B479900 CALL 0099:479B
|
|
3281:36E7 B83866 MOV AX,6638
|
|
3281:36EA 50 PUSH AX
|
|
3281:36EB A03407 MOV AL,[0734]
|
|
3281:36EE B400 MOV AH,00
|
|
3281:36F0 50 PUSH AX
|
|
3281:36F1 B80C00 MOV AX,000C
|
|
3281:36F4 50 PUSH AX
|
|
3281:36F5 B8CF00 MOV AX,00CF
|
|
3281:36F8 50 PUSH AX
|
|
3281:36F9 8B46DC MOV AX,[BP-24]
|
|
3281:36FC BA5800 MOV DX,0058
|
|
3281:36FF F7E2 MUL DX
|
|
3281:3701 8BD8 MOV BX,AX
|
|
3281:3703 8A87F640 MOV AL,[BX+40F6]
|
|
3281:3707 B400 MOV AH,00
|
|
3281:3709 8BD8 MOV BX,AX
|
|
3281:370B 81C39400 ADD BX,0094
|
|
3281:370F D1E3 SHL BX,1
|
|
3281:3711 D1E3 SHL BX,1
|
|
3281:3713 FFB7F25D PUSH [BX+5DF2]
|
|
3281:3717 FFB7F05D PUSH [BX+5DF0]
|
|
3281:371B 9AE7019900 CALL 0099:01E7
|
|
3281:3720 83C40C ADD SP,+0C
|
|
3281:3723 8B46DA MOV AX,[BP-26]
|
|
3281:3726 3D0500 CMP AX,0005
|
|
3281:3729 7603 JBE 372E
|
|
3281:372B E9B200 JMP 37E0
|
|
3281:372E 8BD8 MOV BX,AX
|
|
3281:3730 D1E3 SHL BX,1
|
|
3281:3732 2E CS:
|
|
3281:3733 FFA73737 JMP [BX+3737]
|
|
3281:3737 43 INC BX
|
|
3281:3738 37 AAA
|
|
3281:3739 5E POP SI
|
|
3281:373A 37 AAA
|
|
3281:373B 7837 JS 3774
|
|
3281:373D 92 XCHG DX,AX
|
|
3281:373E 37 AAA
|
|
3281:373F AC LODSB
|
|
3281:3740 37 AAA
|
|
3281:3741 C637B8 MOV BYTE PTR [BX],B8
|
|
3281:3744 2000 AND [BX+SI],AL
|
|
3281:3746 50 PUSH AX
|
|
3281:3747 B82E01 MOV AX,012E
|
|
3281:374A 50 PUSH AX
|
|
3281:374B B88100 MOV AX,0081
|
|
3281:374E 50 PUSH AX
|
|
3281:374F B87348 MOV AX,4873
|
|
3281:3752 50 PUSH AX
|
|
3281:3753 9AD6029900 CALL 0099:02D6
|
|
3281:3758 83C408 ADD SP,+08
|
|
3281:375B E98200 JMP 37E0
|
|
3281:375E B82000 MOV AX,0020
|
|
3281:3761 50 PUSH AX
|
|
3281:3762 B82E01 MOV AX,012E
|
|
3281:3765 50 PUSH AX
|
|
3281:3766 B88100 MOV AX,0081
|
|
3281:3769 50 PUSH AX
|
|
3281:376A B88648 MOV AX,4886
|
|
3281:376D 50 PUSH AX
|
|
3281:376E 9AD6029900 CALL 0099:02D6
|
|
3281:3773 83C408 ADD SP,+08
|
|
3281:3776 EB68 JMP 37E0
|
|
3281:3778 B82000 MOV AX,0020
|
|
3281:377B 50 PUSH AX
|
|
3281:377C B82E01 MOV AX,012E
|
|
3281:377F 50 PUSH AX
|
|
3281:3780 B88100 MOV AX,0081
|
|
3281:3783 50 PUSH AX
|
|
3281:3784 B8AD48 MOV AX,48AD
|
|
3281:3787 50 PUSH AX
|
|
3281:3788 9AD6029900 CALL 0099:02D6
|
|
3281:378D 83C408 ADD SP,+08
|
|
3281:3790 EB4E JMP 37E0
|
|
3281:3792 B82000 MOV AX,0020
|
|
3281:3795 50 PUSH AX
|
|
3281:3796 B82E01 MOV AX,012E
|
|
3281:3799 50 PUSH AX
|
|
3281:379A B88100 MOV AX,0081
|
|
3281:379D 50 PUSH AX
|
|
3281:379E B8C748 MOV AX,48C7
|
|
3281:37A1 50 PUSH AX
|
|
3281:37A2 9AD6029900 CALL 0099:02D6
|
|
3281:37A7 83C408 ADD SP,+08
|
|
3281:37AA EB34 JMP 37E0
|
|
3281:37AC B82000 MOV AX,0020
|
|
3281:37AF 50 PUSH AX
|
|
3281:37B0 B82E01 MOV AX,012E
|
|
3281:37B3 50 PUSH AX
|
|
3281:37B4 B88100 MOV AX,0081
|
|
3281:37B7 50 PUSH AX
|
|
3281:37B8 B8E848 MOV AX,48E8
|
|
3281:37BB 50 PUSH AX
|
|
3281:37BC 9AD6029900 CALL 0099:02D6
|
|
3281:37C1 83C408 ADD SP,+08
|
|
3281:37C4 EB1A JMP 37E0
|
|
3281:37C6 B82000 MOV AX,0020
|
|
3281:37C9 50 PUSH AX
|
|
3281:37CA B82E01 MOV AX,012E
|
|
3281:37CD 50 PUSH AX
|
|
3281:37CE B88100 MOV AX,0081
|
|
3281:37D1 50 PUSH AX
|
|
3281:37D2 B80F49 MOV AX,490F
|
|
3281:37D5 50 PUSH AX
|
|
3281:37D6 9AD6029900 CALL 0099:02D6
|
|
3281:37DB 83C408 ADD SP,+08
|
|
3281:37DE EB00 JMP 37E0
|
|
3281:37E0 B82D00 MOV AX,002D
|
|
3281:37E3 50 PUSH AX
|
|
3281:37E4 B88200 MOV AX,0082
|
|
3281:37E7 50 PUSH AX
|
|
3281:37E8 9A96029900 CALL 0099:0296
|
|
3281:37ED 59 POP CX
|
|
3281:37EE 59 POP CX
|
|
3281:37EF B82849 MOV AX,4928
|
|
3281:37F2 50 PUSH AX
|
|
3281:37F3 9A3F039900 CALL 0099:033F
|
|
3281:37F8 59 POP CX
|
|
3281:37F9 837ED800 CMP WORD PTR [BP-28],+00
|
|
3281:37FD 7505 JNZ 3804
|
|
|
|
Here is the first point of interest. The call on the
|
|
following line will display the "what is xxxx" message. Ä¿
|
|
³
|
|
3281:37FF 9A1B019900 CALL 0099:011B <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
|
|
3281:3804 FF46D8 INC WORD PTR [BP-28]
|
|
3281:3807 837ED802 CMP WORD PTR [BP-28],+02
|
|
3281:380B 7D03 JGE 3810
|
|
3281:380D E9D2FE JMP 36E2
|
|
3281:3810 8B46DA MOV AX,[BP-26]
|
|
3281:3813 3D0500 CMP AX,0005
|
|
3281:3816 7603 JBE 381B
|
|
3281:3818 E97401 JMP 398F
|
|
3281:381B 8BD8 MOV BX,AX
|
|
3281:381D D1E3 SHL BX,1
|
|
3281:381F 2E CS:
|
|
3281:3820 FFA72438 JMP [BX+3824]
|
|
3281:3824 3038 XOR [BX+SI],BH
|
|
3281:3826 6E DB 6E
|
|
3281:3827 38AC38EA CMP [SI+EA38],CH
|
|
3281:382B 3827 CMP [BX],AH
|
|
3281:382D 396439 CMP [SI+39],SP
|
|
3281:3830 B81000 MOV AX,0010
|
|
3281:3833 50 PUSH AX
|
|
3281:3834 16 PUSH SS
|
|
3281:3835 8D46E2 LEA AX,[BP-1E]
|
|
3281:3838 50 PUSH AX
|
|
3281:3839 9AFB149900 CALL 0099:14FB
|
|
3281:383E 83C406 ADD SP,+06
|
|
3281:3841 8D46E2 LEA AX,[BP-1E]
|
|
3281:3844 50 PUSH AX
|
|
3281:3845 9A0F00B81B CALL 1BB8:000F
|
|
3281:384A 59 POP CX
|
|
3281:384B 8B46DC MOV AX,[BP-24]
|
|
3281:384E BA5800 MOV DX,0058
|
|
3281:3851 F7E2 MUL DX
|
|
3281:3853 05F740 ADD AX,40F7
|
|
3281:3856 50 PUSH AX
|
|
3281:3857 8D46E2 LEA AX,[BP-1E]
|
|
3281:385A 50 PUSH AX
|
|
3281:385B 9A0E00661A CALL 1A66:000E
|
|
3281:3860 59 POP CX
|
|
3281:3861 59 POP CX
|
|
3281:3862 0BC0 OR AX,AX
|
|
3281:3864 7505 JNZ 386B
|
|
3281:3866 C746DEFFFF MOV WORD PTR [BP-22],FFFF
|
|
3281:386B E92101 JMP 398F
|
|
3281:386E B81000 MOV AX,0010
|
|
3281:3871 50 PUSH AX
|
|
3281:3872 16 PUSH SS
|
|
3281:3873 8D46E2 LEA AX,[BP-1E]
|
|
3281:3876 50 PUSH AX
|
|
3281:3877 9AFB149900 CALL 0099:14FB
|
|
3281:387C 83C406 ADD SP,+06
|
|
3281:387F 8D46E2 LEA AX,[BP-1E]
|
|
3281:3882 50 PUSH AX
|
|
3281:3883 9A0F00B81B CALL 1BB8:000F
|
|
3281:3888 59 POP CX
|
|
3281:3889 8B46DC MOV AX,[BP-24]
|
|
3281:388C BA5800 MOV DX,0058
|
|
3281:388F F7E2 MUL DX
|
|
3281:3891 050841 ADD AX,4108
|
|
3281:3894 50 PUSH AX
|
|
3281:3895 8D46E2 LEA AX,[BP-1E]
|
|
3281:3898 50 PUSH AX
|
|
3281:3899 9A0E00661A CALL 1A66:000E
|
|
3281:389E 59 POP CX
|
|
3281:389F 59 POP CX
|
|
3281:38A0 0BC0 OR AX,AX
|
|
3281:38A2 7505 JNZ 38A9
|
|
3281:38A4 C746DEFFFF MOV WORD PTR [BP-22],FFFF
|
|
3281:38A9 E9E300 JMP 398F
|
|
3281:38AC B81000 MOV AX,0010
|
|
3281:38AF 50 PUSH AX
|
|
3281:38B0 16 PUSH SS
|
|
3281:38B1 8D46E2 LEA AX,[BP-1E]
|
|
3281:38B4 50 PUSH AX
|
|
3281:38B5 9AFB149900 CALL 0099:14FB
|
|
3281:38BA 83C406 ADD SP,+06
|
|
3281:38BD 8D46E2 LEA AX,[BP-1E]
|
|
3281:38C0 50 PUSH AX
|
|
3281:38C1 9A0F00B81B CALL 1BB8:000F
|
|
3281:38C6 59 POP CX
|
|
3281:38C7 8B46DC MOV AX,[BP-24]
|
|
3281:38CA BA5800 MOV DX,0058
|
|
3281:38CD F7E2 MUL DX
|
|
3281:38CF 051941 ADD AX,4119
|
|
3281:38D2 50 PUSH AX
|
|
3281:38D3 8D46E2 LEA AX,[BP-1E]
|
|
3281:38D6 50 PUSH AX
|
|
3281:38D7 9A0E00661A CALL 1A66:000E
|
|
3281:38DC 59 POP CX
|
|
3281:38DD 59 POP CX
|
|
3281:38DE 0BC0 OR AX,AX
|
|
3281:38E0 7505 JNZ 38E7
|
|
3281:38E2 C746DEFFFF MOV WORD PTR [BP-22],FFFF
|
|
3281:38E7 E9A500 JMP 398F
|
|
3281:38EA B81000 MOV AX,0010
|
|
3281:38ED 50 PUSH AX
|
|
3281:38EE 16 PUSH SS
|
|
3281:38EF 8D46E2 LEA AX,[BP-1E]
|
|
3281:38F2 50 PUSH AX
|
|
3281:38F3 9AFB149900 CALL 0099:14FB
|
|
3281:38F8 83C406 ADD SP,+06
|
|
3281:38FB 8D46E2 LEA AX,[BP-1E]
|
|
3281:38FE 50 PUSH AX
|
|
3281:38FF 9A0F00B81B CALL 1BB8:000F
|
|
3281:3904 59 POP CX
|
|
3281:3905 8B46DC MOV AX,[BP-24]
|
|
3281:3908 BA5800 MOV DX,0058
|
|
3281:390B F7E2 MUL DX
|
|
3281:390D 052A41 ADD AX,412A
|
|
3281:3910 50 PUSH AX
|
|
3281:3911 8D46E2 LEA AX,[BP-1E]
|
|
3281:3914 50 PUSH AX
|
|
3281:3915 9A0E00661A CALL 1A66:000E
|
|
3281:391A 59 POP CX
|
|
3281:391B 59 POP CX
|
|
3281:391C 0BC0 OR AX,AX
|
|
3281:391E 7505 JNZ 3925
|
|
3281:3920 C746DEFFFF MOV WORD PTR [BP-22],FFFF
|
|
3281:3925 EB68 JMP 398F
|
|
3281:3927 B81000 MOV AX,0010
|
|
3281:392A 50 PUSH AX
|
|
3281:392B 16 PUSH SS
|
|
3281:392C 8D46E2 LEA AX,[BP-1E]
|
|
3281:392F 50 PUSH AX
|
|
|
|
Next point of interest. When you execute this line, the
|
|
game will pause and wait for you to enter the code word from
|
|
the manual. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³
|
|
³
|
|
3281:3930 9AFB149900 CALL 0099:14FB <ÄÄÄÄÄÙ
|
|
|
|
3281:3935 83C406 ADD SP,+06
|
|
3281:3938 8D46E2 LEA AX,[BP-1E]
|
|
3281:393B 50 PUSH AX
|
|
3281:393C 9A0F00B81B CALL 1BB8:000F
|
|
3281:3941 59 POP CX
|
|
3281:3942 8B46DC MOV AX,[BP-24]
|
|
3281:3945 BA5800 MOV DX,0058
|
|
3281:3948 F7E2 MUL DX
|
|
3281:394A 053B41 ADD AX,413B
|
|
3281:394D 50 PUSH AX
|
|
3281:394E 8D46E2 LEA AX,[BP-1E]
|
|
3281:3951 50 PUSH AX
|
|
3281:3952 9A0E00661A CALL 1A66:000E
|
|
3281:3957 59 POP CX
|
|
3281:3958 59 POP CX
|
|
3281:3959 0BC0 OR AX,AX
|
|
3281:395B 7505 JNZ 3962
|
|
3281:395D C746DEFFFF MOV WORD PTR [BP-22],FFFF
|
|
3281:3962 EB2B JMP 398F
|
|
3281:3964 33D2 XOR DX,DX
|
|
3281:3966 B8B80B MOV AX,0BB8
|
|
3281:3969 52 PUSH DX
|
|
3281:396A 50 PUSH AX
|
|
|
|
Next point of interest. This call is the final
|
|
evaluation of the entered word (or phrase). On return, it
|
|
checks a checksum value. This whole next section of code
|
|
(up to 3281:39Ad) simply test the validity of the keyword you
|
|
entered. I have marked the all jumps that happened when I
|
|
entered my keyword with an " * ".
|
|
|
|
3281:396B 9A71139900 CALL 0099:1371
|
|
3281:3970 59 POP CX
|
|
3281:3971 59 POP CX
|
|
3281:3972 8946E0 MOV [BP-20],AX
|
|
3281:3975 8B46DC MOV AX,[BP-24]
|
|
3281:3978 BA5800 MOV DX,0058
|
|
3281:397B F7E2 MUL DX
|
|
3281:397D 8BD8 MOV BX,AX
|
|
3281:397F 8B874C41 MOV AX,[BX+414C]
|
|
3281:3983 3B46E0 CMP AX,[BP-20]
|
|
3281:3986 7505 *JNZ 398D
|
|
3281:3988 C746DEFFFF MOV WORD PTR [BP-22],FFFF
|
|
3281:398D EB00 JMP 398F
|
|
3281:398F 837EDE00 CMP WORD PTR [BP-22],+00
|
|
3281:3993 7402 *JZ 3997
|
|
3281:3995 EB0C JMP 39A3
|
|
3281:3997 FF46D6 INC WORD PTR [BP-2A]
|
|
3281:399A 837ED602 CMP WORD PTR [BP-2A],+02
|
|
3281:399E 7D03 *JGE 39A3
|
|
3281:39A0 E937FD JMP 36DA
|
|
3281:39A3 837EDE00 CMP WORD PTR [BP-22],+00
|
|
3281:39A7 7504 *JNZ 39AD
|
|
3281:39A9 0E PUSH CS
|
|
3281:39AA E8E8FC CALL 3695
|
|
|
|
This is the last point of interest. The next
|
|
instruction is where we set the key (by moving FFFFh to the
|
|
memory location DS:0744h). This is what we need to fake to
|
|
allow the system to run. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³
|
|
3281:39AD C7064407FFFF MOV WORD PTR [0744],FFFF <ÄÄÄÙ
|
|
3281:39B3 B8FFFF MOV AX,FFFF
|
|
3281:39B6 50 PUSH AX
|
|
3281:39B7 9AC0479900 CALL 0099:47C0
|
|
3281:39BC 59 POP CX
|
|
3281:39BD 8BE5 MOV SP,BP
|
|
3281:39BF 5D POP BP
|
|
3281:39C0 CB RETF
|
|
|
|
Ok, we have now finished the doc check, and control has
|
|
returned (when the RETF instruction was executed) to
|
|
21DD:3EA9. We are now ready to continue with the game.
|
|
|
|
|
|
Notice the instruction at 3281:39AD. This is where EFH
|
|
sets that external flag. But how did I determine this.
|
|
Well, by luck. If you look through the entire routine, you
|
|
will not find any other instructions placing a value in the
|
|
data segment (DS). And since I decided a long time ago that
|
|
EFH was written in a higher level language, we can assume
|
|
that it is writting to some variable.
|
|
|
|
So, hoping that we have found the flag, we go back to
|
|
step 1. This time, we manualy edit the word at DS:0744 and
|
|
place the value FFFFh there. We then skip over the call the
|
|
the doc check and execute the game. Then before our eyes,
|
|
shit happenes. The game comes up, and everything is fine.
|
|
By George you've got it.
|
|
|
|
So how do we fix the program to always return a good doc
|
|
check. Well, we could go about it 2 ways. The first, is you
|
|
could simple modify the instruction at 3281:3935 to perform a
|
|
long jump to 3281:39AD. This would force set the value no
|
|
matter what was typed. But who the fuck wants to have to
|
|
type anything. I sure don't so lets think of another way.
|
|
|
|
If we look at the entire doc check routine, we will see
|
|
that it does nothing but handle the doc check (remember when
|
|
we first bypassed the check. The screen came up and
|
|
everything looked fine until it dropped you out. So we can
|
|
assume that the actual screen is not setup in doc check. So
|
|
I suggest placing a small patch right in the begining of the
|
|
doc check.
|
|
|
|
But what should this patch do? (BTW: it's late and I
|
|
don't know If I'm using ?s right. So if not TOO FUCKING
|
|
BAD). Well, all it should do is place the value FFFFh at
|
|
DS:0744h. Here is the assembly language routine to do it.
|
|
|
|
50 PUSH AX
|
|
B8FFFF MOV AX,FFFF
|
|
3E DS:
|
|
A34407 MOV WORD PTR [0744],AX
|
|
58 POP AX
|
|
CB RETF
|
|
|
|
This small routine will place the value FFFFh at DS:744
|
|
and then exit back to the main loop. Simple huh (note, you
|
|
don't really need the save AX or load AX with FFFFh for that
|
|
matter but I did it for clarity).
|
|
|
|
So now that we have the patch, and now where to put it,
|
|
how do we get it there. Well, thats where the file editor
|
|
comes in, but first you will need 2 things. The hex
|
|
equivlent of out patch (in this case the 10 bytes :
|
|
50,B8,FF,FF,3E,A3,44,07,58,CB) and some string to search for.
|
|
I suggest usings the first 14 bytes of the routines we are
|
|
going to write over (the code at address 3281:36A5). Those
|
|
bytes are 55, 8B, EC, 83, EC ,2A ,C7, 46, DE ,00 ,00, B8, 06,
|
|
and 00. When selecting the search string, select only
|
|
instructions that ARN'T call, jump, loop or any instruction
|
|
that has a memory address in them. This value will NOT be
|
|
the same when you do the search.
|
|
|
|
Now, using for file editor (I used PCTOOLS, but NORTON's
|
|
will do) search for our string (55,8B, etc). When it is
|
|
found (somewhere near sector 200) write down the sector #.
|
|
Now, go and edit that sector. Find our search string (55,8B,
|
|
etc) and replace it with the patch string (50,B8,FF, etc).
|
|
Now save the sector.
|
|
|
|
Your down. Try playing the game. It should load up,
|
|
and then go right from the title page (or the intro) to the
|
|
game without stopping at the doc check. If your doesn't,
|
|
then you fucked up. Restart from the beginning (NO, this
|
|
file didn't fuck up, and I DON'T MAKE MISTAKES).
|
|
|
|
Well, you did it. You have now removed your first doc
|
|
check. Don't ya feel real good. With time, you will be able
|
|
to remove any type of doc check.
|
|
|
|
|
|
-BUCKAROO BANZAI
|
|
|
|
|
|
At this time I would just like to say
|
|
|
|
`ALL CRACKING GROUPS SUCK!'
|