Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Принцип работы CreateToolhelp32Snapshot 
V
    Опции темы
Riply
Дата 20.11.2008, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Здравствуйте !
Подскажите, пожалуйста, как работает CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ...) ?
Пробовала получать аналогичный результат при помощи RtlQueryProcessDebugInformation.
Но не все так сладко, как хотелось бы.
RtlQuery... на некоторых процессах возвращает STATUS_ACCESS_DENIED, 
а вот Toolhelp32Snapshot на этих же процессах отрабатывает успешно.
(WinXP SP3. Работаем под администратором и даем себе SE_DEBUG_NAME - привилегии)
При трассировке Toolhelp32 в этих случаях, ничего "такого", 
кроме подготовки и вызова той же RtlQuery.., не увидела.
Но в трассировке на меня не стоит полагаться ибо слабовата я в этом  smile 
Что же она (Toolhelp32) такое хитрое делает для получения информации ?

CreateRemoteThread не очень подходит, ибо целевой процесс долен разрешить
создание нити, да еще и запись "в себя", на что согласны отнюдь не все  smile 
Можно попробовать пробегаться, примерно таким образом:
Код

Result := NtReadVirtualMemory(hProcess, @pProcPEB.LdrData, @pLoaderData, SizeOf(pLoaderData), nil);
if NT_SUCCESS(Result) then
 begin
  pHeadEntry := @pLoaderData.InLoadOrderModuleList;
  Result := NtReadVirtualMemory(hProcess, @pLoaderData.InLoadOrderModuleList,
                                @pCurrentEntry, SizeOf(pCurrentEntry), nil);
  if NT_SUCCESS(Result) then
   while pCurrentEntry <> pHeadEntry do
    begin
     Result := NtReadVirtualMemory(hProcess, @PLDR_DATA_TABLE_ENTRY(pCurrentEntry).InLoadOrderLinks,
                                   @pLoaderModule, SizeOf(pLoaderModule), nil);
     if NT_SUCCESS(Result)
      then pCurrentEntry := @pLoaderModule.InLoadOrderLinks.Flink
      else Break;
   end;
 end;

Работает на всех процессах, на которых работает и CreateToolhelp,
только вот пользоваться подобной пробежкой без блокировки PEB.LdrData нельзя.
Способов залочить LdrData без использования CreateRemoteThread я не вижу.
Варианты типа SuspendProcess(или все нити поочереди) мне не нравятся (очень грубые), 
уж не говоря о том, что хоть почти все процессы и открываются с PROCESS_SUSPEND_RESUME доступом, 
но вызов же непосредственно NtSuspendProcess на некоторых возвращает STATUS_ACCESS_DENIED.
А вот Toolhelp32 как-то выкручивается. Очень хочется понять как именно.

Если, вдруг, кто захочет повозится с этим делом,   smile 
набросала пару процедур для сравнения работы сабжевых ф-ий:
Код

function ZwQuerySystemInformationMem(const SysInfoClass: SYSTEM_INFORMATION_CLASS; var pBuffer: PVOID; var BytesPerBuffer: ULONG): NTSTATUS;
var
 RetLength: ULONG;
begin
 Result := ZwQuerySystemInformation(SysInfoClass, pBuffer, BytesPerBuffer, @RetLength);
 while Result = STATUS_INFO_LENGTH_MISMATCH do
  if RetLength > BytesPerBuffer then
   begin
    BytesPerBuffer := RetLength;
    ReallocMem(pBuffer, BytesPerBuffer);
    Result := ZwQuerySystemInformation(SysInfoClass, pBuffer, BytesPerBuffer, @RetLength);
   end
  else Result := STATUS_DBG_IMPOSSIBLE;
end;

const
 AVERAGE_PROC_ARR_SIZE = (MAXWORD + 1) shr 1;

function CompareRtlAndToolHelp: NTSTATUS;
var
// ModEntry: MODULEENTRY32W;
 pProcessBuffer: PVOID;
 BytesPerBuffer, ModuleCount: ULONG;
 CurrentProcID, hModuleSnap: THANDLE;
 pProcInfo: PSYSTEM_PROCESS_INFORMATION;
 pDbgBuffer: PRTL_DEBUG_INFORMATION;
begin
 BytesPerBuffer := AVERAGE_PROC_ARR_SIZE;
 pProcessBuffer := GetMemory(BytesPerBuffer);
 if pProcessBuffer <> nil then
  try
   Result := ZwQuerySystemInformationMem(SystemProcessesAndThreadsInformation, pProcessBuffer, BytesPerBuffer);
   if NT_SUCCESS(Result) then
    begin
     pDbgBuffer := RtlCreateQueryDebugBuffer(0, False);
     if pDbgBuffer <> nil then
      try
       pProcInfo := pProcessBuffer;
       CurrentProcID := GetCurrentProcessId;

       while True do
        with pProcInfo^ do
         begin

          if (UniqueProcessId > THANDLE(4)) and (UniqueProcessId <> CurrentProcID) then
           begin
            Result := RtlQueryProcessDebugInformation(UniqueProcessId, PDI_MODULES, pDbgBuffer);
            if Result = STATUS_ACCESS_DENIED then
             begin
              hModuleSnap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, UniqueProcessId);
              if hModuleSnap <> INVALID_HANDLE_VALUE then
               try
