⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bpr.cpp

📁 ICEExt for Driver Studio3.2的sourcecode
💻 CPP
字号:
/*++
    Copyright  (c) 2002 Sten
    Contact information:
        mail: stenri@mail.ru

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 
Module Name:
    bpr.cpp

Abstract:  Breapoint on Range helper library. Implements some useful functions. 

Revision History:

 Sten        05/06/2002
      Initial release


--*/

extern "C"{
#pragma warning ( push, 3 )
#include <ntddk.h>
#pragma warning ( pop )
}

#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed

#define  __BPR_C__
#include "bpr.h"
#undef   __BPR_C__

#include "defs.h"
#include "softice.h"
#include "stdlib.h"

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Check 
//  Check if any break point on range matches conditions
//
/////////////////////////////////////////////////////////////////////////////

ULONG bpr_Check(ULONG _CR3, ULONG _CR2, ULONG ErrCode)
{
    for (ULONG i=0; i<bpr_Count; i++)
    {
         if (BPR[i].CR3 == (_CR3 & 0xFFFFF000)) // address space matches breakpoint
         {
             if (                               // check if page fault is inside breakpoint range?
                  (_CR2 >= BPR[i].VA      ) && 
                  (_CR2 <  BPR[i].VA + BPR[i].Len)
                )
             {
                // TO DO: test for breakpoint type!
                if ((ErrCode & 0x02) == 0x02) 
                { // write attempt
                    if (BPR[i].Type == 'W')
                       return i;
                    else
                       return i | 0x80000000; // emulate memory access 
                }
                else
                { // read attempt
                    if (BPR[i].Type == 'R')
                       return i;
                    else
                       return i | 0x80000000; // emulate memory access 
                }
             }
             else
             {
                ULONG nPTEs = (BPR[i].Len + PAGE_SIZE - 1)/PAGE_SIZE;

                if (                               // check if page fault is inside PAGEs range?
                     (_CR2 >= (BPR[i].VA & 0xFFFFF000)) && 
                     (_CR2 <  ((BPR[i].VA & 0xFFFFF000) + nPTEs*PAGE_SIZE))
                   )
                {
                    // break address is not inside our BPR range but fits into PAGEs range so
                    // we must emulate memory access
                    return i | 0x80000000; // emulate memory access 
                }
             }
         }
    }
    return 0xFFFFFFFF; // no break point matches conditions
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Set 
//  Set breakpoint on range.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_Set(ULONG bpr_Type,
             ULONG bpr_Addr,
             ULONG bpr_Len,
             ULONG bpr_CR3)

