Новые процессы
Заражение всех запущенных процессов не затронет процессы, которые будут
запущены позже. Мы должны получить список процессов, через некоторое время
получить новый, сравнить их, а затем заразить те процессы, которые есть во
втором списке и отсутствуют в первом. Но этот метод очень ненадежен.
Намного лучше перехватить функцию, которая вызывается, когда стартует
новый процесс. Так как все запущенные в системе процессы заражены, мы не сможем
пропустить ни один новый процесс, используя данный метод. Мы можем перехватить
NtCreateThread, но это не самый простой путь. Мы будем перехватывать функцию
NtResumeThread, которая также всегда вызывается при старте нового процесса.
Она вызвается после NtCreateThread.
Единственная проблема с NtResumeThread состоит в том, что она
вызывается не только при запуске нового процесса. Но мы легко решим эту
проблему. NtQueryInformationThread предоставит нам информацию о том, какой
процесс владеет данным потоком. Мы должны просто проверить, заражен ли этот
процесс. Это можно определить прочитав первые байты любой из функций, которые
мы перехватываем.
NTSTATUS NtQueryInformationThread(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
В нашем случае параметр ThreadInformationClass должен быть равен
ThreadBasicInformation. ThreadInformation - это буфер для результата, размер
этого буфера указан в параметре ThreadInformationLength.
#define ThreadBasicInformation 0
Для класса ThreadBasicInformation возвращается такая структура:
typedef struct _THREAD_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PNT_TIB TebBaseAddress;
CLIENT_ID ClientId;
KAFFINITY AffinityMask;
KPRIORITY Priority;
KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
В параметре ClientId находится PID процесса, владеющего этим потоком.
Теперь мы должны заразить новый процесс. Проблема в том, что процесс
имеет в своей памяти только ntdll.dll. Все остальные модули загружаются сразу
после вызова NtResumeThread. Существует несколько путей решения этой проблемы.
Например, можно перехватить функцию LdrInitializeThunk, которая вызывается при
инициализации процесса.
NTSTATUS LdrInitializeThunk(
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3
);
Сначала нужно выполнить оригинальный код, а замет перехватить все
нужные функции в новом процессе. Затем лучше снять перехват LdrInitializeThunk,
так как она будет вызвана позже много раз, а мы не хватим заново перехватывать
все функции. Все это будет сделано до выполнения первых инструкций процесса,
поэтому нет вероятности того, что этот процесс вызовет какую-нибудь из
перехватываемых функций до того, как мы ее перехватим.
Перехват функций в своем процессе такой же как и перехват в запущенном
процессе, но нам не нужно беспокоиться о потоках.
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!