There was a thread about how to protect CDs etc against copying - basic copy protection techniques. When checking one of my ancient archives before blowing it away entirely, I happened upon the following piece of code that was written to circumvent a basic key-disk floppy based copy protection scheme. I had written it to show someone how easy these schemes were to get around (actually, some, based on hardware hasps and self-modifying code are pretty tough, so beware!).
I reproduce the code here for anyone who is interested in the guts of a fairly trivial copy protection scheme and its antidote. The code is pretty heavily commented, since it was in the nature of a tutorial, so that you should not have any trouble following it if you are at all familiar with x86 architecture and the DOS/ BIOS system call scheme.
Old timers like me who date back to the days of the 2 x 360 KB FDD based PCs may wax nostalgic at the mention of Central Point Software's CopyIINokey (nokey.com).
Incidentally, although this code works, it probably will render your PC's floppy unusable without a reboot, since it does not do any process based vaildation. Also, although it circumvents a copy protection scheme, PLEASE DO NOT USE IT FOR SOFTWARE PIRACY! It is intended for use as an educational exercise for people to learn about program design and the PC's architecture, and not as a cracker shortcut. I am definitely not a cracker!
Here goes:
; kundli key disk buster program ; v 1.2 coded 1.6.98 ; ; Copyleft (sic) S. Krishnan, 1998 ; ; This software is freely copyable and distributable provided the above ; version and copyright info are retained in whole. Send your comments, ; questions, flames et al to sri_krishnan@yahoo.com. ; ; You will find kundli, a multilingual MS-DOS Indian astrology program, on the ; infamous Installer 4 CD that is a part of every hardware assembler's armoury. ; Incidentally, kundli is coded in MS QuickBasic. ; ; ------------------------------------------------------------------ ; Written for MS-DOS and NASM; will NOT assemble under MASM or TASM or A86 ; Anyone who wants to assemble under the latter programs will have to do a little rewriting. ; ;------------------------------------------------------------------ ; ; The kundli program is copy protected through a key disk scheme. ; It checks for a key disk in drive a: by issuing a BIOS int 13h ; disk read using service 02h, for reading one sector. This sector ; presumably exists on the key disk as follows: ; ; Track No. 19, Sector No. 01, Head No. 0, Drive No. 0 (FDD) ; No. of sectors to be read: 1; results to be placed as usual in es:bx ; ; The result is one word read into the buffer pointed to by es:bx ; This word is compared with 434Bh, using a cmp operation, as follows, ; by the kundli.exe program: ; ; cmp wo ptr es:[bx], 434Bh ; jne exit ; ; Eureka! If the word pointed to by es:bx !=0x434B, then exit. ; ; Incidentally I got this information by disassembling kundli.exe in ; bxd 2.6 (the BrandX debugger by Sonam S. Gyato; you can download it ; off simtel.net if you want). ; ; The scheme may therefore be broken if one intercepts int 13h, function ; 02h. If the read request for Function 02h is for Track No. 19, Sector No.1, ; then we can be sure it is for kundli. Hence one performs an iret with all ; the details that the program expects, including placing 434Bh at the ; location pointed to by es:bx. It is also essential to clear the carry flag, ; since a set carry flag means error, and kundli.exe incorporates processing ; to ; check for the results of the carry flag after the int. ; ; On to programming, then!
org 100h ; align psp for com program
segment .text ; standard for bin files under NASM
jmp start
tsr_start:
nokey: ; far procedure for interrupt servicing ; named in memory of Central Point Software
cs pop word [useraddr] ; save caller's ip return address cs pop word [useraddr+2] ; save caller's cs
popf ; get rid of old flags
push ax ; save caller's registers push bx ; -do- push cx ; -do- push dx ; -do- push es ; -do-
pushf ; simulate int call by pushing flags on stack cs call far [old_int13] ; call the original int 13h ISR
; after servicing the original int 13h request, our ISR is reentered at ; this point. First we save the old ax since int 13h returns the results ; in ah or ax, and then restore the registers to what they were when our isr ; was entered. We then check to see if the call conditions were that of ; kundli.exe : service no.2, 1 sector to be read, track no. 19, drive 0, etc. ; if so we return with the preset reply of 434Bh, else we jump to exit, which ; restores the ax returned by the original int 13h isr, pushes the flags, ; caller's cs: and caller's ip: on to the stack and executes an iret to ; return to the calling program
mov word [cs:temp], ax ; save ax contents returned by old int 13 call
pop es ; restore caller's registers pop dx ; -do- pop cx ; -do- pop bx ; -do- pop ax ; -do-
cmp ah, 02h ; cmp. al - is the request for service No.2 jnz exit ; no - then return to caller
cmp dl, 00h ; cmp dl - is request for FDD No.1 jnz exit
cmp ch, 19h ; cmp ch - is track no.==19h jnz exit
cmp cl, 01h ; cmp cl - is sector no.==01 jnz exit
; Now that we've come this far, it appears that the request is indeed by the ; kundli program Hence we stuff 434Bh into the buffer pointed to by es:bx
mov word [es:bx], 434Bh ; stuff the code into kundli's disk read buffer
clc ; clear the carry flag mov ah, 00h ; disk read sucessful mov al, 01h ; 1 sector read jmp far [cs:useraddr] ; return to kundli.exe with pseudo-disk read
exit: ; normal exit if caller is not kundli.exe
mov ax, word [cs:temp] ; restore ax returned by old int 13 isr pushf ; save the flags rtd. by original int 13h call push word [cs:useraddr+2] ; push caller's saved cs on stack for iret push word [cs:useraddr] ; push push caller's ip on stack for iret
iret ; return to calling program
temp dw 0 old_int13 dd 0 useraddr dd 0
tsr_end:
start: ; initialization code for loading the int vector
; get and save the vector for int 13h
xor ax, ax ; set ax to 0 mov ah, 35h ; Int 21h function 35h mov al, 13h ; Int 13h vector to be obtained int 21h ; go for it
mov word [old_int13], bx ; save old int 13h offset mov word [old_int13+2], es ; save old int 13h segment
; next, install our new handler for int 13h
push ds ; save data seg. mov ax, cs ; code seg to be loaded into ds for seg add of mov ds, ax ; new interrupt handler mov dx, nokey ; offset of our new int 13h ISR mov ah, 25h ; Func. 25h for setting int. vect. mov al, 13h ; vector to substitute with our isr int 21h
pop ds ; restore ds
mov ah, 09h ; display line mov dx, msg1 ; address of message int 21h ; sign on message
mov ax, tsr_end shr ax, 4 add ax, 01h mov dx, ax mov ax, 3100h int 21h ; terminate and stay resident
SEGMENT .data msg1 db ' The Kundli Buster program: written by S. Krishnan, 1998$' last db 0 SEGMENT .bss
__________________________________________________ Do You Yahoo!? Get personalized email addresses from Yahoo! Mail http://personal.mail.yahoo.com/