Отслеживание созданных потоков

Тема в разделе "WASM.NT.KERNEL", создана пользователем float, 10 май 2011.

  1. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Задача в отслеживании стартовых адресов новых потоков.
    Сейчас у меня для отслеживания новых потоков идет перехват NtContinue. Из переданного в нее контекста, в Eax лежит адрес старта нового потока, это работает на хр сп3 и windows 7/+wow64. Недавно задумался насколько это грамотно или неграмотно, и будет ли это работать на всех остальных NT, если нет то какой способ отслеживания стартовых адресов предпочтительнее?

    ой... промахнулся разделом извините. Имел в виду WASM.WIN32
     
  2. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Определённо тот, который ваш фаерволл не будет отслеживать. Я бы создавал копии нормальных потоков и получал управление в начале их исполнения(тоесть пока поток гдето в загрузчике например). Такие потоки не вызывают подозрений, да и не могут, так как адреса стартап процедур нормальные(ну определите вы что CONTEXT.rEax = AddressOfEntryPoint, что дальше ?), а отследить куда такой тред перейдёт не получится.
     
  3. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    да собственно задача то намного проще у меня. просто я не уверен что на всех версиях винды именно в eax будет адрес старта.
     
  4. steelfactor

    steelfactor New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    501
    http://www.wasm.ru/forum/viewtopic.php?id=26630
    не?
     
  5. C2H5OH

    C2H5OH New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2008
    Сообщения:
    42
    Или еще точнее - нужно получить ETHREAD интересующего тебя потока
    Там:
    Код (Text):
    1. typedef struct _ETHREAD
    2. {
    3.      KTHREAD Tcb;
    4.      LARGE_INTEGER CreateTime;
    5.      union
    6.      {
    7.           LARGE_INTEGER ExitTime;
    8.           LIST_ENTRY KeyedWaitChain;
    9.      };
    10.      union
    11.      {
    12.           LONG ExitStatus;
    13.           PVOID OfsChain;
    14.      };
    15.      union
    16.      {
    17.           LIST_ENTRY PostBlockList;
    18.           struct
    19.           {
    20.                PVOID ForwardLinkShadow;
    21.               [b] PVOID StartAddress;[/b]
    22.           };
    23.      };
    24.      union
    25.      {
    26.           PTERMINATION_PORT TerminationPort;
    27.           PETHREAD ReaperLink;
    28.           PVOID KeyedWaitValue;
    29.           PVOID Win32StartParameter;
    30.      };
    31.     [skip]
    32. } ETHREAD, *PETHREAD;
     
  6. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    C2H5OH
    у меня юзермод. ETHREAD можно получить в юзермоде?
     
  7. izl3sa

    izl3sa New Member

    Публикаций:
    0
    Регистрация:
    22 апр 2010
    Сообщения:
    164
    Адрес:
    Spb
    нет конечно =)
     
  8. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
  9. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    izl3sa
    SYSTEM_HANDLE_INFORMATION.Object не ?

    Код (Text):
    1. ; +
    2. ; Опредедяет адрес описателя обьекта(KPROCESS, KTIMER etc).
    3. ;
    4. QueryObject proc uses ebx ObjectHandle:HANDLE, Object:PVOID
    5. Local SystemInformation:PVOID, SystemInformationLength:ULONG
    6. Local ProcessInformation:PROCESS_BASIC_INFORMATION
    7. Local HandleInformation[sizeof(SYSTEM_HANDLE_INFORMATION) + 4]:BYTE
    8.     invoke ZwQueryInformationProcess, NtCurrentProcess, ProcessBasicInformation, addr ProcessInformation, sizeof(PROCESS_BASIC_INFORMATION), NULL
    9.     test eax,eax
    10.     jnz Exit
    11.     mov SystemInformation,eax
    12.     invoke ZwQuerySystemInformation, SystemHandleInformation, addr HandleInformation, sizeof(SYSTEM_HANDLE_INFORMATION) + 4, addr SystemInformationLength
    13.     cmp eax,STATUS_INFO_LENGTH_MISMATCH
    14.     jne Exit
    15.     cmp SystemInformationLength,NULL
    16.     je Exit
    17.     add SystemInformationLength,50*sizeof(SYSTEM_HANDLE_INFORMATION)
    18.     invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr SystemInformation, 0, addr SystemInformationLength, MEM_COMMIT, PAGE_READWRITE
    19.     test eax,eax
    20.     jnz Exit
    21.     invoke ZwQuerySystemInformation, SystemHandleInformation, SystemInformation, SystemInformationLength, Eax
    22.     test eax,eax
    23.     mov edx,SystemInformation
    24.     jnz Error
    25.     mov ebx,ProcessInformation.UniqueProcessId
    26.     mov ecx,dword ptr [edx]
    27.     mov eax,ObjectHandle
    28.     add edx,4
    29.     assume edx:PSYSTEM_HANDLE_INFORMATION
    30. Next:
    31.     cmp [edx].ProcessId,ebx
    32.     jne @f
    33.     cmp [edx].Handle,ax
    34.     je Objext
    35. @@:
    36.     add edx,sizeof(SYSTEM_HANDLE_INFORMATION)
    37.     loop Next
    38.     mov eax,STATUS_NOT_FOUND
    39.     jmp Error
    40. Objext:
    41.     mov edx,[edx].Object
    42.     mov ebx,Object
    43.     xor eax,eax
    44.     mov dword ptr [ebx],edx
    45. Error:
    46.     push eax
    47.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr SystemInformation, addr SystemInformationLength, MEM_RELEASE
    48.     pop eax
    49. Exit:
    50.     ret
    51. QueryObject endp
    Только как вы будите дальше читать память ядра %
     
  10. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    float
    Скажите, что вы будите делать дальше с полученной ссылкой ?

    В шелле(shlwapi.dll) есть функа SHCreateThread():
    Код (Text):
    1. typedef struct
    2. {
    3.     LPTHREAD_START_ROUTINE pfnMain;
    4.     LPTHREAD_START_ROUTINE pfnSync;
    5.     HANDLE hSync;
    6.     void *pvData;
    7.     DWORD dwFlags;
    8.     IUnknown *punkThreadRef;
    9.     IUnknown *punkProcessRef;
    10. } PRIVCREATETHREADDATA;
    11.  
    12. DWORD CALLBACK WrapperThreadProc(void *pv)
    13. {
    14.     // make a copy of the input buffer, this is sitting on the calling threads stack
    15.     // once we signal him his copy will be invalid
    16.     PRIVCREATETHREADDATA rgCreate = *((PRIVCREATETHREADDATA *)pv);
    17.     HRESULT hrInit;
    18.  
    19.     if (rgCreate.dwFlags & CTF_COINIT)
    20.         hrInit = SHCoInitialize();
    21.  
    22.     // call the synchronous ThreadProc while the other thread is waiting on hSync
    23.     if (rgCreate.pfnSync)
    24.         rgCreate.pfnSync(rgCreate.pvData);
    25.  
    26.     SetEvent(rgCreate.hSync);   // release the main thread..
    27.  
    28.     // call the main thread proc
    29.     DWORD dwRes = rgCreate.pfnMain(rgCreate.pvData);
    30.  
    31.     if (rgCreate.punkThreadRef)
    32.         rgCreate.punkThreadRef->Release();
    33.  
    34.     if (rgCreate.punkProcessRef)
    35.         rgCreate.punkProcessRef->Release();
    36.  
    37.     if (rgCreate.dwFlags & CTF_COINIT)
    38.         SHCoUninitialize(hrInit);
    39.  
    40.     return dwRes;
    41. }
    42.  
    43.  
    44. // Call if you want to kick off an independent thread and
    45. // you don't care about the handle or thread ID.
    46. //
    47. // If the create fails, call synchronously.
    48. //
    49. // optionally call a secondary callback when the thread
    50. // is created.
    51. // returns:
    52. //      TRUE if the thread was created
    53.  
    54. STDAPI_(BOOL) SHCreateThread(
    55.     LPTHREAD_START_ROUTINE pfnThreadProc,
    56.     void *pvData,
    57.     DWORD dwFlags,                          // CTF_*
    58.     LPTHREAD_START_ROUTINE pfnCallback)     OPTIONAL
    59. {
    60.     BOOL bRet = FALSE;
    61.     PRIVCREATETHREADDATA rgCreate = {0};  // can be on the stack since we sync the thread
    62.  
    63.     ASSERT(dwFlags & CTF_INSIST ? pfnCallback == NULL : TRUE);  // can't have a sync if you insist
    64.  
    65.     if (CTF_THREAD_REF & dwFlags)
    66.         SHGetThreadRef(&rgCreate.punkThreadRef);
    67.  
    68.     if (CTF_PROCESS_REF & dwFlags)
    69.         _SHGetInstanceExplorer(&rgCreate.punkProcessRef);
    70.  
    71.     rgCreate.pfnMain = pfnThreadProc;
    72.     rgCreate.pfnSync = pfnCallback;
    73.     rgCreate.pvData = pvData;
    74.     rgCreate.dwFlags = dwFlags;
    75.     rgCreate.hSync = CreateEvent(NULL, FALSE, FALSE, NULL);
    76.     if (rgCreate.hSync)
    77.     {
    78.         DWORD idThread;
    79.         HANDLE hThread = CreateThread(NULL, 0, WrapperThreadProc, &rgCreate, 0, &idThread);
    80.         if (hThread)
    81.         {
    82.             // BUGBUG: should this be infinite, or should it be say 20 seconds ?
    83.             WaitForSingleObject(rgCreate.hSync, INFINITE);
    84.             CloseHandle(hThread);
    85.  
    86.             bRet = TRUE;
    87.         }
    88.         CloseHandle(rgCreate.hSync);
    89.     }
    90.  
    91.     if (!bRet)
    92.     {
    93.         if (rgCreate.punkThreadRef)
    94.             rgCreate.punkThreadRef->Release();
    95.  
    96.         if (rgCreate.punkProcessRef)
    97.             rgCreate.punkProcessRef->Release();
    98.  
    99.         if (dwFlags & CTF_INSIST)
    100.         {
    101.             // failed to create another thread... call synchronously
    102.  
    103.             ASSERT(pfnCallback == NULL);  // can't have a sync if you insist
    104.  
    105.             pfnThreadProc(pvData);
    106.             bRet = TRUE;        // what should the return be here?
    107.         }
    108.     }
    109.  
    110.     return bRet;
    111. }
    Она создаёт тред в текущем процессе. Но стартап процедура системная - WrapperThreadProc(), далее она вызывает колбек, ссылка на который передана аргументом в SHCreateThread(). Получите вы контекст потока, также ссылку на стартап код. Что делать дальше, как определить что тред паразитный и найти реальный стартап код ?
    Это только частный случай, общая модель таких вызовов - используется шлюз, через который вызывается стартап процедура. Взять любой код, который передаёт управление по произвольной ссылке, например:
    Код (Text):
    1. ZwClose:
    2.     mov eax,19
    3.     mov edx,7FFE0300
    4.     call dword ptr ds:[edx]
    5.     ret 4
    Первое что пришло на ум, ссылка на колбек расположена в [Edx]. Формируем её и загружаем в контекст @ZwClose(). Вы определите что стартап процедура расположена в системном модуле. Разумеется это самые простейшие способы, можно использовать весьма сложные механизмы вызова, так что в контексте будет мусор с первого взгляда.

    Весьма пичально, что во всей малваре используются примитивные механизмы таких вызовов(решение "в лоб"), вызовы апи не безопасны(не скрывается адрес возврата), потоки создаются с стартапом, который пайлод и тп.