|
감사합니다!! 덕분에 좋은걸 많이 알아가네요
빌더(TWx) 님이 쓰신 글 :
: 얼덜 님이 쓰신 글 :
: : 안녕하세요 프로세스를 서스펜드 하다가
: :
: : 의문점이 생겨서 질문드립니다.
: :
: : 예전에는 프로세스랑 쓰레드 둘다 스냅샷을 찍어서 pid 동일한거 찾은다음
: :
: : 쓰레드를 SuspendThread 시켰는데 이 방식이 불안정(?) 하다는 말을 들어서
: :
: : NtSuspendProcess 함수를 써서 서스펜드 시키게 됬습니다
: :
: : 문제는 기존 함수였던 SuspendThread / ResumeThread 함수들은 리턴값으로 서스펜드 카운트를 반환해서
: :
: : 몇번 서스펜드 명령이 있었는지를 보고 그만큼 Resume 을줬었는데
: :
: : NtSuspendProcess 함수는 그런걸 반환안하더라구요 그냥 반환값 무조건 0;
: :
: : 그래서인지 서스펜드를 여러번 시켜서 서스펜드 카운트는 쌓였는데 Resume 은 한번만 줘서
: :
: : 프로그램이 정상작동을 하지 않는등의 문제가 생깁니다.
: :
: : NtSuspendProcess 함수로 서스펜드 카운트를 받는 방법이 있을까요?
: :
: : 그리고 NtSuspendProcess 랑 SuspendThread 랑 무슨 차이가 있나요?
: :
:
:
: 답변:
:
:
:
: NtSuspendProcess()는 리턴값으로 NT_STATUS 를 사용하므로... 성공하면 0 값을 리턴하게 됩니다.
: 커널 내부 자료구조에서 카운트를 유지하고 있어서 NtSuspendProcess()를 여러번 호출했다면 프로세스를 Resume 시키기
: 위해선 NtSuspendProcess()를 호출한 횟수 만큼 NtResumeProcess()를 호출해줘야 합니다.
:
: 그에 반해서...
: NtResumeProcess()는 여러번 호출해도 상관 없습니다. NtSuspendProcess()를 호출한 수 만큼 NtResumeProcess()를
: 호출하면 프로세스가 Resume 상태가 되고, 그 후에 또 다시 NtResumeProcess()를 호출해도 카운트 되는 것은 없다는 거죠.
:
: 카운트 값은 커널 내부 자료구조에서 갖고 있으므로...
: 위 두개의 API를 이용해서 처리할 경우.. 타겟 프로세스 상태가 Suspend상태인지 아닌지를 알아내서 Suspend 가 풀릴 때 까지
: NtResumeProcess()를 계속 호출하는 구조로 로직을 구성해야 합니다.
:
: 타겟 프로세스의 Resume/Suspended 상태는 NtQuerySystemInformation()를 이용해서 알아 낼 수 있습니다.
: 어떤 프로세스의 SYSTEM_THREAD 라는 자료구조의 WaitReason 필드 값이 '5'이면 Suspended 상태 입니다.
:
:
: SuspendThread()를 이용하는 것 보다 NtSuspendProcess()을 이용하는 게 유리한 것은...
:
: 하나의 프로세스는 여러개의 쓰레드를 가질 수 있고, 각기의 쓰레드를 개별적으로 Resume/Suspended 처리를 하게 되면
: 쓰레드 간의 종속관계로 인해서 문제가 발생할 수도 있기 때문 입니다. 잘못하면 데드락 상황이 발생할 수도 있고요.
:
:
: NtQuerySystemInformation(), NtSuspendProcess(), NtResumeProcess() 등의 함수는 Undocumented API 이지만...
: XP 이후부터 현재의 Windows 10 에 이르기 까지 계속 사용되고 있습니다. 커널 변경에 따라서 함수의 내부 Implementation이
: 바뀔 수는 있어도... Win32 레이어가 존재하는 한... 이 API들이 사라질 가능성은 ... 전혀 없다고 봐도 무방 하지요.
:
: 시스템 유틸리티 프로그램을 만들 때... 상당히 자주 사용되는 API이기도 합니다.(MS에서도 자신들이 만든 프로그램에서 자주
: 사용하기도 합니다.) Undocumented API라고 해서 꺼릴 필요는 없다는 겁니다.
:
:
:
:
|