{
    if (bpr_Count >= MAX_BPR) return;

    BPR[bpr_Count].Type  = bpr_Type;
    BPR[bpr_Count].VA    = bpr_Addr;
    BPR[bpr_Count].Len   = bpr_Len; 
    if (BPR[bpr_Count].Len == 0) BPR[bpr_Count].Len = PAGE_SIZE;
    BPR[bpr_Count].CR3   = bpr_CR3  & 0xFFFFF000; // align to the page boundary

    if ((BPR[bpr_Count].VA+BPR[bpr_Count].Len) > NT_HIGHEST_USER_ADDRESS)
    {
          DbgPrint("BPR ERROR: break points on range aren't allowed in system code.\n");
          return; 
    }

    if (bpr_CheckPTEs(bpr_Count, TRUE) == FALSE) return;

    DbgPrint("BPR: %c %x %x (CR3=%08X)\n", BPR[bpr_Count].Type, 
                                           BPR[bpr_Count].VA, 
                                           BPR[bpr_Count].Len,
                                           BPR[bpr_Count].CR3);


    BPR[bpr_Count].Flags = BPRFLG_SET | BPRFLG_DEACTIVATED;

    BPR[bpr_Count].PTEs = (PULONG)ExAllocatePool(NonPagedPool,
                                                4*(BPR[bpr_Count].Len/PAGE_SIZE+1));
	
    bpr_Count++;
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_CheckPTEs 
//  Check PTEs of given break point for range for validity.
//  Print error messages if asked.
//
/////////////////////////////////////////////////////////////////////////////

BOOLEAN bpr_CheckPTEs(ULONG bpNo, BOOLEAN Info)
{
    ULONG *Pte;

    for(ULONG VA = BPR[bpNo].VA; VA < (BPR[bpNo].VA+BPR[bpNo].Len); VA += PAGE_SIZE)
    {

        Pte = (PULONG)GetPte((void*)VA);
  
        if (Pte == 0)
        {
              if (Info)
                  DbgPrint("Error: invalid PTE at virtual address VA=%08X.\n", VA);
              return FALSE; // invalid PTE?
        }

        if ((*Pte & 0x1) == 0)
        {
              if (Info)
                  DbgPrint("Error: some page in range is not physically present in memory (VA=%08X).\n", VA);
              return FALSE;
        }
  
        if ((*Pte & 0x4) == 0)
        {
              if (Info)
                  DbgPrint("Error: some page in range is supervisor page (VA=%08X).\n", VA);
              return FALSE;
        }
  
        if ((*Pte & 0x100) == 0x100)
        {
              if (Info)
                  DbgPrint("Error: some page in range is global page (VA=%08X).\n", VA);
              return FALSE;
        }
    }
   
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_SavePTEsAndMakeInvalid
//  Saves PTEs of the given breakpoint and makes them invalid
//
/////////////////////////////////////////////////////////////////////////////

ULONG bpr_SavePTEsAndMakeInvalid(ULONG bpNo)
{
    PULONG Pte;
    ULONG _CR3;

    if (bpr_Count >= MAX_BPR) return 0;

//    if ((BPR[bpNo].Flags & BPRFLG_DEACTIVATED) == 0) return;

    __asm
    {
         mov         eax, cr3
         mov        _CR3, eax
    }

    if (BPR[bpNo].CR3 != _CR3) return 0;

    if (bpr_CheckPTEs(bpNo, FALSE) == FALSE) return 0;

    ULONG nPTEs = (BPR[bpNo].Len + PAGE_SIZE - 1)/PAGE_SIZE;

    for(ULONG i=0; i < nPTEs; i++)     // handle PTEs
    {                                             
        Pte = (PULONG)GetPte((void*)(BPR[bpNo].VA+i*PAGE_SIZE));
        *(BPR[bpNo].PTEs+4*i) = *Pte;             // save the PTE
        *Pte = 0;                                 // make PTE invalid
    } 

    __asm                   // flush TLBs
    {
         mov        eax,cr3
         mov        cr3,eax

    }

    return 1; 
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_RestorePTEs
//  Restores PTEs of the given breakpoint
//
/////////////////////////////////////////////////////////////////////////////

ULONG bpr_RestorePTEs(ULONG bpNo)
{
    PULONG Pte;
    ULONG _CR3;

    if (bpr_Count >= MAX_BPR) return 0;

    // PTEs can only be restored when SET flag is cleared
    if ((BPR[bpNo].Flags & BPRFLG_SET) == BPRFLG_SET) return 1;

    __asm
    {
         mov         eax, cr3
         mov        _CR3, eax
    }

    if (BPR[bpNo].CR3 != _CR3) return 0;
  
    ULONG nPTEs = (BPR[bpNo].Len + PAGE_SIZE - 1)/PAGE_SIZE;
   
    for(ULONG i=0; i < nPTEs; i++) // handle PTEs
    {                                             
        Pte = (PULONG)GetPte((void*)(BPR[bpNo].VA+i*PAGE_SIZE));
        *Pte = *(BPR[bpNo].PTEs+4*i);             // restore the PTE
    } 

    __asm                   // flush TLBs
    {
         mov        eax,cr3
         mov        cr3,eax
    }

    return 1;
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Disable 
//  Disables given breakpoint on range.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_Disable(ULONG bpNo)
{
   if (bpNo >= bpr_Count) return;

   if ((BPR[bpNo].Flags & BPRFLG_DISABLED) == 0)
   {
       if (bpr_RestorePTEs(bpNo) != 0)
           BPR[bpNo].Flags |= BPRFLG_DISABLED; // Set DISABLED flag
   }
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Enable 
//  Enables given breakpoint on range.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_Enable(ULONG bpNo)
{
   if (bpNo >= bpr_Count) return;

   if ((BPR[bpNo].Flags & BPRFLG_DISABLED) == BPRFLG_DISABLED)
   {
       if (bpr_SavePTEsAndMakeInvalid(bpNo) != 0)
             BPR[bpNo].Flags &= !BPRFLG_DISABLED; // Clear DISABLED flag
   }
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Activate 
//  Activates given breakpoint on range.
//
/////////////////////////////////////////////////////////////////////////////

ULONG bpr_Activate(ULONG bpNo)
{
   if (bpNo >= bpr_Count) return 0;

   if (
        ((BPR[bpNo].Flags & BPRFLG_DEACTIVATED) == BPRFLG_DEACTIVATED) ||
        ((BPR[bpNo].Flags & BPRFLG_SET) == BPRFLG_SET)
      )
   {
       if (bpr_SavePTEsAndMakeInvalid(bpNo) != 0)
       {
           // Clear DEACTIVATED and SET flag
           BPR[bpNo].Flags &= !(BPRFLG_DEACTIVATED | BPRFLG_SET); 
           return 1;
       }
   }

   return 0;
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Deactivate 
//  Deactivates given breakpoint on range.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_Deactivate(ULONG bpNo)
{
   if (bpNo >= bpr_Count) return;

   if ((BPR[bpNo].Flags & BPRFLG_DEACTIVATED) == 0)
   {
       if (bpr_RestorePTEs(bpNo) != 0)
           BPR[bpNo].Flags |= BPRFLG_DEACTIVATED; // Set DEACTIVATED flag
   }
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_ActivateAll 
//
//   Tries to activate all breakpoints on range.
//
/////////////////////////////////////////////////////////////////////////////

ULONG bpr_ActivateAll()
{
     ULONG dwActivatedNum = 0;

     for (ULONG i=0; i<bpr_Count; i++)
     {
         if (bpr_Activate(i)) dwActivatedNum++;
     }

     return dwActivatedNum;
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_DeactivateAll 
//
//   Tries to deactivate all breakpoints on range.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_DeactivateAll()
{
     for (ULONG i=0; i<bpr_Count; i++)
     {
           bpr_Deactivate(i);
     }
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_IsDisabled 
//  Check if given breakpoint is disabled.
//
/////////////////////////////////////////////////////////////////////////////

ULONG bpr_IsDisabled(ULONG bpNo)
{
   return (BPR[bpNo].Flags & BPRFLG_DISABLED);
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_Clear 
//  Clear given breakpoint on range.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_Clear(ULONG bpNo)
{
     if (bpr_Count == 0)
     {
        DbgPrint("Warning: nothing to clear.\n");
        return;
     }

     if (bpNo >= bpr_Count)
     {
        DbgPrint("ERROR: no such breakpoint (%d).\n",bpNo);
        return;
     }

     bpr_Deactivate(bpNo);

     bpr_Count--;     // Decrease BPRs count

     // Delete a structure member
     RtlMoveMemory((void*)&BPR[bpNo],(void*)&BPR[bpNo+1],(bpr_Count - bpNo)*sizeof(BPR[0]));

     BPR[bpr_Count].Flags  = 0;
     BPR[bpr_Count].CR3    = 0;
     BPR[bpr_Count].VA     = 0;
     BPR[bpr_Count].Len    = 0;
     BPR[bpr_Count].Type   = 0;

     if (BPR[bpr_Count].PTEs)
     {
         ExFreePool(BPR[bpr_Count].PTEs);
         BPR[bpr_Count].PTEs   = 0;
     }
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_ClearAll
//  Clear all breakpoints for the current process.
//
/////////////////////////////////////////////////////////////////////////////

void bpr_ClearAll()
{
    ULONG _CR3;

    __asm
    {
          mov        eax, CR3
          mov       _CR3, eax
    }

    for(ULONG i=0;i<bpr_Count;i++)
    {
        if (BPR[i].CR3 == (_CR3 & 0xFFFFF000))
        {
            bpr_Clear(i);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// bpr_ListAll
//  Lists all breakpoints on range
//
/////////////////////////////////////////////////////////////////////////////

void bpr_ListAll ()
{
    for(ULONG i=0;i<bpr_Count;i++)
    {
        DbgPrint("%02d)   BPR %c %x %x (CR3=%08X, Flags=%08X)\n", i,
                                                   BPR[i].Type, 
                                                   BPR[i].VA, 
                                                   BPR[i].Len,
                                                   BPR[i].CR3,
                                                   BPR[i].Flags);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -