home *** CD-ROM | disk | FTP | other *** search
- 40Hex Number 7 Volume 2 Issue 3 File 002
-
-
- ■ Code Concealment ■
- ■ -Demogorgon/PHALCON/SKISM ■
-
- In the previous issue of 40hex, I wrote about how a programmer can
- keep his code from being stolen by others. Ways of doing this are
- endless, and I will talk about a few more methods in this installment.
-
- Part I : Fun with int3
- Part II : Fun with int8
- Part III: The Prefetch
-
-
- Part_I : Fun with int3
-
- Int three is the debugger breakpoint. Every time a debugger breaks
- while tracing through a chunk of code, it will call int3. Int3 is
- called after every instruction is executed in trace mode, and after
- a breakpoint is reached. Note that protected mode debuggers do not
- execute int3 in trace mode, but they will break when int3 is called from
- your code. You can use this to your advantage. Simply install a new
- handler for int3 and it will execute instead of the debugger if a thief
- tries to trace through your program.
-
- start: mov ax, 2503h
- mov dx, offset int_start
- int 21h ; put in the new handler at ds:dx
-
- ... ; rest of real code here
- int 20h
-
- text db 'Smoke Mah Ass!$'
- int_start:
- mov ah, 9
- mov dx, offset text
- int 21h
- int 20h
-
- As soon as the first int21 call in this program is made, the code
- at int_start will execute if it is being traced in a debugger.
- Otherwise, the int call will be ignored and your normal code will
- execute. The program can do whatever you want if a debugger is found.
- For example, you can format the hard drive or display a message. The
- possabilities are endless. By the way, it might be wise to restore the
- old interrupt handler before you exit the program, because it is bad
- programming practice to leave interrupts pointed into non-allocated
- memory.
-
-
- compatability:(works against all debuggers marked with an X)
- -------------------------------------------------------------------------
- Debug Turbo Debug Turbo Debug 386 Soft-Ice
- X X
- -------------------------------------------------------------------------
-
-
- Part_II: Fun with int8
-
- The next segment will show you how to make a program nearly
- impossable to trace. The concept is simple. All you need to do is
- place the main body ofyour program into an int8 handler. Int8 is the
- timer interrupt, and it is called 18.2 times a second. Debuggers do not
- execute int8, so whatever you put there will only go when it is run from
- dos. The only drawback to this is a short delay before the main program
- is executed. It will probably go unnoticed, in most cases. Here is
- some code:
-
- thyroid:mov ax, 3508h
- int 21h ; get int8 handler
- mov word ptr [int_store], bx ; store it
- mov word ptr [int_store+2], es
- mov dx, offset prog_start
- mov ah, 25h
- int 21h ; install new int8 handler
-
- yip: cmp flaag, 1
- jne yip ; wait for int8 to be called
- ; int8 must set the flaag to 1
- push bx
- pop dx ; restore
- push es ; old
- pop ds ; int8
- int 21h ; handler
- int 20h
-
- flaag db 0
- int_store dd ?
- prog_start:
- _main_program proc far
- ; save all the necessary registers here
- ; ... your code
- mov flaag, 1
- ; restore the registers
-
- jmp dword ptr [offset int_store] ; chain to real int8 handler
- _main_program endp
-
- This code is quite useful in that if some guy tries to trace
- through it, he will be stuck forever in the 'yip' loop. The main code
- will never be executed. If he tries to get out of the loop by
- 'executing to' the next instruction, he will end up running the entire
- program. No debugger I know of can trace through this, because int8 is
- not called from within the debugger.
-
- -------------------------------------------------------------------------
- Debug Turbo Debug Turbo Debug 386 Soft-Ice
- X X X X
- -------------------------------------------------------------------------
-
-
- Part_III: The Prefetch
-
- My favorite way to confuse debuggers is to mess with the prefetch
- queue. All intel processors have a small queue where the next
- instructions to be executed are stored. In this way, the CPU does not
- have to waste clock cycles by fetching the next instruction, except in
- the cases of branching instructions such as jmps and calls. The next
- chunk of code makes use of this:
-
- eapple: mov ah, 9
- mov word ptr [offset ear_lobe-2], offset sukk_debug
- mov dx, offset text
- ear_lobe:
- int 21h
- int 20h
-
- text db 'snee!$'
- sukk_debug db 0Ah, 0Dh, 09h, 'blow a goat!', 07h, 0Ah, 0Dh, '$'
-
- All this program does is print out a text string. If it is run
- from dos, it will print out 'snee!'. If it is traced through by any
- debugger, however, it will print 'blow a goat!', and beep the PC speaker
- (07h is ctrl-g). Let me explain how this works.
- When any chunk of code is executed by dos, the first few bytes are
- sent into the prefetch queue. The actual number of bytes depends on the
- model of intel chip, and what year it was made in. My computer is a
- 386DX-20 (early model), which has a 16 byte prefetch. Be sure to check
- your code on several machines to insure compatability.
- When the second instruction is reached, it places the offset of
- sukk_debug into the next instruction. That is, the next instruction
- becomes 'mov dx, offset sukk_debug', rather than 'mov dx, offset text'.
- The system memory will be changed, but the prefetch will not, therefore
- only a debugger will respond to the new code. Dos will execute it as if
- the instruction had never changed, because the instruction will already
- have been loaded into the prefetch. This theory can be used, with a
- little modification, in order to branch to various subroutines, rather
- than just printing out different text. One interesting application of
- this is to use the prefetch area to store registers. This way, a person
- debugging your code can not simply nop it out, because it will be
- referred to later on. In fact, you can even put the stack on the
- prefetch. Try to debug through the following fragment, and watch what
- happens:
-
- nee: mov ax, 4Ch
- mov dx, offset text
- mov sp, offset fin_rot
- push ax
- mov ah, 9
- fin_rot:int 21h
- pop ax
- int 21h
- text: db 'Duck is proud of her feet. They can catch things.$'
-
- If you run it through debug, the entire program will be corrupted
- as soon as you move the stack pointer. This is because the debug code
- uses the stack and expects it to be in a safe location. If you run it
- through soft ice, the code will be corrupted as soon as you push ax.
- The stack area will be overwritten when int21 is executed, because the
- interrupt uses the stack. However, in this example, the instruction
- pointer will already be beyond this area, so the program will execute
- normally.
- Remember not to place the stack past any calls, because then the
- prefetch would have to be reloaded after the main program was returned
- to, and the instructions that were there before will be gone.
-
- -------------------------------------------------------------------------
- Debug Turbo Debug Turbo Debug 386 Soft-Ice
- X X X X
- -------------------------------------------------------------------------
-
- That about wraps it up for this installment. I will probably have
- some new methods for you the next issue, unless I get bored and decide
- to drop the whole idea. Keep in mind that the best ideas are your own.
-
-
- Remember: Unprotected code is public domain!
-
-
- [] If anyone has any questions or comments about my series, []
- [] or some more suggestions for methods that can be added to []
- [] it, feel free to drop me a note on Landfill BBS []
-