NtQueryInformationProcess가 프로세스 정보 가져오는 법
오랜만에 글을 올려봅니다. 개인적인 프로젝트때문에 회사일때문에 못했네요.
오늘 다룰 내용은 Nt/ZwQueryInformationProcess(이하 NtQueryInformationProcess)가 프로세스 정보를 어떻게 가져오는지에 대해 기재합니다.
어떻게 이글을 진행하게 됐냐면~ 나중에 다루겠지만 프로세스가 생성될 때 초기화를 거치지 않고 일반적으로 모듈주소들을 가져오려고 CreateToolhelp32Snapshot를 호출할 때 ERROR_PARTIAL_COPY이런 에러가 뜹니다.
MSDN확인해보니 64비트 TH32CS_SNAPMODULE32를 사용하고 32비트는 TH32CS_SNAPMODULE사용할 경우, 이 에러가 나온다고 하는데 이부분은 다른 글에서 자세히 다루겠습니다.
본론으로 가서 다른 방법인NtQueryInformationProcess를 사용했는데 이 API는 어떻게 프로세스 정보에 접근하는 지 궁금하여 본 문을 작성하게 되었습니다.
먼저, NtQueryInformationProcess를 확인하겠습니다. (커널 / 유저 동일)
__kernel_entry NTSTATUS NtQueryInformationProcess( ※ 설명 - ProcessHandle : 대상 프로세스 핸들 - ProcessInformationClass : 받아올 프로세스 정보 타입 - ProcessInformation : 결과 값 - ProcessInformationLength : 입력 버퍼 값 크기 - ReturnLength : 결과 값 크기 |
처음 목적인 모듈 베이스 주소를 가져 오기 위해서는 프로세스 정보타입(두번째 파라미터) ProcessBasicInformation를 전달해주어 가져옵니다.
(자세한 내용 : https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntqueryinformationprocess )
ntdll에서 ZwQueryInformationProcess 별다른 코드 없이 커널 영역으로 넘어가는 것을 볼 수 있었습니다.
(Windows7 x86환경입니다.)
그래서 커널영역으로 가서 내부 코드를 확인했습니다. 가장 먼저 확인하는 것은 호출된 곳이 커널모드인지 유저 모드인지를 확인하고 초기화(ProcessInformation, ProcessInformationLength등)를 진행합니다.
이후, 어떤 정보들을 유저영역에 전달할지 결정하는 ProcessInformationClass를 비교하고 ObReferenceObjectByHandle를 호출합니다. 이 서비스는 Handle, ObjectType에서 전달되는 타입에따라 오프젝트를 반환합니다. nt.NtQueryInformationProcess는 프로세스핸들과 PsProcessType를 전달하여 EPROCESS주소를 가져옵니다.
NTSTATUS ObReferenceObjectByHandle( ※ 설명 - Handle: 오브젝트 핸들 - DesiredAccess: 접근 타입 - ObjectType: 오브젝트 타입 - KPROCESSOR_MODE: 접근모드(유저모드인지 커널모드인지 ) - Object: 결과 값 - HandleInformation : 드라이버들은 NULL값 |
최종적으로 EPROCESS구조체를 참조하여 프로세스 정보인 ExitStatus, PEB, AffinityMask, BasePriority, UniqueProcessId, InheritedFromUniqueProcessId를 가져옵니다.
이상으로 글을 마쳐봅니다. 갑작스럽게 궁금하여 진행했는데 나름 재미있게 했습니다.하하하