Выявление вирусов через потоки
Итак приступим к действиям выявления вредоносных "программ" с основных понятий без которых ну ни как не обойтись.
Мы должны четко и ясно разделять две вещи:
1. процессы они же программы могут работать на низком привелигированном уровне ( User mode - 3 ring - пользовательский режим - 3 кольцо процессора )
2. процессы работающие на высоком уровне доступа к ОСи (Kernel mode - 0 ring - ядерный режим нулевое кольцо процессора) ядерный в смысле ядро ОСи
Для простоты будем рассматривать ядерные процессы или структуры если не указаны они значит мы обсуждаем пользовательский режим.
На сегоднящний день мы знаем что технология файлового заражения все больше и больше отступает вирусам (любой вредоносный код) которые не заражают файлы и не создают отдельные файлы т.к это слишком подозрительно и любой сегоднящний антивирус умеет найти новый или зараженный файл.
Можно даже смело сказать что серьезные вирусные вещи забыли что такое файл и процесс. Почему это так я объсню.
С далеких времен пошло что внедрятся в чужой процесс вирусам намного легче и менее заметно чем устаревшие технологии заражения файлов или что еще хуже создавать свой файл как бы он не назывался не суть важно. Заражение чужих процессов такое как внедрение библиотеки *.dll или внедрение вирусного потока threads в потоки законной программы это сегоднящний уровень развития малвари ( малварь будет короче и звучнее вирусов )
Итак что мы имеем? Имеется программа к примеру винамп лежит себе спокойно на любом известном нам носителе и никого не трогает. Все изменяется при запуске винампа
а что происходит при запуске винампа? да то что и при запуске любой программы - происходит проэцирование файла программы в оперативку ОСи фактически можно сказать что ОСь копирует файл с диска в память это будет конечно не правильно с точки зрения программиста, ну да мы сейчас не об этом ведем речь.
Проэцируясь в память программа переходит на новый этап создавая процесс в системе. Процесс имеет код, ресурсы, потоки и многое другое. Код это конечно сам алгоритм программы выраженный в машинных кодах ресурсы это данные над которыми работает программа включая различные необходимые вещи как иконки курсоры картинки строки и пр.
Все это понятно, но что такое поток? Многие из нас слышали про многопоточные программы к примеру брутофорсеры. Понятие потока заводит нас в тему однозадачных и многозадачных ОСей в первом случае это ms dos во втором win98 и все остальные. В однозадачных системах в любой момент времени выполнялась всего лишь одна задача и не более, если нужно было к примеру подсчитать что нибудь математическое то требовалось закрыть текстовый редактор а потом открыть калькулятор, выполнив вычисления закрыть программу и открыть снова редактор дабы продолжить записывать то с чем мы работали.
Вот такое вот неудобство было в далеком времени но слава Богу эти времена канули в прошлое и мы сегодня можем запустить бесконечное количество программ и переключатся между ними в любое удобное нам время. В многозадачных системах решение было найдено путем переключения процессов по сути это кратковременное выделение времени процессора какому либо одному процессу, а т.к мы сегодня имеем большие мощности процессоров то мы не можем заметить как система успевает обслужить все процессы в системе а их не мало! и уделить внимание любой нуждаещейся в этом программе.
В понятиях системы время - это период начинающийся с переключения одного процесса на другой. Раз мы можем запускать энное количество процессов то почему бы нам не запускать внутри любого процесса энное количество потоков ( подпрограмм ) так и поступили разработчики осуществив эту задачу.
Самый простой пример потоков какой только приводят в подобных статьях это офиссный пакет не важно ворд или эксель важно то что один поток проверяет орфографию текста другой подсчитывает количество слов в документе третий вообще может проверять текст на внедренный макровирусы (макросы внутри доков). С точки зрения программирования т.е практики то здесь все намного проще когда ваша написанная программа будет довольно значительное время занята работой ( долгая закачка файла из сети, обработка базы данных, смещивание фотографий или наложение на них различных эффектов ну и т.д) и выводить как положено временную шкалу указывающую сколько осталось до конца операций с данными то фактически программа не сможет реагировать на действия пользователя, а пользователь может захотеть залезть в настройки вашей программы или побегать по меню посмотрев чем же богата программа и каков ее потенциал то в этот момент программа даже не сможет себя прорисовать т.е свой интерфейс не то что бы выполнить еще одну задачу это говорит о том что программа не выделяет потоки для одновременной обработки данных.
В таком случае приходят к многопоточности которую нужно реализовать в программе. Не вдаваясь в технические подробности как писать потоки и как их реализовать в своем софте можно смело сказать что поток это подпрограмма и не более того. В таком случае выходит что система мало того что переключает процессы и каждому выделяет квант времени да к тому же еще переключает и потоки процесса. Ну да мы слегка отвлеклись вернемся к тому как же выявить чужеродный поток в законном процессе.
Открыв карту памяти любого процесса ( к примеру это можно сделать в любом вам известном отладчике, а тем кому это не известно используем отладчик OllyDbg) в ольке ))) OllyDebuger хорошо сейчас опишу по проше.
Открываем отладчик шагаем в file -> attache запускаем блокнот notepad.exe или что вам хочется эт по вкусу и выбираем блокнот в списке процессов нажав атач.
Дальше не обращая внимание на все окна в программе смело шагаем в меню view->Memory и вот перед нами открывает карта процесса блокнота.
Не спешите разбиратся что здесь к чему это отдельная тема нам нужна всего лишь одна колонка Type т.е тип памяти. Каждая область памяти имеет атрубуты :
только для чтения, выполнение и другие это похоже на файловые атрибуты. Важно понять что атрибуты эти указывают права для данного участка памяти т.е либо на страницу памяти стоит запрет на запись и тогда при попытке записать что-то либо произойдет исключение аля критическая ошибка.
Так вот код программы должен находится в секции памяти с типом Image ( Imag 0100 лично у меня так отображает отладчик ) если он код программы находится в приватном типе Priv то это очень подозрительно и так не должно быть. Есть еше один тип Map это мэппирование файлов ( читай проэцирование больших объемных файлов в память ) по этому поводу листай темы по функциям CreateFileMapping(); Mapviewoffile(); конечно же это не принципиально важно в делфи в си или си++ вы будете писать, структуры и апи одни и теже разница только в оформлении и синтаксисе вашего языка программирования.
Короче говоря вы должны усвоить важное понятие что в каком бы участке памяти процесса не был бы код нужно смотреть на ассемблерный листинг что там происходит а это конечно же уже отдельная тема и здесь я об этом не буду говорить.
Вы спросите меня причем здесь внедренный код в память процесса ? когда я собирался говорить о потоках.
Да здесь я немножко виноват забыв описать одну технологию внедрения кода малвари во все процессы к примеру проэцирование кода малварной библиотечки.
Имеется такая функция VirtualAlloc(Ex) которая может выделить из кучи памяти необходимый вам буфер нужного вам размера потом с помощью WriteProcessMemory мы внедряем вирусный код. Вот для этого я и описывал эту технологию.
А теперь шагаем дальше и посмотрим потоки блокнота view->Threads не знаю как у вас у меня их обнаружилось всего лишь два ну да ничего это не страшно два или десять )))
Что бы понять что поток наш а не внедренный вирусом необходимо все таки поднатаскатся опыта либо взламывания программ ( www.exelab.ru вам в помощь ) либо практика программирования системы плюс ко всему необходимо хотя бы минимальное знание ассемблера - машинного кода который отображает нам отладчик только тогда будет понятно что делает код потока или процесса.
Диспетчер задач Марка Руссиновича показывает довольно подробные сведенья о потоках можно по надеятся на аномальные показатели в количестве потоков в процессе или очень большое время процессор выделяет какому либо процессу ну и как следствие потоку или потокам но это как говорится как повезет 50 на 50 по крайней мере знать об этом полезно, но в большинстве случаев необходимо разбиратся с кодом и смотреть что он делает и что может сделать.
Варианты когда вирус мог сильно нагружать систему как по процессору так и по памяти ушли в далекие времена,а если и будет что-то подобное то это скорее исключение чем правило либо вирус далеких времен. Сейчас малварь сидит тихо ( если вообще сидит ? собрали пароли,скопировали важные данные и ушли зачем сидеть в системе? ) и не делает критических ошибок и не пожирает память неимоверно.
Еще стоит нам рассмотреть такую тему как чем же отличается получение списка процессов в 3м кольце со списком процессов в нулевом кольце?
В нулевом кольце аля ядре системы имеется двусвязный список - замкнутый кольцевой список в этом списке и имеются все процессы ОСи.
Стоит сравнить результаты получения списка процессов в пользовательском режиме и в ядерном и будет сразу видно скрытые процессы - руткиты или поточнее скрытый процесс малвари использующей руткитные технологии. С уровня пользователя мы не сможем увидеть все скрытые процессы ( если конечно малварь закрепилась в ядре ОС) только нырнув глубже ближе к ядру ОС теплее )))
И в ядре малварь может себя скрыть, но там это будет легко узнать,а вот с высоты пользовательского режима это сделать не возможно.
Доступ к ядру имеют драйверы поэтому диспетчер задач если будете писать его должен использовать драйвер для перехода в режим ядра либо в другой какой нибудь антивирусной утилитке. Ну про это как нибудь напишу в другой раз.
Ну и для закрепления всей описанной мной теории стоит попрактиковатся и посмотреть кто есть кто
советую почитать книгу по руткитам вирусам Олега Зайцева автора антивируса AVZ
вот пример который взят из его книги это по поводу внедрения дллки в процесс.
1.Собираем библиотечку test_td в делфи
2.собираем программу код ее ниже и запускаем ее смотрим как происходит это на практике
Если не знаете как это делать то значит пока еще рано к этому переходить начните с азов, а для тех кто в силах провести испытание
сразу предупреждаю что код я не тестировал просто валялся в далеком уголке винта и я решил добавить его сюда, если есть страх "заражения" то лучше
не пробуйте это на практике. Сама суть этой же практике довольно подробно описана у Зайцева читайте.
И еще изучайте ассемблер,программируйте побольше и конечно же приобретите навыки крякера будет полезно в любом случае. Удачи вам в борьбе добра со злом :)
=============================== Код самой дллки ================================
library test_td;
uses
wintypes,
winprocs,
messages;
var HookHandle :hHook;
function HookProc(ncode:integer;wparam:word; lparam:longint):longint;stdcall
begin
result:=callnexthookex(hookhandle,ncode,wparam,lparam);
end;
function sethook(hookhandle:hhook):hhook;stdcall;
begin
if hookhandle=0 then
result:=setwindowshookex(wh_getmessage,@hookproc,hinstance,0);
end;
procedure DelHook;stdcall;
begin
if HookHandle<>0 then begin
UnHookWindowsHookEx(HookHandle);
HookHandle:=0;
end;
end;
exports SetHook,DelHook;
begin
HookHandle:=0;
end.
================================= конец дллки =============================
================================= код программы инжектора =================
unit Loader_Injecter;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
PopupMenu1: TPopupMenu;
SetHook1: TMenuItem;
DelHook1: TMenuItem;
procedure Button1Click(Sender: TObject);
procedure SetHook1Click(Sender: TObject);
procedure DelHook1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
MyHookDllName='test_td.dll';
function SetHook:LongInt;stdcall;external MyHookDllName;
function DelHook:LongInt;stdcall;external MyHookDllName;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
popupmenu1.Popup(mouse.CursorPos.X,mouse.CursorPos.Y);
end;
procedure TForm1.SetHook1Click(Sender: TObject);
var recipients:dword;
begin
sethook;
recipients:=bsm_allcomponents;
BroadCastSystemMessage(bsf_forceifhung or bsf_ignorecurrenttask,@recipients,wm_null,0,0);
end;
procedure TForm1.DelHook1Click(Sender: TObject);
begin
delhook;
end;
procedure TForm1.FormCreate(Sender: TObject);
var hlib:cardinal;
begin
hLib:=loadlibrary(pchar('test_td.dll'));
if hLib=0 then begin showmessage('Library is not found');exit;end;
end;
end.
================================ Конец инжектора ))) ==============================
Итак приступим к действиям выявления вредоносных "программ" с основных понятий без которых ну ни как не обойтись.
Мы должны четко и ясно разделять две вещи:
1. процессы они же программы могут работать на низком привелигированном уровне ( User mode - 3 ring - пользовательский режим - 3 кольцо процессора )
2. процессы работающие на высоком уровне доступа к ОСи (Kernel mode - 0 ring - ядерный режим нулевое кольцо процессора) ядерный в смысле ядро ОСи
Для простоты будем рассматривать ядерные процессы или структуры если не указаны они значит мы обсуждаем пользовательский режим.
На сегоднящний день мы знаем что технология файлового заражения все больше и больше отступает вирусам (любой вредоносный код) которые не заражают файлы и не создают отдельные файлы т.к это слишком подозрительно и любой сегоднящний антивирус умеет найти новый или зараженный файл.
Можно даже смело сказать что серьезные вирусные вещи забыли что такое файл и процесс. Почему это так я объсню.
С далеких времен пошло что внедрятся в чужой процесс вирусам намного легче и менее заметно чем устаревшие технологии заражения файлов или что еще хуже создавать свой файл как бы он не назывался не суть важно. Заражение чужих процессов такое как внедрение библиотеки *.dll или внедрение вирусного потока threads в потоки законной программы это сегоднящний уровень развития малвари ( малварь будет короче и звучнее вирусов )
Итак что мы имеем? Имеется программа к примеру винамп лежит себе спокойно на любом известном нам носителе и никого не трогает. Все изменяется при запуске винампа
а что происходит при запуске винампа? да то что и при запуске любой программы - происходит проэцирование файла программы в оперативку ОСи фактически можно сказать что ОСь копирует файл с диска в память это будет конечно не правильно с точки зрения программиста, ну да мы сейчас не об этом ведем речь.
Проэцируясь в память программа переходит на новый этап создавая процесс в системе. Процесс имеет код, ресурсы, потоки и многое другое. Код это конечно сам алгоритм программы выраженный в машинных кодах ресурсы это данные над которыми работает программа включая различные необходимые вещи как иконки курсоры картинки строки и пр.
Все это понятно, но что такое поток? Многие из нас слышали про многопоточные программы к примеру брутофорсеры. Понятие потока заводит нас в тему однозадачных и многозадачных ОСей в первом случае это ms dos во втором win98 и все остальные. В однозадачных системах в любой момент времени выполнялась всего лишь одна задача и не более, если нужно было к примеру подсчитать что нибудь математическое то требовалось закрыть текстовый редактор а потом открыть калькулятор, выполнив вычисления закрыть программу и открыть снова редактор дабы продолжить записывать то с чем мы работали.
Вот такое вот неудобство было в далеком времени но слава Богу эти времена канули в прошлое и мы сегодня можем запустить бесконечное количество программ и переключатся между ними в любое удобное нам время. В многозадачных системах решение было найдено путем переключения процессов по сути это кратковременное выделение времени процессора какому либо одному процессу, а т.к мы сегодня имеем большие мощности процессоров то мы не можем заметить как система успевает обслужить все процессы в системе а их не мало! и уделить внимание любой нуждаещейся в этом программе.
В понятиях системы время - это период начинающийся с переключения одного процесса на другой. Раз мы можем запускать энное количество процессов то почему бы нам не запускать внутри любого процесса энное количество потоков ( подпрограмм ) так и поступили разработчики осуществив эту задачу.
Самый простой пример потоков какой только приводят в подобных статьях это офиссный пакет не важно ворд или эксель важно то что один поток проверяет орфографию текста другой подсчитывает количество слов в документе третий вообще может проверять текст на внедренный макровирусы (макросы внутри доков). С точки зрения программирования т.е практики то здесь все намного проще когда ваша написанная программа будет довольно значительное время занята работой ( долгая закачка файла из сети, обработка базы данных, смещивание фотографий или наложение на них различных эффектов ну и т.д) и выводить как положено временную шкалу указывающую сколько осталось до конца операций с данными то фактически программа не сможет реагировать на действия пользователя, а пользователь может захотеть залезть в настройки вашей программы или побегать по меню посмотрев чем же богата программа и каков ее потенциал то в этот момент программа даже не сможет себя прорисовать т.е свой интерфейс не то что бы выполнить еще одну задачу это говорит о том что программа не выделяет потоки для одновременной обработки данных.
В таком случае приходят к многопоточности которую нужно реализовать в программе. Не вдаваясь в технические подробности как писать потоки и как их реализовать в своем софте можно смело сказать что поток это подпрограмма и не более того. В таком случае выходит что система мало того что переключает процессы и каждому выделяет квант времени да к тому же еще переключает и потоки процесса. Ну да мы слегка отвлеклись вернемся к тому как же выявить чужеродный поток в законном процессе.
Открыв карту памяти любого процесса ( к примеру это можно сделать в любом вам известном отладчике, а тем кому это не известно используем отладчик OllyDbg) в ольке ))) OllyDebuger хорошо сейчас опишу по проше.
Открываем отладчик шагаем в file -> attache запускаем блокнот notepad.exe или что вам хочется эт по вкусу и выбираем блокнот в списке процессов нажав атач.
Дальше не обращая внимание на все окна в программе смело шагаем в меню view->Memory и вот перед нами открывает карта процесса блокнота.
Не спешите разбиратся что здесь к чему это отдельная тема нам нужна всего лишь одна колонка Type т.е тип памяти. Каждая область памяти имеет атрубуты :
только для чтения, выполнение и другие это похоже на файловые атрибуты. Важно понять что атрибуты эти указывают права для данного участка памяти т.е либо на страницу памяти стоит запрет на запись и тогда при попытке записать что-то либо произойдет исключение аля критическая ошибка.
Так вот код программы должен находится в секции памяти с типом Image ( Imag 0100 лично у меня так отображает отладчик ) если он код программы находится в приватном типе Priv то это очень подозрительно и так не должно быть. Есть еше один тип Map это мэппирование файлов ( читай проэцирование больших объемных файлов в память ) по этому поводу листай темы по функциям CreateFileMapping(); Mapviewoffile(); конечно же это не принципиально важно в делфи в си или си++ вы будете писать, структуры и апи одни и теже разница только в оформлении и синтаксисе вашего языка программирования.
Короче говоря вы должны усвоить важное понятие что в каком бы участке памяти процесса не был бы код нужно смотреть на ассемблерный листинг что там происходит а это конечно же уже отдельная тема и здесь я об этом не буду говорить.
Вы спросите меня причем здесь внедренный код в память процесса ? когда я собирался говорить о потоках.
Да здесь я немножко виноват забыв описать одну технологию внедрения кода малвари во все процессы к примеру проэцирование кода малварной библиотечки.
Имеется такая функция VirtualAlloc(Ex) которая может выделить из кучи памяти необходимый вам буфер нужного вам размера потом с помощью WriteProcessMemory мы внедряем вирусный код. Вот для этого я и описывал эту технологию.
А теперь шагаем дальше и посмотрим потоки блокнота view->Threads не знаю как у вас у меня их обнаружилось всего лишь два ну да ничего это не страшно два или десять )))
Что бы понять что поток наш а не внедренный вирусом необходимо все таки поднатаскатся опыта либо взламывания программ ( www.exelab.ru вам в помощь ) либо практика программирования системы плюс ко всему необходимо хотя бы минимальное знание ассемблера - машинного кода который отображает нам отладчик только тогда будет понятно что делает код потока или процесса.
Диспетчер задач Марка Руссиновича показывает довольно подробные сведенья о потоках можно по надеятся на аномальные показатели в количестве потоков в процессе или очень большое время процессор выделяет какому либо процессу ну и как следствие потоку или потокам но это как говорится как повезет 50 на 50 по крайней мере знать об этом полезно, но в большинстве случаев необходимо разбиратся с кодом и смотреть что он делает и что может сделать.
Варианты когда вирус мог сильно нагружать систему как по процессору так и по памяти ушли в далекие времена,а если и будет что-то подобное то это скорее исключение чем правило либо вирус далеких времен. Сейчас малварь сидит тихо ( если вообще сидит ? собрали пароли,скопировали важные данные и ушли зачем сидеть в системе? ) и не делает критических ошибок и не пожирает память неимоверно.
Еще стоит нам рассмотреть такую тему как чем же отличается получение списка процессов в 3м кольце со списком процессов в нулевом кольце?
В нулевом кольце аля ядре системы имеется двусвязный список - замкнутый кольцевой список в этом списке и имеются все процессы ОСи.
Стоит сравнить результаты получения списка процессов в пользовательском режиме и в ядерном и будет сразу видно скрытые процессы - руткиты или поточнее скрытый процесс малвари использующей руткитные технологии. С уровня пользователя мы не сможем увидеть все скрытые процессы ( если конечно малварь закрепилась в ядре ОС) только нырнув глубже ближе к ядру ОС теплее )))
И в ядре малварь может себя скрыть, но там это будет легко узнать,а вот с высоты пользовательского режима это сделать не возможно.
Доступ к ядру имеют драйверы поэтому диспетчер задач если будете писать его должен использовать драйвер для перехода в режим ядра либо в другой какой нибудь антивирусной утилитке. Ну про это как нибудь напишу в другой раз.
Ну и для закрепления всей описанной мной теории стоит попрактиковатся и посмотреть кто есть кто
советую почитать книгу по руткитам вирусам Олега Зайцева автора антивируса AVZ
вот пример который взят из его книги это по поводу внедрения дллки в процесс.
1.Собираем библиотечку test_td в делфи
2.собираем программу код ее ниже и запускаем ее смотрим как происходит это на практике
Если не знаете как это делать то значит пока еще рано к этому переходить начните с азов, а для тех кто в силах провести испытание
сразу предупреждаю что код я не тестировал просто валялся в далеком уголке винта и я решил добавить его сюда, если есть страх "заражения" то лучше
не пробуйте это на практике. Сама суть этой же практике довольно подробно описана у Зайцева читайте.
И еще изучайте ассемблер,программируйте побольше и конечно же приобретите навыки крякера будет полезно в любом случае. Удачи вам в борьбе добра со злом :)
=============================== Код самой дллки ================================
library test_td;
uses
wintypes,
winprocs,
messages;
var HookHandle :hHook;
function HookProc(ncode:integer;wparam:word; lparam:longint):longint;stdcall
begin
result:=callnexthookex(hookhandle,ncode,wparam,lparam);
end;
function sethook(hookhandle:hhook):hhook;stdcall;
begin
if hookhandle=0 then
result:=setwindowshookex(wh_getmessage,@hookproc,hinstance,0);
end;
procedure DelHook;stdcall;
begin
if HookHandle<>0 then begin
UnHookWindowsHookEx(HookHandle);
HookHandle:=0;
end;
end;
exports SetHook,DelHook;
begin
HookHandle:=0;
end.
================================= конец дллки =============================
================================= код программы инжектора =================
unit Loader_Injecter;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
PopupMenu1: TPopupMenu;
SetHook1: TMenuItem;
DelHook1: TMenuItem;
procedure Button1Click(Sender: TObject);
procedure SetHook1Click(Sender: TObject);
procedure DelHook1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
MyHookDllName='test_td.dll';
function SetHook:LongInt;stdcall;external MyHookDllName;
function DelHook:LongInt;stdcall;external MyHookDllName;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
popupmenu1.Popup(mouse.CursorPos.X,mouse.CursorPos.Y);
end;
procedure TForm1.SetHook1Click(Sender: TObject);
var recipients:dword;
begin
sethook;
recipients:=bsm_allcomponents;
BroadCastSystemMessage(bsf_forceifhung or bsf_ignorecurrenttask,@recipients,wm_null,0,0);
end;
procedure TForm1.DelHook1Click(Sender: TObject);
begin
delhook;
end;
procedure TForm1.FormCreate(Sender: TObject);
var hlib:cardinal;
begin
hLib:=loadlibrary(pchar('test_td.dll'));
if hLib=0 then begin showmessage('Library is not found');exit;end;
end;
end.
================================ Конец инжектора ))) ==============================
Комментариев нет:
Отправить комментарий