Текущая статья не является практическим руководством или руководством к действию. Представленный материал представлен исключительно в образовательных целях и несёт в себе концепцию «пища для размышления» не нарушая авторского и/или смежного права. Повторять описанные процессы не рекомендуется. Часть материала может быть полезна инженерам занимающихся различными вопросами и проблемами криптологии. Некоторые материалы, находящиеся в теле статьи, являются собственностью их многоуважаемых авторов, о чем будет предметно указано. Статья не претендует на полноту. Некоторые значения и параметры были сознательно изменены.
Подопытным экземпляром будет выступать программное обеспечение для обработки изображений получаемых при рентгенографии под названием DXRay Diagnost от компании ANGELL TECHNOLOGY CO. LTD, www.szangell.com. Указанное программное обеспечение поставляется, например, в комплекте с цифровой медицинской гамма радиографической системой DTP580B-3 китайской компании ShenZhen Angell Technology Co. Ltd.
Очень печально, но я не владею «китайской грамотой», и оригинальные названия изделий и компаний приходится указывать на языке указанном в других доступных источниках, а это английский язык. Учитывая проблемы формализации языка и русскоязычного перевода, русскоязычный интерфейс программного обеспечения и поставляемые пользовательские и сервисные инструкции желают быть на много лучшими. Зачастую приходится догадываться, о чем идёт речь. Отчасти кину камень в огород тем, кто занимается локализацией.
Подготовка и запуск
Дня защиты программного обеспечения, в комплекте, поставляются ключ защиты в виде UBS-dongle который необходимо вставить в свободный USB разъём.
Используйте для такого рода устройств разъём USB 2.0, он черного цвета. Синего цвета порт USB 3.0. Старайтесь использовать порт расположенный непосредственно на материнской плате, обычно с тыльной стороны системного блока.
При установке ключа защиты в USB разъём в диспетчере устройств должно появится HID устройство класса USBKey. Попалось устройство HID\VID_3689&PID_8762&REV_0200. HID устройство не требует установки дополнительных драйверов или программного обеспечения. Обработка данных HID устройств производится на уровне API системы. Сложностей с идентификацией ключа в системе быть не должно. В операционных системах других версий ключ может называться иначе.
Если «правильный» ключ не установить, то при запуске DXRay Diagnost.exe появится сообщение «Пожалуйста, вставьте ключ».
Если все хорошо, то при запуске программного обеспечения не должно появляться информационных и диалоговых окон, появится окно выбора пользователя и ввода пароля. Информация о механизме хранения паролей будет указана дальше.
Если есть какие-то проблемы, то появятся соответствующие информационные и/или диалоговые окна. Например:
Возможные проблемы запуска программного обеспечения:
- Срок действия лицензии истёк.
- Не совпадает версия программного обеспечения.
- Не совпадает hash-значение железа с hash-значением записанным в ключе. Да, ключ «вяжется» к железу при инициализации. Если быть более точным, вызывается функция определения жесткого диска MasterHardDiskSerial. И именно это значение участвует в формировании hash-значения, например, «KINGSTONSA400S37480G». Так же участвует в формировании hash-значения модель видеокарты, например «Quadro P2000».
- Не соответствует код авторизации самого ключа, например «C0000000».
- Не соответствует ответ ключа при формировании заголовка пакетов на ключ, например «HidP KDP». Тут используются две тетрады «HidP» и «[пробел]KDP».
- Ключ не инициализирован (активирован).
Зачастую при большинстве проблем после информационного окна появляется модальное диалоговое окно предлагающее ввести номер регистрации. Такое окно однозначно появляется при окончании лицензии или при попытке запустить программное обеспечение на другом железе.
При переносе программы на другое железо в системе обязательно должен быть файл nvcuda.dll. Без него система не запустится. В идеале должен быть установлен пакет NVidia CUDA, для карты NVidia Quadro P2000 нужен пакет 10.0 в котором так же находятся драйвера для указанной видеокарты. Рекомендую установить обновления 10.1 и 10.2. Quda 10 - максимальная версия библиотеки для Windows 7. Как минимум файл nvcuda.dll должен находиться в одной директории с программой, если его принудительно не регистрировать в системе, например, через regsvr32.
Акромя указанной библиотеки, для ПО требуется AccessDatabaseEngine_x64 2010 года. Учтите что библиотека не совместима с 32 разрядным офисным пакетом. Однако "натянуть" его принудительно можно с ключом /passive.
Предварительная инициализация
При запуске программного обеспечения происходит вызов функции agAuthorityValidate, которая расположена в библиотеке CAgDongle_64.dll. Эта функция вызывает процедуру agInitialKey которая читает из ключа 5 (пять) основных значений:
- agReadLastDate– Получает дату последнего запуска программного обеспечения. Например «20240224». 24 февраля 2024 года.
- agReadValidDate– Получает дату, до которой лицензировано программное обеспечение. Например «20250115». 15 января 2025 года.
- agReadSoftID– Получает версию программного обеспечения. Например «4.0».
- agReadAuthorityCode – Получает код авторизации. Например «C0000000».
- agReadMachineID– Получает hash-значение «железки» к которой привязан ключ. Например «EB4A2DC024DE54».
После, функция agAuthorityValidate получает значения от agGetLocalMachinecode, которая формирует локальный машинный код. И естественно GetHDInfo получающую информацию о типе накопителя. После этого, полученные данные, используя, если судить по названию, якобы функции AES (жалкое подобие на Rijndael) указанная функция формирует номер и ID машины, отображаемые в модальном диалоговом окне.
Система контроля срока лицензии
Система контроля срока лицензии организована с использованием USB-dongle. В ключе находятся две даты LastDate и ValidDate. Значение LastDate содержит дату последнего запуска программного обеспечения. Значение ValidDate содержит дату, до которой лицензировано программное обеспечение. При каждом запуске программного обеспечения, если текущая системная дата больше даты LastDate, происходит обновление значения LastDate на ключе на текущую системную дату при любых других событиях.
Будьте внимательны! Неверно установленная текущая системная дата может нарушить срок лицензирования. Т.е. случайно установленная дата больше чем значение ValidDate гарантированно лишит вас лицензии. Обратно откатить, классическими методами уже не удастся.
В общем виде механизм выглядит следующим образом. При каждом запуске значение LastDate обновляется (происходит перезапись) на значение текущей системной даты, которая в свою очередь потихоньку увеличивается. Таким образом, пока значение LastDate и значение текущей системной даты меньше значения ValidDate – приложение работает нормально.
Как только значение LastDate превысит значение ValidDate - наступает момент прекращения действия лицензии.
Попытки откатить системную дату не приведут к успеху т.к. значение LastDate превышает значение ValidDate.
Как временное решение запрета перезаписи значения LastDate возможно в фиксе библиотеки CAgDongle_64.dll – «занопить» вызов функции YWriteString. Иными словами по адресу 180009FABh можно заменить E8E079FFFFh на 9090909090h. Операция NOP (код 90) для процессора – ничего не делать.
Данное решение будет эффективно только в том случае, пока значение LastDate в ключе не превысило значение ValidDate. Т.е. поправив библиотеку можно смело отматывать дату в диапазон между LastDate и ValidDate. Однако появляется следующая особенность при откате системной даты – если закрыть на это глаза, неверная дата регистрации пациентов в базе данных, со всеми вытекающими неудобствами.
Наблюдения вглубь механизма лицензирования
Рекомендуется скачать PDB файлы символов в каталог поближе к корню (например, C:\symbols\ ), и добавить в переменные окружения _NT_ALT_SYMBOL_PATH и _NT_SYMBOL_PATH путь к символам. Настройка сервера символов тут.
Не забываем в строке WINDBG (при трассировке) дать команду для подгрузки символов:
.sympath srv*c:\symbols*https://msdl.microsoft.com/download/symbols
и
.reload /f
Если остановиться на процедуре и трассировать по пути до вызова подпрограммы _strcmp:
То по адресу [RAX-7] можно наблюдать синтезированный промежуточный ID код. Например: «EB4A2DC024DE54». Заменив его принудительно, по адресу в [RAX-7], на строку как в строке находящейся по адресу CAgDongle_64:000007FEF390ED30, а именно «EAEAEAEAEAEAEA», то можно трассируя дальше найти вызов подпрограммы (Внимание, регистр символов имеет значение) agWriteLastDate.
Данный вызов подпрограммы заменяет в ключе значение LastDate, смотри описание выше. Если трассировать вызовы до подпрограммы вызова HID драйвера. А именно:
То по адресу [RBP+0Dh] будет находиться текущая системная дата, которая будет записана в ключ в качестве значения LastDate. Можно изменить её на «нужную» дату и выполнить ТОЛЬКО подпрограмму HID драйвера. Т.е. сразу после подпрограммы cagdongle_64_l_HidD_GetFeature необходимо удалить ключ из гнезда и терминально завершить приложение. Таким образом, можно изменить значение параметра LastDate.
Подпрограммы WriteLastDate и WriteValidDate отличаются одним байтом практически почти перед вызовом подпрограммы YWriteString.
Таким образом, трассируя подпрограмму, и на лету (on fly) изменив значение одного байта можно вместо подпрограммы WriteLastDate вызвать подпрограмму WriteValidDate. И указав соответствующую дату, как смотри выше, записать «нужное» значение в ключ.
Если подпрограмма WriteLastDate не вызывается по предложенной схеме, рекомендуется в подпрограмме agAutorityValidate, указанным выше способом, уменьшить значение при вызове функции ReadLastDate на значение меньше чем системное временя, а значение при вызове функции ReadValidDate изменить на значение больше чем системное время. Все процедуры записи данных в ключ должны завершаться ТОЛЬКО вызовом HID драйвера с удалением ключа и терминальным завершением приложения.
Авторизация
При успешном старте приложения появится окно авторизации, в котором необходимо выбрать пользователя и указать пароль. Список пользователей можно посмотреть в раскрывающемся списке. Если нет информации о паролях, то можно найти файл DXdb.mdb в каталоге с программным обеспечением и открыть его, например, с помощью MS Access. В таблице userC находится список пользователей, hash-значений пароля и привилегий. По умолчанию находится только один пользователь administrator с hash-значением пароля -171771655 и максимальным уровнем привилегий. Можно добавить кортеж для пользователей, hash-значения паролей и указать уровень привилегий. По умолчанию пароль пользователя administrator 410947. В инструкции по эксплуатации предлагается при регистрации пользователя указывать пароль от одного до шести цифр. По факту пароль воспринимает и специальными символами и символами в другой кодировке. Регистр символов имеет значение. Hash-функция предметно не изучалась.
Список некоторых hash-значений представлен в таблице ниже. Т.е. указав необходимое hash-значение можем войти с предложенным паролем.
Уровень привилегий учетной записи можно редактировать в атрибуте Us_UserPrivilege, состоящий из строки единиц и нулей. Где единица указывает установку флага, нуль указывает на то, что флаг сброшен и этот параметр для пользователя недоступен. У администратора все значения установлены в единицу по умолчанию. Перечень флагов указан на изображении. Где первый флаг это «Регистрация», второй – «Коллекция», третий – «Список», четвертый – «Отчет» и так далее, слева на право и сверху вниз. Таким образом можно редактировать привилегии учетных записей не имея доступа к системе.
Рекомендуется перезагружать систему после любых танцев с бубном.
Аппендикс
В качестве дополнения есть следующая информация:
Необходимо удалить все распространяемые пакеты Visual C++ и установить свежие, скачать которые можно с сайт мелкософта. А именно 2005, 2008, 2010, 2012, 2013 как 64 разрядные версии так и 32 разрядные (до 2012 уже не обновляются). Начиная с 2015 и далее, идёт новый один пакет 2015-2023. По этому если у вас установлены версии 2015, 2017, 2019 и так далее, то их надо удалить и установить новый 2015-20ХХ, как 32 разрядную так и 64 разрядную версию.
В системе установлена видеокарта Quadro P2000, необходимо удалить драйвера и библиотеки CUDA 8 (если есть), скачать CUDA 10.2 с двумя обновлениями и установить. В самой библиотеке CUDA 10 есть драйвера на видеокарту, их необходимо установить. Иначе есть проблемы описываемые в лог файлах.
С системой идёт офис 2007, система 64 разрядная а офис 32 разрядный (64 разрядного MS Office 2007 не существует). Для работы используется AccessDatabaseEngine x64 (2010 года). Учитывая тот факт, что движок x64 не работает корректно с 32 разрядным офисом, устанавливается AccessDatabaseEngine x32 2010 и 2016 года, а затем (от имени администратора) устанавливается AccessDatabaseEngine x64 2010 с ключом /passive.
При калибровке аппарата используется утилита CalibrationTool. При создании калибровки AEC Corr, появляется ошибка. В самой утилите баг с путями.
Т.е. утилита не может нормально определить путь из-за двойного слеша. Если посмотреть код, то по смещению 49978 можно найти дефектный путь \tmp\AEC.
Передвинув на один байт влево с затиранием слеша, получим tmp\AEC (заполнить байт справа 00). После этой коррекции файлы коррекции 60% серого нормально сохраняются. Однако при формировании таблицы AEC, появляется ошибка что не найдена таблица черного. Утилита CalibrationTool содержит множественные ошибки. Но базовую калибровку позволяет пройти и использовать аппарат без режима IDC.
Дальнейшие изучения и корректировки, из-за цейтнота пока не проводились.