//                ModEntry.dwSize := SizeOf(MODULEENTRY32W);
//                ModuleCount := 0;
//                if Module32FirstW(hModuleSnap, ModEntry) then
//                 repeat
//                  inc(ModuleCount);
//                 until not Module32NextW(hModuleSnap, ModEntry);
//                ShowMessage('UniqueProcessId: ' + IntToStr(UniqueProcessId) + sLineBreak +
//                            'ModuleCount: ' + IntToStr(ModuleCount));
               finally
                CloseHandle(hModuleSnap);
               end;
             end;
           end;

          if NextEntryOffset > 0
           then pProcInfo := PSYSTEM_PROCESS_INFORMATION(ULONG_PTR(pProcInfo) + NextEntryOffset)
           else Break;
         end;

      finally
       RtlDestroyQueryDebugBuffer(pDbgBuffer);
      end
     else Result := RtlGetLastNtStatus;
    end;
  finally
   FreeMemory(pProcessBuffer);
  end
 else Result := STATUS_INSUFFICIENT_RESOURCES;
end;

PM MAIL   Вверх
Rrader
  Дата 23.11.2008, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 29
Всего: 191



Хитроумная функция smile Думаю, лучший способ понять принцип работы - дизассемблирование.

Что удалось выяснить, работает она в три этапа, первые два связаны - если первый не отрабатывает, то до второго дело не доходит. И только после успешно завершенного второго идет третий smile

Вот, собственно, листинг:
Код

<HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);>

    mov edi,edi
    push ebp                           ; Код входа 
    mov ebp,esp                        ; Код входа - новый фрейм 
    sub esp,0Ch                        ; Код входа - 12 байт для локальных переменных 
    push esi                           ; ESI будет использоваться - сохраняем
    mov esi,[ebp+0Ch]                  ; ESI := th32ProcessID
    test esi,esi                       ; if ESI <> 0 then goto @@PIDIsValid

    ; Прыгаем, если в параметре передали не ноль

    jnz @@PIDIsValid

    ; Получаем CurrentPID, если в параметре передали ноль

    call GetCurrentProcessId           ; EAX := CurrentPID 
    mov esi,eax                        ; ESI := CurrentPID
    
@@PIDIsValid:

    ; Готовим буферы для вызова основной подпроцедуры (а в ней уже Rtl...)
    ; Принимает флаги, PID и указатели на три выходных буфера

    lea eax,[ebp-04h]                  ; @Var1 (Out)
    push eax
    lea eax,[ebp-08h]                  ; @Var2 (Out)
    push eax
    lea eax,[ebp-0Ch]                  ; @Var3 (Out) 
    push eax
    push esi                           ; PID 
    push dword ptr [ebp+08h]           ; dwFlags    
    
    ; Цепочка вызовов ThpCreateRawSnap:
    
    ; __SEH_prolog        
    ; NtAllocateVirtualMemory        
    ; NtQuerySystemInformation        
    ; NtFreeVirtualMemory        
    ; RtlCreateQueryDebugBuffer      
    ; RtlQueryProcessDebugInformation      
    ; RtlDestroyQueryDebugBuffer        
    ; __SEH_epilog
        
    call ThpCreateRawSnap              ; ThpCreateRawSnap(Flags, PID: DWORD; var Var1, var Var2, var Var3: Pointer)
    test eax,eax                       ; if Result(ThpCreateRawSnap) >= 0 then goto @@Stage2
    
    ; Прыгаем, если функция первого этапа успешно отработала
    jnl @@Stage2

    ; Первый этап провален...

;  ...Либо провалился второй этап    
@@MaybeStage2Failed:    
    push eax                           ; if Result < 0 then BaseSetLastNTError(EAX)
    jmp @@GeneralFailed

; Этап 2
    
@@Stage2:    
    push dword ptr [ebp-04h]           ; Var1 (In)
    lea eax,[ebp+0Ch]                  ; EAX := @th32ProcessID
    push dword ptr [ebp-08h]           ; Var2 (In)
    push dword ptr [ebp-0Ch]           ; Var3 (In) 
    push esi                           ; PID
    push dword ptr [ebp+08h]           ; dwFlags
    push eax                           ; @th32ProcessID

    ; Основная функция второго этапа ThpAllocateSnapshotSection - она запишет результат во фрейм прямо в параметр th32ProcessID, и он станет дескриптором
    
    ; Цепочка вызовов ThpAllocateSnapshotSection:
    
    ; BaseFormatObjectAttributes     
    ; NtCreateSection        
    ; NtMapViewOfSection        
    ; CloseHandle        
    ; NtFreeVirtualMemory        
    ; RtlDestroyQueryDebugBuffer     
    ; NtUnmapViewOfSection

    call ThpAllocateSnapshotSection    ; ThpAllocateSnapshotSection(var th32ProcessID: DWORD; dwFlags, PID: DWORD; Var1, Var2, Var3: DWORD)
    test eax,eax                       ; if ThpAllocateSnapshotSection(Proc2) < 0 then goto @@MaybeStage2Failed

    ; Завалили второй этап - прыгаем

    jl @@MaybeStage2Failed

    ; Второй этап прошел успешно

    push dword ptr [ebp-04h]           ; Var1 (In)
    push dword ptr [ebp-08h]           ; Var2 (In)
    push dword ptr [ebp-0Ch]           ; Var3 (In)
    push dword ptr [ebp+0Ch]           ; th32ProcessID, но в нем уже дескриптор SnapshotHandle
    push esi                           ; PID
    push dword ptr [ebp+08h]           ; dwFlags
    
    ; Заключительный третий этап
    
    ; Цепочка вызовов ThpProcessToSnap:
    
    ; NtMapViewOfSection        
    ; RtlDestroyQueryDebugBuffer        
    ; ThpCopyAnsiToUnicode     
    ; lstrcpyW
    ; NtFreeVirtualMemory        
    ; NtUnmapViewOfSection

    call ThpProcessToSnap              ; ThpProcessToSnap(dwFlags, PID, hSnapshotHandle: DWORD; Var1, Var2, Var3: DWORD)
    mov esi,eax                        ; ESI := Result(ThpProcessToSnap) 
    test esi,esi                       ; if Result(ThpProcessToSnap) >= 0 then goto @@Success
     
    ; Отработали успешно - прыгаем

    jnl @@Success

    ; Ошибка третьего этапа - закрываем SnapshotHandle

    push dword ptr [ebp+0Ch]           ; if Result(ThpProcessToSnap) < 0 then CloseHandle(SnapshotHandle)
    call CloseHandle
    push esi

