Как работает диспетчер задач

Всем хай! Сегодня мы займемся исследованием работы такой системной утилиты, как taskmgr.exe. Вам никогда не хотелось узнать, что кроется внутри?

Для этого увлекательного процесса будем использовать IDA Pro. Можно купить по огромной цене на официальном сайте скачать с форумов.

Для простоты реверсить будем 32-х битную версию.



В Windows x86 она лежит по пути \Windows\system32\taskmgr.exe
В Windows x64 по пути \Windows\SysWOW64\taskmgr.exe

Откроем 32-х битную версию. Добрые мелкомягкие предоставили нам ее вместе с Debug информацией. Так что когда спросит о загрузке дебаг инфы жмите Yes.

Окно откроется на точке входа. Там будет всякая инициализация окон и т.д. Она нас не интересует. Идем во вкладку import и смотрим какие функции импортирует.

Список довольно огромный. Есть несколько способов найти в исполняемом файле интересуемый нас функционал:

1) Поиск вызовов нужных нам API функций
2) Трассировка в отладчике

Так как второй способ громоздкий и неудобный крайне для оконных приложений, то выбираем первый. Для интереса найдем код, который отвечает за поиск процессов. Как узнать при помощи какой функции это происходит?

Использовать будем API Monitor. При помощи данной софтины можно посмотреть какие API вызывает программа в ходе своей работы и в каком порядке! Прекрасно!

Качаем по ссылке: http://www.rohitab.com/downloads 

Качайте x64 версию, она установит и x86 и x64. Далее запускаем API Monitor 32-bit. Слева выбираем в API Filter: Nt Native, System Services и Undocumented. Это мы сделали из предположения, что скорее всего используются либо низкоуровневые ( еще ниже WinAPI ) вызовы функций Native API, либо WINAPI функции по управлению объектами ядра: хэндлы, файлы, процессы, треды. А также сделали предположение, что может быть что-то недокументированное. Запускаем taskmgr. Видим огромное количество API.

Мы можем их всех просматривать, но так дело не пойдет. Сузим круг поиска. Раскроем NT Native и System Services, чтобы выбрать там только Processes and threads. Запустим еще раз.

Увидим там огромный список. Подождите! Он весь состоит из TlsGetValue и TlsSetValue. Жмем по ним и выбираем Hide API (Delete)

Видим, что используются Native API функции, как мы и предполагали.

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
11    1:43:46.027 AM    1    KERNELBASE.dll    NtOpenProcess ( 0x0016f8b4, PROCESS_QUERY_INFORMATION, 0x0016f888, 0x0016f8a0 )    STATUS_SUCCESS        0.0000060
12    1:43:46.027 AM    1    KERNELBASE.dll    NtQueryInformationProcess ( 0x000000b8, ProcessSessionInformation, 0x0016f8a8, 4, NULL )    STATUS_SUCCESS        0.0000021
13    1:43:46.027 AM    1    taskmgr.exe    GetCurrentProcess (  )    GetCurrentProcess()        0.0000013
14    1:43:46.027 AM    1    KERNELBASE.dll    NtSetInformationThread ( GetCurrentThread(), ThreadImpersonationToken, 0x0016f89c, 4 )    STATUS_SUCCESS        0.0000034
15    1:43:46.027 AM    1    KERNELBASE.dll    NtQueryInformationProcess ( GetCurrentProcess(), ProcessDefaultHardErrorMode, 0x0016f8b0, 4, NULL )    STATUS_SUCCESS        0.0000021
16    1:43:46.027 AM    1    KERNELBASE.dll    NtQueryInformationProcess ( GetCurrentProcess(), ProcessDefaultHardErrorMode, 0x0016f89c, 4, NULL )    STATUS_SUCCESS        0.0000013
17    1:43:46.027 AM    1    KERNELBASE.dll    NtSetInformationProcess ( GetCurrentProcess(), ProcessDefaultHardErrorMode, 0x0016f8ac, 4 )    STATUS_SUCCESS        0.0000021


Итак. Посмотрим в каких областях вызываются данные функции. Возвращаемся в IDA, выбираем imports и ищем там, например, NtQueryInformationProcess

Жмем по ней два раза и видим нечто подобное:

 .idata:01001578 ; NTSTATUS __stdcall NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength)  
 .idata:01001578         extrn __imp__NtQueryInformationProcess@20:dword  

Мы оказались внутри таблицы импорта! Выбираем часть строки, где
__imp__NtQueryInformationProcess

и жмем клавишу X ( английскую ), смотрим какой код ссылается на эту функцию 



Это список внутренних функций, где используется NtQueryInformationProcess. Нажав два раза на любую из функций мы окажемся на строчке, где вызывается наша искомая API

Но... тут нет создания списка процессов. Как так?

