Для того чтобы заставить программу работать так, как она работала бы с ключом, можно или внести исправления в программу, или эмулировать наличие ключа. Модификация программы, как правило, возможна лишь в тех случаях, когда ответы, полученные от ключа, просто проверяются, но не являются математически необходимыми для обеспечения работоспособности программы. Но это значит, что ключ, по большому счету, не требуется для достижения полной функциональности. Такое случается, когда программа не использует всех возможностей ключа или когда возможности ключа очень ограничены. При эмуляции никакого воздействия на программу не происходит, т. е., например, не нарушается контрольная сумма исполняемых модулей. И полный эмулятор, если его удается построить, просто повторяет все поведение реального ключа.
Не вдаваясь очень глубоко в технические подробности, будем исходить из предположения, что у противника есть следующие возможности: • перехватывать все обращения к ключу; • протоколировать и анализировать эти обращения; • посылать запросы к ключу; • получать ответы от ключа; • протоколировать и анализировать эти ответы; • посылать ответы от имени ключа. Такие широкие возможности противника можно объяснить тем, что в его распоряжении есть вся та информация, какая есть и у программиста, защищающего программу с помощью аппаратного ключа. То есть противник имеет доступ ко всем открытым интерфейсам, документации, драйверам и может их анализировать на практике с привлечением любых средств. Следовательно, можно предположить, что противник со временем научится полностью контролировать протокол, по которому происходит обмен информацией между прикладной программой и ключом. Контроль может осуществляться на любом уровне, но чаще всего запросы перехватываются при передаче данных между программой и драйвером ключа. Однако стоит учитывать, что возможность эмуляции еще не означает, что противник способен вычислять правильные ответы на любые запросы, которые посылает ключу программа.