; Сюда попадаем в случае провала (либо первый этап, либо второй после успешного первого, либо третий)    
@@GeneralFailed:

    ; Основа - RtlNtStatusToDosError, в параметре для нее будет лежать NTSTATUS для проваленных функций первого, второго или третьего этапа
    ; Затем SetLastError
    call BaseSetLastNTError
    or eax,-1
    ; Идем на выход со слезами на глазах...Результат работы функции == INVALID_HANDLE_VALUE
    jmp @@End
    
@@Success:    
    ; Результат работы - валидный SnapshotHandle, идем на выход
    mov eax,[ebp+0Ch]
    
@@End:    
    pop esi                             ; Восстанавливаем ESI
    leave                               ; Код выхода
    ret 8                               ; Подровнять стек на 8 байт


Думаю, для полноты понимания придется дизассемблировать неэкспортируемые внутренние функции библиотеки. Ну а сейчас можно попробовать пошагово проэмулировать работу функции на Delphi. А конкретно первый этап выполнить. Может там вся разгадка smile

Это сообщение отредактировал(а) Rrader - 24.11.2008, 18:22


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
Virtuals
Дата 23.11.2008, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



Rrader
а так не более удобочитаемо?
да и комментарий достаточно интересен smile 

 Copyright © Microsoft Corporation
Код

HANDLE
WINAPI
CreateToolhelp32Snapshot(
    IN DWORD dwFlags,
    IN DWORD th32ProcessID)
/*++

Routine Description:

    Takes a snapshot of the Win32 processes, heaps, modules, and threads used
    by the Win32 processes. Returns an open handle to the specified snapshot if
    successful or  -1 otherwise.

    NOTE that all of the snapshots are global except for the heap and module
    lists which are process specific. To enumerate the heap or module state for
    all WIN32 processes call with TH32CS_SNAPALL and the current process. Then
    for each process in the TH32CS_SNAPPROCESS list that isn't the current
    process, do a call with just TH32CS_SNAPHEAPLIST and/or TH32CS_SNAPMODULE.

    Use CloseHandle to destroy the snapshot

    This function is not multi-thread safe.  All of the other functions are.

Arguments:

    dwFlags - Supplies switches to specify action as follows:
        TH32CS_INHERIT  Indicates that the snapshot handle is to be inheritable.
        TH32CS_SNAPALL  Equivalent to specifying the TH32CS_SNAPHEAPLIST,
                        TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS, and
                        TH32CS_SNAPTHREAD values.
        TH32CS_SNAPHEAPLIST     Includes the heap list of the specified Win32
                                process in the snapshot.
        TH32CS_SNAPMODULE       Includes the module list of the specified Win32
                                process in the snapshot.
        TH32CS_SNAPPROCESS      Includes the Win32 process list in the snapshot.
        TH32CS_SNAPTHREAD       Includes the Win32 thread list in the snapshot.

    th32ProcessID - Supplies a Win32 process identifier. This parameter can be
        zero to indicate the current process. This parameter is used when the
        TH32CS_SNAPHEAPLIST or TH32CS_SNAPMODULE value is specified. Otherwise,
        it is ignored. The snapshot taken by this function is examined by the
        other tool help functions to provide their results.  Access to the
        snapshot is read only. The snapshot handle acts like a Win32 object
        handle and is subject to the same rules regarding which processes and
        threads it is valid in.

Return Value:

    Returns an open handle to the specified snapshot if successful or -1 if not.
    To retrieve an extended error status code generated by this function, use
    the GetLastError function.
    To destroy the snapshot, use the CloseHandle function.

--*/
{
    HANDLE SnapSection;
    PUCHAR RawProcess;
    PRTL_DEBUG_INFORMATION RawModule;
    PRTL_DEBUG_INFORMATION RawDebugInfo;
    NTSTATUS Status = 0;

    if (th32ProcessID == 0) {
        th32ProcessID = GetCurrentProcessId();
    }

    //
    // process the requested data types
    //

    Status = ThpCreateRawSnap(dwFlags,
                              th32ProcessID,
                              &RawProcess,
                              &RawModule,
                              &RawDebugInfo);

    if (!NT_SUCCESS(Status)) {
        BaseSetLastNTError(Status);
        return (HANDLE)-1;
    }

    Status = ThpAllocateSnapshotSection(&SnapSection,
                                        dwFlags,
                                        th32ProcessID,
                                        RawProcess,
                                        RawModule,
                                        RawDebugInfo);

    if (!NT_SUCCESS(Status)) {
        BaseSetLastNTError(Status);
        return (HANDLE)-1;
    }

    Status = ThpProcessToSnap(dwFlags,
                              th32ProcessID,
                              SnapSection,
                              RawProcess,
                              RawModule,
                              RawDebugInfo);

    if (!NT_SUCCESS(Status)) {
        CloseHandle(SnapSection);
        BaseSetLastNTError(Status);
        return (HANDLE)-1;
    }

    return SnapSection;
}



