프로세스를 다루는 API에 관해서 알아보자[펌]

안녕하십니까. (응?)

 

오늘은 오랜만에 제가 좋아하는 간단한 주제로 넘어가 볼까 합니다. (어째 말이 이상하다??)

바로 프로세스에 관한 겁니다.

"프로세스" 는 여러분이 작업 관리자에서 보셨듯이, [프로세스] 탭에서 많이 보셨으리라 생각됩니다.

이것은 영어로 "수행하다", "진행" ....

같은 뜻을 담고 있는데요, 그와 마찬가지로 생각하시면 됩니다.

(일을 수행하는 하나의 객체로 보면 되는건가......설명이 좀 애매하군)

 

자, 그렇다면 이제 프로세스에 관한 간단한 API를 알아 보도록 합시다.

(앞에서 프로세스에 대한 정의도 제대로 하지 않았으면서, 뭘 설명하려는거냐!!!!)

 

이 글에서 설명하는 API는 이렇습니다.

OpenProcess

CreateProcess

TerminateProcess

ExitProcess

GetPriorityClass

SetPriorityClass

GetCurrentProcess

GetCurrentProcessId

SetProcessAffinityMask

GetExitCodeProcess

Process32First

Process32Next

NtSuspendProcess [Windows XP 이상에서만 동작]

NtResumeProcess [Windows XP 이상에서만 동작]

NtOpenProcess [Windows 2000/NT 이상에서만 동작, NT는 예외]

NtTerminateProcess [Windows 2000/NT 이상에서만 동작, NT는 예외]

NtQueryInformationProcess [Windows 2000/NT 이상에서만 동작, NT는 예외]

NtSetInformationProcess [Windows 2000/NT 이상에서만 동작, NT는 예외]

NtCreateProcess [Windows 2000/NT 이상에서만 동작, NT는 예외]

NtCreateProcessEx [Windows XP 이상에서만 동작]

 

OpenProcess : 프로세스의 핸들을 얻는다. 프로세스를 다룰 때에는 유저모드에서는 대부분 핸들로 다루고,

커널모드에서는 Process Object(Executive Process:EPROCESS)로 다루나, 여전히 핸들도 같이 쓰인다.

WINBASEAPI

HANDLE

WINAPI

OpenProcess(

      IN DWORD dwDesiredAccess,

      IN BOOL bInheritHandle,

      IN DWORD dwProcessId);

dwDesiredAccess : 프로세스의 핸들을 얻을 때의 설정할 권한.

간단하게 몇개만 설명하자면,

PROCESS_CREATE_THREAD : 프로세스에 쓰레드 생성시에

PROCESS_VM_READ : 프로세스의 메모리를 읽을 시에

PROCESS_VM_WRITE : 프로세스의 메모리를 쓸 시에

PROCESS_TERMINATE : 프로세스를 종료할 시에

PROCESS_QUERY_INFORMATION : 프로세스의 정보를 얻고자 할 시에

PROCESS_ALL_ACCESS (최강) : 이 플래그를 주어서 얻어진 핸들에는 모든 권한이 주어진다.

bInheritHandle : 핸들을 상속할지의 여부. 대부분 FALSE.

dwProcessId : 프로세스를 열 때 필요한 프로세스 아이디. PID라고도 불리며, 프로세스 식별자라고도 한다.

성공시 NULL이 아닌 값을, 실패시 NULL을 반환한다.

이 경우, GetLastError()를 이용해서 오류 코드를 얻을 수 있다.

 

CreateProcess : 프로세스를 생성한다.

WINBASEAPI

BOOL

WINAPI

CreateProcess(

       IN LPCTSTR lpApplicationName,

       IN LPTSTR lpCommandLine,

       IN LPSECURITY_ATTRIBUTES lpProcessAttributes, 
       IN LPSECURITY_ATTRIBUTES lpThreadAttributes,

       IN BOOL bInheritHandles,

       IN DWORD dwCreationFlags,

       IN LPVOID lpEnvironment, 
       IN LPCTSTR lpCurrentDirectory,

       IN LPSTARTUPINFO lpStartupInfo,

       IN LPPROCESS_INFORMATION lpProcessInformation);
