Information of how to stop your programs from being hacked --------------------------------------------------------------------------- This information is provided as is, and the author provides no form of guarantee what so ever. --------------------------------------------------------------------------- There is a better FAQ called RADFAQ. You can download it here or EMail: ****@*********.de. It is compiled by ROSE, the author of HACKSTOP. The latest version I have is 1.02. Released 26 July 1996. For FILE_ID.DIZ ROSE's Anti-Debugger FAQ (rADFAQ) - All anti-debugger tricks you can imagine. Includes SRC and COM files too! Freeware --------------------------------------------------------------------------- Overview and Objectives This information is only really for advanced assembler programmers and it makes the assumption that you are using one segment. It also uses 16 bit memory addresses. All of the ideas are fundamental to this sort of programming and could be easily adapted to other programming languages and applications. It's to help assembler programmers to protect their hard work from:- * Lamers placing their own names in your executable. * Crackers removing your password routines * Hackers removing / finding out program passwords In other words, generally protecting your own hard work. --------------------------------------------------------------------------- Rule 1 :- Encrypt your code This will really foil any initial attempts to change the code with a simple hex editor. The only problem with this, is you have to write a program to encrypt your compiled source.I.E.. You can't expect your program to modify itself and write itself back to disk like a virus. This is because your program will be stopped by virus checkers, because it has changed from the last time it was executed. A simple encryptor would be as follows :- .model tiny .RADIX 16 .code org 0100 begin: Call Decrypt Code_to_decrypt_Start: Code_to_decrypt_End: Encryption_Key: Db 0feh Decrypt: Mov cx,Offset Code_to_decrpyt_End - Offset Code_to_decrypt_Start Mov bl,Byte ptr [Encryption_Key] Mov Si, 0100h ; The code entry point is cs:0100h Loop_Decrypt: Add byte ptr [si],bl inc si Loop Loop_Decrypt Retn ; Finished carry on with program end begin You have to then write a program which uses the correct encryption algorithm and key to encrypt the code.I.E. In the above example this will need to subtract the encryption key from each byte. The XOR command is very useful in this regard, because you can use the identical algorithm for encryption and decryption; But it's ease of use it perhaps it's downfall. Everybody will look for code in a program to XOR , [WORD|BYTE] ptr [] in a little loop. So the message is get creative. A particular Encryption / Decryption algorithm can be unique to you. --------------------------------------------------------------------------- Rule 2 :- Obscurity Remember you want to confuse the would be hacker into giving up. Don't do obvious things like calling documented and well known interrupts when there are probably dozens of other methods of getting the same info. The idea of an interrupt was to create a common platform for programmers to work off. Many of them were documented, but many more were shrouded in mystery. Lots of people have spend hours tracing such interrupts and they can be found in interrupt listings on many common FTP archives. These interrupts are very useful in the battle against hackers. Other methods involve long methods of getting data which is always constant. In other words instead of directly accessing a byte in memory, you take a very long approach. Everybody knows that the first word of the program segment prefix (PSP) is 020cdh, in reverse order lintel format. Use can use this to your advantage in the following example. Mov ax,0100h Mov cx,0030h add ax,cx jmp short skip GarbageBytes: db 012h,0fh,00,090h,021h skip: Mov bx,Offset GarbageBytes ; Point to the Garbage Table Mov al,03 ; Point to db 00 which is ; at [GarbageBytes + AL] Xlat bx ; Replaces the byte AL with ; the byte from a user table ; addressed by BX. The ; original value of AL is the ; index into the translation ; table. The best way to ; describe this is ; Mov AL,[BX + AL] ; AL is now 00h mov AH,AL ;Ax is now 0000h XOR Word ptr [Next_Instruction],AX ; Does nothing since AX is 0000h Next_Instruction: Another thing regarding to obscurity is to pad your functional code with lots of useless, but non-interfering instructions. Example :- Mov ax,0100h Mov bx,0200h Mov si,0300h Mov di, 0400h Mov cx,020h rep Lodsb Could become Mov ax,0100h Mul bx Nothing:Push si mul di pop dx Mov bx,0200h Mov cx, Byte ptr [Nothing] push ax mul cx pop ax Mov si,0300h nop cli std cld add di,ax add di, byte ptr [Nothing] " " " ;And so on ....... --------------------------------------------------------------------------- Rule 3 :- Anti - Debugging Tricks This is a very large topic and will be covered by two subheadings. Namely Interrupt replacement and self modifying code. * Self Modifying Code Before a command is executed on the Intel processor, it is loaded into a buffer called the Prefetch Instruction Queue (PIQ). This buffer ranges in size from 15 to 64 bytes, depending on the power of the processor. This buffer is designed to reduce the time the processor spends executing the Fetch Process, by fetching more than one byte at a time. This means that code in memory, less than 15 bytes in front of CP:IP, will not change when executed, even if you change the bytes in physical memory. Mov word ptr [Dont_Change],01212h Dont_Change: Nop ; This will still be executed as a NOP When you run a debugger, and you Trace or Step through code, your PIQ will always apparently be 0 bytes. So to make a debugger bomb out, all you have to do is change the bytes a couple of instructions ahead and then wait for disaster to strike, when the debugger encounters these changes. This is a very useful feature of the Intel chip, but you need to remember that the byte in memory has changed, the processor just does not know it yet. That is why, if you use Prefetch Instruction Queuing, as it is called, you must replace the bytes after they are executed. Especially if it is in a loop of some description. Insidently, Interrupt 3 will clear the PIQ buffer. Here is an example of PIQ in a loop:- Mov cx,0100h Looper: Mov word ptr [Change_This], 020cdh Lodsb Changethis:stosb cmp al,020h je Anywhere Mov word ptr [Change_This],03CAAh Loop Looper Anywhere: * Interrupt Replacement The following on Interrupt replacement was cut from 40HEX Magazine. Volume 9 Article 004 1.1. Interrupt disable: Interrupt disable is probably the most common form of anti-debugging trick. It can be done in several ways: 1.1.1. Hardware masking of interrupt: In order to avoid tracing of a code, one usually disables the interrupt via the 8259 Interrupt Controller, addressed by read/write actions to port 21h. The 8259 Interrupt Controller controls the IRQ lines. This means that any IRQ between 0 and 7 may be disabled by this action. Bit 0 is IRQ0, bit 1 is IRQ1 etc. Since IRQ1 is the keyboard interrupt, you may disable the keyboard without the debugger being able to bypass it. Example: CS:0100 E421 IN AL,21 CS:0102 0C02 OR AL,02 CS:0104 E621 OUT 21,AL Just as a side notice, the keyboard may be also disabled by commanding the Programmable Perepheral Interface (PPI), port 61h. Example: CS:0100 E461 IN AL,61 CS:0102 0C80 OR AL,80 CS:0104 E661 OUT 61,AL 1.1.2. Software masking of interrupt: This is quite an easy form of anti-debugging trick. All you have to do is simply replace the vectors of interrupts debuggers use/any other interrupt you will not be using or expecting to happen. Do not forget to restore the original vectors when you are finished. It is adviseable to use manual change of vector, as shown below, rather than to change it using interrupt 21h service 25h, because any debugger that has gained control of interrupt 21h may replace your vector with the debugger's. The example shows an interception of interrupt 03h - the breakpoint interrupt. Example: CS:0100 EB04 JMP 0106 CS:0102 0000 ADD [BX+SI],AL CS:0104 0000 ADD [BX+SI],AL CS:0106 31C0 XOR AX,AX CS:0108 8EC0 MOV ES,AX CS:010A 268B1E0C00 MOV BX,ES:[000C] CS:010F 891E0201 MOV [0102],BX CS:0113 268B1E0E00 MOV BX,ES:[000E] CS:0118 891E0401 MOV [0104],BX CS:011C 26C7064C000000 MOV Word Ptr ES:[000C],0000 CS:0123 26C7064E000000 MOV Word Ptr ES:[000E],0000 1.1.3. Vector manipulation This method involves manipulations of the interrupt vectors, mainly for proper activation of the algorithm. Such action, as exampled, may be used to decrypt a code (see also 2.1), using data stored ON the vectors. Ofcourse, during normal operation of the program, vectors 01h and 03h are not used, so unless you are trying to debug such a program, it works fine. Example: CS:0100 31C0 XOR AX,AX CS:0102 8ED0 MOV SS,AX CS:0104 BC0600 MOV SP,0006 CS:0107 8B0E0211 MOV CX,[1102] CS:010B 50 PUSH AX CS:010C 21C8 AND AX,CX CS:010E 01C5 ADD BP,AX CS:0110 58 POP AX CS:0111 E2F8 LOOP 010B 1.1.4. Interrupt replacement This is a really nasty trick, and it should be used ONLY if you are ABSOLUTELY sure that your programs needs no more debugging. What it does is simply copy the vectors of some interrupts you will be using, say 16h and 21h, onto the vectors of interrupt 01h and 03h, that do not occure during normal operation of the program. If the user wants to debug the program, he would have to search for every occurance of INT 01, and replace it with the appropriate INT instruction. Example: CS:0100 FA CLI CS:0101 31C0 XOR AX,AX CS:0103 8EC0 MOV ES,AX CS:0105 26A18400 MOV AX,ES:[0084] CS:0109 26A30400 MOV ES:[0004],AX CS:010D 26A18600 MOV AX,ES:[0086] CS:0111 26A30600 MOV ES:[0006],AX CS:0115 B44C MOV AH,4C CS:0117 CD01 INT 01 --------------------------------------------------------------------------- There is a lot more you can do to prevent debugging, but in the end you have to out-smart the hacker. For more information Watch this space! or subscribe to lots of ASM newsgroups. --------------------------------------------------------------------------- Return to Stewart Moss's Page --------------------------------------------------------------------------- Intel is a registered trademark of the Intel corp. © Stewart Moss 1995 ------------------------------