eXeL@B —› Основной форум —› Вопрос по CryptoAPI |
. 1 . 2 . >> |
Посл.ответ | Сообщение |
|
Создано: 20 августа 2013 21:05 · Поправил: ARCHANGEL · Личное сообщение · #1 Добрый вечер, уважаемые. Ковыряю одну программку, всё мне, в общих чертах, с ней понятно. Но есть один интересный момент. Попробую его подробно описать. Дело в том, что программка эта использует CryptoAPI в ходе проверки регистрационного ключа. Если описывать процесс подробно, то всё обстоит примерно так. Вначале программа вычисляет hwid по параметру даты биоса из реестра и GetVolumeInformation, это неважно. Далее эти параметры она, типа, хэширует по какому-то самопальному алгоритму, тоже неважно. Потом начинается самое интересное. Вначале создаётся объект для работы с md5 хэшем: Code:
Потом, естественно, идёт вычисление хэша md5 от слабого (самопального) хэша. Code:
Далее, как я понимаю, на основе md5-хэша по алгоритму rc2 создаётся сессионный ключ: Code:
Теперь вспомним про то, что мы ведь тоже ввели какой-то серийник, который, собственно и проверяется в ходе регистрации. Так вот, в ходе проверки из этого серийника всегда получается массив длиной в восемь байт. Всегда! Алгоритм проверки реализован без косяков, т.е. на вычиисление длины не влияет, есть ли внутри массива нулевые байты или нет - всё работает, как часы. Ок, идём дальше. Сейчас у нас есть сессионный ключ, и есть 8-ми байтовый массив. Далее происходит расшифровка массива по сессионному ключу: Code:
И вот здесь - самое вкусное. Расшифровка-то происходит (на месте старых 8-ми байт появляются новые значения), но вот функция CryptDecrypt возвращает FALSE, GetLastError() возвращает NTE_BAD_DATA. Я тут гуглил-гуглил, и нагуглил The typical reason why CryptDecrypt would fail with NTE_BAD_DATA would be that you're decrypting the last block of a block cypher (as you are) and the decrypted padding bytes are incorrect. This can happen if the input is truncated (not all encrypted bytes were saved to the file) or if the key is incorrect. В общем, если то, что написано, правда, то тут ситуация ясна - key is incorrect стопудово, т.к. откуда ж мне знать его правильный. В связи с этим возникает несколько вопросов. 1. Правда ли, что при неправльном сессионном ключе может возникать такая ошибка? (А то я просто думал, что если ключ для алгоритма расшифровки неверный, то просто будут данные некорректные, но в ходе расшифровки это никак не спалить, это ж не цифровая подпись) 2. Если правда, то как выполнить атаку, чтоб найти правильный? Спасибо всем, кто осилил сей пост до конца и проникся моими проблемами. Саму программу я не прикладываю, ибо большая, узкоспециализированная и никому сама по себе неинтересна. Примечание int, я надеюсь, что снятся тебе каждую ночь. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 20 августа 2013 21:15 · Личное сообщение · #2 |
|
Создано: 20 августа 2013 21:17 · Личное сообщение · #3 |
|
Создано: 20 августа 2013 21:19 · Личное сообщение · #4 |
|
Создано: 20 августа 2013 21:46 · Поправил: Rainbow · Личное сообщение · #5 |
|
Создано: 20 августа 2013 22:07 · Поправил: ARCHANGEL · Личное сообщение · #6 Rainbow По поводу брутится - если в лоб, то нужно перебрать 255^8 = 17878103347812890625 вариантов. Многовато как-то. reversecode пишет: ты ключем дешифруешь только 8 байт и уже ошибка? Именно, всего 8 байт, там только один вызов CryptDecrypt, параметр Final сразу равен TRUE. И всё - ошибка. r_e пишет: Судя по описанию тебе не ключ крипты нужно подбирать, а на основании имеющегося ключа подобрать серийник Ну, получается, что так. hwid - он ведь на параметрах оборудования основывается, его бесполезно под что-то подгонять. Собственно, если ты знаешь что после декрипта должно получиться - не вижу проблемы с атакой. Так я и не знаю. Мне нужно просто, чтоб функция отрабатывала нермально. Хрен его знает, как этого добиться. Возможно, декрипт для последнего блока ожидает неполный блок данных + паддинг с инфой о реальном размере. Про паддинг я читал в МСДН, но вот только там не сказано, что он из себя должен представлять. Не подскажете, где бы разжиться инфой об этом? ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 20 августа 2013 22:07 · Поправил: reversecode · Личное сообщение · #7 r_e пишет: Потому что обработано всего 8 байт, а паддинг+размер не совпадают я это и имел ввиду под выравниванием если блок 9 байт, а должен быть кратным 8 но кроме паддинга можеть быть еще и варавнивание самого буффера, это часто используется во всяких крипто ускорителях или обработка видео для оптимзированого доступа к данным , но тогда первый же проход даст уже не верный результат |
|
Создано: 20 августа 2013 22:11 · Поправил: bbuc · Личное сообщение · #8 Самый простой убедиться почему это происходит это скачать символы в pdb-файлах и продебажить внутренности винды. К примеру, проверьте есть ли вызовы функции: CryptSetKeyParam с параметрами dwParam=KP_PADDING и pbData=PKCS5_PADDING Если такое есть, то оно может по паддингу палить что ключ неправильный. Хотя об этом уже сказали выше. |
|
Создано: 20 августа 2013 23:01 · Поправил: ARCHANGEL · Личное сообщение · #9 В общем, дебажил я дебажил криптоапи, и пришёл внутрь библиотеки rsaenh.dll, там есть функция BlockDecrypt, внутри этой функции происходит всякая интересная шняга. А конкретно - следующее. Вначале мой буферок расшифровался. Т.е. я получил некие 8 байт (отличные от первоначально зашифрованных). Потом вот здесь: Code:
Последний расшифрованный байт сверяется с длиной буфера. Она у меня была равна 8, помните? Должно быть меньше либо равно 8. Потом этот же байт сравнивается с единицей: Code:
Если у меня последний байтик был больше 1, то дальше начинается проверка моего предпоследнего расшифрованного байта: Code:
Теперь от меня хотят, чтоб байты (последний и предпоследний были одинаковы): Code:
А потом от меня хотят, чтоб последний символ был меньше либо равен двойке (двойка потому, что смотрим сейчас второй с конца символ - там цикл): Code:
Когда мы выходим из этого прекрасного цикла, то оказывается, что последний байт вычитается из входной длины (длины входного буфера, котрая равна 8): Code:
И тогда функа вернёт истину (функа - CryptDecrypt). Это что - документированное поведение? Добавлено Сейчас перечитал своё сообщение и понял, что тут же чёрт ногу сломит. А суть всего этого можно уместить в несколько предложений. Паддинг здесь - это такая штука, которая дополняет буфер до нужной длины, если он изначально был короткий. Т.е. у нас буфер длиной в 8 байт, а данных в нём, например, 7 байт. Тогда нужен ещё один байт паддинга. Вот он и приписывается в конце - 01. Если полезных данных не 7, а, скажем, 6 байт, то приписывается два байта с одинаковым значением: 02 02. Если 5 байт, то 03 03 03 и т.д. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 20 августа 2013 23:17 · Поправил: reversecode · Личное сообщение · #10 |
|
Создано: 20 августа 2013 23:31 · Поправил: bbuc · Личное сообщение · #11 ARCHANGEL >Если полезных данных не 7, а, скажем, 6 байт, то приписывается два байта с одинаковым значением: 02 02. Если 5 байт, то 03 03 03 и т.д. Такой паддинг зовется PADDING_PKCS5, причем если полезных байт будет ровно по длине блока - например у нас длина блока 8 байт и длина исходного сообщения 8 байт, то добавиться еще один блок с 08 08 08 08 08 08 08 08, а потом зашифруется (если речь идет о зашифровке) | Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 21 августа 2013 00:03 · Личное сообщение · #12 |
|
Создано: 21 августа 2013 09:43 · Поправил: reversecode · Личное сообщение · #13 |
|
Создано: 21 августа 2013 10:15 · Поправил: ARCHANGEL · Личное сообщение · #14 reversecode Если верить МСДН, то да, именно так. Applications that use CryptoAPI need not add padding to their plaintext before it is encrypted, nor do they have to remove it after decrypting. Сами криптоАПИ не считают паддинг, который получается в буфере при расшифровке, как часть расшифрованного текста (длина паддинга вычитается из выходной длины). Но только кто ж знал, в каком виде паддинг они (криптоапи) желали увидеть - мне ведь нужно было подставить валидное криптованное значение, которого у меня не было, так как не было валидного серийника. Ну а теперь, вроде бы, всё ясно. Пробую кейгенить дальше... ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 21 августа 2013 10:32 · Поправил: reversecode · Личное сообщение · #15 я к чему веду, если к примеру брать 8 байт и пытатся шифровать - это же нормальный размер для твоего случая? то крипто апи выдаст ошибку о том что буффер маленький? или расширит буффер до своего паддинга и зашифрует? тогда это конечно забавно, если подавая навход крипто айпи один размер буффера получать другой, только потому что M$ позаботилась о своих апи думаю ищет паддинг оно только в включеным флагом "финал" поэтому в твоем случае можно его выключить, что бы криптоапи думал что есть еще данные и не ругалось ошибками |
|
Создано: 21 августа 2013 11:14 · Личное сообщение · #16 |
|
Создано: 21 августа 2013 11:21 · Личное сообщение · #17 |
|
Создано: 21 августа 2013 11:32 · Личное сообщение · #18 reversecode ARCHANGEL пишет: мне ведь нужно было подставить валидное криптованное значение, которого у меня не было, так как не было валидного серийника PS: автор еще rsa на крипто-апи не мучал. вот, где вопросы тоннами ----- От многой мудрости много скорби, и умножающий знание умножает печаль | Сообщение посчитали полезным: hors |
|
Создано: 21 августа 2013 12:49 · Личное сообщение · #19 |
|
Создано: 21 августа 2013 13:01 · Личное сообщение · #20 r_e Тут ведь видите, в чём вопрос, в МСДН написано, что паддинг должен быть. Но не написано, что он должен из себя представлять. Или, может быть, где-то в недрах МСДН написано, но ссылок со страницы функции CryptDecrypt нет, есть описание ошибки, где говорится, что проблемы могут быть с паддингом, есть определение паддинга, а вот про его структуру ничего не сказано. Вы говорите, что это стандарт, а скажите, в каком стандарте с этой инфой можно ознакомиться? ajax Ну, я ж не выбираю, что разбирать. Что авторы в процедуре проверки ключа намутили, то и разбираем. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 21 августа 2013 13:04 · Поправил: Модератор · Личное сообщение · #21 |
|
Создано: 21 августа 2013 13:22 · Поправил: ARCHANGEL · Личное сообщение · #22 Archer Ну, я в гугле вот так написал Глянул результат - где вы там увидели RFC 1423, мне неясно, но за название документа спасибо, посмотрю. Вот, кажись, оно: The input to the DES CBC encryption process shall be padded to a multiple of 8 octets, in the following manner. Let n be the length in octets of the input. Pad the input by appending 8-(n mod 8) octets to the end of the message, each having the value 8-(n mod 8), the number of octets being added. In hexadecimal, the possible paddings are: 01, 0202, 030303, 04040404, 0505050505, 060606060606, 07070707070707, and 0808080808080808. All input is padded with 1 to 8 octets to produce a multiple of 8 octets in length. The padding can be removed unambiguously after decryption. Только то ж про DES CBC, а про rc2 там - ни слова. Вот, кстати, ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 21 августа 2013 13:39 · Поправил: ajax · Личное сообщение · #23 ARCHANGEL сейчас не помню, но есть сайт со всеми PKCS - RFC пдфами. последний раз лазил по смарткартам, давно было. да, дотнетовское криптоапи отличается от нативного. это так, на будущее. портов нет -> натив не видел - если кто покажет, буду признателен. рипать туекучу из нетлиб нет желания ----- От многой мудрости много скорби, и умножающий знание умножает печаль |
|
Создано: 21 августа 2013 13:53 · Личное сообщение · #24 |
|
Создано: 21 августа 2013 13:55 · Поправил: r_e · Личное сообщение · #25 Смотрите ----- старый пень | Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 21 августа 2013 13:57 · Личное сообщение · #26 r_e Ну да, вот оно: 4. Concatenate M and a padding string PS to form an encoded message EM: EM = M || PS , where the padding string PS consists of 8-(||M|| mod 8) octets each with value 8-(||M|| mod 8). The padding string PS will satisfy one of the following statements: PS = 01, if ||M|| mod 8 = 7 ; PS = 02 02, if ||M|| mod 8 = 6 ; ... PS = 08 08 08 08 08 08 08 08, if ||M|| mod 8 = 0. The length in octets of the encoded message will be a multiple of eight and it will be possible to recover the message M unambiguously from the encoded message. (This padding rule is taken from RFC 1423 [3].) ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 21 августа 2013 14:12 · Поправил: ajax · Личное сообщение · #27 |
|
Создано: 21 августа 2013 14:16 · Личное сообщение · #28 ajax Я не так выразился. У меня софт написан на Borland C++, но там так много гемороя с кейгеннингом, что захотел я себе это дело немного упростить, а потому решил юзать дотнет с С#. Так вот получается, что работу с криптопровайдерами я буду либо реализовывать вручную (DllImport мне в помощь), либо просто не получится реализовать никак. Я правильно вас понимаю? ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 21 августа 2013 14:20 · Личное сообщение · #29 |
|
Создано: 21 августа 2013 14:26 · Личное сообщение · #30 ajax Тогда не пойму логики, как же оно может работать. Вот беру я какие-то свои данные, криптую, а оно мне рандомный заголовок туда всунуло, потом я декриптую, а у меня какая-то хрень вместо ожидаемых данных, так что ли? Да ну это ж гон! ----- Stuck to the plan, always think that we would stand up, never ran. |
. 1 . 2 . >> |
eXeL@B —› Основной форум —› Вопрос по CryptoAPI |