2017-12-18 1 views
0

커널 모드 드라이버로 FindProcessidByName을 시도했습니다. ImageName.Buffer가 NULL로 바뀌면 ImageName.Buffer가 NULL로 바뀌는 경우가 있습니다. 프로세스 ID를 찾을 수 없습니다. ImageName.Buffer가 때때로 NULL이되는 이유를 알고 있습니까? 당신은 ZwQuerySystemInformation를 호출하지 않아야ZwQuerySystemInformation이 제대로 작동하지 않습니다.

typedef struct _SYSTEM_PROCESS_INFO_L 
    { 
     ULONG     NextEntryOffset; 
     ULONG     NumberOfThreads; 
     LARGE_INTEGER   Reserved[3]; 
     LARGE_INTEGER   CreateTime; 
     LARGE_INTEGER   UserTime; 
     LARGE_INTEGER   KernelTime; 
     UNICODE_STRING   ImageName; 
     ULONG     BasePriority; 
     HANDLE     ProcessId; 
     HANDLE     InheritedFromProcessId; 
    }_SYSTEM_PROCESS_INFO_L, *P_SYSTEM_PROCESS_INFO_L; 

HANDLE LSFindProcess(LPSTR name) 
{ 
    NTSTATUS durum; 
    ULONG retsize; 
    HANDLE hProcid = -1; 
    P_SYSTEM_PROCESS_INFO_L pi; 
    durum = ZwQuerySystemInformation(SystemProcessInformation, NULL, NULL, &retsize); // request how much memory size we need. 
    if (!NT_SUCCESS(durum) && durum !=STATUS_INFO_LENGTH_MISMATCH) 
    { 
     DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : ZwQuerySystemInformation Failed 1 durum : %p \n",durum); 
     return -1; 
    } 
    PVOID memPtr; 
    memPtr = ExAllocatePool(PagedPool, retsize); 
    if (!memPtr) 
    { 
     DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : ExAllocatePool Failed \n"); 
     return -1; 
    } 
    memset(memPtr, 0, retsize);// zero mem 

    durum = ZwQuerySystemInformation(SystemProcessInformation, memPtr, retsize, NULL); 
    pi = (P_SYSTEM_PROCESS_INFO_L)memPtr; // parselliyorz 
    if (!NT_SUCCESS(durum)) 
    { 
     DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : ZwQuerySystemInformation Failed 2 durum : %p \n", durum); 
     return -1; 
    } 
    while (pi->NextEntryOffset) 
    { 
     if (pi->ImageName.Buffer) //some process null if I dont use this I am getting BSOD. 
     { 
      if (!_stricmp(pi->ImageName.Buffer, name)) 
      { 
       DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : name %ws , pid : %d \n", pi->ImageName.Buffer, pi->ProcessId); 
       hProcid = pi->ProcessId; // pid 
       break; // foundedd 
      } 
     } 

     pi = (P_SYSTEM_PROCESS_INFO_L)((unsigned char*)pi + pi->NextEntryOffset); 
    } 
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : LSFindProcess bitti \n"); 
    return hProcid; 
} 
+0

[MCVE]를 참조하십시오. 질문은 프로그래밍 언어 관련 질문이 아니라 Windows API 질문입니다. – jwdonahue

+1

처음에는 루프에서이 정보를 쿼리/크기 조정해야합니다. 요청 된 버퍼 크기를 얻은 후에 새로운 프로세스/스레드가 될 수 있고 두 번째 호출시 * ZwQuerySystemInformation * * retsize *는 이미 충분히 클 수 없습니다. 두 번째'while (pi-> NextEntryOffset)'오류입니다 - 당신은 항상 목록의 마지막 프로세스를 잃어 버렸습니다. do()는 while() 루프가 필요합니다. – RbMm

+0

또한'ImageName'은'UNICODE_STRING'입니다. - 반드시 0으로 종료해야하는 것은 아닙니다. 예를 들어 여기에 'RtlEqualUnicodeString'을 사용해야합니다. – RbMm

답변

1

ZwQuerySystemInformation 이것은 물론 거짓 제대로

작동하지 않습니다. API가 제대로 작동합니다. 잘못된 결과가 나오면 이는 코드의 만기 오류입니다. 구체적인 코드에서 spinet 몇 가지 오류가 존재합니다. 필요가 전화를 필요 버전 (이 콘크리트의 경우처럼) 모두 내 보낸 이해한다면 - 커널 모드에서

