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![]()
84
BOOL 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 //////////////////////////////////
// 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 block6
//哈今天状态不错7
//Windows98线程堆栈所在内存区域的的特点是最后4个内存块依次为8
//reserved、PAGE_NOACCESS、PAGE_READWRITE、reserved9
//dwProtectBlock这个结构的定义就是为了存储最后4个块的页面保护信息10
//用来判断正在访问的内存区域是不是符合Windows98下的线程堆栈区域的特点11
//分两步走看代码吧:12
//这个就是内存区域中的内存块的个数小于4那么dwProtectBlock分配的空间足以存储和进行判断直接存储就可以了13
if (pVMQHelp->dwRgnBlocks < 4) {14
// 0th through 3rd block, remember the block's protection15
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
//内存块数量+133
pVMQHelp->dwRgnBlocks++; // Add another block to the region34
//这个区域的总大小=当前大小+已知的最后一内存块的大小35
pVMQHelp->RgnSize += mbi.RegionSize; // Add block's size to region size36

37
// If block has PAGE_GUARD attribute, add 1 to this counter38
// 这个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 the44
// block. This is a guess because some blocks can convert from MEM_IMAGE45
// to MEM_PRIVATE or from MEM_MAPPED to MEM_PRIVATE; MEM_PRIVATE can46
// 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_PRIVATE52
//的内存块的类型赋给区域内存页面类型为止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 stack61
// Windows 2000: Assume stack if region has at least 1 PAGE_GUARD block62
// Windows 9x: Assume stack if region has at least 4 blocks with63
// 3rd block from end: reserved64
// 2nd block from end: PAGE_NOACCESS65
// 1st block from end: PAGE_READWRITE66
// 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

84
BOOL VMQuery(HANDLE hProcess, LPCVOID pvAddress, PVMQUERY pVMQ) {85

86
if (gs_dwAllocGran == 0) {87
// Set allocation granularity if this is the first call88
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 failure102

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 will120
// show that the reserved block inherits the protection attribute121
// 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
浙公网安备 33010602011771号