Programming/System Programming

NtQueryInformationProcess가 프로세스 정보 가져오는 법

Winduck 2019. 4. 4. 20:12
반응형

오랜만에 글을 올려봅니다. 개인적인 프로젝트때문에 회사일때문에 못했네요.

 

오늘 다룰 내용은 Nt/ZwQueryInformationProcess(이하 NtQueryInformationProcess)가 프로세스 정보를 어떻게 가져오는지에 대해 기재합니다.

어떻게 이글을 진행하게 됐냐면~ 나중에 다루겠지만 프로세스가 생성될 때  초기화를 거치지 않고 일반적으로 모듈주소들을 가져오려고 CreateToolhelp32Snapshot를 호출할 때 ERROR_PARTIAL_COPY이런 에러가 뜹니다.

MSDN확인해보니 64비트 TH32CS_SNAPMODULE32를 사용하고 32비트는 TH32CS_SNAPMODULE사용할 경우, 이 에러가 나온다고 하는데 이부분은 다른 글에서 자세히 다루겠습니다.

 

 

본론으로 가서 다른 방법인NtQueryInformationProcess를 사용했는데 이 API는 어떻게 프로세스 정보에 접근하는 지 궁금하여 본 문을 작성하게 되었습니다. 

먼저, NtQueryInformationProcess를 확인하겠습니다. (커널 / 유저 동일)

 

__kernel_entry NTSTATUS NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
)
;

※ 설명

- ProcessHandle : 대상 프로세스 핸들

- ProcessInformationClass : 받아올 프로세스 정보 타입

- ProcessInformation : 결과 값

- ProcessInformationLength : 입력 버퍼 값 크기

ReturnLength : 결과 값 크기

처음 목적인 모듈 베이스 주소를 가져 오기 위해서는 프로세스 정보타입(두번째 파라미터) ProcessBasicInformation를 전달해주어 가져옵니다.

(자세한 내용 : https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntqueryinformationprocess )

 

ntdll에서 ZwQueryInformationProcess 별다른 코드 없이 커널 영역으로 넘어가는 것을 볼 수 있었습니다. 

(Windows7 x86환경입니다.)

 

ntdll.ZwQueryInformationProcess

 그래서 커널영역으로 가서 내부 코드를 확인했습니다. 가장 먼저 확인하는 것은 호출된 곳이 커널모드인지 유저 모드인지를 확인하고 초기화(ProcessInformation, ProcessInformationLength등)를 진행합니다.

 

nt.NtQueryInformationProcess - 초기화 코드

 이후, 어떤 정보들을 유저영역에 전달할지 결정하는 ProcessInformationClass를 비교하고 ObReferenceObjectByHandle를 호출합니다. 이 서비스는 Handle, ObjectType에서 전달되는 타입에따라 오프젝트를 반환합니다. nt.NtQueryInformationProcess는 프로세스핸들과 PsProcessType를 전달하여 EPROCESS주소를 가져옵니다. 

NTSTATUS ObReferenceObjectByHandle(
HANDLE Handle,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID *Object,
POBJECT_HANDLE_INFORMATION HandleInformation
)
;

※ 설명

- Handle: 오브젝트 핸들

- DesiredAccess: 접근 타입

- ObjectType: 오브젝트 타입

- KPROCESSOR_MODE: 접근모드(유저모드인지 커널모드인지 )

- Object: 결과 값 

HandleInformation : 드라이버들은 NULL값

 

ObReferenceObjectByHandle 호출 코드

최종적으로 EPROCESS구조체를 참조하여 프로세스 정보인 ExitStatus, PEB, AffinityMask, BasePriority, UniqueProcessId, InheritedFromUniqueProcessId를 가져옵니다.

 

nt.NtQueryInformationProcess - 정보 획득 코드

이상으로 글을 마쳐봅니다. 갑작스럽게 궁금하여 진행했는데 나름 재미있게 했습니다.하하하

 

반응형