lpApplicationName : 실행 파일의 경로.(Full Path가 아니어도 된다.)

lpCommandLine : 프로세스 실행시 넣어줄 추가적 명령줄.

lpProcessAttributes : 프로세스 생성시의 보안 속성(이라고 보여진다). 대부분 NULL.

lpThreadAttributes : 프로세스의 메인 쓰레드 생성시의 보안 속성(이라고 보여진다). 대부분 NULL.

bInheritHandles : 핸들 상속 여부. 대부분 FALSE.

dwCreationFlags : 프로세스 생성시의 추가 플래그.

CREATE_SUSPENDED : 프로세스 생성시에 프로세스를 일시정지 상태로 생성한다.

XXX_PRIORITY_CLASS : 프로세스의 우선 순위. (XXX에는 NORMAL, HIGH 등이 올 수 있다.)

이 외에도 여러가지가 있다.

lpEnvironment : 환경 설정(혹은 변수???)로 여겨진다. 필자는 이것을 NULL이 아닌 값을 주어본 적이 없다.

lpCurrentDirectory : 생성되는 프로세스가 인식할 Current Directory.

lpStartupInfo : 프로세스의 시작 정보. (절대로 NULL이 들어가서는 안된다.)

lpProcessInformation : 프로세스와 메인 쓰레드의 정보. (절대로 NULL이 들어가서는 안된다.)

성공시 1, 실패시 0을 반환한다.

 

TerminateProcess : 프로세스를 종료한다.

WINBASEAPI

BOOL

WINAPI

TerminateProcess(

      IN HANDLE hProcess,

      IN DWORD dwExitCode);

hProcess : 프로세스의 핸들.

dwExitCode : 프로세스 종료시에 Set할 종료 코드.

성공시 1, 실패시 0을 반환한다.

※ 주의 : 이 함수는 비동기 함수이다. 때문에 1을 반환한다 할지라도 완전히 종료가 되지 않는 경우가 있다.

 

ExitProcess : 자기 자신을 종료한다.

WINBASEAPI

VOID

WINAPI

ExitProcess(

      IN DWORD ExitCode);

ExitCode : 자기자신 종료시에 Set할 종료 코드.

반환값 없음

 

GetPriorityClass : 프로세스의 우선순위를 얻어온다.

WINBASEAPI

DWORD

WINAPI

GetPriorityClass(

      IN HANDLE hProcess);

hProcess : 프로세스의 핸들.

프로세스의 우선순위값을 반환한다.

 

SetPriorityClass : 프로세스의 우선순위를 조정한다.

WINBASEAPI

BOOL

WINAPI

SetPriorityClass(

      IN HANDLE hProcess,

      IN DWORD dwProcessPriorityClass);

hProcess : 프로세스의 핸들.

dwProcessPrioriyClass : 변경할 프로세스의 우선 순위값.

XXX_PRIORITY_CLASS 가 있다. (XXX에는 NORMAL, HIGH 등이 있다.)

성공시 1, 실패시 0을 반환한다.

 

GetCurrentProcess : 자기자신의 프로세스 핸들을 얻는다.

WINBASEAPI

HANDLE

WINAPI

GetCurrentProcess(

      VOID);

필요인자 없음.

자기자신의 프로세스 핸들값을 반환한다. (특히나, Windows 2000/NT/XP/2003/Vista 등은 항상 0xFFFFFFFF를 반환한다.)

 

GetCurrentProcessId : 자기자신의 프로세스 아이디를 얻는다.

WINBASEAPI

DWORD

WINAPI

GetCurrentProcessId(

      VOID);

필요인자 없음.

자기자신의 프로세스 아이디를 반환한다.

 

SetProcessAffinityMask : 프로세스의 동작 프로세서(Processor)를 지정한다.

WINBASEAPI

BOOL

WINAPI

SetProcessAffinityMask(

       IN HANDLE hProcess,

       IN DWORD dwProcessAffinityMask);

