1          // We have a block contained in the region.
  2
  3          // The following if statement is for detecting stacks in Windows 98.
  4          // A Windows 98 stack region's last 4 blocks look like this:
  5          //    reserved block, no access block, read-write block, reserved block
  6          //哈今天状态不错
  7          //Windows98线程堆栈所在内存区域的的特点是最后4个内存块依次为
  8          //reserved、PAGE_NOACCESS、PAGE_READWRITE、reserved
  9          //dwProtectBlock这个结构的定义就是为了存储最后4个块的页面保护信息
 10          //用来判断正在访问的内存区域是不是符合Windows98下的线程堆栈区域的特点
 11          //分两步走看代码吧:
 12          //这个就是内存区域中的内存块的个数小于4那么dwProtectBlock分配的空间足以存储和进行判断直接存储就可以了
 13      if (pVMQHelp->dwRgnBlocks < 4{
 14          // 0th through 3rd block, remember the block's protection
 15         dwProtectBlock[pVMQHelp->dwRgnBlocks] =
 16            (mbi.State == MEM_RESERVE) ? 0 : mbi.Protect;
 17      }
 else {
 18             //如果该内存区域中内存块的个数大于4那么我们上面非配的4个存储位置将无法存储全部的内存区块。
 19             //幸运的是我们并不关心全部的内存区块(在判断内存区域是否符合Windows98线程堆栈所在内存区域的特点的时候)
 20             //我们只关心内存区域中的最后4个内存块,好了不是最后最后4个内存块的内存块可以移出我们的判断结构数组dwProtectBlock了
 21             // We've seen 4 blocks in this region.
 22             // Shift the protection values down in the array.
 23         MoveMemory(&dwProtectBlock[0], &dwProtectBlock[1],
 24            sizeof(dwProtectBlock) - sizeof(DWORD));
 25
 26                 // Add the new protection value to the end of the array.
 27                 //空闲出一个位置供我们存放当前已知的最后一块内存块
 28                 //这个过程让我想起了一个故事叫黑瞎子掰棒子不过这头熊有点小猛他能留住4个到最后。
 29         dwProtectBlock[3= (mbi.State == MEM_RESERVE) ? 0 : mbi.Protect;
 30      }

 31          //将已知的区域中的最后一内存块更新到pVMQHelp、
 32          //内存块数量+1
 33      pVMQHelp->dwRgnBlocks++;             // Add another block to the region
 34          //这个区域的总大小=当前大小+已知的最后一内存块的大小
 35      pVMQHelp->RgnSize += mbi.RegionSize; // Add block's size to region size
 36
 37          // If block has PAGE_GUARD attribute, add 1 to this counter
 38          // 这个Windows2000中判断一个区域是不是线程堆栈所在区域的办法
 39          //只要区域中有一个内存块的页面保护属性为PAGE_GUARD那么这个区段就是线程堆栈所在的区块了
 40      if ((mbi.Protect & PAGE_GUARD) == PAGE_GUARD)
 41         pVMQHelp->dwRgnGuardBlks++;
 42
 43          // Take a best guess as to the type of physical storage committed to the
 44          // block. This is a guess because some blocks can convert from MEM_IMAGE
 45          // to MEM_PRIVATE or from MEM_MAPPED to MEM_PRIVATE; MEM_PRIVATE can
 46          // always be overridden by MEM_IMAGE or MEM_MAPPED.
 47          //一些内存块的保护属性能从MEM_IMAGE变为MEM_PRIVATE或从MEM_MAPPED变为MEM_PRIVATE。
 48          //MEM_PRIVATE能被MEM_IMAGE or MEM_MAPPED重写
 49          //一个对当前内存区域类型的一个猜测首先要明确的是这是在一个循环内部发生的
 50          //也就是说dwRgnStorage肯能不只一次的被置为MEM_PRIVATE但是不要紧我们会坚持下去
 51          //用整个区域中所有内存块的页面保护属性来测试直到我们把一个页面类型不为MEM_PRIVATE
 52          //的内存块的类型赋给区域内存页面类型为止
 53      if (pVMQHelp->dwRgnStorage == MEM_PRIVATE)
 54         pVMQHelp->dwRgnStorage = mbi.Type;
 55          //获取下一个内存块的地址(这个块可能属于现在的区域也有可能是下一个相邻区域的)
 56          // Get the address of the next block.
 57      pvAddressBlk = (PVOID) ((PBYTE) pvAddressBlk + mbi.RegionSize);
 58   }
 59
 60   // After examining the region, check to see whether it is a thread stack
 61   // Windows 2000: Assume stack if region has at least 1 PAGE_GUARD block
 62   // Windows 9x:   Assume stack if region has at least 4 blocks with
 63   //               3rd block from end: reserved
 64   //               2nd block from end: PAGE_NOACCESS
 65   //               1st block from end: PAGE_READWRITE
 66   //               block at end: another reserved block.
 67   //现在的情况清晰了只要有一个内存块中页面的保护属性为Guard那么这个内存区域就是线程堆栈所在的区域了
 68   //或者在Windows98 系统中需要判断该内存区域中最后4个内存块的页面保护类型。
 69   pVMQHelp->fRgnIsAStack =
 70      (pVMQHelp->dwRgnGuardBlks > 0)         ||
 71      ((pVMQHelp->dwRgnBlocks >= 4)          &&
 72       (dwProtectBlock[0== 0)              &&
 73       (dwProtectBlock[1== PAGE_NOACCESS)  &&
 74       (dwProtectBlock[2== PAGE_READWRITE) &&
 75       (dwProtectBlock[3== 0));
 76
 77   return(TRUE);
 78}
 79
 80
 81///////////////////////////////////////////////////////////////////////////////
 82
 83
 84BOOL VMQuery(HANDLE hProcess, LPCVOID pvAddress, PVMQUERY pVMQ) {
 85
 86   if (gs_dwAllocGran == 0{
 87      // Set allocation granularity if this is the first call
 88      SYSTEM_INFO sinf;
 89      GetSystemInfo(&sinf);
 90      gs_dwAllocGran = sinf.dwAllocationGranularity;
 91   }

 92
 93   ZeroMemory(pVMQ, sizeof(*pVMQ));
 94
 95   // Get the MEMORY_BASIC_INFORMATION for the passed address.
 96   MEMORY_BASIC_INFORMATION mbi;
 97   BOOL fOk = (VirtualQueryEx(hProcess, pvAddress, &mbi, sizeof(mbi))
 98      == sizeof(mbi));
 99
100   if (!fOk)
101      return(fOk);   // Bad memory address, return failure
102
103   // The MEMORY_BASIC_INFORMATION structure contains valid information.
104   // Time to start setting the members of our own VMQUERY structure.
105
106   // First, fill in the block members. We'll fill the region members later.
107   switch (mbi.State) {
108      case MEM_FREE:       // Free block (not reserved)
109         pVMQ->pvBlkBaseAddress = NULL;
110         pVMQ->BlkSize = 0;
111         pVMQ->dwBlkProtection = 0;
112         pVMQ->dwBlkStorage = MEM_FREE;
113         break;
114
115      case MEM_RESERVE:    // Reserved block without committed storage in it.
116         pVMQ->pvBlkBaseAddress = mbi.BaseAddress;
117         pVMQ->BlkSize = mbi.RegionSize;
118
119         // For an uncommitted block, mbi.Protect is invalid. So we will
120         // show that the reserved block inherits the protection attribute
121         // of the region in which it is contained.
122         pVMQ->dwBlkProtection = mbi.AllocationProtect;  
123         pVMQ->dwBlkStorage = MEM_RESERVE;
124         break;
125
126      case MEM_COMMIT:     // Reserved block with committed storage in it.
127         pVMQ->pvBlkBaseAddress = mbi.BaseAddress;
128         pVMQ->BlkSize = mbi.RegionSize;
129         pVMQ->dwBlkProtection = mbi.Protect;   
130         pVMQ->dwBlkStorage = mbi.Type;
131         break;
132
133      default:
134          DebugBreak();
135          break;
136   }

137
138   // Now fill in the region data members.
139   VMQUERY_HELP VMQHelp;
140   switch (mbi.State) {
141      case MEM_FREE:       // Free block (not reserved)
142         pVMQ->pvRgnBaseAddress = mbi.BaseAddress;
143         pVMQ->dwRgnProtection  = mbi.AllocationProtect;
144         pVMQ->RgnSize          = mbi.RegionSize;
145         pVMQ->dwRgnStorage     = MEM_FREE;
146         pVMQ->dwRgnBlocks      = 0;
147         pVMQ->dwRgnGuardBlks   = 0;
148         pVMQ->fRgnIsAStack     = FALSE;
149         break;
150
151      case MEM_RESERVE:    // Reserved block without committed storage in it.
152         pVMQ->pvRgnBaseAddress = mbi.AllocationBase;
153         pVMQ->dwRgnProtection  = mbi.AllocationProtect;
154
155         // Iterate through all blocks to get complete region information.         
156         VMQueryHelp(hProcess, pvAddress, &VMQHelp);
157
158         pVMQ->RgnSize          = VMQHelp.RgnSize;
159         pVMQ->dwRgnStorage     = VMQHelp.dwRgnStorage;
160         pVMQ->dwRgnBlocks      = VMQHelp.dwRgnBlocks;
161         pVMQ->dwRgnGuardBlks   = VMQHelp.dwRgnGuardBlks;
162         pVMQ->fRgnIsAStack     = VMQHelp.fRgnIsAStack;
163         break;
164
165      case MEM_COMMIT:     // Reserved block with committed storage in it.
166         pVMQ->pvRgnBaseAddress = mbi.AllocationBase;
167         pVMQ->dwRgnProtection  = mbi.AllocationProtect;
168
169         // Iterate through all blocks to get complete region information.         
170         VMQueryHelp(hProcess, pvAddress, &VMQHelp);
171
172         pVMQ->RgnSize          = VMQHelp.RgnSize;
173         pVMQ->dwRgnStorage     = VMQHelp.dwRgnStorage;
174         pVMQ->dwRgnBlocks      = VMQHelp.dwRgnBlocks;
175         pVMQ->dwRgnGuardBlks   = VMQHelp.dwRgnGuardBlks;
176         pVMQ->fRgnIsAStack     = VMQHelp.fRgnIsAStack;
177         break;
178
179      default:
180          DebugBreak();
181          break;
182   }

183
184   return(fOk);
185}

186
187
188//////////////////////////////// End of File //////////////////////////////////
 posted on 2009-11-12 16:18  wParma  阅读(1371)  评论(0编辑  收藏  举报