Речь здесь пойдёт о некоторых аспектах компьютерной безопасности, связанных с запутыванием кода программы. Именно это мне было интересно в связи с разработкой обфускатора .NET приложений – программы для защиты .NET кода от взлома. Есть и другая – тёмная сторона: запутыванием кода очень интересуются разработчики вирусов и других нехороших штук, но нам они неинтересны.
Эмуляторы
Итак, Вы придумали супер алгоритм для запутывания кода программы. При декомпиляции код выглядит просто вырвиглазно и никто точно такое анализировать не будет. Казалось: победа! Но нет. Естественно обфусцированный код никто анализировать не будет… руками. Хакер поймёт как вы код запутывали и напишет «распутывалку». Если Ваш алгоритм был достаточно силён, то хакеру придётся писать собственный эмулятор, но и это не такая проблема как может показаться на первый взгляд – в сети есть доступные эмуляторы и даже специально написанные именно для целей взлома.
Из теории компьютерных наук известно, что не существует и никогда не будет существовать алгоритма, определяющего остановится ли программа или будет работать вечно – так называемая «проблема останова». Это гарантирует, что хакерский эмулятор, распутывающий обфусцированную программу, будет делать это как бы «локально»: он не сможет узнать состояние и значение всех переменных, задействованных в каждом участке кода и поэтому в точках условного ветвления часто будет полагать, что возможны все варианты хода программы. Вот тут-то на ум и приходит решение: запутанный код будет наполнен переходами по условиям, которые будут всегда истинны, но проэмулировать и понять это будет трудно. Примерно вот так:
if ((x*x & 1) == 0)
good_code
else
мусор
«Но это же как раз одна из тех запутывалок, которые хакер и собирается обходить с помощью эмулятора» — скажете Вы и будете правы. А что если придумать тысячу подобных фокусов? О, это решение, если у Вас есть легион программистов, каждый из которых придумывает трюки не похожие на трюки других. В реальности это не так. В реальности Вы думаете неделю и придумываете тридцать трюков, а хакер смотрит на код один день и находит все тридцать трюков, потому что тридцать – это не так уж много.