400 lines
15 KiB
Plaintext
400 lines
15 KiB
Plaintext
![]() |
|
|||
|
CRACKING 101 - 1990 edition
|
|||
|
|
|||
|
Lesson 3
|
|||
|
|
|||
|
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
<20> CHAMBER OF THE SCI-MUTANT PREISTEST <20>
|
|||
|
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
|
|||
|
Oh shit, I have finally found a newer program that has
|
|||
|
on disk copy protection. Good, you'all need a refresher
|
|||
|
course on so here it is (YO JB study hard, you might learn
|
|||
|
something).
|
|||
|
|
|||
|
CHAMBER of the SCI-MUTANT PREISTEST (CSMP) is a really
|
|||
|
fucked up game but was simple to unprotect. So, lets dive
|
|||
|
right in. We will be using DEBUG here (although I used
|
|||
|
periscope but then shit I'm special) to do the crack. Lets
|
|||
|
dive in. When we first load CSMP (the file ERE.COM) and
|
|||
|
unassemble it here is what we get.
|
|||
|
|
|||
|
u 100 10B
|
|||
|
|
|||
|
119A:0100 8CCA MOV DX,CS
|
|||
|
119A:0102 81C2C101 ADD DX,01C1
|
|||
|
119A:0106 52 PUSH DX
|
|||
|
119A:0107 BA0F00 MOV DX,000F
|
|||
|
119A:010A 52 PUSH DX
|
|||
|
119A:010B CB RETF
|
|||
|
|
|||
|
I included the register listing for a reason. NOTICE
|
|||
|
that this piece of code just seem to stop (the RETF)
|
|||
|
statement. Well, what is really does is place the address
|
|||
|
(segment and offset) of the real starting point on to the
|
|||
|
stack and the execute a far return to that location. Now
|
|||
|
this might fool a real beginner (or at least make him worry a
|
|||
|
bit but us...no way).
|
|||
|
|
|||
|
If you take the current CS value and add 1C1 to it (in
|
|||
|
segment addition) you will get the segment address 135B (that
|
|||
|
is if you are using my example of 119A. If not then you will
|
|||
|
not get 135B but trust me, it's the right value).
|
|||
|
|
|||
|
So since we want to be at the real program, execute the
|
|||
|
code until 10B (ie use the command "G 10B") then trace
|
|||
|
through the next instruction.
|
|||
|
|
|||
|
If you now unassemble the code, here is what it should
|
|||
|
look like.
|
|||
|
|
|||
|
-u 000f 36
|
|||
|
|
|||
|
135B:000F 9C PUSHF
|
|||
|
135B:0010 50 PUSH AX
|
|||
|
135B:0011 1E PUSH DS
|
|||
|
135B:0012 06 PUSH ES
|
|||
|
135B:0013 0E PUSH CS
|
|||
|
135B:0014 1F POP DS
|
|||
|
135B:0015 0E PUSH CS
|
|||
|
135B:0016 07 POP ES
|
|||
|
135B:0017 FC CLD
|
|||
|
135B:0018 89260B00 MOV [000B],SP
|
|||
|
135B:001C C70600000102 MOV WORD PTR [0000],0201
|
|||
|
135B:0022 B013 MOV AL,13
|
|||
|
135B:0024 A23500 MOV [0035],AL
|
|||
|
135B:0027 A2FF01 MOV [01FF],AL
|
|||
|
135B:002A A22F02 MOV [022F],AL
|
|||
|
135B:002D A23901 MOV [0139],AL
|
|||
|
135B:0030 B280 MOV DL,80
|
|||
|
135B:0032 B408 MOV AH,08
|
|||
|
135B:0034 CD21 INT 21
|
|||
|
135B:0036 7232 JB 006A
|
|||
|
|
|||
|
|
|||
|
Since we are looking for a disk based copy protection,
|
|||
|
it might be a good time to look for INT 13. So search the
|
|||
|
current segment for INT 13 with the command
|
|||
|
|
|||
|
S 135B:0 FFFF CD 13
|
|||
|
|
|||
|
But shit, nothing. You mean this program doesn't use
|
|||
|
int 13. Be real. Reread the first lesson. You know the one
|
|||
|
that talks about self modifing code. This is what we have
|
|||
|
here. Let's take a closer look at the last bit of code but
|
|||
|
this time, with my comments added.
|
|||
|
|
|||
|
-u 000f 36
|
|||
|
|
|||
|
; The first part of the code simple sets up for the return to
|
|||
|
; dos as well as sets ES and DS
|
|||
|
|
|||
|
135B:000F 9C PUSHF
|
|||
|
135B:0010 50 PUSH AX
|
|||
|
135B:0011 1E PUSH DS
|
|||
|
135B:0012 06 PUSH ES
|
|||
|
135B:0013 0E PUSH CS
|
|||
|
135B:0014 1F POP DS ; Set DS to CS
|
|||
|
135B:0015 0E PUSH CS
|
|||
|
135B:0016 07 POP ES ; Set ES to DS
|
|||
|
135B:0017 FC CLD
|
|||
|
|
|||
|
135B:0018 89260B00 MOV [000B],SP
|
|||
|
|
|||
|
; The next instruction sets up a variable that is used in the
|
|||
|
; routine that reads in the sectors from the disk. More on
|
|||
|
; later.
|
|||
|
|
|||
|
135B:001C C70600000102 MOV WORD PTR [0000],0201
|
|||
|
|
|||
|
; Now, here is the self modifing code. Notice at AL is 13
|
|||
|
; (INT 13h ... Get it). Look at the first memory location
|
|||
|
; (35h) and remember that DS = CS. With this in mind, when
|
|||
|
; then instuction at 135B:0024 is executed byte at 135B:0035
|
|||
|
; will be changed to 13h. That will in fact change the
|
|||
|
; INT 21h at 135B:0034 to an INT 13h. And so on, and so on.
|
|||
|
|
|||
|
135B:0022 B013 MOV AL,13 ; New value
|
|||
|
135B:0024 A23500 MOV [0035],AL ; Change to INT 13h
|
|||
|
135B:0027 A2FF01 MOV [01FF],AL ; Change to INT 13h
|
|||
|
135B:002A A22F02 MOV [022F],AL ; Change to INT 13h
|
|||
|
135B:002D A23901 MOV [0139],AL ; Change to INT 13h
|
|||
|
|
|||
|
; If you lookup DOS function 08 you will find it's CONSOLE
|
|||
|
; INPUT. Now does that seem out of place to you.
|
|||
|
|
|||
|
135B:0030 B280 MOV DL,80
|
|||
|
135B:0032 B408 MOV AH,08
|
|||
|
135B:0034 CD21 INT 21 ; Changed to INT 13h
|
|||
|
135B:0036 7232 JB 006A
|
|||
|
|
|||
|
|
|||
|
Whoa, that was tricky. If you execute up to 135B:30
|
|||
|
here is what it should look like..
|
|||
|
|
|||
|
|
|||
|
135B:0030 B280 MOV DL,80
|
|||
|
135B:0032 B408 MOV AH,08
|
|||
|
135B:0034 CD13 INT 13
|
|||
|
135B:0036 7232 JB 006A
|
|||
|
|
|||
|
AHA, now we are getting somewhere. If we lookup what
|
|||
|
disk function 08 means, you won't be suprised. Function 08h
|
|||
|
is GET DRIVE TYPE. It will tell what type of disk drive we
|
|||
|
have. Remember, if you are loading off of a hard disk then
|
|||
|
it wants to use a different routine. Since we want it to
|
|||
|
think we are loading off of disk, then we want to take this
|
|||
|
jump. So for now, force the jmp by setting IP to 6A.
|
|||
|
|
|||
|
At 135B:006A you find another jmp instruction
|
|||
|
|
|||
|
135B:006A EB6B JMP 00D7
|
|||
|
|
|||
|
|
|||
|
This jumps to the routine that does the actual disk
|
|||
|
check. Here is the outer loop of that code (With my comments
|
|||
|
of course).
|
|||
|
|
|||
|
; This first part of this routine simply test to see how many
|
|||
|
; disk drives you have.
|
|||
|
|
|||
|
|
|||
|
135B:00D7 CD11 INT 11
|
|||
|
135B:00D9 25C000 AND AX,00C0
|
|||
|
135B:00DC B106 MOV CL,06
|
|||
|
135B:00DE D3E8 SHR AX,CL
|
|||
|
135B:00E0 FEC0 INC AL
|
|||
|
135B:00E2 FEC0 INC AL
|
|||
|
135B:00E4 A20200 MOV [0002],AL
|
|||
|
|
|||
|
; Next, so setup for the actual disk check
|
|||
|
|
|||
|
|
|||
|
135B:00E7 C606090000 MOV BYTE PTR [0009],00
|
|||
|
135B:00EC B9F127 MOV CX,27F1
|
|||
|
135B:00EF 8BE9 MOV BP,CX
|
|||
|
135B:00F1 B107 MOV CL,07
|
|||
|
135B:00F3 F8 CLC
|
|||
|
|
|||
|
; This calls the protection routine part 1
|
|||
|
|
|||
|
135B:00F4 E82F00 CALL 0126
|
|||
|
|
|||
|
135B:00F7 B9DE27 MOV CX,27DE
|
|||
|
135B:00FA 8BE9 MOV BP,CX
|
|||
|
135B:00FC B108 MOV CL,08
|
|||
|
135B:00FE F9 STC
|
|||
|
|
|||
|
; This calls the protection routine part 2
|
|||
|
|
|||
|
135B:00FF E82400 CALL 0126
|
|||
|
|
|||
|
135B:0102 8D1E5802 LEA BX,[0258]
|
|||
|
135B:0106 8D361C01 LEA SI,[011C]
|
|||
|
135B:010A 8BCD MOV CX,BP
|
|||
|
135B:010C AC LODSB
|
|||
|
135B:010D 8AC8 MOV CL,AL
|
|||
|
|
|||
|
; This calls the protection routine part 3
|
|||
|
|
|||
|
135B:010F E8E300 CALL 01F5
|
|||
|
|
|||
|
; Makes the final check
|
|||
|
|
|||
|
135B:0112 7271 JB 0185
|
|||
|
135B:0114 AC LODSB
|
|||
|
135B:0115 0AC0 OR AL,AL
|
|||
|
135B:0117 75F4 JNZ 010D ; If not correct, try again
|
|||
|
135B:0119 EB77 JMP 0192 ; Correct, continue program
|
|||
|
135B:011B 90 NOP
|
|||
|
|
|||
|
|
|||
|
There are calls to 2 different subroutines. The routine
|
|||
|
at 126 and the routine at 1F5. If you examine the routine at
|
|||
|
126 you find that it makes several calls to the routine at
|
|||
|
1F5. Then you you examine the routine at 1F5 you see the
|
|||
|
actual call to INT 13. Here is the code for both routine
|
|||
|
with comments
|
|||
|
|
|||
|
|
|||
|
; First, it sets up the sector, head and drive information.
|
|||
|
; DS:000A holds the sector to read
|
|||
|
|
|||
|
135B:0126 880E0A00 MOV [000A],CL
|
|||
|
135B:012A 8A160900 MOV DL,[0009]
|
|||
|
135B:012E B600 MOV DH,00
|
|||
|
|
|||
|
; Sets the DTA
|
|||
|
|
|||
|
135B:0130 8D365802 LEA SI,[0258]
|
|||
|
135B:0134 7213 JB 0149
|
|||
|
|
|||
|
; Resets the disk
|
|||
|
|
|||
|
135B:0136 33C0 XOR AX,AX
|
|||
|
135B:0138 CD13 INT 13
|
|||
|
|
|||
|
; Calls the the check
|
|||
|
|
|||
|
135B:013A B90114 MOV CX,1401 ; TRACK 14 sector 1
|
|||
|
135B:013D 8BDE MOV BX,SI
|
|||
|
135B:013F E8B300 CALL 01F5
|
|||
|
|
|||
|
|
|||
|
; The next track/sector to read in is stored in BP
|
|||
|
|
|||
|
135B:0142 8BCD MOV CX,BP
|
|||
|
135B:0144 E8AE00 CALL 01F5
|
|||
|
135B:0147 7234 JB 017D ; If an error occured,
|
|||
|
; trap it.
|
|||
|
|
|||
|
|
|||
|
135B:0149 88160900 MOV [0009],DL ; Reset drive
|
|||
|
135B:014D 8A0E0A00 MOV CL,[000A] ; reset sector
|
|||
|
135B:0151 E8A100 CALL 01F5 ; check protection
|
|||
|
135B:0154 722F JB 0185 ; Check for an error
|
|||
|
|
|||
|
135B:0156 8D5C20 LEA BX,[SI+20]
|
|||
|
|
|||
|
135B:0159 8BCD MOV CX,BP ; Get next T/S
|
|||
|
135B:015B B010 MOV AL,10 ; Ignore this
|
|||
|
135B:015D E89500 CALL 01F5 ; Check protection
|
|||
|
135B:0160 7223 JB 0185 ; check for error
|
|||
|
|
|||
|
; The next sector of code checks to see if what was read in
|
|||
|
; is the actual protected tracks
|
|||
|
|
|||
|
; First check
|
|||
|
|
|||
|
135B:0162 8DBCAC00 LEA DI,[SI+00AC]
|
|||
|
135B:0166 B91000 MOV CX,0010
|
|||
|
135B:0169 F3 REPZ
|
|||
|
135B:016A A7 CMPSW
|
|||
|
|
|||
|
; NOTE: If it was a bad track, it will jmp to 185. A good
|
|||
|
; read should just continue
|
|||
|
|
|||
|
135B:016B 7518 JNZ 0185
|
|||
|
|
|||
|
; Second check
|
|||
|
|
|||
|
135B:016D 8D365802 LEA SI,[0258]
|
|||
|
135B:0171 8D3E3702 LEA DI,[0237]
|
|||
|
135B:0175 B90400 MOV CX,0004
|
|||
|
135B:0178 F3 REPZ
|
|||
|
135B:0179 A7 CMPSW
|
|||
|
|
|||
|
; see NOTE above
|
|||
|
|
|||
|
135B:017A 7509 JNZ 0185
|
|||
|
|
|||
|
; This exit back to the main routine.
|
|||
|
|
|||
|
135B:017C C3 RET
|
|||
|
|
|||
|
; Here is the start of the error trap routines. Basicly what
|
|||
|
; they do is check an error count. If it's not 0 then it
|
|||
|
; retries everything. If it is 0 then it exit back to dos.
|
|||
|
|
|||
|
135B:017D FEC2 INC DL
|
|||
|
135B:017F 3A160200 CMP DL,[0002]
|
|||
|
135B:0183 72B1 JB 0136
|
|||
|
135B:0185 E85400 CALL 01DC
|
|||
|
135B:0188 8B260B00 MOV SP,[000B]
|
|||
|
135B:018C 2BC9 SUB CX,CX
|
|||
|
135B:018E 58 POP AX
|
|||
|
135B:018F 50 PUSH AX
|
|||
|
135B:0190 EB1F JMP 01B1
|
|||
|
|
|||
|
|
|||
|
** Here is the actual code the does the check **
|
|||
|
|
|||
|
; ES:BX points to the buffer
|
|||
|
|
|||
|
135B:01F5 1E PUSH DS
|
|||
|
135B:01F6 07 POP ES
|
|||
|
|
|||
|
; SI is set to the # of retries
|
|||
|
|
|||
|
135B:01F7 56 PUSH SI
|
|||
|
135B:01F8 BE0600 MOV SI,0006
|
|||
|
|
|||
|
; Remember how I said we would use what was in DS:0000 later.
|
|||
|
; well, here is where you use it. It loads in the FUNCTION
|
|||
|
; and # of sectors from what is stored in DS:0000. This is
|
|||
|
; just a trick to make the int 13 call more vague.
|
|||
|
|
|||
|
135B:01FB A10000 MOV AX,[0000]
|
|||
|
135B:01FE CD13 INT 13
|
|||
|
|
|||
|
; If there is no errors, then exit this part of the loop
|
|||
|
|
|||
|
135B:0200 7309 JNB 020B
|
|||
|
135B:0202 F6C480 TEST AH,80
|
|||
|
|
|||
|
; Check to see if it was a drive TIMEOUT. If so, then set
|
|||
|
; an error flag and exit
|
|||
|
|
|||
|
135B:0205 7503 JNZ 020A
|
|||
|
|
|||
|
; It must have been a load error. Retry 6 times
|
|||
|
|
|||
|
135B:0207 4E DEC SI
|
|||
|
135B:0208 75F1 JNZ 01FB
|
|||
|
|
|||
|
; Set the error flag
|
|||
|
|
|||
|
135B:020A F9 STC
|
|||
|
|
|||
|
; restore SI and return
|
|||
|
|
|||
|
135B:020B 5E POP SI
|
|||
|
135B:020C C3 RET
|
|||
|
|
|||
|
|
|||
|
If you follow through all of that. You will see that
|
|||
|
the only real way out is the jmp to "135B:0192" at 135B:0119.
|
|||
|
So, how do we test it. Simple. Exit back to dos and let's
|
|||
|
add a temporary patch.
|
|||
|
|
|||
|
Reload ERE.COM under debug. Execute the program setting
|
|||
|
a breakpoint at 135B:0022 (if you remember, that is right at
|
|||
|
the begining of the self modifing code). When execution
|
|||
|
stops, change you IP register to 192. Now execute the code.
|
|||
|
|
|||
|
Well shit, we are at the main menu. We just bypassed
|
|||
|
the entire protection routine. So, now where to add the
|
|||
|
patch. We will be adding the patch at 135B:0022. But what
|
|||
|
should the patch be. In this case, simply jumping to
|
|||
|
135B:0192 will do. So, reload ERE.COM under debug. Execute
|
|||
|
the code until 135B:0022. Now unassemble it. Here is the
|
|||
|
code fragment we need.
|
|||
|
|
|||
|
135B:0022 B013 MOV AL,13
|
|||
|
135B:0024 A23500 MOV [0035],AL
|
|||
|
135B:0027 A2FF01 MOV [01FF],AL
|
|||
|
135B:002A A22F02 MOV [022F],AL
|
|||
|
135B:002D A23901 MOV [0139],AL
|
|||
|
|
|||
|
Here is the code we want to use as the patch
|
|||
|
|
|||
|
135B:0022 E96D01 JMP 192
|
|||
|
|
|||
|
So, to add the patch, we search the file ERE.COM using
|
|||
|
PC-TOOLS. For our search string we use
|
|||
|
|
|||
|
B0 13 A2 35 00 A2 FF 01 A2 2F 02 A2 39 01
|
|||
|
|
|||
|
PC-TOOLS should find the search string at reletive
|
|||
|
sector #13. Edit the sector and change "B0 13 A2" to
|
|||
|
"E9 6D 01" (our patch) and save the sector.
|
|||
|
|
|||
|
BOOM! your done and CSMP is cracked. Fun huh. You just
|
|||
|
kicked 5 seconds off of the load time. Preaty fucken good.
|
|||
|
Well, I hope this textfile helped.
|
|||
|
|
|||
|
|
|||
|
-Buckaroo Banzai
|
|||
|
-Cracking Guru
|