думаю эта функция более интересна

 Copyright © Microsoft Corporation
Код

NTSTATUS
ThpAllocateSnapshotSection(
    OUT PHANDLE SnapSection,
    IN DWORD dwFlags,
    IN DWORD th32ProcessID,
    PUCHAR RawProcess,
    PRTL_DEBUG_INFORMATION RawModule,
    PRTL_DEBUG_INFORMATION RawDebugInfo)
/*++

Routine Description:

    This function calculates the size of the snapshot and allocates a
    file mapping object for it in the pagefile.
    Also, initialize snapshot information in the header

Arguments:

    th32ProcessID - Supplies a WIN32 process ID.  See CreateToolhelp32Snapshot
        for full description.

    dwFlags - Supplies switches describing requested data.  See
        CreateToolhelp32Snapshot for full description.

    th32ProcessID -

    RawProcess -

    RawDebugInfo -

Return Value:

    Handle to to the mapping object if successful, -1 otherwise

--*/
{
    NTSTATUS Status = 0;
    PSNAPSHOTSTATE SnapshotBase;
    SECURITY_ATTRIBUTES SecurityAttributes;
    LPSECURITY_ATTRIBUTES lpSecurityAttributes;
    ULONG SnapShotSize;
    ULONG Offset1;
    PSYSTEM_PROCESS_INFORMATION ProcessInfo;
    OBJECT_ATTRIBUTES Obja;
    POBJECT_ATTRIBUTES pObja;
    LARGE_INTEGER SectionOffset;
    LARGE_INTEGER SectionSize;
    SIZE_T ViewSize;
    SIZE_T Size;
    ULONG ProcessCount = 0;
    ULONG HeapListCount = 0;
    ULONG ModuleCount = 0;
    ULONG ThreadCount = 0;

    SnapShotSize = sizeof(SNAPSHOTSTATE);

    Offset1 = 0;

    //
    // calculate the required snapshot size
    //

    if ((dwFlags & TH32CS_SNAPPROCESS) || (dwFlags & TH32CS_SNAPTHREAD)) {
        do {
            ProcessCount++;
            ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&RawProcess[Offset1];
            Offset1 += ProcessInfo->NextEntryOffset;
            ThreadCount += ProcessInfo->NumberOfThreads;
        } while (ProcessInfo->NextEntryOffset != 0);

        if (dwFlags & TH32CS_SNAPPROCESS) {
            SnapShotSize += ProcessCount * sizeof(PROCESSENTRY32W);
        }
        if (dwFlags & TH32CS_SNAPTHREAD) {
            SnapShotSize += ThreadCount * sizeof(THREADENTRY32);
        }
    }

    if (dwFlags & TH32CS_SNAPMODULE) {
        SnapShotSize += RawModule->Modules->NumberOfModules * sizeof(MODULEENTRY32W);
        ModuleCount = RawModule->Modules->NumberOfModules;
    }

    if (dwFlags & TH32CS_SNAPHEAPLIST)   {
        SnapShotSize += RawDebugInfo->Heaps->NumberOfHeaps * sizeof(HEAPLIST32);
        HeapListCount = RawDebugInfo->Heaps->NumberOfHeaps;
    }

    //
    // Create a security object if needed
    //

    if (dwFlags & TH32CS_INHERIT) {
        SecurityAttributes.lpSecurityDescriptor = NULL;
        SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
        SecurityAttributes.bInheritHandle = TRUE;
        lpSecurityAttributes = &SecurityAttributes;
    } else {
        lpSecurityAttributes = NULL;
    }

    //
    // create a pagefile section to contain the snapshot
    //

    pObja = BaseFormatObjectAttributes(&Obja, lpSecurityAttributes, NULL);

    SectionSize.LowPart = SnapShotSize;
    SectionSize.HighPart = 0;

    Status = NtCreateSection(SnapSection,
                STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
                pObja,
                &SectionSize,
                PAGE_READWRITE,
                SEC_COMMIT,
                NULL);

    if ( !NT_SUCCESS(Status) ) {
        return Status;
    }

    SectionOffset.LowPart = 0;
    SectionOffset.HighPart = 0;
    ViewSize = 0;
    SnapshotBase = 0;

    Status = NtMapViewOfSection(*SnapSection,
                NtCurrentProcess(),
                &SnapshotBase,
                0L,
                0L,
                &SectionOffset,
                &ViewSize,
                ViewShare,
                0L,
                PAGE_READWRITE);

    SnapshotBase->ProcessCount  = ProcessCount;
    SnapshotBase->HeapListCount = HeapListCount;
    SnapshotBase->ModuleCount   = ModuleCount;
    SnapshotBase->ThreadCount   = ThreadCount;

    //
    // free all memory if failure
    //

    if ( !NT_SUCCESS(Status) ) {
        CloseHandle(*SnapSection);

        if ((dwFlags & TH32CS_SNAPTHREAD) || (dwFlags & TH32CS_SNAPPROCESS)){

        Size = 0;
        NtFreeVirtualMemory(NtCurrentProcess(),
                            &RawProcess,
                            &Size,
                            MEM_RELEASE);

        }

        if (dwFlags & TH32CS_SNAPPROCESS) {
            RtlDestroyQueryDebugBuffer(RawModule);
        }

        if (dwFlags & TH32CS_SNAPHEAPLIST) {
            RtlDestroyQueryDebugBuffer(RawDebugInfo);
        }

        return Status;
    }

    //
    // return resources
    //

    NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);

    return STATUS_SUCCESS;
}