hProcess : 프로세스의 핸들.

dwProcessAffinityMask : 프로세서의 번호. (1부터 시작한다.)

성공시 1, 실패시 0을 반환한다.

 

GetExitCodeProcess : 프로세스의 상태코드를 얻어온다.

WINBASEAPI

BOOL

WINAPI

GetExitCodeProcess(

      IN HANDLE hProcess,

      OUT PDWORD lpdwExitCode);

hProcess : 프로세스의 핸들.

lpdwExitCode : DWORD의 포인터형. 여기로 프로세스의 상태코드가 넘어온다.

성공시 1, 실패시 0을 반환한다.

 

Process32First : 맨 처음 프로세스 정보를 얻는다.

WINBASEAPI

BOOl

WINAPI

Process32First(

     IN HANDLE hSnapshot,

     OUT LPPROCESSENTRY32 lpProcessEntry32);

hSnapshot : CreateToolhelp32Snapshot() 으로 얻어진 올바른 스냅샷 핸들.

lpProcessEntry32 : PROCESSENTRY32 구조체의 포인터형. 여기로 프로세스의 정보가 넘어온다.

성공시 1, 실패시 0을 반환한다.

 

Process32Next : 그 다음의 프로세스 정보를 얻는다.

WINBASEAPI

BOOl

WINAPI

Process32Next(

     IN HANDLE hSnapshot,

     OUT LPPROCESSENTRY32 lpProcessEntry32);

hSnapshot : CreateToolhelp32Snapshot() 으로 얻어진 올바른 스냅샷 핸들.

lpProcessEntry32 : PROCESSENTRY32 구조체의 포인터형. 여기로 프로세스의 정보가 넘어온다.

성공시 1, 실패시 0을 반환한다.

 

NT_SUCCESS 매크로. (이것은 보너스.)

리턴값이 NTSTATUS 형인 경우, 이 리턴값이 성공적인지를 확인하는 매크로가 있는데, 이것을 NT_SUCCESS() 라고 한다.

#define NT_SUCCESS(_Status)        _Status<=0 ? TRUE : FALSE

 

NtSuspendProcess : 프로세스를 일시정지시킨다.

NTSYSAPI

NTSTATUS

NTAPI

NtSuspendProcess(

      IN HANDLE ProcessHandle);

ProcessHandle : 프로세스의 핸들.

주의할 점 : 성공했다 할지라도, SuspendCount가 0을 넘지 않으면 프로세스는 일시정지되지 않는다.

성공시, 0 이하의 값을 반환한다.

 

NtResumeProcess : 일시정지된 프로세스를 재개시킨다.

NTSYSAPI

NTSTATUS

NTAPI

NtResumeProcess(

     IN HANDLE ProcessHandle);

ProcessHandle : 프로세스의 핸들.

성공시, 0 이하의 값을 반환한다.

 

NtOpenProcess : 프로세스를 연다. OpenProcess()가 내부적으로 호출하는 함수.

NTSYSAPI

NTSTATUS

NTAPI

NtOpenProcess(

     OUT PHANDLE ProcessHandle,

     IN ACCESS_MASK DesiredAccess,

     IN POBJECT_ATTRIBUTES ObjectAttributes,

     IN PCLIENT_ID ClientId OPTIONAL);

ProcessHandle : 프로세스의 핸들.

DesiredAccess : 프로세스의 핸들을 얻을 때의 설정할 권한.

간단하게 몇개만 설명하자면,

PROCESS_CREATE_THREAD : 프로세스에 쓰레드 생성시에

PROCESS_VM_READ : 프로세스의 메모리를 읽을 시에

PROCESS_VM_WRITE : 프로세스의 메모리를 쓸 시에

PROCESS_TERMINATE : 프로세스를 종료할 시에

PROCESS_QUERY_INFORMATION : 프로세스의 정보를 얻고자 할 시에

PROCESS_ALL_ACCESS (최강) : 이 플래그를 주어서 얻어진 핸들에는 모든 권한이 주어진다.

