Давным-давно появились штуки типа DKOM, позволяющие скрывать потоки/процессы/(да и другие объекты ядра) от посторонних глаз, через удаление их из списков ОС( PsActiveProcessLinks/SessionProcessLinks и т.д. ).
Но так получилось, что теже самые потоки/процессы удаленные из одних мест, вполне себе продолжали жить в других(как списках, так и модулях).
Яркий пример подобного можно было наблюдать в 2008м, когда EP_X0FF опубликовал детект процессов(CsrWalker) через перечисление их в сервере подсистемы вин32(csrss).
Однако скрыв потоки/процессы и в этом месте нужно не забыть скрыть их и в третьем.
Третье место находится в ядре графической подсистемы - в win32k.sys.
Каким образом в этом списке оказываются процессы и потоки?
При конвертации потока в gui-поток, то есть тогда, когда поток делает свой первый вызов из shadow sdt.
Конвертация осуществляется ф-цией PsConvertToGuiThread, которая создает новый, больший по размеру ядерный стек для потока(для механизма рекурсивных вызовов шадоу сервисов) и налету заменяет его, устанавливает у потока поле ServiceTable, а также вызывает 2 коллаута:
typedef NTSTATUS (*PKWIN32_PROCESS_CALLOUT)( IN PEPROCESS Process, IN BOOLEAN Initialize );
typedef NTSTATUS (*PKWIN32_THREAD_CALLOUT)( IN PETHREAD Thread, IN PSW32THREADCALLOUTTYPE CalloutType );
extern PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout;
extern PKWIN32_THREAD_CALLOUT PspW32ThreadCallout;
Которые и добавляют потоки в списки win32k.sys.
Что такое коллаут и с чем его едят?
При создании сессии smss.exe загружает ядро графической подсистемы win32k.sys через полудокументированный вызов:
NtSetSystemInformation( SystemLoadAndCallImage, ... ), который маппит win32k.sys в сессинное пространство и вызывает точку входа драйвера.
А в точке входа вызывается ф-ция:
PsEstablishWin32Callouts( W32pProcessCallout,
W32pThreadCallout,
UserGlobalAtomTableCallout,
UserPowerEventCallout,
UserPowerStateCallout,
UserJobCallout,
(PVOID)NtGdiFlushUserBatch);
Которая инициализирует указатели валидными адресами ф-ций.
То есть коллаут это просто указатель который будет проинициализирован при загрузке win32k.sys.
Таким образом при конвертации потока в гуишный вызовется соответствующие коллауты для потока и процесса.
Внутри которых будут выделены новые entry принадлежащие win32k.sys и представленные структурами PROCESSINFO и THREADINFO.
Данные коллауты также вызываются и при уничтожении потока, чтобы соответственно отлинковаться из списков.
PPROCESSINFO gppiList; // глобальный список процессов
ULONG gdwGuiThreads; // счетчик гуишных потоков, апдейтится каждый раз при создании нового гуишного треда
Добравшись до процесса можно получить список его потоков:
typedef struct tagPROCESSINFO
{
W32PROCESS;
PTHREADINFO ptiList;
...
}PROCESSINFO;
Ну и соот-но для любого потока есть указатель на структуру процесса:
typedef struct tagTHREADINFO
{
W32THREAD;
PTL ptl;
PPROCESSINFO ppi;
...
}THREADINFO;
Кроме того, в данных структурах много интересной информации, такой как очереди сообщений(input/post), Integrity Level (vista+, т.к. UIPI появилась с висты), инфа о win station и десктопе и т.д.
Таким образом, недостаточно хорошо спрятанный процесс/поток может быть найден через перечисление процессов и их потоков в ядре графической подсистемы.
Ограничение: НЕ-gui потоки не будут найдены.
Но так получилось, что теже самые потоки/процессы удаленные из одних мест, вполне себе продолжали жить в других(как списках, так и модулях).
Яркий пример подобного можно было наблюдать в 2008м, когда EP_X0FF опубликовал детект процессов(CsrWalker) через перечисление их в сервере подсистемы вин32(csrss).
Однако скрыв потоки/процессы и в этом месте нужно не забыть скрыть их и в третьем.
Третье место находится в ядре графической подсистемы - в win32k.sys.
Каким образом в этом списке оказываются процессы и потоки?
При конвертации потока в gui-поток, то есть тогда, когда поток делает свой первый вызов из shadow sdt.
Конвертация осуществляется ф-цией PsConvertToGuiThread, которая создает новый, больший по размеру ядерный стек для потока(для механизма рекурсивных вызовов шадоу сервисов) и налету заменяет его, устанавливает у потока поле ServiceTable, а также вызывает 2 коллаута:
typedef NTSTATUS (*PKWIN32_PROCESS_CALLOUT)( IN PEPROCESS Process, IN BOOLEAN Initialize );
typedef NTSTATUS (*PKWIN32_THREAD_CALLOUT)( IN PETHREAD Thread, IN PSW32THREADCALLOUTTYPE CalloutType );
extern PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout;
extern PKWIN32_THREAD_CALLOUT PspW32ThreadCallout;
Которые и добавляют потоки в списки win32k.sys.
Что такое коллаут и с чем его едят?
При создании сессии smss.exe загружает ядро графической подсистемы win32k.sys через полудокументированный вызов:
NtSetSystemInformation( SystemLoadAndCallImage, ... ), который маппит win32k.sys в сессинное пространство и вызывает точку входа драйвера.
А в точке входа вызывается ф-ция:
PsEstablishWin32Callouts( W32pProcessCallout,
W32pThreadCallout,
UserGlobalAtomTableCallout,
UserPowerEventCallout,
UserPowerStateCallout,
UserJobCallout,
(PVOID)NtGdiFlushUserBatch);
Которая инициализирует указатели валидными адресами ф-ций.
То есть коллаут это просто указатель который будет проинициализирован при загрузке win32k.sys.
Таким образом при конвертации потока в гуишный вызовется соответствующие коллауты для потока и процесса.
Внутри которых будут выделены новые entry принадлежащие win32k.sys и представленные структурами PROCESSINFO и THREADINFO.
Данные коллауты также вызываются и при уничтожении потока, чтобы соответственно отлинковаться из списков.
PPROCESSINFO gppiList; // глобальный список процессов
ULONG gdwGuiThreads; // счетчик гуишных потоков, апдейтится каждый раз при создании нового гуишного треда
Добравшись до процесса можно получить список его потоков:
typedef struct tagPROCESSINFO
{
W32PROCESS;
PTHREADINFO ptiList;
...
}PROCESSINFO;
Ну и соот-но для любого потока есть указатель на структуру процесса:
typedef struct tagTHREADINFO
{
W32THREAD;
PTL ptl;
PPROCESSINFO ppi;
...
}THREADINFO;
Кроме того, в данных структурах много интересной информации, такой как очереди сообщений(input/post), Integrity Level (vista+, т.к. UIPI появилась с висты), инфа о win station и десктопе и т.д.
Таким образом, недостаточно хорошо спрятанный процесс/поток может быть найден через перечисление процессов и их потоков в ядре графической подсистемы.
Ограничение: НЕ-gui потоки не будут найдены.
Комментариев нет:
Отправить комментарий