Код

NTSTATUS
ThpProcessToSnap(
    IN DWORD dwFlags,
    IN DWORD th32ProcessID,
    IN HANDLE SnapSection,
    PUCHAR RawProcess,
    PRTL_DEBUG_INFORMATION RawModule,
    PRTL_DEBUG_INFORMATION RawDebugInfo)
/*++

Routine Description:

    This function processes the data in the raw dumps specified by dwFlage into
    a mapped file.

Arguments:

    dwFlags - Supplies switches describing the data requested.  See
        CreateToolhelp32Snapshot for full description.

    th32ProcessID - Supplies a WIN32 process ID. See CreateToolhelp32Snapshot
        for full description.

    SnapSection - Supplies handle to section allocated by ThpAllocateSnapshotSection.

    RawProcess -

    RawDebugInfo -

Return Value:

    TRUE if successful, FALSE if there was a problem encountered

--*/
{
    PSNAPSHOTSTATE SnapshotBase;
    PUCHAR BufferWriteAddr;  /* working pointer into out process data - usually points at end */
    LARGE_INTEGER SectionOffset;
    SIZE_T ViewSize;
    NTSTATUS Status = 0;
    SIZE_T Size;

    SectionOffset.LowPart = 0;
    SectionOffset.HighPart = 0;
    ViewSize = 0;
    SnapshotBase = 0;

    Status = NtMapViewOfSection(SnapSection,
                NtCurrentProcess(),
                &SnapshotBase,
                0L,
                0L,
                &SectionOffset,
                &ViewSize,
                ViewShare,
                0L,
                PAGE_READWRITE);

    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    BufferWriteAddr = &SnapshotBase->DataBegin;

    //
    // write heap list to snapshot
    // some of this code adapted from dh.c
    //
    if (dwFlags & TH32CS_SNAPHEAPLIST) {
        ULONG HeapListCount = 0;
        ULONG HeapEntryCount = 0;
        LPHEAPLIST32 pHeapList;

        SnapshotBase->HeapListHead = (PHEAPLIST32)(BufferWriteAddr - (PUCHAR)SnapshotBase);
        pHeapList = (LPHEAPLIST32)BufferWriteAddr;

        // heaplist
        for (HeapListCount = 0; HeapListCount < SnapshotBase->HeapListCount; HeapListCount++){
            pHeapList->dwSize = sizeof(HEAPLIST32);
            pHeapList->th32ProcessID = th32ProcessID;
            /* handle = baseaddress = ID we will use internally */
            pHeapList->th32HeapID = (ULONG_PTR)RawDebugInfo->Heaps->Heaps[HeapListCount].BaseAddress;
            pHeapList->dwFlags = RawDebugInfo->Heaps->Heaps[HeapListCount].Flags;
            ++pHeapList;
        }
        // update the pointer to the write area
        BufferWriteAddr = (PCHAR)(BufferWriteAddr + HeapListCount * sizeof(HEAPLIST32));
        RtlDestroyQueryDebugBuffer(RawDebugInfo);
    }

    //
    // write module list to snapshot
    //
    if (dwFlags & TH32CS_SNAPMODULE) {
        LPMODULEENTRY32W pModule;
        ULONG Offset1 = 0;
        ULONG mCount = 0;
        PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;

        SnapshotBase->ModuleListHead = (PMODULEENTRY32W)(BufferWriteAddr - (PUCHAR)SnapshotBase);

        //
        // get module info from buffer
        //

        pModule = (LPMODULEENTRY32W)(BufferWriteAddr);
        ModuleInfo = &RawModule->Modules->Modules[ 0 ];
        for (mCount = 0; mCount < RawModule->Modules->NumberOfModules; mCount++)   {

            pModule->dwSize = sizeof(MODULEENTRY32W);

            pModule->th32ProcessID = th32ProcessID;

            //
            // base == handle
            //

            pModule->hModule = ModuleInfo->ImageBase;

            //
            // Base address of module in th32ProcessID's context
            //

            pModule->modBaseAddr = ModuleInfo->ImageBase;

            //
            // Path
            //

            ThpCopyAnsiToUnicode(pModule->szExePath,
                                 ModuleInfo->FullPathName,
                                 sizeof(pModule->szExePath));

            //
            // module name
            //

            ThpCopyAnsiToUnicode(pModule->szModule,
                                 &ModuleInfo->FullPathName[ModuleInfo->OffsetToFileName],
                                 sizeof(pModule->szModule));

            //
            // Size in bytes of module starting at modBaseAddr
            //

            pModule->modBaseSize = ModuleInfo->ImageSize;


            //
            // these are meaningless on NT
            // but some apps may care... Gruntz (bugid 327009)
            // was failing because th32ModuleID was 0, so
            // now we stick in the address of the Module descriptor
            //
            // However it turns out that a pointer doesn't fit in a DWORD,
            // so we stick in the value 1 instead.
            //

            pModule->th32ModuleID = 1;
            pModule->GlblcntUsage = ModuleInfo->LoadCount;  // will be 0xffff
            pModule->ProccntUsage = ModuleInfo->LoadCount;  // will be 0xffff

            ++ModuleInfo;
            ++pModule;
        }

        //
        // update the pointer to the write area
        //
        BufferWriteAddr = (PCHAR)(BufferWriteAddr + mCount * sizeof(MODULEENTRY32W));
        RtlDestroyQueryDebugBuffer(RawModule);
    }

    //
    // write process list to snapshot
    //
    if (dwFlags & TH32CS_SNAPPROCESS) {

        PSYSTEM_PROCESS_INFORMATION ProcessInfo;
        LPPROCESSENTRY32W pEntry;
        ULONG cProcess = 0;
        ULONG Offset1 = 0;

        SnapshotBase->ProcessListHead = (PPROCESSENTRY32W)(BufferWriteAddr - (PUCHAR)SnapshotBase);
        pEntry = (LPPROCESSENTRY32W)(BufferWriteAddr + cProcess * sizeof(PROCESSENTRY32W));

        do {
            /* get process info from buffer */
            ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&RawProcess[Offset1];

            pEntry->dwSize              = sizeof(PROCESSENTRY32W);
            pEntry->th32ProcessID       = HandleToUlong(ProcessInfo->UniqueProcessId);
            pEntry->pcPriClassBase      = ProcessInfo->BasePriority;
            pEntry->cntThreads          = ProcessInfo->NumberOfThreads;
            pEntry->th32ParentProcessID = HandleToUlong(ProcessInfo->InheritedFromUniqueProcessId);
            pEntry->cntUsage            = 0;
            pEntry->th32DefaultHeapID   = 0;
            pEntry->th32ModuleID        = 0;
            pEntry->dwFlags             = 0;

            // Path
            if (ProcessInfo->ImageName.Buffer == NULL) {
                lstrcpyW(pEntry->szExeFile, L"[System Process]");
            } else {
                if (ProcessInfo->ImageName.Length >= ARRAYSIZE(pEntry->szExeFile)) {
                    ProcessInfo->ImageName.Length = ARRAYSIZE(pEntry->szExeFile)-1;
                }
                memcpy(pEntry->szExeFile, ProcessInfo->ImageName.Buffer, ProcessInfo->ImageName.Length);
                pEntry->szExeFile[ProcessInfo->ImageName.Length] = TEXT('\0');
            }

            Offset1 += ProcessInfo->NextEntryOffset;
            ++cProcess;
            ++pEntry;

        } while (ProcessInfo->NextEntryOffset != 0);

        // update the pointer to the write area
        BufferWriteAddr = (PCHAR)(BufferWriteAddr + cProcess * sizeof(PROCESSENTRY32W));
    }

    //
    // write thread list to snapshot
    //

    if (dwFlags & TH32CS_SNAPTHREAD) {
        PSYSTEM_PROCESS_INFORMATION ProcessInfo;
        PSYSTEM_THREAD_INFORMATION ThreadInfo;
        LPTHREADENTRY32 tEntry;
        ULONG Offset1 = 0;
        ULONG cThread = 0;

        SnapshotBase->ThreadListHead = (PTHREADENTRY32)(BufferWriteAddr - (PUCHAR)SnapshotBase);
        tEntry = (LPTHREADENTRY32)(BufferWriteAddr + cThread * sizeof(THREADENTRY32));

        do {
            ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&RawProcess[Offset1];
            ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);

            for (cThread = 0; cThread < ProcessInfo->NumberOfThreads; cThread++) {

                tEntry->dwSize              = sizeof(THREADENTRY32);
                tEntry->th32ThreadID        = HandleToUlong(ThreadInfo->ClientId.UniqueThread);
                tEntry->th32OwnerProcessID  = HandleToUlong(ThreadInfo->ClientId.UniqueProcess);
                tEntry->tpBasePri           = ThreadInfo->BasePriority;
                tEntry->tpDeltaPri          = 0;
                tEntry->cntUsage            = 0;
                tEntry->dwFlags             = 0;

            ++ThreadInfo;
            ++tEntry;
            }

            Offset1 += ProcessInfo->NextEntryOffset;

        } while (ProcessInfo->NextEntryOffset != 0);

        BufferWriteAddr = (PUCHAR)(BufferWriteAddr + cThread * sizeof(THREADENTRY32)); // update the pointer to the write area
    }

    if ((dwFlags & TH32CS_SNAPTHREAD) || (dwFlags & TH32CS_SNAPPROCESS)){

        Size = 0;
        NtFreeVirtualMemory(NtCurrentProcess(),
                            &RawProcess,
                            &Size,
                            MEM_RELEASE);
    }

    NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);

    return STATUS_SUCCESS;
}