ZW수 (Nt) API의 차이를 존재한다. 이전 모드가 커널 모드라는 것을 알고 있다면 Nt 버전을 사용해야합니다. 이 시점에서 (컴파일 타임에) 이전 모드 나 이전 모드 사용자 모드를 모르는 경우 Zw 버전을 사용해야합니다. 그러나 이것은 일반적으로 참고하고

최초의 심각한 오류 ZW를 호출 항상 오류되지는 않습니다 -이 호출 방법 ZwQuerySystemInformation입니다 - 처음 (코드) 쿼리 요청 버퍼 크기 retsize와 두 번째로 이미 버퍼 크기 . 이 호출 사이에 새로운 스레드와 프로세스가 시스템에 생성 될 수 있습니다. 결과로 리턴 된 버퍼 크기는 이미 충분히 클 수 없습니다. 올바른 해결책 -이 API를 루프로 호출하면 반환됩니다. STATUS_INFO_LENGTH_MISMATCH

두 번째 메모리는 항상 사용 가능해야합니다. 특히 커널 모드에서. 그 코드는 불완전하다. 변명 할 필요가 없다. 코드는 불완전하고 중간 일 수 있지만 할당 후 사용 가능한 메모리는 항상 즉시 삽입해야합니다.

다른 하나의 심각한 오류 - while (pi->NextEntryOffset) 루프 -이 루프를 사용하면 마지막 항목 (마지막으로 생성 된 프로세스)이 항상 손실 (처리되지 않음)됩니다. 이것을 바꿀 필요가있다.

if (pi-> ImageName.Buffer) //이 프로세스를 사용하지 않으면 null입니다. BSOD를 얻는 중입니다.

ImageNameUNICODE_STRING이고 각각 ​​작업해야합니다. ImageName.Buffer의 경우 ImageName.Length도 0입니다. UNICODE_STRING ImageName;은 정확합니다. 사용법이 잘못되었습니다.

!_stricmp(pi->ImageName.Buffer, name); // ??

pi->ImageName.Buffer

때문에이 원칙의 문제로 _stricmp와 함께 사용할 수 없습니다 PWSTR입니다. 당신이 사용하는 것 같아 컴파일러 C++ 여기에 오류를 제공하십시오.심지어 _wcsicmp을 사용하더라도 여기에 올바르지 않습니다. 다시 pi->ImageNameUNICODE_STRING이고 이름은 물론 PCUNICODE_STRING이어야하며 PCSTR 또는 PSTR 또는 PCWSTR이 아니어야합니다. 입력으로 PCWSTR name이있는 경우이 API를 호출하기 전에 UNICODE_STRING으로 묶어야합니다. 코드 예 :

NTSTATUS LSFindProcess(PCUNICODE_STRING ImageName, PHANDLE UniqueProcessId) 
{ 
    ULONG cb = 0x20000; 

    PVOID buf; 
    NTSTATUS status; 
    do 
    { 
     status = STATUS_INSUFFICIENT_RESOURCES; 

     if (buf = ExAllocatePool(PagedPool, cb)) 
     { 
      if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb))) 
      { 
       union { 
        PVOID pv; 
        PBYTE pb; 
        PSYSTEM_PROCESS_INFORMATION pspi; 
       }; 

       pv = buf; 
       ULONG NextEntryOffset; 

       goto __0; 

       do 
       { 
        pb += NextEntryOffset; 
__0: 
        if (RtlEqualUnicodeString(&pspi->ImageName, ImageName, TRUE)) 
        { 
         *UniqueProcessId = pspi->UniqueProcessId; 
         break; 
        } 

       } while (NextEntryOffset = pspi->NextEntryOffset); 
      } 
      ExFreePool(buf); 
     } 

    } while (status == STATUS_INFO_LENGTH_MISMATCH); 

    return status; 
} 
NTSTATUS LSFindProcess(PCWSTR ImageName, PHANDLE UniqueProcessId) 
{ 
    UNICODE_STRING us; 
    RtlInitUnicodeString(&us, ImageName); 

    return LSFindProcess(&us, UniqueProcessId); 
} 
0

, 그것은 쉽게 윈도우 OS의에서 휴대용 아니라, 심지어 그들 중 일부에 사용하지 못할 수 있습니다. MSDN documentation for this function은 특정 용도에 따라 다른 기능을 권장합니다.

