|
Моделирование эпидемии
|
|
| На главную | Контакты | Карта сайта | Регистрация доменов | Cотовая связь | Учебник PHP | Интернет |
Моделирование эпидемии |
||||
<<...я чувствовал себя Кевином Митником.
Это было охуительно...>>
Неизвестный хакер
Честно говоря, и во-первых, не эпидемии. Потому что под эпидемией мы понимаем неконтролируемое распространение компьютерного вируса, либо червя. Если же некий контроль имеется, то это уже не эпидемия -- несмотря на то, что со стороны так может показаться. Потому что, и это понятно, тот, у кого была возможность задать параметры размножения, отнюдь не преследует целей засрать всю сеть ненужным траффиком. Но поскольку подавляющее большинство сегодняшних самораспространяющихся программ не предусматривают никакого контроля, то мы и имеем то, что имеем.
О моделировании, так и это тоже не совсем правда. Потому, что моделирование в массовом сознании как бы подразумевает отсутствие практики. Это не так. Наше моделирование -- это средство для получения информации о том, что будет ПОСЛЕ.
Итак, мы ведем речь о планировании действий самораспространяющейся программы.
Поскольку этот текст -- первая попытка описать то, что мы знаем о моделировании, здесь навряд ли получится рассказать обо всем, о чем хотелось... так что не плюйте в монитор.
Основные понятия таковы:
| червь -- | Самораспространяющаяся программа. Направлена на захват интернетовских машин с целью использования их ресурсов. | ||
| сеть -- | (сеть червей) -- виртуальная сущность, множество связанных друг с другом инфицированных машин. Считается, что предусматривается возможность удаленного контроля над элементами сети по-отдельности и над сетью в целом. То есть сеть -- это когда все инфицированные машины действуют согласно некоторому единому плану, при этом обмениваясь некоторой внутренней информацией. Интересным свойством является возможность хранения и обработки распределенной базы данных, т.к. это позволит написать программу, работающую постоянно и независимо от ее носителей. | ||
| Nmax -- | Число моделируемых машин. Будем считать константой. Другими словами, это общее число машин, являющихся потенциальными носителями червя. То есть это те машины, в которых есть такие дыры, которые мы можем использовать. Естественно, мы моделируем не все предполагаемое множество реальных машин, а только некоторую его часть. | ||
| Cgmt -- |
Это число отражает вращение земного шарика вокруг своей оси;
что, в свою очередь, означает смену дня и ночи,
и соответственно здесь есть некоторая связь с
включенными/выключенными машинами.
Более точно, Cgmt показывает, какую часть суток
включена среднестатистическая моделируемая машина.
Мы будем называть эту ситуацию "проблемой GMT", так уж повелось.
Например при 8-часовом рабочем дне Cgmt может быть равно 8/24=0.33. Более того, при случайно выбираемых машинах, при большом их числе, Cgmt всегда меньше единицы, так как всегда есть вероятность того, что какие-то из машин выключены. | ||
| Na -- | Число активных машин. Переменно. Зависит от времени дня, от типа моделируемых машин, от распределения машин по временным зонам, и десятков прочих факторов. Поскольку мы ориентируемся на то, что машины разбросаны повсюду, то будем считать, что в среднем, при нормальном положении дел (т.е. изначально), Na=Nmax*Сgmt, где Cgmt=0.3(imho!) для юзерских машин и Cgmt=1 для серверов. | ||
| Ni -- | Число инфицированных машин, т.е. машин, уже являющихся носителями червя. Переменно. Зависит от времени, прошедшего с момента запуска червя, т.е. от поведения моделируемой системы за прошедшее время. Сюда входят активные и пассивные зараженные машины, т.е. как работающие, так и недоступные в настоящее время (например, выключенные). | ||
| Nai -- | Число активных инфицированных машин. Переменно.
Другими словами, это число инфицированных машин,
активных на данный момент.
Ибо другая часть инфицированных машин "спит",
согласно своей временной зоне и привычкам хозяина машины.
Если же червь таков, что хранится исключительно в памяти компьютера, т.е. инфицированная машина после перезагрузки самоизлечивается, то Nai очень близко к Ni, но не равно, так как тут есть такая фича как гибернация (hibernate), и ее стоит иметь в виду -- потому что из этого следует что всегда есть вероятность "всплывания" червя через некоторое время. Кроме того, связь с червем может быть прервана на некоторое время и без всякого выключения/гибернации машины-носителя, хотя бы и из-за временных глюков в сети. | ||
| Nai0 -- | Начальное число активных инфицированных машин, т.е. число машин, с которых начинается массовое распространение червя. Обычно считалось, что равно 1 (запуск с одной машины). Это число суть весьма важный фактор, и увеличивая его можно существенно сократить суммарное время захвата всех машин, а также более точно предсказать изменение числа инфицированных машин Ni, так как в самом начале, при малом числе инфицированных машин, влияние случайных факторов велико. | ||
| t -- | Время, прошедшее с момента активирования червя. Эксперимент мы считаем закончившимся тогда, когда все Nmax (или чуть меньше, 99%) машин инфицированы. Последний 1% машин можно не рассматривать, так как при выборе адреса случайным образом их нахождение потребует сравнительно много времени. | ||
| Ts -- | Время, необходимое на поиск (s=search) новой машины.
В случае, если червь изначально содержит в себе список необходимых адресов, Ts=0. Это может быть достигнуто предварительным сканом. В случае, если черви хранят и обновляют распределенную базу данных об обработанных адресах, то это время будет постоянно уменьшаться. Поясним на примере: на левой картинке поиск адресов происходит случайным образом, на правой -- с учетом ранее найденных адресов.
| ||
| Tc -- | Время, необходимое на проверку (c=check) того, что в софте машины есть одна или несколько определенных используемых нами дыр. | ||
| Pc -- | Вероятность того, что дыры присутствуют. То есть вероятность того, что после проверки (затрачено время Tc) мы будем пытаться машину инфицировать. | ||
| Ti -- | Время, необходимое на инфицирование одной машины. То есть время от начала инфицирования и до получения с инфицированной машины ответа от успешно запущенного червя, плюс (опционально) передача новому червю каких-то данных, в случае, если черви объединены в сеть. | ||
| Pi -- | Вероятность успеха при инфицировании машины. То есть 1-Pi отражает те случаи, когда затрачено Ts+Tc+Ti. | ||
| S -- | шаг по времени. |
Откуда взять Cgmt, Ts, Tc, Pc, Ti, Pi ?
Подсчитать на практике. Прикинуть. Спросить у дяди васи. Все зависит от типа машин (и используемых дыр), от качества червя, само собой, и прочего и прочего.
Как выбрать Nmax и S ?
Таким образом, задав вышеописанные Nmax, S, Cgmt, Ts, Tc, Pc, Ti, Pi и Nai0, можно построить графики Na(t), Ni(t) и Nai(t).
Теперь собственно о моделировании, но для начала -- о рандомном генераторе. Точнее -- о том, как при моделировании включить/выключить некую i-ю машину около, например, десяти часов. Ясно, что моделировать такое событие для каждой машины ровно в указанное время нельзя -- это будет лажа. Но и рандомно разбросать время включения [9:30..10:30] -- тоже как-то не очень. Ибо тогда получится что до 9:30 машины молчали, а потом в течении ровно часа включались то там то здесь.
Поэтому вам предлагаются следующие графики, показывающие, как можно извратить обычный рандомный генератор так, чтобы изменить распределение генерируемых им значений.
|
|
|
|
Вот весьма простая моделирующая програмка:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define Nmax 10000
#define Nai0 10
#define Cgmt 30 // %
#define S 10 // sec
#define Ts 60 // sec
#define Tc 60 // sec
#define Pc 10 // %
#define Ti 300 // sec
#define Pi 90 // %
#define INMEMORY 0 // 0/1
int t, Na, Ni, Nai;
// биты состояния машины: параметр:
#define ST_ACTIVE 0x00000001 // активная m_time1
#define ST_INFECTED 0x00000002 // инфицированная m_time1
#define ST_SEARCHING 0x00000004 // идет поиск цели m_time2
#define ST_CHECKING 0x00000008 // идет проверка цели m_time2
#define ST_INFECTING 0x00000010 // идет инфицирование цели m_time2
// моделируемые машины
int m_state[Nmax]; // ST_xxx -- состояние
int m_time1[Nmax]; // [sec] -- время последующего включения/выключения
int m_time2[Nmax]; // [sec] -- время окончания поиска/проверки/инфицирования
int m_target[Nmax]; // # -- индекс обрабатываемой цели
int tmpn; // временный массив индексов активных машин для ускорения выбора
int tmp[Nmax]; // случайной машины при инфицировании
// рандомер
DWORD randseed;
DWORD my_random(DWORD range)
{
randseed = randseed * 214013 + 2531011;
if (range >= 65536)
return randseed % range;
else
return ((randseed >> 16) * range) >> 16; // в 1.5 раза быстрее чем %
}
#define rndX(x) ((x) + my_random((x)/30) - my_random((x)/30))
void main()
{
randseed = GetTickCount(); // randomize
FILE*log=fopen("model.log","wb");
// инициализируем машины
for(int i=0; i<Nmax; i++)
{
if ((my_random(100) < Cgmt) || (i < Nai0))
{
m_state[i] = ST_ACTIVE; // активная машина
m_time1[i] = my_random( 24*3600*Cgmt/100 ); // время выключения
if (i < Nai0)
m_state[i] |= ST_INFECTED; // изначально инфицированные машины
}
else
{
m_state[i] = 0; // выключенная машина
m_time1[i] = my_random( 24*3600*(100-Cgmt)/100 ); // время включения
}
}
for(t = 0; ; t += S) // главный цикл, для каждого момента времени
{
// включения/выключения машин,
// это действо имеет больший приоритет чем червь
for(int i=0; i<Nmax; i++)
if (t >= m_time1[i]) // окончилось время ожидания?
if ( m_state[i] & ST_ACTIVE ) // была активная машина?
{
m_state[i] &= INMEMORY ? 0 : ST_INFECTED; // теперь выключена
m_time1[i] = t + rndX( 24*3600*(100-Cgmt)/100 ); // время включения
}
else // была выключенная машина?
{
m_state[i] |= ST_ACTIVE; // теперь включена
m_time1[i] = t + rndX( 24*3600*Cgmt/100 ); // время выключения
}
// создаем временный список активных машин,
// для ускорения выбора случайной машины при инфицировании
tmpn = 0;
for(int j=0; j<Nmax; j++)
if (m_state[j] == ST_ACTIVE)
tmp[tmpn++] = j;
// моделируем действия червя
for(int i=0; i<Nmax; i++) // для каждой машины
if (m_state[i] & ST_ACTIVE) // для каждой активной
if (m_state[i] & ST_INFECTED) // для каждой активной-инфицированной
// ничего не делает?
if ((m_state[i] & (ST_SEARCHING|ST_CHECKING|ST_INFECTING))==0)
{
m_state[i] |= ST_SEARCHING; // теперь ищет цель
m_time2[i] = t + rndX( Ts ); // время окончания поиска
}
else // окончилось время поиска/проверки/инфицирования?
if (t >= m_time2[i])
{
if (m_state[i] & ST_SEARCHING) // искали новую машину?
{
m_state[i] &= ~ST_SEARCHING; // больше не ищем
// выбираем случайную цель
if (tmpn) // если таковая имеется
{
int ti = my_random(tmpn);
int tv = tmp[ti];
tmp[ti] = tmp[--tmpn];
m_target[i] = tv; // индекс цели
m_state[i] |= ST_CHECKING; // будем проверять на наличие дыр
m_time2[i] = t + rndX( Tc ); // время окончания проверки
}
}
else
if (m_state[i] & ST_CHECKING) // проверяли найденную цель?
{
m_state[i] &= ~ST_CHECKING; // больше не проверяем
if (my_random(100) < Pc) // с вероятностью Pc успех
{
m_state[i] |= ST_INFECTING; // теперь будем инфицировать
m_time2[i] = t + rndX( Ti ); // время на инфицирование
}
}
else
if (m_state[i] & ST_INFECTING) // инфицировали?
{
m_state[i] &= ~ST_INFECTING; // закончили
if (my_random(100) < Pi) // с вероятность Pi все OK
{
// помечаем найденную и проверенную машину как инфицированную
if (m_state[m_target[i]] == ST_ACTIVE)
m_state[m_target[i]] |= ST_INFECTED;
}
}
}
// считаем статистику
Na = Ni = Nai = 0;
for(int i=0; i<Nmax; i++)
{
if (m_state[i] & ST_ACTIVE) Na++;
if (m_state[i] & ST_INFECTED) Ni++;
if (m_state[i] & ST_ACTIVE) if (m_state[i] & ST_INFECTED) Nai++;
}
// выводим статистику в лог
fprintf(log,"t=%i Na=%i Ni=%i Nai=%i\n", t,Na,Ni,Nai);
// последние машины не проверяем -- это долго
if (Ni >= Nmax*99/100) break;
}
fclose(log);
} //main
|
И вот некоторые результаты:
Как видим на графике выше, в начале число инфицированных машин Ni растет экспоненциально, но с учетом Cgmt, рост резко ограничивается, и далее Ni увеличивается только линейно: ибо Земля вращается равномерно ;-), и начиная со второй части графика все вновь поступившие машины тут же инфицируются. Из этого следует, что с учетом Cgmt, невозможно инфицировать равномерно распределенные по временным зонам машины меньше чем за 24*(1-Cgmt) часов.
Увеличим число моделируемых машин Nmax:
Становится ясно, что Nmax почти не влияет на результат. Таким образом, в случае, когда затратами времени на связь можно пренебречь, адреса машин известны заранее, а вероятность ошибок мала, время инфицирования всех машин будет определяться одним только Cgmt, и если оно близко к 1 (сервера), то все произойдет в течении буквально одного-двух часов, так как линейная часть графика будет отсутствовать и прирост инфицированных машин будет идти по экспоненте.
Теперь поизменяем различные параметры и посмотрим что получится. Уменьшаем шаг по времени, S:
Результат совсем немного изменился, причем в лучшую сторону; но это не стоит втрое больших затрат по времени (хотя это все равно какие-то минуты).
Увеличим число изначально активных инфицированных машин, Nai0, с которых начинается распространение:
Как видно, в области, близкой к 0, удалось покоцать медленно растущий участок экспоненциальной части графика. В случае, если линейная часть Ni(t) незначительна, и все приходится на экспоненциальную часть, этим можно предельно уменьшить суммарное время на инфицирование всех машин, а также снизить влияние случайных факторов.
Увеличиваем Cgmt до 90%, то есть моделируем машины, включенные большую часть времени:
Результат радует, не правда ли? Несколько часов на все.
Предположим, что червь поддерживает большое количество операционных систем, софта и дыр. Это будет означать, что слегка увеличится время проверок машин на наличие дыр Tc, но вместе с тем и увеличится вероятность их нахождения Pc:
Экспоненциальная часть графика резко увеличилась, и действительно, в этом случае почти каждое обращение к найденной машине ведет к ее инфицированию.
Рассмотрим случай, когда червь хранится только в памяти компьютера, и после перезагрузки машина возвращается в обычное не-инфицированное состояние:
Как видим, при Cgmt существенно меньшем единицы, становится невозможным единовременно захватить большую часть машин, так как червь с них постоянно исчезает.
И тут есть красивая ситуация. Ведь вновь инфицированные машины -- это не те же самые, что были инфицированы раньше; так как повторные инфицирования тех же машин пойдут только через интервалы времени кратные суткам, и таким образом червь, находясь исключительно на активных машинах, будет каждый день "обползать" Землю по кругу, при этом, в основной своей массе, находясь на солнечной стороне, так как там активных машин больше.
Теперь в кратце рассмотрим то, что мы здесь забыли.
| На главную | Карта сайта | Windows 7 | Windows Registry | Stop-экраны | Update for Windows | Файл настроек .htaccess | Всё для мобильного телефона | |
|
|
po gonn © 2004 "JULI'S BEEHIVE" | |
| |