Я читал книга [rus] (извините, на данный момент я не могу найти английскую версию), написанную Крисом Касперским, объясняющую философию и методы обеспечения безопасности программного обеспечения.
В книге есть один пример. В нем говорится, что код:
if ( ! IsValidUser() )
{
Message("Invalid user! Abroting...");
Abort;
}
совершенно небезопасно, потому что переводится в это:
CALL IsValidUser
OR AX,AX
JZ continue
^^^^^^^^^^^^^
PUSH offset str_invalid_user
CALL Message
CALL Abort
continue: ; normal program execution
...........
Таким образом, программу можно взломать, изменив только один байт в дизассемблере. Если мы изменим JZ continue
в JMP continue
проверка не будет выполнена правильно.
Тогда Крис пишет:
исправленная версия программы на С:
IsValidUser();
if (!true)
{
Message("Invalid user! Aborting...");
Abort;
}
В этой версии {...}
раздел никогда не получит контроль.
Я действительно не понимаю, как исправленная версия должна работать. Почему он использует if-statement
который никогда не будет выполнен таким образом, может быть даже удален компилятором?
Это опечатка или ошибка? Или я что-то не понимаю?
Это твоя вина, а не Крис. Это не «безопасная версия кода подтверждения пользователя», а код, полученный после исправления, внесенного хакером.
Цитата на русском из этой книги:
На языке Си исправленная
программа будет выглядеть так:
Переводчик Google:
Язык C модифицированный (или исправленный) программа будет выглядеть
как это:
Автор хотел показать вид «эквивалентного» кода на C, который бы представлял безусловный переход (JMP continue
) замена проверки оригинального пароля на JZ continue
, Вы правы, что этот код (в C) не имеет смысла, но он служит только для иллюстрации того, что сделал хакер.