Русский / Russian English / Английский

Сейчас на форуме: (+1 невидимый пользователь)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS ·

 eXeL@B —› Основной форум —› Вопрос по CryptoAPI
. 1 . 2 . >>
Посл.ответ Сообщение


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 20 августа 2013 21:05 · Поправил: ARCHANGEL New!
Цитата · Личное сообщение · #1

Добрый вечер, уважаемые. Ковыряю одну программку, всё мне, в общих чертах, с ней понятно. Но есть один интересный момент. Попробую его подробно описать.

Дело в том, что программка эта использует CryptoAPI в ходе проверки регистрационного ключа. Если описывать процесс подробно, то всё обстоит примерно так. Вначале программа вычисляет hwid по параметру даты биоса из реестра и GetVolumeInformation, это неважно. Далее эти параметры она, типа, хэширует по какому-то самопальному алгоритму, тоже неважно. Потом начинается самое интересное.

Вначале создаётся объект для работы с md5 хэшем:

Code:
  1.  lea     ecx, [ebp+hHash]                ; Load Effective Address
  2. push    ecx                             ; phHash
  3.  push    0                               ; dwFlags
  4.  push    0                               ; hKey
  5.  push    CALG_MD5                        ; Algid
  6.  push    [ebp+hProv]                     ; hProv
  7.  call    CryptCreateHash            


Потом, естественно, идёт вычисление хэша md5 от слабого (самопального) хэша.

Code:
  1. push    0                               ; dwFlags
  2. push    [ebp+pbData]                    ; s
  3. call    _strlen                         ; Call Procedure
  4. pop     ecx
  5. push    eax                             ; dwDataLen
  6. push    [ebp+pbData]                    ; pbData
  7. push    [ebp+hHash]                     ; hHash
  8. call    CryptHashData              


Далее, как я понимаю, на основе md5-хэша по алгоритму rc2 создаётся сессионный ключ:

Code:
  1. lea     ecx, [ebp+hKey]                 ; Load Effective Address
  2. push    ecx                             ; phKey
  3. push    0                               ; dwFlags
  4. push    [ebp+hHash]                     ; hBaseData
  5. push    CALG_RC2                        ; Algid
  6. push    [ebp+hProv]                     ; hProv
  7. call    CryptDeriveKey             


Теперь вспомним про то, что мы ведь тоже ввели какой-то серийник, который, собственно и проверяется в ходе регистрации. Так вот, в ходе проверки из этого серийника всегда получается массив длиной в восемь байт. Всегда! Алгоритм проверки реализован без косяков, т.е. на вычиисление длины не влияет, есть ли внутри массива нулевые байты или нет - всё работает, как часы. Ок, идём дальше.

Сейчас у нас есть сессионный ключ, и есть 8-ми байтовый массив. Далее происходит расшифровка массива по сессионному ключу:

Code:
  1.  lea     edx, [ebp+pdwDataLen]           ; Load Effective Address
  2.  push    edx                             ; pdwDataLen
  3.  push    [ebp+var_34]                    ; pbData
  4.  push    0                               ; dwFlags
  5.  push    TRUE                            ; Final
  6.  push    0                               ; hHash
  7.  push    [ebp+hKey]                      ; hKey
  8.  call    CryptDecrypt               