Это сообщение отредактировал(а) Virtuals - 23.11.2008, 21:05
PM MAIL ICQ   Вверх
Riply
Дата 24.11.2008, 05:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(Rrader @  23.11.2008,  19:43 Найти цитируемый пост)
Хитроумная функция 


Будем считать это ответом на вопрос, заданный между строк:
"А не заблудилась ли я в трех соснах ?"   smile 

Цитата(Virtuals @  23.11.2008,  20:32 Найти цитируемый пост)
думаю эта функция более интересна


Основательно, поразбираться пока еще не успела, но мне кажется, что Rrader прав
в предположении:  
Цитата(Rrader @  23.11.2008,  19:43 Найти цитируемый пост)
А конкретно первый этап выполнить. Может там вся разгадка 

Т.е. мне кажется, что все спрятано в ThpCreateRawSnap (imho, после нее идет только обработка результатов)
Случайно Microsoft Corporation, не предоставила тебе исходники и этой функции ?  smile 



Это сообщение отредактировал(а) Riply - 24.11.2008, 05:21
PM MAIL   Вверх
Virtuals
Дата 24.11.2008, 05:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



Riply,  smile тссс, какие исходники, этож общедоступные доки  smile 
хм а там как раз все ваши предположения  smile 
Код

NTSTATUS
ThpCreateRawSnap(
    IN DWORD dwFlags,
    IN DWORD th32ProcessID,
    PUCHAR *RawProcess,
    PRTL_DEBUG_INFORMATION *RawModule,
    PRTL_DEBUG_INFORMATION *RawDebugInfo)
