-
Notifications
You must be signed in to change notification settings - Fork 15
/
dpgn_rus.txt
290 lines (221 loc) · 11.3 KB
/
dpgn_rus.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
"DELAYED CODE"
technology
версия 1.1
[*] Введение
Итак, мы написали вирус. Будет написан антивир, и через некоторое время
все инфицированные компьютеры будут вылечены.
Эта статья о том, как увеличить продолжительность этого периода.
[*] Идея
Вставим в вирус "изменяющий код", то есть код, который сработает,
скажем, через два месяца, и изменит некоторые команды около вирусной
точки входа (и/или любые другие характеристики вируса).
В результате чего изменится контрольная сумма, и вирус перестанет
определяться.
Если изменяющий код будет присутствовать в вирусе изначально,
антивирус будет содержать такие контрольные суммы, на которые наше
изменение не подействует.
Существует только один способ запретить анализ "изменяющего кода" -
скрыть его от всех. И есть следующие реализации этого способа:
1. Ждать получения изменяющего кода из Интернета, либо зашифровать код
и ждать получения ключа расшифровки.
2. Зашифровать код так, чтобы его расшифровка заняла как раз требуемое
время, например обозначенные выше два месяца. ("delayed code")
Как можно видеть, последний вариант позволяет написать полностью
автоматический вирус со скрытыми свойствами.
[*] Теория (кривая хрень, использовать которую мы на самом деле не будем)
Извратим буфер из случайных чисел A[] некоторым хэшируем алгоритмом
столько раз N, чтобы это заняло некоторый период T.
В результате чего получим буфер B[], который и будет использоваться
для шифровки/расшифровки "отложенного" кода.
Отметим, что эти N итераций никак нельзя распараллелить на несколько
компьютеров, так что минимальное время шифровки/расшифровки будет
ограничиваться только максимальной скоростью процессора.
Так что если взять достаточно быстрый компьютер, и потратить
на зашифровку буфера некоторое время, то можно быть уверенным,
что то же самое действие никто не произведет за меньший период.
Итак, все свое свободное время вирус будет посвящать
зашифровке буфера A[], пока он не превратится в B[].
После того, как на шифровку будет потрачено N итераций (время T)
полученным буфером B[] будет расшифрован "отложенный" код.
Ну и запущен, само собой.
[*] Теория (теперь правильная)
Основная проблема предыдущих рассуждений в том, что преобразование
A[] в B[] и у нас и у вируса занимает одинаковое время.
А мы не хотим тратить пару месяцев своего времени на всякую хуйню.
Так что будем использовать RSA.
Тот самый хитроизъебский алгоритм, который используется в PGP.
Основное его достоинство в том, что шифровка и расшифровка производятся
с использованием разных ключей.
Итак, сгенерим рандомный буфер A[] и зашифруем им наш код.
После чего N раз зашифруем A[] и получим B[].
Теперь, в отличие от описанной ранее шифровки хэширующим алгоритмом,
вирус будет повторять отнюдь не ту же самую операцию.
Вирус будет расшифровывать буфер B[] обратно в A[].
В шифровании будет использован маленький ключ, а в расшифровании -
большой. Это значит что расшифровка займет во много раз больше времени,
чем зашифровка. Например пара часов у нас, и несколько месяцев у них.
[*] Зависимость времени шифрования и расшифрования
Здесь задача такая: вычислить, сколько времени T (или итераций N)
нужно потратить на зашифровку, чтобы на расшифровку пришлось, скажем
пара месяцев.
Как вы знаете, шифрование алгоритмом RSA выглядит так:
шифровка: encr = (text ^ e) % m
расшифровка: text = (encr ^ d) % m
где {e,m} и {d,m} - открытый и закрытый ключи.
('^' означает возведение в степень, '%' означает модуль, или же
остаток от деления)
Как правило, число e маленькое, например 3, 17, 50003 и так далее.
А вот число d весьма нехилое, состоящее из например 1023х бит.
В нашей схеме шифрования не будет таких понятий как открытый/закрытый
ключ, числа d и m - открытые, а чему равно e несложно догадаться.
Вот наша схема:
Шифровка: Расшифровка:
~~~~~~~~~ ~~~~~~~~~~~
(шифруем "изменяющий код", (расшировка "изменяющего кода",
у себя дома) на инфицированных машинах)
* A[] <-- любые данные * x = B[]
* шифруем код буфером A[] N раз: x = (x ^ d) % m
* x = A[] A[] = x
N раз: x = (x ^ e) % m * расшифровываем код буфером A[]
B[] = x
* сохраняем буфер B[] в вирусе
Далее расмотрим процедуру 'modexp'.
// modexp: возводит в степень и возвращает модуль
// действие: x = (a ^ e) % m
void modexp(bignumber& x, // выход
bignumber a, // вход
bignumber e, // степень
bignumber m, // модуль
{
x = 1;
bignumber t = a;
for (int i = 0; i <= MaxBit(e); i++)
{
if (e.GetBit[i] == 1)
x = (x * t) % m; // modmult()
t = (t * t) % m; // modmult()
}
}
Как можно видеть, modexp() вызывает процедуру modmult()
(e.#bit + e.#bit1 - 1) раз.
(-1 взялась оттуда, что самое последнее умножение не происходит;
хоть это и не показано в приведенной подпрограмме)
Задачей подпрограммы modmult() является умножить два числа и вернуть
результат по модулю.
Короче говоря, число вызовов процедуры modmult() пропорционально
времени шифровки и расшифровки. Отсюда:
Decr.time = Encr.time * (D.#bit+D.#bit1 - 1) / (E.#bit1+E.#bit1 - 1) * K
где:
#bit == общее количество бит в D или E
#bit1 == количество единичных бит
(принимая число за рандомное, можно сказать что их половина.
хотя в дальнейшем будем их подсчитывать для конкретных ключей)
#bit + #bit1 - 1 == общее число вызовов modmult()
K = 0.9+-10% -- Коэффициент, появился из-за того, что каждый modmult()
выполняется переменное время, плюс там всякая
оптимизация. По видимому, при N-->oo K-->1
[*] Пример
Давайте подсчитаем, сколько раз нам нужно зашифровать сообщение
чтобы его расшифровка заняла 10 минут.
К сведению: результаты тестов приведены для весьма медленного
компьютера, так что смысл не в числах, а в их пропорциональности.
Во-первых, сделаем RSA ключ. Пусть это будет 1024-битный ключ, e = 3.
Выполняем: 'KEYGEN.EXE KEY\DPGN 1024 3 3'
Параметры полученного ключа: 1024-bit N, E==3, D=1023-bit/519*'1'
Пропорциональность времени шифровки/расшифровки (в теории):
ratio = (1023+519-1)/(2+2-1)*0.9 = 462+-10%
Но мы хотим большую точность, так что проведем пару вычислений,
так сказать оттарируем ключ.
Выполняем: 'DGPGN.EXE e 100'
результат: 100 итераций, время шифровки = 815 мс
Выполняем: 'DGPGN.EXE d 100'
результат: 100 итераций, время расшифровки = 360228 мс
ratio = 360228/815 = 441
Теперь посчитаем N для 10-минутной расшифровки.
Если 100 итераций расшифровки занимают 360228 мс,
а N итераций должны занять 10*60*1000 мс (10 минут), то
N = 60*10*1000 * 100 / 360228 = 167
Если 167 итераций расшифровки должны занять 60*10*1000 мс, то
время шифровки = 60*10*1000 / 441 = 1360 мс.
Таким образом чуть больше секунды шифровки
потребуют расшифровки в течение 10-ти минут.
Проверим.
Выполняем: 'DPGN.EXE e 167'
время шифровки: 1268 мс
Выполняем: 'DPGN.EXE d 167'
время расшифровки: 600477 мс = 10 минут 0.5 секунд
Некоторые другие результаты:
/* пропорциональность времени верна только для этого ключа */
Расшифровка: Шифровка: N (1024х-битный ключ)
K5-100 Celeron-500
10 минут 1.3 секунды 167 950
1 час 7.8 секунды 1000 5700
1 день 3 минуты 24000 136800
1 неделя 21 минута 168000 957600
1 месяц 1.5 часа 672000 3830400
1 год 18 часов 8064000 45964800
16 месяцев 1 день
10 лет 1 неделя
40 лет 1 месяц
[*] Как увеличить скорость вычислений
Алгоритм расшифровки 'text = (encr ^ d) % m' может быть
представлен так:
a = ((encr % p) ^ dp) % p // dp = d % (p-1)
b = ((encr % q) ^ dq) % q // dq = d % (q-1)
if (b < a) b += q
text = a + p * (((b - a) * u) % q) // u: (u * p) % q = 1
Таким образом время расшифровки будет увеличено в несколько раз.
Но мы публикуем только d и m, и я не знаю, можно ли с их помощью
найти p и q.
[*] Как замедлить скорость вычислений
Поскольку d не является уникальным ключом, а некоторые
его варианты могут быть вычислены по формуле:
d' = d + (p-1)*(q-1) * t, где t=0,1,2,...,
то можно увеличить d до необходимой длины,
тем самым замедлив скорость вычислений в десятки раз.
Однако тут все упирается в следующее: смогут и станут ли те, кто
хочет произвести DPGN-расшифровку быстрее всех остальных,
найти p и q, зная d'.
Если смогут, то они вычислят оригинальное d, и тогда
их расшифровка будет произведена в те же десятки раз быстрее,
что нежелательно.
[*] Остальные фичи
1. На практике, совсем не нужно хранить число итераций N,
достаточно будет простой CRC.
Таким образом никто не будет знать,
что ЭТО такое и когда ОНО будет запущено.
Также, следует добавлять к N некоторый случайный элемент,
не делая его кратным например 1000 и не делая время расшифровки
кратным например одному дню.
2. Я не уверен, но - может быть - операция {N раз: x = (x ^ d) % m}
может быть заменена на что нибудь более быстрое (не p и q),
используя какую-нибудь извращенную математику или что-то,
чего я не заметил.
Чтобы такого не произошло, можно ввести дополнительную шифровку
между вызовами modexp()а, например проксорить (ну а что ж еще):
N раз:
{
x = (x ^ d) % m;
x = x xor <что-нибудь>;
}
Программа DPGN.EXE ксорит всего пару двордов, но этого хватит.
[*] Использование "отложенного кода" (что криптовать?)
* Как было сказано раньше, код, модифицирующий точку входа и,
соответственно, контрольную сумму.
Представьте: вирус разошелся, антивир вышел, 99% машин полечили.
И тут оставшийся 1% изменяется (перестает определяться) и вирус
начинает всх иметь с новыми силами, но уже стартуя не с одной-двух
тачек, как было сначала, а с тысяч их.
* Все мы думаем о выкачивании плугинов из Интернета.
Технология "delayed code" позволяет вирусу содержать любые url-ки,
да так, что никто ваши сайты не закроет, до времени.
* Вместо похеривания важных данных можно быстро их зашифровать,
оставляя шанс на расшифровку... через несколько лет.
* Расшифрованный код может содержать внутри себя еще один такой же
"сюрприз". И так далее.
* Вообще интересна позиция аверов: разошелся какой-нибудь loveletter,
который через месяц может запросто превратиться в циха.
И что писать про такой вирус, "очень опасный" или "неопасный"?
Предлагаю вариант с намеком: "а хуй его знает". ;-)
(x) 2000 Z0MBiE
* * *