ObjectAttributes : 프로세스를 얻을 때의 핸들에 부여할 추가적 속성.

ClientId : 프로세스 아이디가 이 구조체에 들어간다.

성공시, 0 이하의 값을 반환한다.

 

NtTerminateProcess : 프로세스를 종료한다. TerminateProcess()가 내부적으로 호출하는 함수.

NTSYSAPI

NTSTATUS

NTAPI

NtTerminateProcess(

     IN HANDLE hProcess,

     IN NTSTATUS ExitStatus);

hProcess : 프로세스의 핸들.

ExitStatus : 프로세스 종료시에 Set할 종료 코드.

이 함수 역시 비동기함수이다.

성공시, 0 이하의 값을 반환한다.

 

NtQueryInformationProcess : 프로세스의 정보를 가져온다.

GetExitCodeProcess(), GetPriorityClass() 등이 내부적으로 호출하는 함수.

NTSYSAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
      IN HANDLE ProcessHandle,
      IN PROCESS_INFORMATION_CLASS ProcessInformationClass,
      OUT PVOID ProcessInformationBuffer,
      IN ULONG ProcessInformationLength,
      OUT PULONG ReturnLength OPTIONAL);

ProcessHandle : 프로세스의 핸들.

ProcessInformationClass : 이 값에 따라서 얻을 수 있는 정보가 달라진다.

typedef enum _PROCESS_INFORMATION_CLASS {

      ProcessBasicInformation,

      ........

} PROCESS_INFORMATION_CLASS, *PPROCESS_INFORMATION_CLASS;

이런 꼴이나, 설명하기에는 너무 길기 때문에 생략하겠다.

ProcessInformationBuffer : ProcessInformationClass로 지정한 값에 따라서 구조체가 달라진다.

ProcessInformationClass이 ProcessBasicInformation인 경우는 PROCESS_BASIC_INFORMATION 의 포인터형이다.

다 설명하자면 너무 길으므로 생략하겠다.

ProcessInformationLength : ProcessInformationClass로 지정한 값에 따라서 크기가 달라진다.

ProcessInformationClass이 ProcessBasicInformation인 경우는 PROCESS_BASIC_INFORMATION 구조체의 크기이다.

ReturnLength : 실패시, 길이가 맞지 않거나 한 경우는 여기로 필요한 길이가 넘어온다.

성공시, 0 이하의 값을 반환한다.

 

NtSetInformationProcess : 프로세스의 정보를 변경한다. SetPriorityClass() 등이 내부적으로 호출하는 함수.

NTSYSAPI
NTSTATUS
NTAPI

NtSetInformationProcess(

      IN HANDLE ProcessHandle,
      IN PROCESS_INFORMATION_CLASS ProcessInformationClass,
      IN PVOID ProcessInformationBuffer,
      IN ULONG ProcessInformationLength);

ProcessHandle : 프로세스의 핸들.

ProcessInformationClass : 이 값에 따라서 얻을 수 있는 정보가 달라진다.

typedef enum _PROCESS_INFORMATION_CLASS {

      ProcessBasicInformation,

      ........

} PROCESS_INFORMATION_CLASS, *PPROCESS_INFORMATION_CLASS;

이런 꼴이나, 설명하기에는 너무 길기 때문에 생략하겠다.

ProcessInformationBuffer : ProcessInformationClass로 지정한 값에 따라서 구조체가 달라진다.

ProcessInformationClass이 ProcessBasicInformation인 경우는 PROCESS_BASIC_INFORMATION 의 포인터형이다.

다 설명하자면 너무 길으므로 생략하겠다.

ProcessInformationLength : ProcessInformationClass로 지정한 값에 따라서 크기가 달라진다.

ProcessInformationClass이 ProcessBasicInformation인 경우는 PROCESS_BASIC_INFORMATION 구조체의 크기이다.

성공시, 0 이하의 값을 반환한다.

 

NtCreateProcess : 프로세스 객체를 생성한다. CreateProcess()가 내부적으로 호출하는 함수.