+0

* Windows OS *에서 쉽게 이식 할 수 없습니다. 이것은 절대 거짓입니다. 이 함수는 안정적인 인터페이스 – RbMm

+0

@ RbMm이있는 모든 Windows 버전에 존재하며 [MSDN doc] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms725506(v=vs.85)/) .aspx), 제목 바로 아래에있는 페이지의 첫 번째 줄을보십시오. – jwdonahue

+0

내가 쓴 것은 msdn 워드 프로세서 (특별한 거짓말)가 아닌 거대한 경험을 바탕으로 썼다. win2000에서 최신 win10까지이 API를 사용하십시오. 확장 된 (새로운 정보 클래스를 추가 한) * 포트 * 안정적인 인터페이스는 필요하지 않습니다. 이 API는 훌륭합니다. – RbMm

0

감사합니다. 특히 @RbMm에게 감사드립니다. 완성 된 코드이 게시물이 도움이되기를 바랍니다.

/// <summary> 
/// Struct SystemProcessInformation 
/// </summary> 

typedef struct _SYSTEM_PROCESS_INFO_L 
{ 
    ULONG     NextEntryOffset; 
    ULONG     NumberOfThreads; 
    LARGE_INTEGER   Reserved[3]; 
    LARGE_INTEGER   CreateTime; 
    LARGE_INTEGER   UserTime; 
    LARGE_INTEGER   KernelTime; 
    UNICODE_STRING   ImageName; 
    ULONG     BasePriority; 
    HANDLE     ProcessId; 
    HANDLE     InheritedFromProcessId; 
}_SYSTEM_PROCESS_INFO_L, *P_SYSTEM_PROCESS_INFO_L; 

/// <summary> 
/// Find Process ID By Name , thanks @RbMm 
/// </summary> 
/// <param name="imagename">Process name </param> 
/// <param name="pid">Output Process id</param> 
/// <returns>NTSTATUS.</returns> 

NTSTATUS LSFindProcessIdByName(IN PCWSTR imagename, OUT PHANDLE pid) 
{ 

    NTSTATUS durum = STATUS_UNSUCCESSFUL; 
    ULONG qmemsize = 0x1024; 
    PVOID qmemptr = 0; 
    P_SYSTEM_PROCESS_INFO_L spi; 
    UNICODE_STRING uimagename; 
    RtlInitUnicodeString(&uimagename, imagename); // @RbMm 
    *pid = -1; 
    do 
    { 
     qmemptr = ExAllocatePool(PagedPool, qmemsize); // alloc memory for spi 
     if (qmemptr == NULL) // check memory is allocated or not. 
     { 
      return STATUS_UNSUCCESSFUL; 
     } 
     durum = ZwQuerySystemInformation(SystemProcessInformation,qmemptr, qmemsize, NULL); 
     if (durum == STATUS_INFO_LENGTH_MISMATCH) 
     { 
      qmemsize = qmemsize * 2; // increase qmemsize for next memory alloc 
      ExFreePool(qmemptr); // free memory 
     } 
    } while (durum == STATUS_INFO_LENGTH_MISMATCH); // resize memory 
    spi = (P_SYSTEM_PROCESS_INFO_L)qmemptr; 

    while(1) 
    { 

     if (RtlEqualUnicodeString(&uimagename, &spi->ImageName, TRUE)) // @RbMm 
     { 
      *pid = spi->ProcessId; 
      break; 
     } 

     if (spi->NextEntryOffset == 0) 
      break; 

     spi = (P_SYSTEM_PROCESS_INFO_L)((unsigned char*)spi + spi->NextEntryOffset); // next info 
    } 

    if (!NT_SUCCESS(durum)) 
    { 
     ExFreePool(qmemptr); // free memory 
     return STATUS_UNSUCCESSFUL; 
    } 
    ExFreePool(qmemptr); // free memory 
    return STATUS_SUCCESS; 
} 
+0

'qmemsize = qmemsize * 2; '당신이 이것을해서는 안되지만,'ZwQuerySystemInformation'의 마지막 매개 변수를 사용하십시오 -'& qmemsize'로 설정하십시오 -이 시점에서 실제로 필요한 크기를 반환합니다. 다음에 호출하기 전에 필요한 크기가 증가한 경우 일정한 크기 (예를 들어'qmemsize + = 0x1000')로 증가시킵니다. – RbMm

관련 문제