본문 바로가기

자료

루트킷 프로세스 숨기기(Hiding the Rootkit Process -3)

728x90

 

블로그 인기글

● 메이플스토리 신규 룬패치/자동해제 프로그램 [링크 이동]

● 메이플스토리 거짓말탐지기 알림 프로그램 [링크 이동]

C#에서 TensorFlow 사용하는법 [링크 이동]


  • CSRSS 프로세스 핸들 열거가있는 HPD

실행될 때 모든 Windows 프로세스에는 숨겨진 프로세스를 감지하는 데 사용할 수있는 프로세스, 스레드, 명명 된 개체, 파일, 포트, 레지스트리 등에 대한 많은 열린 핸들이 있습니다. 네이티브 API 기능을 사용할 수 있습니다. 핸들을 열거하는 효과적인 방법은 첫 번째 매개 변수와 함께 NtQuerySystemInformation을 SystemHandleInformation으로 사용하는 것입니다. 시스템에서 실행중인 모든 프로세스의 핸들을 나열합니다. 열거 된 각 핸들에 대해 소유 프로세스의 핸들, 핸들 유형 및 프로세스 ID와 같은 정보를 제공합니다. 따라서 모든 핸들을 열거 한 다음 관련 프로세스 ID를 사용하여 표준 API 함수를 통해 공개되지 않은 모든 가능한 숨겨진 프로세스를 감지 할 수 있습니다.

실행중인 모든 프로세스에 대한 핸들을 보유하는 CSRSS.EXE라는 흥미로운 시스템 프로세스가 있습니다. 따라서 모든 다른 핸들을 거치지 않고 CSRSS.EXE 프로세스의 프로세스 핸들을 스크롤 할 수 있습니다. 흥미롭게도이 방법은 사용자 영역 숨겨진 프로세스뿐만 아니라 CSRSS.EXE 프로세스 내에서 프로세스 핸들을 숨기지 않고 커널 영역 기술을 사용하는 일부 루트킷 프로세스도 감지 할 수 있습니다.

다음은이 방법을 보여줄 수있는 코드 조각입니다.

 PVOID bufHandleTable = malloc(dwSize);
 status = NtQuerySystemInformation
     (SystemHandleInformation, bufHandleTable, dwSize, 0);

 SYSTEM_HANDLE_INFORMATION *HandleInfo = 
     (SYSTEM_HANDLE_INFORMATION *) bufHandleTable;

// Process handles within CSRSS will not have handle 
// to following processes system idle process, system
// process, smss.exe, csrss.exe.

for(int i=0; i< HandleInfo->NumberOfHandles; i++)
{
  int pid = HandleInfo->Handles[i].UniqueProcessId;
	
  // For XP & 2K3 : HANDLE_TYPE_PROCESS = 0x5
  // For Vista & Longhorn : HANDLE_TYPE_PROCESS = 0x6
	
  if( HandleInfo->Handles[i].ObjectTypeIndex == 
                                  HANDLE_TYPE_PROCESS) 
  {
   //check if this process id is that of CSRSS.EXE process.

   if( IsCSRSSProcess(pid) ) 
   {
 	 hprocess = OpenProcess(PROCESS_DUP_HANDLE, false, pid);
	 
   if( hprocess )
   {
       if( DuplicateHandle(hprocess, 
	   (HANDLE)HandleInfo->Handles[i].Handle, 
	   GetCurrentProcess(), 
	   &tprocess, 
	   PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, 0))

	   {
		
		targetPid = GetProcessId(tprocess);

		 //check if this is hidden process

		 if( IsHiddenProcess(targetPid) )
		 {
		   printf("\n Found hidden process %d", targetPid);
		 }

	   }

	 }// End of if( hprocess )
		
   } // End of if( IsCSRSSProcess(pid) )

  } // End of if

 } // End of for-loop

CSRSS.EXE는 Windows 부팅시 시작되는 첫 번째 프로세스가 아니므로 시스템 유휴 프로세스 (pid = 0), 시스템 프로세스 (pid = 4), smss.exe 및 해당 프로세스 자체와 같이 이미 시작된 프로세스에 대한 핸들을 포함하지 않습니다.

Windows Vista 시스템에서는 여러 사용자가 로그인 한 경우 두 개 이상의 CSRSS.EXE 프로세스가 가능합니다. XP 시스템에서도 두 명 이상의 사용자가 '사용자 전환'메커니즘을 통해 작동하는 경우 동일한 상황이 발생합니다. 이 경우 열거 된 프로세스가 이러한 CSRSS 프로세스 ID 중 하나에 속하는지 확인해야합니다. 위의 IsCSRSSProcess () 함수는 발견 된 프로세스 ID를 실행중인 모든 CSRSS.EXE 프로세스 목록과 비교하여 정확히 동일합니다.

한 가지 더 방법은 대부분의 루트킷이이 기술을 알고 있기 때문에 프로세스 핸들 대신 CSRSS 프로세스 내의 모든 스레드 핸들을 열거하는 것입니다. CSRSS 프로세스에는 프로세스 핸들뿐만 아니라 실행중인 모든 프로세스에 대한 스레드 핸들도 있습니다. 스레드 핸들이 알려지면 GetProcessIdOfThread 함수를 사용하여 복제 한 후 해당 스레드와 관련된 프로세스 ID를 가져올 수 있습니다.

모든 루트킷 프로세스는 NtQuerySystemInformation 또는 NtOpenProcess 함수를 후킹하여이 기술을 무력화 할 수 있지만 "직접 NT 시스템 호출 구현을 사용하여 숨겨진 프로세스 감지"에 설명 된대로 이러한 기본 API 함수를 직접 구현하면 쉽게 우회 할 수 있습니다.


  • 숨겨진 프로세스를 감지하는 다른 방법

숨겨진 루트킷 프로세스를 감지하는 여러 가지 다른 사용자 영역 방법이 있지만 위에서 설명한 방법만큼 효과적이지 않습니다. 그러나 필요에 따라 특정 루트킷을 대상으로하는 경우가 많습니다.

이러한 방법 중 하나는 EnumWindows API 함수를 사용하여 시스템 내의 프로세스에 의해 생성 된 모든 열린 Windows를 열거 한 다음 GetWindowThreadProcessId 함수를 호출하여 해당 Window와 관련된 프로세스 ID를 가져 오는 것입니다.

다음은 동일한 작업을 수행하는 샘플 코드입니다.

 //Setup the callback function to enumerate through windows
 EnumWindows(EnumWindowsProc, NULL);

 //This is callback function to enumerate windows
 BOOL CALLBACK EnumWindowsProc(HWND hwnd, PARAM lParam)
 {
	DWORD procId;
	
	GetWindowThreadProcessId(hwnd, &procId);
	
	if( IsHiddenProcess(procId) )
	{
		printf("Found hidden process %d", procId);
	}

 }
 		

사용자 영역에서 숨겨진 프로세스를 감지하는 여러 다른 방법이 있으며 매일 새로운 방법이 발견되고 있습니다. 이러한 탐지 기술은 커널 영역에서 쉽게 무력화 될 수 있지만 사용자 영역 루트킷을 발견하기위한 간단하고 덜 위험한 메커니즘을 제공합니다.

728x90