![]() |
|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
![]() |
|
|
Опции темы | Поиск в этой теме |
![]() |
#31 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
![]()
Значит шифрование готовой программы..
Как говорилось выше, при двойном шифровании порядок следования ключей роли не играет, если ключи одинаковые. Но это не наш случай! У нас разные алгоритмы шифрований. Это означает, что нужно придерживаться правил работы со-стеком: первым пришёл, последним уйдёшь. В нашей программе первым дешифрует криптор(1) ключом(A7h), поэтому шифровать этим ключом мы должны в последнюю очередь. Сначала нужно зашифровать все процедуры, причём каждую из них отдельно, с начальным значением ключа(0). Уже потом зашифруем всё тело программы. Для процедур получится двойное шифрование, да ещё и с разными алгоритмами. При шифровании нужно быть предельно осторожными, чтобы не зашифровать лишний байтик. Это может обломать нас по-полной. Нам нужно вычислить точный размер шифруемых процедур, и адрес их начала. Адрес конца не обязателен, т.к. есть длина. На всякий/пожарный нужно иметь ввиду, что все процедуры заканчиваются командой(RET/RETN), опкод которой имеет значение(С3h). Тут произошёл небольшой конфуз с процедурами! Статья сырая и пишу её на-ходу, опираясь только на теорию не проверив на практике. Одним словом, нужно на входе в процедуры сохранять/восстанавливать содержимое регистра(DX), т.к. криптор(2) использует его в качестве счётчика. В идеале, нужно сохранять/восстанавливать вообще все регистры командами(Pusha/Popa), но здесь нам хватит и одного(DX). Причём внутри процедуры 'Message2' есть 'Hex2Asc', которая является отдельной процедурой. Её нужно обработать отдельно. Законченный вариант будет такой: Код:
На подготовительном этапе удобно вставить в хвост исходника одну полезную/отладочную функцию, которая вычислит начальные адреса процедур и их длинну. Вставлять эту функцию нужно обязательно в хвост, иначе адреса изменятся и мы получим неверный результат: Код:
Код:
Проделав всю/эту работу мы встречаем процесс шифрования во-всеоружии!
Нашедшего выход - затаптывают первым..
|
![]() |
![]() |
![]() |
#32 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
![]()
Загружаем готовый COM-файл в HIEW. Шифрование начинаем с любой из понравившихся процедур, ..пусть будет 'Message1'. Как видно из отчёта выше, эта процедура начинается с адреса(220h) и заканчивается адресом(22Аh). Сам адрес(22Аh) не входит в процедуру, т.к. отсчёт с нуля, поэтому адресом конца будет(229h) с опкодом RET(C3h).
Юзая HIEW нужно учитывать, что он считает адреса не с ORG-100h (как у нас в программе), а с ORG-0h, поэтому адрес(220h) он будет отображать как 120h. Значит загрузив программу в HIEW жмём в его окне такую последовательность клавиш: [F4->F3->F5->120->Enter] и попадаем сюда: Код:
Код:
Код:
Шифрование остальных процедур происходит по такой-же схеме. Адреса процедур в окне HIEW'а будут следующими: - начало 'Message1': 220h - 100h = 0120h - конец 'Message1': 220h + 00Ah = 022Ah - 0101h = 0129h - начало 'Message2': 232h - 100h = 0132h - конец 'Message2': 232h + 029h = 025Bh - 0101h = 015Ah - начало ' inpBuff': 263h - 100h = 0163h - конец ' inpBuff': 263h + 00Ah = 026Dh - 0101h = 016Ch - начало 'FullSize': 104h - 100h = 0004h - конец 'FullSize': 104h + 169h = 026Dh - 0101h = 016Ch Зашифровав все/три процедуры одинаковым алгоритмом, приступаем к шифровке всего тела, чтобы программа на диске лежала в зашифрованном виде. Тут ничего нового, только вместо 'Edit->Crypt', нужно будет заюзать 'Edit->Xor' с ключом(А7h), т.к. криптор(1) внутри программы расшифровывает тело именно этим ключом. Значит перезапустив HIEW открываем нашу программу с зашифрованными процедурами и жмём последовательность клавиш: [F4->F2->F5->4->Enter->F3->F8->A7->Enter] Эта комбинация перевела HIEW в режим шифрования 'XOR' с ключом(А7). Процесс шифрования привязан к клавише(F8). Шифруем все значения от макушки с адресом(0004) и до хвоста с адресом(016Ch) включительно. Шифруемые значения меняют свой цвет с голубого на жёлтый. Достигнув адреса(016Dh) сохраняем изменения по(F9), и с чувством выполненного долга выходим из HIEW'a по(F10). Запустив на исполнение новоиспечённый/шифрованный файл обнаруживаем, что мы всё сделали правильно и рубашка у нас ни-в-каких, ни-в-трусах, о чём свидетельствует окно консоли. Радость переполняет нас, мы бежим за-пивом, но ...через час обнаруживаем, что программа уже кем-то взломана! Не успели мы выложить нашу софтину на варез, как все/наши мечты разлетелись в-пух-и-прах. Мы потратили пару дней чтобы организовать всё/это дело, а взломщик выловил алгоритм за пару минут. Этот мир дермово устроен! Поиск ошибок при шифровании может послужить темой для следующего разговора..
Нашедшего выход - затаптывают первым..
|
![]() |
![]() |
![]() |
#33 | |
Участник клуба
Регистрация: 11.01.2010
Сообщений: 1,139
|
![]() Цитата:
|
|
![]() |
![]() |
![]() |
#34 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
![]()
Mikl___, так тут мысль такая, что "как сделать" и "как будут ломать".
Само-собой, что тема для новичков, т.к. за всё время сколько я на этом сайте, в этом разделе не видел ни одной темы от профи. ..только студенты и тусуются.
Нашедшего выход - затаптывают первым..
|
![]() |
![]() |
![]() |
#35 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
![]()
Наигравшись вдоволь в VXеров, перейдём на сторону AVеров, и посмотрим, как-бы кодокопатели пытались расшифровать наш файл, какие ошибки мы допустили, чего не нужно было делать. Заметим, что в природе соотношение тех кто пишет программы, и кто их ломает - идёт примерно 50:1. Интересным фактом является и то, что взломщики в этой войне выигрывают!
В общем случае, бесполезно защищать программу, т.к. её всё-равно сломают. Для этого даже ломать ничего не нужно, а достаточно просто найти координаты защитного механизма в коде и забить его NOP'ами (no operation). Но такой подход не везде срабатывает. Например зашифрованный/основной код не забьёшь пустой операцией(NOP), т.к. программа потеряет свою функциональность, и взломщику приходиться подбирать ключ, чтобы расшифровать это тело. Однобайтный ключ (как в нашем случае) может иметь максимум FFh = 256 значений. Чтобы найти из 256-ти именно наш ключ, взломщику потребуется всего-лишь перебрать все ключи в диапазоне 0..256. Учитывая скорость выполнения операций современными ЦП это не займёт много времени. Следуя ходу его мыслей, приведём возможный алгоритм вычисления им, нашего ключа шифрования.. Для DOS-программ, в качестве самой/юзерской скан-строки может выступить обычный вызов прерывания INT-21h, как наиболее/часто встречаемый. Опкодом этой команды является значение(CD21h), которое и будет служить сигнатурой для поиска. Читаем зашифрованный файл в свой буфер и начинаем последовательно ксорить его слова ключами 0..256. После каждого ксора проверяем результ на 'CD21h'. Вот и весь алгоритм: Код:
- 1 байт = 000000FFh = 256 вариантов ключей; - 2 байта = 0000FFFFh = 65.535 вариантов ключей; - 4 байта = FFFFFFFFh = 4.294.967.295 вариантов ключей; - 8 байт = FFFFFFFFFFFFFFFFh = 18.446.744.073.709.551.615 ключей! Разрядность регистров современных ЦП составляет 64-бит, а это целых 8 байт, которые можно обрабатывать за-раз! Да сюда можно поместить целую строку символов! В таблице выше видно, сколько вариантов ключей придётся перебирать взломщику, если мы заюзаем 8-байтный ключ для шифрования всего тела нашей программы криптором(1). Ясно, что наш/однобайтный ключ(A7h) здесь отдыхает.. От сюда вывод: что ключ шифрования должен быть как-минимум 4-байтным (32-бит). Всё-что нам нужно было сделать, так это брать в регистр(EAX) сразу по 4 байта из шифруемой программы, и ксорить их 32-битным ключом например так (благо HIEW позволяет это делать по F6): Код:
Помимо разрядности ключа, атмосферу подряжают ещё множество заряжённых частиц, которые могут прервать наш полёт. Одной из них является хранение самого ключа(1) в открытом виде. Это огромная брешь в системе безопасности, которая не даёт нам спокойно спать. Открытый ключ просто прикрывает защиту фиговым листиком, обнажая при этом весь алгоритм шифрования. Нужно срочно куда-то спрятать этот/чёртов ключ, ..но куда? В любом случае нам нужно будет воспользоваться им при дешифровке, а наши партнёры смогут отловить этот момент в отладчике.
Нашедшего выход - затаптывают первым..
|
![]() |
![]() |
![]() |
#36 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
![]()
Но не будем отчаиваться, а рассмотрим такой вариант...
Если в большой программе мы не можем найти тайник куда спрятать ключ, то может пусть этим тайником будет сам юзверь! Пусть он вводит пароль, а мы заюзаем его ввод вместо ключа, но с некоторыми поправками. В клинических случаях, парольная защита программы строится по такому алгоритму. Юзер вводит пароль, который проверяется программой на валидность. Если пароль совпадает, то типа: 'Thank-you!', иначе: 'Fack-you!'. Этот пример в аккурат показывает, как нельзя делать! Толку от пароля, который опять нужно сравнивать с оригиналом? Можно пойти по-более достойному пути, который заключается в следующем.. 1. Снимаем контрольную сумму всей тушки; 2. Сохраняем её в открытом виде; 3. Шифруем всю программу 32-битным ключом: DEAD6666h; 4. Читаем юзерский пассворд, и делаем из него ключ; 5. Дешифруем юзверским ключом тушку; 6. Считаем по-новой контрольную сумму получившегося тела; 7. Сравниваем две контрольные суммы; 8. Здесь (как-правило) Fack-you! Таким образом мы избавляемся от хранения ключа в открытом виде. До шифрования снимается CRC-программы, которая не несёт в себе ни йоты полезной инфы. Её можно хранить обнажённой. После шифрования секретным ключом контрольная сумма меняется, и её можно восстановить только дешифровав тело таким-же ключом, которым мы шифровали. Юзерский пасс от фонаря преобразуется в ключ, которым дефишруется тело. Если после этого ни один тушканчик не постадал, то контрольная сумма совпадёт, что будет означать ОК! Простой алгоритм может вставить такие палки в колёса наших партнёров, что мало не покажется. Ключ шифрования мы использовали только один раз закрывшись в тёмной комнате от всех глаз. Его никто не знает кроме нас и он нигде не хранится. Не знает его и сама программа, которая тупо дешифрует тем, что мы ей подсунем, ..а подсунуть ей мы можем сколько? - точно: 4 млрд. вариантов ключей. Реализуется это просто.. Допустим мы уже посчитали CRC не зашифрованного тела, который равен 8AE5h. На следующем шаге шифруем его секретным ключом, а внутри программы помещаем такую функцию: Код:
Можно спорить до хрипоты, какие алгоритмы лучше: готовые или самопальные, но последнее слово всегда остаётся за нами. Баян у нас на руках - как хотим, так и играем! (лишь-бы не забывать тискать пимпы иногда)
Нашедшего выход - затаптывают первым..
|
![]() |
![]() |
![]() |
|
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Полиморфизм | Anubys | Помощь студентам | 1 | 26.12.2011 20:42 |
Полиморфизм | Zorgan | Visual C++ | 22 | 29.08.2011 12:23 |
Полиморфизм | MasterSporta | Общие вопросы C/C++ | 3 | 10.04.2011 23:46 |
полиморфизм | slayerblya | Общие вопросы C/C++ | 1 | 27.02.2011 01:43 |
Полиморфизм | mister2010 | Общие вопросы C/C++ | 30 | 24.05.2010 01:07 |