И вот здесь - самое вкусное. Расшифровка-то происходит (на месте старых 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, я надеюсь, что &nbsp; снятся тебе каждую ночь.


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 20 августа 2013 21:15 New!
Цитата · Личное сообщение · #2

данные не выровняны(да такое иногда требуется на быстроты вычисления итд)

входной буффер для рашифровки 8 байт? ты ключем дешифруешь только 8 байт и уже ошибка?

Ранг: 583.0 (!)
Статус: Модератор

Создано: 20 августа 2013 21:17 New!
Цитата · Личное сообщение · #3

Судя по описанию тебе не ключ крипты нужно подбирать, а на основании имеющегося ключа подобрать серийник, который бы давал нужные 8 байт - 1 блок RC2.
Собственно, если ты знаешь что после декрипта должно получиться - не вижу проблемы с атакой.

Ранг: 583.0 (!)
Статус: Модератор

Создано: 20 августа 2013 21:19 New!
Цитата · Личное сообщение · #4

reversecode
Возможно, декрипт для последнего блока ожидает неполный блок данных + паддинг с инфой о реальном размере. Вот и валится ошибка. Потому что обработано всего 8 байт, а паддинг+размер не совпадают.


Ранг: 111.0 (ветеран)
Статус: Участник

Создано: 20 августа 2013 21:46 · Поправил: Rainbow New!
Цитата · Личное сообщение · #5

reversecode

Однозначно. Размеры буфферов должны учитывать тип алгоритма и выравнивание. Или же алгоритм сводится к своебразному хешированию, примерно того же плана как в RSA используется Mod.

P.S. 8 байт это брутится...


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 20 августа 2013 22:07 · Поправил: ARCHANGEL New!
Цитата · Личное сообщение · #6

Rainbow

По поводу брутится - если в лоб, то нужно перебрать 255^8 = 17878103347812890625 вариантов. Многовато как-то.

reversecode пишет:
ты ключем дешифруешь только 8 байт и уже ошибка?

Именно, всего 8 байт, там только один вызов CryptDecrypt, параметр Final сразу равен TRUE. И всё - ошибка.

r_e пишет:
Судя по описанию тебе не ключ крипты нужно подбирать, а на основании имеющегося ключа подобрать серийник

Ну, получается, что так. hwid - он ведь на параметрах оборудования основывается, его бесполезно под что-то подгонять.

Собственно, если ты знаешь что после декрипта должно получиться - не вижу проблемы с атакой.

Так я и не знаю. Мне нужно просто, чтоб функция отрабатывала нермально. Хрен его знает, как этого добиться.

Возможно, декрипт для последнего блока ожидает неполный блок данных + паддинг с инфой о реальном размере.

Про паддинг я читал в МСДН, но вот только там не сказано, что он из себя должен представлять. Не подскажете, где бы разжиться инфой об этом?


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 20 августа 2013 22:07 · Поправил: reversecode New!
Цитата · Личное сообщение · #7

r_e пишет:
Потому что обработано всего 8 байт, а паддинг+размер не совпадают

я это и имел ввиду под выравниванием
если блок 9 байт, а должен быть кратным 8

но кроме паддинга можеть быть еще и варавнивание самого буффера,
это часто используется во всяких крипто ускорителях или обработка видео для оптимзированого доступа к данным , но тогда первый же проход даст уже не верный результат

Ранг: 39.2 (посетитель)
Статус: Участник

Создано: 20 августа 2013 22:11 · Поправил: bbuc New!
Цитата · Личное сообщение · #8

Самый простой убедиться почему это происходит это скачать символы в pdb-файлах и продебажить внутренности винды.
К примеру, проверьте есть ли вызовы функции:
CryptSetKeyParam с параметрами dwParam=KP_PADDING и pbData=PKCS5_PADDING
Если такое есть, то оно может по паддингу палить что ключ неправильный. Хотя об этом уже сказали выше.


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 20 августа 2013 23:01 · Поправил: ARCHANGEL New!
Цитата · Личное сообщение · #9

В общем, дебажил я дебажил криптоапи, и пришёл внутрь библиотеки rsaenh.dll, там есть функция BlockDecrypt, внутри этой функции происходит всякая интересная шняга. А конкретно - следующее. Вначале мой буферок расшифровался. Т.е. я получил некие 8 байт (отличные от первоначально зашифрованных). Потом вот здесь:

Code:
  1. rsaenh.dll:68006859 cmp     eax, [ebp+dwBytes]               ; Compare Two Operands
  2. 6800685C ja      short loc_68006892 ; Jump if Above (CF=0 & ZF=0


Последний расшифрованный байт сверяется с длиной буфера. Она у меня была равна 8, помните? Должно быть меньше либо равно 8. Потом этот же байт сравнивается с единицей:

Code:
  1. .text:6800685E                 xor     edx, edx        ; Logical Exclusive OR
  2. .text:68006860                 inc     edx             ; Increment by 1
  3. .text:68006861                 cmp     eax, edx        ; Compare Two Operands
  4. .text:68006863                 jbe     short loc_68006875 ; Jump if Below


Если у меня последний байтик был больше 1, то дальше начинается проверка моего предпоследнего расшифрованного байта:

Code:
  1. 68006865 add     ecx, 0FFFFFFFEh ; от адреса строки отнимается 2, и теперь это адрес предпоследнего байта


Теперь от меня хотят, чтоб байты (последний и предпоследний были одинаковы):

Code:
  1. rsaenh.dll:68006868 movzx   esi, byte ptr [ecx]
  2. rsaenh.dll:6800686B cmp     esi, eax        ; Compare Two Operands
  3. rsaenh.dll:6800686D short loc_68006892 


А потом от меня хотят, чтоб последний символ был меньше либо равен двойке (двойка потому, что смотрим сейчас второй с конца символ - там цикл):

Code:
  1. rsaenh.dll:6800686F inc     edx                             ; Increment by 1
  2. rsaenh.dll:68006870 dec     ecx                             ; Decrement by 1
  3. rsaenh.dll:68006871 cmp     edx, eax                        ; в edx на первой итерации 2, в еах - значение последнего байта
  4. rsaenh.dll:68006873 jb      short loc_68006868           


Когда мы выходим из этого прекрасного цикла, то оказывается, что последний байт вычитается из входной длины (длины входного буфера, котрая равна 8):

Code:
  1. rsaenh.dll:68006875 mov     ecx, [ebp+arg_14]
  2. rsaenh.dll:68006878 sub     [ecx], eax  


И тогда функа вернёт истину (функа - CryptDecrypt). Это что - документированное поведение?

Добавлено
Сейчас перечитал своё сообщение и понял, что тут же чёрт ногу сломит. А суть всего этого можно уместить в несколько предложений. Паддинг здесь - это такая штука, которая дополняет буфер до нужной длины, если он изначально был короткий. Т.е. у нас буфер длиной в 8 байт, а данных в нём, например, 7 байт. Тогда нужен ещё один байт паддинга. Вот он и приписывается в конце - 01. Если полезных данных не 7, а, скажем, 6 байт, то приписывается два байта с одинаковым значением: 02 02. Если 5 байт, то 03 03 03 и т.д.


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 20 августа 2013 23:17 · Поправил: reversecode New!
Цитата · Личное сообщение · #10

скорее MS$ сам решил что паддинг у нее такой,
поэтому дешифровка, будет работать паравильно только с ипользованием шифрования этой же енжин

это если действительно дело в паддинге оказалось

Ранг: 39.2 (посетитель)
Статус: Участник

Создано: 20 августа 2013 23:31 · Поправил: bbuc New!
Цитата · Личное сообщение · #11

ARCHANGEL
>Если полезных данных не 7, а, скажем, 6 байт, то приписывается два байта с одинаковым значением: 02 02. Если 5 байт, то 03 03 03 и т.д.
Такой паддинг зовется PADDING_PKCS5, причем если полезных байт будет ровно по длине блока - например у нас длина блока 8 байт и длина исходного сообщения 8 байт, то добавиться еще один блок с 08 08 08 08 08 08 08 08, а потом зашифруется (если речь идет о зашифровке)

| Сообщение посчитали полезным: ARCHANGEL


Ранг: 583.0 (!)
Статус: Модератор

Создано: 21 августа 2013 00:03 New!
Цитата · Личное сообщение · #12

bbuc
Совершенно верно. Я об этом и писал =) Видать не достаточно подробно.


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 21 августа 2013 09:43 · Поправил: reversecode New!
Цитата · Личное сообщение · #13

ARCHANGEL
так все же уточним
криптованый блок был криптован не с помощю крипто апи M$,
и при раскриптовке? M$ декрипт желал видеть пкс5 паддинг в конце который он бы сам добавил в случае если бы криптовал
так?


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 10:15 · Поправил: ARCHANGEL New!
Цитата · Личное сообщение · #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.

Сами криптоАПИ не считают паддинг, который получается в буфере при расшифровке, как часть расшифрованного текста (длина паддинга вычитается из выходной длины). Но только кто ж знал, в каком виде паддинг они (криптоапи) желали увидеть - мне ведь нужно было подставить валидное криптованное значение, которого у меня не было, так как не было валидного серийника. Ну а теперь, вроде бы, всё ясно. Пробую кейгенить дальше...


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 21 августа 2013 10:32 · Поправил: reversecode New!
Цитата · Личное сообщение · #15

я к чему веду,
если к примеру брать 8 байт и пытатся шифровать - это же нормальный размер для твоего случая?
то крипто апи выдаст ошибку о том что буффер маленький?
или расширит буффер до своего паддинга и зашифрует?
тогда это конечно забавно, если подавая навход крипто айпи один размер буффера получать другой, только потому что M$ позаботилась о своих апи

думаю ищет паддинг оно только в включеным флагом "финал"
поэтому в твоем случае можно его выключить, что бы криптоапи думал что есть еще данные
и не ругалось ошибками

Ранг: 583.0 (!)
Статус: Модератор

Создано: 21 августа 2013 11:14 New!
Цитата · Личное сообщение · #16

reversecode
Это стандарт и касается не только MS.


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 21 августа 2013 11:21 New!
Цитата · Личное сообщение · #17

тогда получается пакет который он расшифровывает, зашифрован не постандарту?


Ранг: 334.7 (мудрец)
Статус: Участник
born to be evil

Создано: 21 августа 2013 11:32 New!
Цитата · Личное сообщение · #18

reversecode
ARCHANGEL пишет:
мне ведь нужно было подставить валидное криптованное значение, которого у меня не было, так как не было валидного серийника

PS: автор еще rsa на крипто-апи не мучал. вот, где вопросы тоннами

| Сообщение посчитали полезным: hors


Ранг: 583.0 (!)
Статус: Модератор

Создано: 21 августа 2013 12:49 New!
Цитата · Личное сообщение · #19

reversecode
Если там полезная инфа меньше размера блока - то все по стандарту.


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 13:01 New!
Цитата · Личное сообщение · #20

r_e
Тут ведь видите, в чём вопрос, в МСДН написано, что паддинг должен быть. Но не написано, что он должен из себя представлять. Или, может быть, где-то в недрах МСДН написано, но ссылок со страницы функции CryptDecrypt нет, есть описание ошибки, где говорится, что проблемы могут быть с паддингом, есть определение паддинга, а вот про его структуру ничего не сказано. Вы говорите, что это стандарт, а скажите, в каком стандарте с этой инфой можно ознакомиться?

ajax
Ну, я ж не выбираю, что разбирать. Что авторы в процедуре проверки ключа намутили, то и разбираем.


Ранг: 2008.6 (!!!!)
Статус: Модератор
retired

Создано: 21 августа 2013 13:04 · Поправил: Модератор New!
Цитата · Личное сообщение · #21

Писали ж выше, PKCS 5 или RFC 1423.
Да это общий дефолтный паддинг, он не привязан к RC или DES.


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 13:22 · Поправил: ARCHANGEL New!
Цитата · Личное сообщение · #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 там - ни слова. Вот, кстати, --> Сам стандарт <--


Ранг: 334.7 (мудрец)
Статус: Участник
born to be evil

Создано: 21 августа 2013 13:39 · Поправил: ajax New!
Цитата · Личное сообщение · #23

ARCHANGEL
сейчас не помню, но есть сайт со всеми PKCS - RFC пдфами. последний раз лазил по смарткартам, давно было. да, дотнетовское криптоапи отличается от нативного. это так, на будущее. портов нет -> натив не видел - если кто покажет, буду признателен. рипать туекучу из нетлиб нет желания


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 13:53 New!
Цитата · Личное сообщение · #24

ajax
да, дотнетовское криптоапи отличается от нативного. это так, на будущее

Читаете мои мысли. Но как же так - алгоритмы ведь одни и те же, неужто кейген на дотнете у меня замутить не получится?

Ранг: 583.0 (!)
Статус: Модератор

Создано: 21 августа 2013 13:55 · Поправил: r_e New!
Цитата · Личное сообщение · #25

Смотрите RFC 2898 (PKCS 5). Можно еще википедию любить.

| Сообщение посчитали полезным: ARCHANGEL



Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 13:57 New!
Цитата · Личное сообщение · #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].)


Ранг: 334.7 (мудрец)
Статус: Участник
born to be evil

Создано: 21 августа 2013 14:12 · Поправил: ajax New!
Цитата · Личное сообщение · #27

ARCHANGEL пишет:
неужто кейген на дотнете у меня замутить не получится?

получится, почему бы нет. только программить на дотнете придется. там паддинг своеобразный


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 14:16 New!
Цитата · Личное сообщение · #28

ajax
Я не так выразился. У меня софт написан на Borland C++, но там так много гемороя с кейгеннингом, что захотел я себе это дело немного упростить, а потому решил юзать дотнет с С#. Так вот получается, что работу с криптопровайдерами я буду либо реализовывать вручную (DllImport мне в помощь), либо просто не получится реализовать никак. Я правильно вас понимаю?


Ранг: 334.7 (мудрец)
Статус: Участник
born to be evil

Создано: 21 августа 2013 14:20 New!
Цитата · Личное сообщение · #29

ARCHANGEL
the .net framework crypto adds a random crypto header to it, its more secure. its agains plaintext attacks


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 21 августа 2013 14:26 New!
Цитата · Личное сообщение · #30

ajax
Тогда не пойму логики, как же оно может работать. Вот беру я какие-то свои данные, криптую, а оно мне рандомный заголовок туда всунуло, потом я декриптую, а у меня какая-то хрень вместо ожидаемых данных, так что ли? Да ну это ж гон!
. 1 . 2 . >>
 eXeL@B —› Основной форум —› Вопрос по CryptoAPI

Видеокурс ВЗЛОМ