/*++

Routine Description:

    This function gets raw snapshots for the data types specified by dwFlags.

Arguments:

    th32ProcessID - Supplies a WIN32 process ID.  See CreateToolhelp32Snapshot
        for full description.

    dwFlags - Supplies switches requesting various data.  See
        CreateToolhelp32Snapshot for full description

Return Value:

    NTSTATUS as appropriate

--*/
{
    NTSTATUS Status = 0;
    ULONG BufferSize = BUFFER_SIZE;
    SIZE_T stBufferSize = BUFFER_SIZE;

    //
    // get process/thread/module/heap info
    //

    *RawProcess = NULL;
    *RawModule = NULL;
    *RawDebugInfo = NULL;

    if((dwFlags & TH32CS_SNAPPROCESS) || (dwFlags & TH32CS_SNAPTHREAD)){
        do {
            try {
                stBufferSize = BufferSize;
                Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                                 RawProcess,
                                                 0,
                                                 &stBufferSize,
                                                 MEM_COMMIT,
                                                 PAGE_READWRITE);
            }
            except( EXCEPTION_EXECUTE_HANDLER ) {
                Status = GetExceptionCode();
            }

            if (!NT_SUCCESS(Status)) {
                break;
            }

            BufferSize = (ULONG)stBufferSize;
            //
            // get all of the status information */
            //
            Status = NtQuerySystemInformation(SystemProcessInformation,
                      *RawProcess,
                      BufferSize,
                      NULL);

            if (Status == STATUS_INFO_LENGTH_MISMATCH)   {
                NtFreeVirtualMemory(NtCurrentProcess(),
                                    RawProcess,
                                    &stBufferSize,
                                    MEM_RELEASE);
                *RawProcess = NULL;
                BufferSize += 8192;
            }

        } while(Status == STATUS_INFO_LENGTH_MISMATCH);
    }

    //
    // get module information
    //

    if(dwFlags & TH32CS_SNAPMODULE)
    {
        if (NT_SUCCESS(Status))    {
            *RawModule = RtlCreateQueryDebugBuffer(0, FALSE);
            if (!*RawModule) {
                Status = STATUS_UNSUCCESSFUL;
            }
        }

        if (NT_SUCCESS(Status)) {
            Status = RtlQueryProcessDebugInformation((HANDLE)LongToHandle(th32ProcessID),
                                                      RTL_QUERY_PROCESS_MODULES,
                                                      *RawModule);
        }
    }

    //
    // get the heap summary information for the specified process */
    //

    if (dwFlags & TH32CS_SNAPHEAPLIST)   {
        if (NT_SUCCESS(Status))    {

            *RawDebugInfo = RtlCreateQueryDebugBuffer(0, FALSE);
            if (!*RawDebugInfo) {
                Status = STATUS_UNSUCCESSFUL;
            }
        }
        if (NT_SUCCESS(Status)) {
            Status = RtlQueryProcessDebugInformation((HANDLE)LongToHandle(th32ProcessID),
                                                      RTL_QUERY_PROCESS_HEAP_SUMMARY,
                                                      *RawDebugInfo);
        }
    }


    if (!NT_SUCCESS(Status))    {
        if (*RawProcess) {
            SIZE_T Size = 0;
            NtFreeVirtualMemory(NtCurrentProcess(),
                                RawProcess,
                                &Size,
                                MEM_RELEASE);
            *RawProcess = NULL;
        }
        if (*RawModule) {
            RtlDestroyQueryDebugBuffer(*RawModule);
            *RawModule = NULL;
        }
        if (*RawDebugInfo) {
            RtlDestroyQueryDebugBuffer(*RawDebugInfo);
            *RawDebugInfo = NULL;
        }
    }

    return Status;
}



