"Fossies" - the Fresh Open Source Software Archive

Member "src/Boot/Windows/IntFilter.cpp" (10 Oct 2018, 13621 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "IntFilter.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "Platform.h"
   14 #include "BootMemory.h"
   15 #include "BootConfig.h"
   16 #include "BootConsoleIo.h"
   17 #include "BootDebug.h"
   18 #include "BootDefs.h"
   19 #include "BootDiskIo.h"
   20 #include "BootEncryptedIo.h"
   21 #include "BootStrings.h"
   22 #include "IntFilter.h"
   23 
   24 static uint32 OriginalInt13Handler;
   25 static uint32 OriginalInt15Handler;
   26 
   27 static Registers IntRegisters;
   28 
   29 
   30 bool Int13Filter ()
   31 {
   32     CheckStack();
   33 
   34     Registers regs;
   35     memcpy (&regs, &IntRegisters, sizeof (regs));
   36     __asm sti
   37 
   38     static int ReEntryCount = -1;
   39     ++ReEntryCount;
   40 
   41     byte function = (byte) (regs.AX >> 8);
   42 
   43 #ifdef TC_TRACE_INT13
   44     DisableScreenOutput();
   45 
   46     PrintHex (function);
   47 
   48     Print (" EN:"); Print (ReEntryCount);
   49     Print (" SS:"); PrintHex (regs.SS);
   50 
   51     uint16 spdbg;
   52     __asm mov spdbg, sp
   53     PrintChar (' ');
   54     PrintHex (spdbg);
   55     PrintChar ('<'); PrintHex (TC_BOOT_LOADER_STACK_TOP);
   56 
   57 #endif
   58 
   59     bool passOriginalRequest = true;
   60 
   61     switch (function)
   62     {
   63     case 0x2: // Read sectors
   64     case 0x3: // Write sectors
   65         {
   66             byte drive = (byte) regs.DX;
   67 
   68             ChsAddress chs;
   69             chs.Cylinder = ((regs.CX << 2) & 0x300) | (regs.CX >> 8);
   70             chs.Head = regs.DX >> 8;
   71             chs.Sector = regs.CX & 0x3f;
   72 
   73             byte sectorCount = (byte) regs.AX;
   74 
   75 #ifdef TC_TRACE_INT13
   76             PrintVal (": Drive", drive - TC_FIRST_BIOS_DRIVE, false);
   77             Print (" Chs: "); Print (chs);
   78 #endif
   79 
   80             uint64 sector;
   81             if (drive == BootDrive)
   82             {
   83                 if (!BootDriveGeometryValid)
   84                     TC_THROW_FATAL_EXCEPTION;
   85 
   86                 ChsToLba (BootDriveGeometry, chs, sector);
   87 #ifdef TC_TRACE_INT13
   88                 PrintVal (" Sec", sector.LowPart, false);
   89 #endif
   90             }
   91 
   92 #ifdef TC_TRACE_INT13
   93             PrintVal (" Count", sectorCount, false);
   94             Print (" Buf: "); PrintHex (regs.ES); PrintChar (':'); PrintHex (regs.BX);
   95             PrintEndl();
   96 #endif
   97 
   98             if (ReEntryCount == 0 && drive == EncryptedVirtualPartition.Drive)
   99             {
  100                 BiosResult result;
  101 
  102                 if (function == 0x3)
  103                     result = WriteEncryptedSectors (regs.ES, regs.BX, drive, sector, sectorCount);
  104                 else
  105                     result = ReadEncryptedSectors (regs.ES, regs.BX, drive, sector, sectorCount);
  106 
  107                 __asm cli
  108 
  109                 memcpy (&IntRegisters, &regs, sizeof (regs));
  110                 IntRegisters.AX = (uint16) result << 8;
  111 
  112                 if (result == BiosResultSuccess)
  113                 {
  114                     IntRegisters.AX |= sectorCount;
  115                     IntRegisters.Flags &= ~TC_X86_CARRY_FLAG;
  116                 }
  117                 else
  118                     IntRegisters.Flags |= TC_X86_CARRY_FLAG;
  119 
  120                 passOriginalRequest = false;
  121             }
  122         }
  123         break;
  124 
  125     case 0x42: // Read sectors LBA
  126     case 0x43: // Write sectors LBA
  127         {
  128             byte drive = (byte) regs.DX;
  129 
  130             BiosLbaPacket lba;
  131             CopyMemory (regs.DS, regs.SI, (byte *) &lba, sizeof (lba));
  132 
  133 #ifdef TC_TRACE_INT13
  134             PrintVal (": Drive", drive - TC_FIRST_BIOS_DRIVE, false);
  135             PrintVal (" Sec", lba.Sector.LowPart, false);
  136             PrintVal (" Count", lba.SectorCount, false);
  137             PrintVal (" Buf", lba.Buffer, false, true);
  138             PrintEndl();
  139 #endif
  140 
  141             if (ReEntryCount == 0 && drive == EncryptedVirtualPartition.Drive)
  142             {
  143                 BiosResult result;
  144 
  145                 uint16 segment = (uint16) (lba.Buffer >> 16);
  146                 uint16 offset = (uint16) lba.Buffer;
  147 
  148                 if (function == 0x43)
  149                     result = WriteEncryptedSectors (segment, offset, drive, lba.Sector, lba.SectorCount);
  150                 else
  151                     result = ReadEncryptedSectors (segment, offset, drive, lba.Sector, lba.SectorCount);
  152 
  153                 __asm cli
  154 
  155                 memcpy (&IntRegisters, &regs, sizeof (regs));
  156                 IntRegisters.AX = (IntRegisters.AX & 0xff) | ((uint16) result << 8);
  157 
  158                 if (result == BiosResultSuccess)
  159                     IntRegisters.Flags &= ~TC_X86_CARRY_FLAG;
  160                 else
  161                     IntRegisters.Flags |= TC_X86_CARRY_FLAG;
  162 
  163                 passOriginalRequest = false;
  164             }
  165         }
  166         break;
  167 
  168     default:
  169 #ifdef TC_TRACE_INT13
  170         PrintEndl();
  171 #endif
  172         break;
  173     }
  174 
  175 #ifdef TC_TRACE_INT13
  176     EnableScreenOutput();
  177 #endif
  178     --ReEntryCount;
  179 
  180     return passOriginalRequest;
  181 }
  182 
  183 
  184 #define TC_MAX_MEMORY_MAP_SIZE 80
  185 
  186 BiosMemoryMapEntry BiosMemoryMap[TC_MAX_MEMORY_MAP_SIZE];
  187 static size_t BiosMemoryMapSize;
  188 
  189 
  190 static void CreateBootLoaderMemoryMapEntry (BiosMemoryMapEntry *newMapEntry, uint32 bootLoaderStart)
  191 {
  192     newMapEntry->Type = 0x2;
  193     newMapEntry->BaseAddress.HighPart = 0;
  194     newMapEntry->BaseAddress.LowPart = bootLoaderStart;
  195     newMapEntry->Length.HighPart = 0;
  196     newMapEntry->Length.LowPart = TC_BOOT_MEMORY_REQUIRED * 1024UL;
  197 }
  198 
  199 
  200 static bool CreateNewBiosMemoryMap ()
  201 {
  202     // Create a new BIOS memory map presenting the memory area of the loader as reserved
  203 
  204     BiosMemoryMapSize = 0;
  205     BiosMemoryMapEntry entry;
  206     BiosMemoryMapEntry *newMapEntry = BiosMemoryMap;
  207 
  208     const BiosMemoryMapEntry *mapEnd = BiosMemoryMap + TC_MAX_MEMORY_MAP_SIZE;
  209 
  210     uint64 bootLoaderStart;
  211     bootLoaderStart.HighPart = 0;
  212 
  213     uint16 codeSeg;
  214     __asm mov codeSeg, cs
  215     bootLoaderStart.LowPart = GetLinearAddress (codeSeg, 0);
  216 
  217     uint64 bootLoaderEnd;
  218     bootLoaderEnd.HighPart = 0;
  219     bootLoaderEnd.LowPart = bootLoaderStart.LowPart + TC_BOOT_MEMORY_REQUIRED * 1024UL;
  220 
  221     bool loaderEntryInserted = false;
  222 
  223     if (GetFirstBiosMemoryMapEntry (entry))
  224     {
  225         do
  226         {
  227             uint64 entryEnd = entry.BaseAddress + entry.Length;
  228 
  229             if (entry.Type == 0x1 && RegionsIntersect (bootLoaderStart, TC_BOOT_MEMORY_REQUIRED * 1024UL, entry.BaseAddress, entryEnd - 1))
  230             {
  231                 // Free map entry covers the boot loader area
  232 
  233                 if (entry.BaseAddress < bootLoaderStart)
  234                 {
  235                     // Create free entry below the boot loader area
  236                     if (newMapEntry >= mapEnd)
  237                         goto mapOverflow;
  238 
  239                     *newMapEntry = entry;
  240                     newMapEntry->Length = bootLoaderStart - entry.BaseAddress;
  241                     ++newMapEntry;
  242                 }
  243 
  244                 if (!loaderEntryInserted)
  245                 {
  246                     // Create reserved entry for the boot loader if it has not been done yet
  247                     if (newMapEntry >= mapEnd)
  248                         goto mapOverflow;
  249 
  250                     CreateBootLoaderMemoryMapEntry (newMapEntry, bootLoaderStart.LowPart);
  251                     ++newMapEntry;
  252                     loaderEntryInserted = true;
  253                 }
  254 
  255                 if (bootLoaderEnd < entryEnd)
  256                 {
  257                     // Create free entry above the boot loader area
  258                     if (newMapEntry >= mapEnd)
  259                         goto mapOverflow;
  260 
  261                     newMapEntry->Type = 0x1;
  262                     newMapEntry->BaseAddress = bootLoaderEnd;
  263                     newMapEntry->Length = entryEnd - bootLoaderEnd;
  264                     ++newMapEntry;
  265                 }
  266             }
  267             else
  268             {
  269                 if (newMapEntry >= mapEnd)
  270                     goto mapOverflow;
  271 
  272                 if (!loaderEntryInserted && entry.BaseAddress > bootLoaderStart)
  273                 {
  274                     // Create reserved entry for the boot loader if it has not been done yet
  275                     CreateBootLoaderMemoryMapEntry (newMapEntry, bootLoaderStart.LowPart);
  276                     ++newMapEntry;
  277                     loaderEntryInserted = true;
  278                 }
  279 
  280                 // Copy map entry
  281                 *newMapEntry++ = entry;
  282             }
  283 
  284         } while (GetNextBiosMemoryMapEntry (entry));
  285     }
  286 
  287     BiosMemoryMapSize = newMapEntry - BiosMemoryMap;
  288     return true;
  289 
  290 mapOverflow:
  291     size_t overSize = 0;
  292     while (GetNextBiosMemoryMapEntry (entry))
  293     {
  294         ++overSize;
  295     }
  296 
  297     PrintErrorNoEndl ("MMP:");
  298     Print (overSize);
  299     PrintEndl();
  300 
  301     return false;
  302 }
  303 
  304 
  305 bool Int15Filter ()
  306 {
  307     CheckStack();
  308 
  309 #ifdef TC_TRACE_INT15
  310     DisableScreenOutput();
  311 
  312     Print ("15-");
  313     PrintHex (IntRegisters.AX);
  314 
  315     Print (" SS:"); PrintHex (IntRegisters.SS);
  316 
  317     uint16 spdbg;
  318     __asm mov spdbg, sp
  319     PrintChar (' ');
  320     PrintHex (spdbg);
  321     PrintChar ('<'); PrintHex (TC_BOOT_LOADER_STACK_TOP);
  322 
  323     Print (" EAX:"); PrintHex (IntRegisters.EAX);
  324     Print (" EBX:"); PrintHex (IntRegisters.EBX);
  325     Print (" ECX:"); PrintHex (IntRegisters.ECX);
  326     Print (" EDX:"); PrintHex (IntRegisters.EDX);
  327     Print (" DI:"); PrintHex (IntRegisters.DI);
  328     PrintEndl();
  329 
  330 #endif
  331 
  332     if (IntRegisters.EBX >= BiosMemoryMapSize)
  333     {
  334         IntRegisters.Flags |= TC_X86_CARRY_FLAG;
  335         IntRegisters.EBX = 0;
  336         IntRegisters.AX = -1;
  337     }
  338     else
  339     {
  340         CopyMemory ((byte *) &BiosMemoryMap[IntRegisters.EBX], IntRegisters.ES, IntRegisters.DI, sizeof (BiosMemoryMap[0]));
  341 
  342         IntRegisters.Flags &= ~TC_X86_CARRY_FLAG;
  343         IntRegisters.EAX = 0x534D4150UL;
  344 
  345         ++IntRegisters.EBX;
  346         if (IntRegisters.EBX >= BiosMemoryMapSize)
  347             IntRegisters.EBX = 0;
  348 
  349         IntRegisters.ECX = sizeof (BiosMemoryMap[0]);
  350     }
  351 
  352     if (IntRegisters.EBX == 0 && !(BootSectorFlags & TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER))
  353     {
  354         // Uninstall filter when the modified map has been issued three times to prevent
  355         // problems with hardware drivers on some notebooks running Windows XP.
  356 
  357         static int CompleteMapIssueCount = 0;
  358         if (++CompleteMapIssueCount >= 3)
  359         {
  360             __asm
  361             {
  362                 cli
  363                 push es
  364 
  365                 lea si, OriginalInt15Handler
  366                 xor ax, ax
  367                 mov es, ax
  368                 mov di, 0x15 * 4
  369 
  370                 mov ax, [si]
  371                 mov es:[di], ax
  372                 mov ax, [si + 2]
  373                 mov es:[di + 2], ax
  374 
  375                 pop es
  376                 sti
  377             }
  378         }
  379     }
  380 
  381 #ifdef TC_TRACE_INT15
  382     BiosMemoryMapEntry entry;
  383     CopyMemory (IntRegisters.ES, IntRegisters.DI, (byte *) &entry, sizeof (entry));
  384     PrintHex (entry.Type); PrintChar (' ');
  385     PrintHex (entry.BaseAddress); PrintChar (' ');
  386     PrintHex (entry.Length); PrintChar (' ');
  387     PrintHex (entry.BaseAddress + entry.Length); PrintEndl();
  388 
  389     Print ("EAX:"); PrintHex (IntRegisters.EAX);
  390     Print (" EBX:"); PrintHex (IntRegisters.EBX);
  391     Print (" ECX:"); PrintHex (IntRegisters.ECX);
  392     Print (" EDX:"); PrintHex (IntRegisters.EDX);
  393     Print (" DI:"); PrintHex (IntRegisters.DI);
  394     Print (" FL:"); PrintHex (IntRegisters.Flags);
  395     PrintEndl (2);
  396 #endif
  397 
  398 #ifdef TC_TRACE_INT15
  399     EnableScreenOutput();
  400 #endif
  401     return false;
  402 }
  403 
  404 
  405 void IntFilterEntry ()
  406 {
  407     // No automatic variables should be used in this scope as SS may change
  408     static uint16 OrigStackPointer;
  409     static uint16 OrigStackSegment;
  410 
  411     __asm
  412     {
  413         pushf
  414         pushad
  415 
  416         cli
  417         mov cs:IntRegisters.DI, di
  418 
  419         lea di, cs:IntRegisters.EAX
  420         TC_ASM_EMIT4 (66,2E,89,05) // mov [cs:di], eax
  421         lea di, cs:IntRegisters.EBX
  422         TC_ASM_EMIT4 (66,2E,89,1D) // mov [cs:di], ebx
  423         lea di, cs:IntRegisters.ECX
  424         TC_ASM_EMIT4 (66,2E,89,0D) // mov [cs:di], ecx
  425         lea di, cs:IntRegisters.EDX
  426         TC_ASM_EMIT4 (66,2E,89,15) // mov [cs:di], edx
  427 
  428         mov ax, [bp + 8]
  429         mov cs:IntRegisters.Flags, ax
  430 
  431         mov cs:IntRegisters.SI, si
  432         mov si, [bp + 2] // Int number
  433 
  434         mov cs:IntRegisters.DS, ds
  435         mov cs:IntRegisters.ES, es
  436         mov cs:IntRegisters.SS, ss
  437 
  438         // Compiler assumes SS == DS - use our stack if this condition is not met
  439         mov ax, ss
  440         mov bx, cs
  441         cmp ax, bx
  442         jz stack_ok
  443 
  444         mov cs:OrigStackPointer, sp
  445         mov cs:OrigStackSegment, ss
  446         mov ax, cs
  447         mov ss, ax
  448         mov sp, TC_BOOT_LOADER_STACK_TOP
  449 
  450     stack_ok:
  451         // DS = CS
  452         push ds
  453         push es
  454         mov ax, cs
  455         mov ds, ax
  456         mov es, ax
  457 
  458         push si // Int number
  459 
  460         // Filter request
  461         cmp si, 0x15
  462         je filter15
  463         cmp si, 0x13
  464         jne $
  465 
  466         call Int13Filter
  467         jmp s0
  468 
  469     filter15:
  470         call Int15Filter
  471 
  472     s0:
  473         pop si // Int number
  474         pop es
  475         pop ds
  476 
  477         // Restore original SS:SP if our stack is empty
  478         cli
  479         mov bx, TC_BOOT_LOADER_STACK_TOP
  480         cmp bx, sp
  481         jnz stack_in_use
  482 
  483         mov ss, cs:OrigStackSegment
  484         mov sp, cs:OrigStackPointer
  485     stack_in_use:
  486 
  487         test ax, ax // passOriginalRequest
  488         jnz pass_request
  489 
  490         // Return results of filtered request
  491         popad
  492         popf
  493         mov ax, cs:IntRegisters.Flags
  494         mov [bp + 8], ax
  495         leave
  496 
  497         lea di, cs:IntRegisters.EAX
  498         TC_ASM_EMIT4 (66,2E,8B,05) // mov eax, [cs:di]
  499         lea di, cs:IntRegisters.EBX
  500         TC_ASM_EMIT4 (66,2E,8B,1D) // mov ebx, [cs:di]
  501         lea di, cs:IntRegisters.ECX
  502         TC_ASM_EMIT4 (66,2E,8B,0D) // mov ecx, [cs:di]
  503         lea di, cs:IntRegisters.EDX
  504         TC_ASM_EMIT4 (66,2E,8B,15) // mov edx, [cs:di]
  505 
  506         mov di, cs:IntRegisters.DI
  507         mov si, cs:IntRegisters.SI
  508         mov es, cs:IntRegisters.ES
  509         mov ds, cs:IntRegisters.DS
  510 
  511         sti
  512         add sp, 2
  513         iret
  514 
  515         // Pass original request
  516     pass_request:
  517         sti
  518         cmp si, 0x15
  519         je pass15
  520         cmp si, 0x13
  521         jne $
  522 
  523         popad
  524         popf
  525         leave
  526         add sp, 2
  527         jmp cs:OriginalInt13Handler
  528 
  529     pass15:
  530         popad
  531         popf
  532         leave
  533         add sp, 2
  534         jmp cs:OriginalInt15Handler
  535     }
  536 }
  537 
  538 
  539 void Int13FilterEntry ()
  540 {
  541     __asm
  542     {
  543         leave
  544         push 0x13
  545         jmp IntFilterEntry
  546     }
  547 }
  548 
  549 
  550 static void Int15FilterEntry ()
  551 {
  552     __asm
  553     {
  554         pushf
  555         cmp ax, 0xe820 // Get system memory map
  556         je filter
  557 
  558         popf
  559         leave
  560         jmp cs:OriginalInt15Handler
  561 
  562     filter:
  563         leave
  564         push 0x15
  565         jmp IntFilterEntry
  566     }
  567 }
  568 
  569 
  570 bool InstallInterruptFilters ()
  571 {
  572 
  573 #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
  574 
  575     // If the filters have already been installed, it usually indicates stack corruption
  576     // and a consequent reentry of this routine without a system reset.
  577 
  578     uint32 currentInt13Handler;
  579     CopyMemory (0, 0x13 * 4, &currentInt13Handler, sizeof (currentInt13Handler));
  580 
  581     if (currentInt13Handler == (uint32) Int13FilterEntry)
  582     {
  583         PrintError ("Memory corrupted");
  584         Print (TC_BOOT_STR_UPGRADE_BIOS);
  585 
  586         GetKeyboardChar();
  587         return true;
  588     }
  589 
  590 #endif
  591 
  592     if (!CreateNewBiosMemoryMap())
  593         return false;
  594 
  595     __asm
  596     {
  597         cli
  598         push es
  599 
  600         // Save original INT 13 handler
  601         xor ax, ax
  602         mov es, ax
  603 
  604         mov si, 0x13 * 4
  605         lea di, OriginalInt13Handler
  606 
  607         mov ax, es:[si]
  608         mov [di], ax
  609         mov ax, es:[si + 2]
  610         mov [di + 2], ax
  611 
  612         // Install INT 13 filter
  613         lea ax, Int13FilterEntry
  614         mov es:[si], ax
  615         mov es:[si + 2], cs
  616 
  617         // Save original INT 15 handler
  618         mov si, 0x15 * 4
  619         lea di, OriginalInt15Handler
  620 
  621         mov ax, es:[si]
  622         mov [di], ax
  623         mov ax, es:[si + 2]
  624         mov [di + 2], ax
  625 
  626         // Install INT 15 filter
  627         lea ax, Int15FilterEntry
  628         mov es:[si], ax
  629         mov es:[si + 2], cs
  630 
  631         // If the BIOS does not support system memory map (INT15 0xe820),
  632         // set amount of available memory to CS:0000 - 0:0000
  633         cmp BiosMemoryMapSize, 1
  634         jg mem_map_ok
  635         mov ax, cs
  636         shr ax, 10 - 4      // CS * 16 / 1024
  637         mov es:[0x413], ax  // = KBytes available
  638     mem_map_ok:
  639 
  640         pop es
  641         sti
  642     }
  643 
  644     return true;
  645 }