Comments 15
На самом деле в реальном мире всё намного страшнее. Даже когда хотят, многие программисты не могут правильно написать правильную очистку памяти. Я эту ошибку регулярно встречаю в разных проектах, натравляя на них PVS-Studio. Она просто везде. Может даже статью как нибудь напишу про этот паттерн ошибки.
Например, это может выглядеть так:
Пример взят из ReactOS, который я как раз в данный момент изучаю. Скоро будет очередная статья с блюющим единорогом.
Например, это может выглядеть так:
#define MEMSET_BZERO(p,l) memset((p), 0, (l)) char *SHA384_End(SHA384_CTX* context, char buffer[]) { ... MEMSET_BZERO(context, sizeof(context)); ... }
Пример взят из ReactOS, который я как раз в данный момент изучаю. Скоро будет очередная статья с блюющим единорогом.
+12
Какой такой SecureZeroMemory… Тут в ночи злодеи путают местами аргументы. Ещё код из ReactOS на эту тему:
Заполнили 0xFF байт вместо 8196. Тут SecureZeroMemory не поможет. :)
#define RtlFillMemory(Destination, Length, Fill) \ memset(Destination, Fill, Length) #define IOPM_FULL_SIZE 8196 HalpRestoreIopm(VOID) { ... RtlFillMemory(HalpSavedIoMap, 0xFF, IOPM_FULL_SIZE); ... }
Заполнили 0xFF байт вместо 8196. Тут SecureZeroMemory не поможет. :)
+9
Хорошие примеры, да пост не об этом. Да, при вызове функции перезаписи можно ошибиться. А можно не ошибиться, но вызвать не ту функцию, и тогда оптимизирующий компилятор может удалить вызов.
+2
Я понимаю, что просто про пользу очитки памяти. Я просто хотел показать, что даже если написан код для очистки, далеко не факт что он работает. И не потому, что компилятор что-то выбросит, а просто из-за того, что программисты не тестируют, чистится память или нет. Вроде есть memset — значит и так сойдет.
P.S. Я очень сомневаюсь, что адекватный компилятор может выбросит вызов функции memset.
P.S. Я очень сомневаюсь, что адекватный компилятор может выбросит вызов функции memset.
+1
(Куда-то исчез мой комментарий. Прошу прощения, если будет дубль.)
Я понимаю, что пост про пользу очитки памяти. Я хотел показать, что даже если код очистки написан, далеко не факт что он работает. И не потому, что компилятор что-то выбросит, а просто из-за того, что программисты не тестируют, очищается память или нет. Вроде есть memset — значит и так сойдет.
P.S. Я очень сомневаюсь, что адекватный компилятор может выбросит вызов функции memset.
Я понимаю, что пост про пользу очитки памяти. Я хотел показать, что даже если код очистки написан, далеко не факт что он работает. И не потому, что компилятор что-то выбросит, а просто из-за того, что программисты не тестируют, очищается память или нет. Вроде есть memset — значит и так сойдет.
P.S. Я очень сомневаюсь, что адекватный компилятор может выбросит вызов функции memset.
+1
>Я очень сомневаюсь, что адекватный компилятор может выбросит вызов функции memset
Очень даже может. Например, Visual C++ 9 при компиляции такого кода с включенной оптимизацией (/O2)
начисто удаляет второй вызов memset() — видно в машинном коде.
На это компилятор имеет полное право — такое изменение не влияет на наблюдаемое поведение, которое описано в Стандарте (1.9/6) как последовательность вызова функций ввода-вывода и чтения-записи volatile данных.
Очень даже может. Например, Visual C++ 9 при компиляции такого кода с включенной оптимизацией (/O2)
int main()
{
WCHAR buffer[1000] = {};
MessageBox( 0, buffer, buffer, 0 );
memset( buffer, 9, sizeof( buffer ) );
return 0;
}
начисто удаляет второй вызов memset() — видно в машинном коде.
На это компилятор имеет полное право — такое изменение не влияет на наблюдаемое поведение, которое описано в Стандарте (1.9/6) как последовательность вызова функций ввода-вывода и чтения-записи volatile данных.
+4
1) Ужасы © «Городок»
2) Место для раздумий по поводу статического анализа. Спасибо за интересную информацию.
2) Место для раздумий по поводу статического анализа. Спасибо за интересную информацию.
+4
Очень хороший пример оптимизации. Думаю, нелишним будет добавить его в статью в качестве иллюстрации того, что будет если не использовать SecureZeroMemory.
0
Добавьте тэг «безопасность» или что-либо в этом духе.
+1
Кстати говоря, бывают случаи, когда использование SecureZeroMemory штука спорная. В том плане, что наличие этой функции в импорте приложения для потенциального кодокопателя — как красная тряпка для быка — «хотят стереть что-то секретное». Соответственно, не надо даже особо стараться в поисках «секретных» данных и вникать в код, просто ставим breakpoint на SecureZeroMemory и вуаля, то, что хотели спрятать у нас как на ладони перед самым затиранием. «Ручное затирание» в этом отношении выглядит всё же лучше, если, конечно, подсказать компилятору не оптимизировать этот кусочек кода. Кодокопателю в этом случае хотя бы придётся вникать в код и найти это место, а это уже время. Аналогично рассуждая, можно понять, что схожими свойствами обладает и использование CryptoAPI. Но всё же, лучше SecureZeroMemory, чем оставлять данные в памяти.
+8
Пост в ИнфоБез бы переместить. Он его достоен.
Спасибо! Есть куда теперь тыкать носом.
Спасибо! Есть куда теперь тыкать носом.
0
Написать правильную очистку памяти сложно даже хорошему программисту. Это всегда было большой проблемой.
0
Опасность чтения из RAM-модулей напрямую мягко говоря преуменьшена.
cryptome.org/0003/RAMisKey.pdf
Но при кривых руках — вся система сплошная дыра
cryptome.org/0003/RAMisKey.pdf
Но при кривых руках — вся система сплошная дыра
+1
Sign up to leave a comment.
Перезаписывать память – зачем?