NTSYSAPI
NTSTATUS
NTAPI
NtCreateProcess(
      OUT PHANDLE ProcessHandle,
      IN ACCESS_MASK DesiredAccess,
      IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
      IN HANDLE ParentProcess, 
      IN BOOLEAN InheritObjectTable,
      IN HANDLE SectionHandle OPTIONAL,
      IN HANDLE DebugPort OPTIONAL,
      IN HANDLE ExceptionPort OPTIONAL);

ProcessHandle : 생성된 프로세스 객체의 프로세스 핸들.

DesiredAccess : 프로세스 핸들에 줄 권한.

ObjectAttributes : 프로세스 핸들에 줄 추가적 속성. (핸들 권한 상속여부 등을 결정할 수 있다.)

ParentProcess : 부모 프로세스의 핸들. 필자의 생각으로는 대부분 GetCurrentProcess() 또는 0xFFFFFFFF가 들어갈듯 하다.

InheritObjectTable : ???

SectionHandle : 프로세스 생성시 열었던 이미지 파일의 섹션 핸들로 보여진다.

DebugPort : 디버거가 프로세스를 생성할 때에는 이 값이 NULL이 아니다.

ExceptionPort : 잘 모르겠다. 아마도 NtXxxPort()와 연관이 있을듯.

성공시, 0 이하의 값을 반환한다.

 

NtCreateProcessEx : 프로세스 객체를 생성한다. 아마도 NtCreateProcess()가 내부적으로 호출하는 함수.

NTSYSAPI
NTSTATUS
NTAPI
NtCreateProcessEx(
      OUT PHANDLE ProcessHandle,
      IN ACCESS_MASK DesiredAccess,
      IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
      IN HANDLE ParentProcess, 
      IN BOOLEAN InheritObjectTable,
      IN HANDLE SectionHandle OPTIONAL,
      IN HANDLE DebugPort OPTIONAL,
      IN HANDLE ExceptionPort OPTIONAL,

      IN HANDLE UnknownArgument);

ProcessHandle : 생성된 프로세스 객체의 프로세스 핸들.

DesiredAccess : 프로세스 핸들에 줄 권한.

ObjectAttributes : 프로세스 핸들에 줄 추가적 속성. (핸들 권한 상속여부 등을 결정할 수 있다.)

ParentProcess : 부모 프로세스의 핸들. 필자의 생각으로는 대부분 GetCurrentProcess() 또는 0xFFFFFFFF가 들어갈듯 하다.

InheritObjectTable : ???

SectionHandle : 프로세스 생성시 열었던 이미지 파일의 섹션 핸들로 보여진다.

DebugPort : 디버거가 프로세스를 생성할 때에는 이 값이 NULL이 아니다.

ExceptionPort : 잘 모르겠다. 아마도 NtXxxPort()와 연관이 있을듯.

UnknownArgument : ???

성공시, 0 이하의 값을 반환한다.

 

주의점 : NtCreateProcess/NtCreateProcessEx는 완전한 프로세스를 생성시키는 것이 아니라,

프로세스 객체만을 생성시키는 일을 한다. 이 함수를 통해서 생성된 프로세스는 CSRSS.EXE에 등록되어야 하며,

이것은 아직 문서화되지 않았다.

by 이지 | 2008/04/01 13:42 | 02 윈도우 커널 | 트랙백 | 덧글(1)

트랙백 주소 : http://egnala.egloos.com/tb/202243
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by wz1054 at 2008/07/04 23:36
이런......제가 NT_SUCCESS() 매크로를 잘못 알고 있었군요.
#define NT_SUCCESS(_Status) (_Status>=0)
......이 되어야 합니다.
STATUS_UNSUCCESSFUL이 0x00000001로 정의된 줄로 알고 했는데, 알고 보니
0xC0000001이더군요. (이런 안습이 ㅡ,.ㅡ)
다른 NtXxx함수들의 리턴값(반환값) 에 대한 설명도 수정되어야 합니다.
"성공시 0 이상의 값을 반환한다." 라고 말이죠.
죄송합니다. (__)

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