Это сообщение отредактировал(а) Virtuals - 24.11.2008, 05:49
PM MAIL ICQ   Вверх
Riply
Дата 24.11.2008, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(Virtuals @  24.11.2008,  05:46 Найти цитируемый пост)
хм а там как раз все ваши предположения  


В том то и дело, что не все или все, но не такие, или такие, но не совсем, или совсем, но не там smile
Ибо у них, черт побери, это каким-то образом работает, а у меня нет  smile 


PM MAIL   Вверх
Virtuals
Дата 24.11.2008, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



Riply, может чего с правами?
в ThpAllocateSnapshotSection явно извращаются  smile 
PM MAIL ICQ   Вверх
Riply
Дата 24.11.2008, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(Virtuals @  24.11.2008,  09:43 Найти цитируемый пост)
Riply, может чего с правами?


Да, вряд-ли.
Я ж эти функции "одновременно" вызываю. 
Т.е. они в равных условиях, в смысле прав...
"Нет... Тут что-то не так..."    (с) Сильвер     smile
Возможно, где-то в проекте партачу.
Попробую ка переписать модуль заново (не подглядывая в старый, дабы не скопировать ошибку).
Может что и выдет...

Добавлено через 8 минут и 47 секунд
Цитата(Virtuals @  24.11.2008,  09:43 Найти цитируемый пост)
в ThpAllocateSnapshotSection явно извращаются  


Согласна. Извращенцы еще те smile
Но как я понимаю, если не отрабатывает ThpCreateRawSnap, то мы туда и не должны попасть...

PM MAIL   Вверх
Virtuals
Дата 24.11.2008, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



Riply, хм странно
в
ThpCreateRawSnap
все интуитивно понятно, для модулей одно для процессов потоков дпугое, правда прикольно они память выделяют  smile 
PM MAIL ICQ   Вверх
Riply
Дата 1.12.2008, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Переодически возвращаюсь к этому вопросу
Все, чего достигла - получение (из пользовательского режима) BSOD тремя разными способами smile

Это наводит на мысли либо о том, что либо должна существовать обертка,
для использования RtlQueryProcessDebugInformation (Native, а не Toolhelp) ,
либо у меня что-то не-то с константами или экспортом   smile 

Нет ли у кого значений для RTL_QUERY_PROCESS_XXX...,
и заодно ее прототипа   ?
(не из общеизвестных источников, типа Jwa. 
Просто я уже сталкивалась с тиражированием ошибок)




Это сообщение отредактировал(а) Riply - 1.12.2008, 21:35
PM MAIL   Вверх
Rrader
  Дата 2.12.2008, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 29
Всего: 191



Riply, имхо исходники, приведенные Virtuals - те самые обрезки, что от допотопной Win 2000 гуляют... Возможно сейчас все изменилось. Сомнения появились, потому что дизассемблировал некоторые Thp функции (у себя в XP SP2) и нашел несоответствия.

Вы эмулировали эти коды?

Цитата(Riply @  2.12.2008,  03:32 Найти цитируемый пост)
Нет ли у кого значений для RTL_QUERY_PROCESS_XXX...,

RTL_QUERY_PROCESS_HEAP_SUMMARY = 4;

Самое интересное, что у меня в kernel32.dll вызов в ThpCreateRawSnap произошел с RTL_QUERY_PROCESS_MODULES = $80000001
Код

RtlQueryProcessDebugInformation((HANDLE)LongToHandle(th32ProcessID), RTL_QUERY_PROCESS_MODULES, *RawModule);



--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
Riply
Дата 2.12.2008, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Цитата(Rrader @  2.12.2008,  16:33 Найти цитируемый пост)
Возможно сейчас все изменилось


Не возможно, а точно smile
Постоянно сталкиваюсь с этим.

Цитата(Rrader @  2.12.2008,  16:33 Найти цитируемый пост)
Вы эмулировали эти коды?


Может "на ты" а ? smile




Цитата(Rrader @  2.12.2008,  16:33 Найти цитируемый пост)
Самое интересное, что у меня в kernel32.dll вызов в ThpCreateRawSnap произошел с RTL_QUERY_PROCESS_MODULES = $80000001


Я предполагала наличие дополнительных битов в маске.
Очень похоже, что именно здесь собачка то и порылась smile
Побежала проверять smile

P.S.
 Это займет время, ибо не могу тестировать на основном компьютере из-за 
возможных BSOD-ов smile

PM MAIL   Вверх
Riply
Дата 2.12.2008, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 21
Всего: 32



Есть у меня список задач с пометкой "нерешенные".
(Ну нехватает мне ума или знаний для их решения в настоящий момент)
И когда я вычеркиваю из этого списка задачу - то у меня маленький праздник smile

Rrader и Virtuals устроили мне сегодня такой праздник smile 
Спасибо вам огромное !
Уря !
 smile 




PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1191 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.