Давайте уберем фильтр, выбрав все Native API и запустим скрипт. Итак, предположим, что обновление происходит, как только taskmgr ловит появления новых процессов. Давайте пока работает API Monitor создадим пару процессов и закроем их через исследуемый диспетчер.

После выбивания мусорных функций и сравнения времени открытия/закрытия мы заметим вызов функции NtQuerySystemInformation

Посмотрим где она вызывается и найдем функцию:

; __int32 __thiscall CProcPage::UpdateProcInfoArray(CProcPage *this)

Которая отвечает за обновление информации о процессе.

Так что вот код, который ищет процессы. Теперь мы знаем, что чтобы скрыть наше приложение от диспетчера достаточно перехватить эту функцию! Таким способом вы можете исследовать что угодно

 .text:01002C5B ; __int32 __thiscall CProcPage::UpdateProcInfoArray(CProcPage *this)  
 .text:01002C5B ?UpdateProcInfoArray@CProcPage@@QAEJXZ proc near  
 .text:01002C5B                     ; CODE XREF: CProcPage::TimerEvent(void):loc_100C377 p  
 .text:01002C5B  
 .text:01002C5B var_1F8     = byte ptr -1F8h  
 .text:01002C5B var_1CC     = dword ptr -1CCh  
 .text:01002C5B var_188     = dword ptr -188h  
 .text:01002C5B var_184     = dword ptr -184h  
 .text:01002C5B SystemInformation= byte ptr -0B0h  
 .text:01002C5B var_A8     = dword ptr -0A8h  
 .text:01002C5B var_A4     = dword ptr -0A4h  
 .text:01002C5B var_84     = dword ptr -84h  
 .text:01002C5B var_80     = dword ptr -80h  
 .text:01002C5B var_7C     = dword ptr -7Ch  
 .text:01002C5B var_78     = dword ptr -78h  
 .text:01002C5B var_74     = dword ptr -74h  
 .text:01002C5B var_70     = dword ptr -70h  
 .text:01002C5B var_6C     = dword ptr -6Ch  
 .text:01002C5B var_68     = dword ptr -68h  
 .text:01002C5B var_64     = _LARGE_INTEGER ptr -64h  
 .text:01002C5B var_5C     = dword ptr -5Ch  
 .text:01002C5B var_58     = dword ptr -58h  
 .text:01002C5B var_54     = dword ptr -54h  
 .text:01002C5B var_50     = dword ptr -50h  
 .text:01002C5B var_4C     = dword ptr -4Ch  
 .text:01002C5B i        = dword ptr -48h  
 .text:01002C5B String     = word ptr -44h  
 .text:01002C5B var_4      = dword ptr -4  
 .text:01002C5B  
 .text:01002C5B ; FUNCTION CHUNK AT .text:01002584 SIZE 0000001A BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:0100274F SIZE 00000040 BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:01002994 SIZE 00000041 BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:01002D5B SIZE 000000C6 BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:01003415 SIZE 0000002B BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:0100375A SIZE 00000055 BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:010038AF SIZE 0000005B BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:01003A7B SIZE 00000067 BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:0100673B SIZE 0000001C BYTES  
 .text:01002C5B ; FUNCTION CHUNK AT .text:0100C243 SIZE 00000134 BYTES  
 .text:01002C5B  
 .text:01002C5B         mov   edi, edi  
 .text:01002C5D         push  ebp  
 .text:01002C5E         mov   ebp, esp  
 .text:01002C60         sub   esp, 1F8h  
 .text:01002C66         mov   eax, ___security_cookie  
 .text:01002C6B         xor   eax, ebp  
 .text:01002C6D         mov   [ebp+var_4], eax  
 .text:01002C70         push  ebx  
 .text:01002C71         push  edi  
 .text:01002C72         push  8  
 .text:01002C74         xor   eax, eax  
 .text:01002C76         mov   ebx, ecx  
 .text:01002C78         pop   ecx  
 .text:01002C79         push  eax       ; ReturnLength  
 .text:01002C7A         lea   edi, [ebp+var_84]  
 .text:01002C80         rep stosd  
 .text:01002C82         mov   edi, ds:__imp__NtQuerySystemInformation@16 ; NtQuerySystemInformation(x,x,x,x)  
 .text:01002C88         push  2Ch       ; SystemInformationLength  
 .text:01002C8A         lea   ecx, [ebp+SystemInformation]  
 .text:01002C90         push  ecx       ; SystemInformation  
 .text:01002C91         push  eax       ; SystemInformationClass  
 .text:01002C92         mov   [ebp+var_5C], eax  
 .text:01002C95         mov   [ebp+var_58], eax  
 .text:01002C98         mov   [ebp+var_4C], eax  
 .text:01002C9B         mov   [ebp+i], eax  
 .text:01002C9E         call  edi ; NtQuerySystemInformation(x,x,x,x) ; NtQuerySystemInformation(x,x,x,x)  
 .text:01002CA0         test  eax, eax  
 .text:01002CA2         jl   loc_100C243  
 .text:01002CA8         push  esi  
 .text:01002CA9         mov   esi, [ebp+var_A8]  
 .text:01002CAF         shr   esi, 0Ah  
 .text:01002CB2         imul  esi, [ebp+var_A4]  
 .text:01002CB9         push  0        ; ReturnLength  
 .text:01002CBB         push  148h      ; SystemInformationLength  
 .text:01002CC0         lea   eax, [ebp+var_1F8]  
 .text:01002CC6         push  eax       ; SystemInformation  
 .text:01002CC7         push  2        ; SystemInformationClass  
 .text:01002CC9         mov   [ebp+var_78], esi  
 .text:01002CCC         call  edi ; NtQuerySystemInformation(x,x,x,x) ; NtQuerySystemInformation(x,x,x,x)  
 .text:01002CCE         test  eax, eax  
 .text:01002CD0         jl   loc_100C24D  
 .text:01002CD6         mov   eax, dword_101E490  
 .text:01002CDB         and   dword ptr ?g_MEMMax@@3_JA+4, 0  
 .text:01002CE2         shr   eax, 0Ah  
 .text:01002CE5         mov   ecx, eax  
 .text:01002CE7         imul  ecx, [ebp+var_1CC]  
 .text:01002CEE         mov   edi, eax  
 .text:01002CF0         imul  eax, [ebp+var_184]  
 .text:01002CF7         imul  edi, [ebp+var_188]  
 .text:01002CFE         mov   [ebp+var_6C], eax  
 .text:01002D01         mov   [ebp+var_74], ecx  
 .text:01002D04         add   eax, edi  
 .text:01002D06         mov   ecx, ebx    ; this  
 .text:01002D08         mov   [ebp+var_68], eax  
 .text:01002D0B         mov   dword ptr ?g_MEMMax@@3_JA, esi ; __int64 g_MEMMax  
 .text:01002D11         call  ?GetProcessInfo@CProcPage@@QAEJXZ ; CProcPage::GetProcessInfo(void)  
 .text:01002D16         mov   [ebp+var_54], eax  
 .text:01002D19         test  eax, eax  
 .text:01002D1B         jge   loc_100C257  
 .text:01002D21         jmp   loc_100C353  
 .text:01002D26 ; ---------------------------------------------------------------------------  
 .text:01002D26  
 .text:01002D26 loc_1002D26:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)-503 j  
 .text:01002D26                     ; CProcPage::UpdateProcInfoArray(void)+9611 j  
 .text:01002D26         push  eax       ; unsigned __int32  
 .text:01002D27         push  dword ptr [ebx+0Ch] ; struct CPtrArray *  
 .text:01002D2A         call  ?FindProcInArrayByPID@@YGPAVCProcInfo@@PAVCPtrArray@@K@Z ; FindProcInArrayByPID(CPtrArray *,ulong)  
 .text:01002D2F         test  eax, eax  
 .text:01002D31         jnz   loc_100C271  
 .text:01002D37  
 .text:01002D37 loc_1002D37:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)+9651 j  
 .text:01002D37         mov   eax, [esi+30h]  
 .text:01002D3A         add   eax, [esi+28h]  
 .text:01002D3D         mov   ecx, [esi+34h]  
 .text:01002D40         adc   ecx, [esi+2Ch]  
 .text:01002D43         add   [ebp+var_5C], eax  
 .text:01002D46         mov   eax, [esi+4Ch]  
 .text:01002D49         adc   [ebp+var_58], ecx  
 .text:01002D4C         add   [ebp+var_84], eax  
 .text:01002D52         mov   eax, [esi+4]  
 .text:01002D55         add   [ebp+var_80], eax  
 .text:01002D58         inc   [ebp+var_7C]  
 .text:01002D58 ?UpdateProcInfoArray@CProcPage@@QAEJXZ endp ; sp-analysis failed  
 .text:01002D58  
 .text:01002D5B ; START OF FUNCTION CHUNK FOR ?UpdateProcInfoArray@CProcPage@@QAEJXZ  
 .text:01002D5B  
 .text:01002D5B loc_1002D5B:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)-509 j  
 .text:01002D5B                     ; CProcPage::UpdateProcInfoArray(void)+9640 j  
 .text:01002D5B         mov   eax, [esi]  
 .text:01002D5D         add   [ebp+var_50], eax  
 .text:01002D60         cmp   ?gdwSessionId@@3KA, 0FFFFFFFFh ; ulong gdwSessionId  
 .text:01002D67         jz   loc_100673B  
 .text:01002D6D  
 .text:01002D6D loc_1002D6D:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)+3AE9 j  
 .text:01002D6D                     ; CProcPage::UpdateProcInfoArray(void)+3AF7 j  
 .text:01002D6D         cmp   dword ptr [esi], 0  
 .text:01002D70         jnz   loc_100C25B  
 .text:01002D76         mov   eax, [ebp+var_5C]  
 .text:01002D79         sub   eax, [ebp+var_4C]  
 .text:01002D7C         mov   ecx, [ebp+var_58]  
 .text:01002D7F         sbb   ecx, [ebp+i]  
 .text:01002D82         mov   dword ptr [ebp+var_64], eax  
 .text:01002D85         mov   eax, [ebp+var_7C]  
 .text:01002D88         xor   esi, esi  
 .text:01002D8A         mov   dword ptr [ebp+var_64+4], ecx  
 .text:01002D8D         mov   ?g_cProcesses@@3KA, eax ; ulong g_cProcesses  
 .text:01002D92         cmp   dword_101E554, esi  
 .text:01002D98         jnz   loc_100C2B1  
 .text:01002D9E         jmp   loc_100C2CC  
 .text:01002DA3 ; ---------------------------------------------------------------------------  
 .text:01002DA3  
 .text:01002DA3 loc_1002DA3:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)+B2C j  
 .text:01002DA3                     ; CProcPage::UpdateProcInfoArray(void)+9680 j  
 .text:01002DA3         push  eax       ; dwProcessId  
 .text:01002DA4         push  0        ; bInheritHandle  
 .text:01002DA6         push  1000h      ; dwDesiredAccess  
 .text:01002DAB         call  ds:__imp__OpenProcess@12 ; OpenProcess(x,x,x)  
 .text:01002DB1         mov   [ebp+i], eax  
 .text:01002DB4         test  eax, eax  
 .text:01002DB6         jnz   loc_100275D  
 .text:01002DBC  
 .text:01002DBC loc_1002DBC:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)-4DD j  
 .text:01002DBC         mov   eax, [esi+40h]  
 .text:01002DBF         cmp   eax, 4  
 .text:01002DC2         jle   loc_100C2EC  
 .text:01002DC8         cmp   eax, 6  
 .text:01002DCB         jle   loc_1002783  
 .text:01002DD1         cmp   eax, 8  
 .text:01002DD4         jg   loc_1003415  
 .text:01002DDA         mov   dword ptr [esi+40h], 20h  
 .text:01002DE1  
 .text:01002DE1 loc_1002DE1:              ; CODE XREF: CProcPage::UpdateProcInfoArray(void)-4E3 j  
 .text:01002DE1                     ; CProcPage::UpdateProcInfoArray(void)-4D1 j ...  
 .text:01002DE1         push  dword ptr [esi+44h] ; unsigned __int32  
 .text:01002DE4         push  dword ptr [ebx+0Ch] ; struct CPtrArray *  
 .text:01002DE7         call  ?FindProcInArrayByPID@@YGPAVCProcInfo@@PAVCPtrArray@@K@Z ; FindProcInArrayByPID(CPtrArray *,ulong)  
 .text:01002DEC         test  eax, eax  
 .text:01002DEE         jz   loc_1003A7B  
 .text:01002DF4         push  1        ; int  
 .text:01002DF6         push  ebx       ; struct CProcPage *  
 .text:01002DF7         push  dword ptr stru_101E120+4  
 .text:01002DFD         mov   ecx, eax    ; this  
 .text:01002DFF         push  dword ptr stru_101E120 ; union _LARGE_INTEGER  
 .text:01002E05         push  esi       ; struct _SYSTEM_PROCESS_INFORMATION *  
 .text:01002E06         push  dword ptr [ebp+var_64+4]  
 .text:01002E09         push  dword ptr [ebp+var_64] ; union _LARGE_INTEGER  
 .text:01002E0C         call  ?SetData@CProcInfo@@QAEJT_LARGE_INTEGER@@PBU_SYSTEM_PROCESS_INFORMATION@@0PAVCProcPage@@H@Z ; CProcInfo::SetData(_LARGE_INTEGER,_SYSTEM_PROCESS_INFORMATION const *,_LARGE_INTEGER,CProcPage *,int)  
 .text:01002E11         mov   [ebp+var_54], eax  
 .text:01002E14         test  eax, eax  
 .text:01002E16         jge   loc_100C321  
 .text:01002E1C         jmp   loc_100C353  
 .text:01002E1C ; END OF FUNCTION CHUNK FOR ?UpdateProcInfoArray@CProcPage@@QAEJXZ  








1 комментарий:

  1. Очень хороший блог! надеюсь на продолжение публикиций

    ОтветитьУдалить