VirtualQuery 함수에 특정 주소를 넘기면 해당 주소를 포함하는 첫 번째 페이지의 속성과 페이지 기본 주소를 가져오고
메모리 상태
MEM_COMMIT
MEM_RESERVE
MEM_FREE
MEM_PRIVATE
MEM_MAPPED
MEM_IMAGE
엑세스 권한
PAGE_READONLY
PAGE_READWRITE
PAGE_NOACCESS
PAGE_WRITECOPY
PAGE_EXECUTE
PAGE_EXECUTE_READ
PAGE_EXECUTE_READWRITE
PAGE_EXECUTE_WRITECOPY
PAGE_GUARD
PAGE_NOCACHE
위 2개 나열한 메모리 상태 및 엑세스 권한이 다를 때까지 메모리를 스캔 후 해당 사이즈를 바이트 단위로 가져온다.
사이즈는 VirtualQuery에 넘긴 주소를 포함하는 페이지 기본 주소부터 스캔 완료된 시점까지의 크기이다.
즉, 0x00000000~0x00005FFF 이 상태 및 권한이 같은 경우, 0x00002000 주소를 넘기면 0x00004000 사이즈를 리턴한다.
예시코드
before [0x00000020] 0x00401000 0x00008000
before [0x00000020] 0x00402000 0x00007000
before [0x00000020] 0x00403000 0x00006000
before [0x00000020] 0x00404000 0x00005000
before [0x00000020] 0x00405000 0x00004000
before [0x00000020] 0x00406000 0x00003000
before [0x00000020] 0x00407000 0x00002000
before [0x00000020] 0x00408000 0x00001000
after [0x00000080] 0x00401000 0x00008000
after [0x00000080] 0x00402000 0x00007000
after [0x00000080] 0x00403000 0x00006000
after [0x00000080] 0x00404000 0x00005000
after [0x00000080] 0x00405000 0x00004000
after [0x00000080] 0x00406000 0x00003000
after [0x00000080] 0x00407000 0x00002000
after [0x00000080] 0x00408000 0x00001000
와 같은 결과가 나온다.
또 다른 정보..
MEM_IMAGE 영역을 PAGE_EXECUTE_READWRITE 권한으로 바꾸면 PAGE_EXECUTE_WRITECOPY 권한이 되지만 해당 영역에 Write가 발생하게 되면 PAGE_EXEUCTE_READWRITE 권한으로 바뀌게 된다. copy-on-write 이므로 당연한 결과~
commit된 copy-on-write페이지에 write가 시도되면 프로세스에 해당 페이지가 private 영역에 복사본이 생기고 해당 영역은 PAGE_EXECUTE_READWRITE 가 된다. 그리고 변경 사항은 새로운 페이지에 기록된다.
그렇다고 VirtualQuery 했을 때 그 영역 타입이 MEM_PRIVATE이 되는건 아님.. MEM_IMAGE 그대로..
주저리주저리 썼지만.. 이놈의 VirtualQuery 때문에 애먹은게 짱나서 대충이라도 정리..
아래는 찾은 ReactOS 관련 소스코드.. 슥 보면 아하?!
빨간색으로 된 부분 보시면 어떠한 조건일 때 빠져오는지.. 영역 크기는 어떻게 구해지는지 알 수 있다.
/* Build the initial information block */ Address = PAGE_ALIGN(BaseAddress); MemoryInfo.BaseAddress = Address; MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT); MemoryInfo.AllocationProtect = MmProtectToValue[Vad->u.VadFlags.Protection]; MemoryInfo.Type = MEM_PRIVATE; /* Find the largest chunk of memory which has the same state and protection mask */ MemoryInfo.State = MiQueryAddressState(Address, Vad, TargetProcess, &MemoryInfo.Protect, &NextAddress); Address = NextAddress; while (((ULONG_PTR)Address >> PAGE_SHIFT) <= Vad->EndingVpn) { /* Keep going unless the state or protection mask changed */ NewState = MiQueryAddressState(Address,Vad,TargetProcess,&NewProtect,&NextAddress); if ((NewState != MemoryInfo.State) || (NewProtect != MemoryInfo.Protect)) break; Address = NextAddress; } /* Now that we know the last VA address, calculate the region size */ MemoryInfo.RegionSize = ((ULONG_PTR)Address - (ULONG_PTR)MemoryInfo.BaseAddress);
'My Study > Programming&Theory' 카테고리의 다른 글
MoveFileEx 의 MOVEFILE_DELAY_UNTIL_REBOOT (0) | 2014.05.20 |
---|---|
Visual Studio 컴파일 속도(최적화 옵션) (0) | 2014.03.23 |
Application Verifier 로 프로그램 체크 (2) | 2014.03.01 |
Dll Injection 으로 브라우저 URL 가져오기 (4) | 2014.01.26 |
Windows 메모리 유효성 체크 (4) | 2013.12.10 |