Вот например давеча читаю я A Guide to Kernel Exploitation - конкретно вторую главу, где перечисляются паттерны уязвимостей и думаю, что с поисками описанного вполне способна справиться не особо большая стая дрессированных обезъян:
- uninitialized pointers using, страница 24. Вполне можно положиться на compiler warning
- nonvalidated pointers, страница 25 - аналогично, правда нужно добавить атрибут "этот указатель передан из user mode"
- integer overflow, страница 30 - аналогично
- double fetch, страница 34 - практически один в один п.2
- reference counting overflow, страница 39 - тут уже нужна некоторая подсказка компилятору - если мы не возвращаем значение из этой ф-ции, то любая ветка code flow ниже до return должна уменьшить счетчик ссылок
Причем конкретно для kernel code - он почти всегда написан на plain C, так что его синтаксический разбор и построение графов code flow & data flow вполне способен реализовать в качестве курсача
И хер там - вместо этого мы имеем своры т.н.
К сожалению, еще не создана такая полезная вещь, как всеобъемлющий справочник по вопросам безопасности. Те из нас, кто работают в этой области, зачастую создавали свои собственные справочники, содержащие перечни возможных нападений и уязвимых мест, которые встречаются в коммерческих продуктах, описаны в научной литературе или придуманы нами самими. Подобные перечни огромны — пару лет назад я составил такой список из 759 нападений, но и он не был исчерпывающимПадумаешь, 759, хоть 666 тыщ мульонов - пока они не формализованы в виде правил, которые можно проверять автоматически - все это
Дичайше негодую например
Update: ветка обсуждения непригодности oacr для многих описанных случаев на rsdn
А ещё, уязвимости в драйверах это:
ОтветитьУдалить1) Уязвимости в следствии ошибок проектирования. Эффективной методологии автоматического выявления в принципе невозможно разработать.
2) Уязвимости при парсинге данных какого-либо формата. Эффективно выявляются только фаззингом.
3) Уязвимости, связанные с не очевидными нюансами работы каких-либо системных механизмов, на которые полагается драйвер (см. про известные эпизоды с RtlQueryRegistryValues и ProbeForRead/Write). Эффективно выявляются только после первого прецедента.
уязвимостей при парзинге вполне можно избежать обычным стат. анализом кода. См. например сорцы darwin - конкретно парзер machO - там на каждое действие минимум 2 проверки
ОтветитьУдалитьВпрочем поцт не о том, что компилятор мог бы выловить все 100% багов. Но уже сейчас он вполне справился бы с самыми широко распространенными классами уязвимостей, отправив большую часть раздувающих щеки от осознания собственной важности т.н. "экспертов" на помойку например
Btw, OACR который в состав последнего WDK включен пробовал уже? Он что-то действительно интересное в плане выявления дефектов при статическом анализе умеет?
ОтветитьУдалитьесли под последним имеется в виду wdk7 - то да
ОтветитьУдалитьособо ничего полезного он не умеет находить
OACR - очередное частное решение, призванное выявлять наиболее типичные ошибки в ужасном коде, писанном откровенно криворукими программерами. В таком коде оно, конечно, что-нибудь найдет. Но для более-менее аккуратного программиста, использующего вдобавок собственные средства верификации (хоть те же assert'ы), такие проверялки - что телеге пятое колесо.
ОтветитьУдалитьПо уму, проверки надо встраивать в компилятор. Например, дать возможность навешивать на функции, константы/переменные, классы и прочие сущности различные атрибуты, и указывать правила, которым они должны соответствовать. Например, функции можно приписать атрибуты Paged=true/false, IRQL=n, Locked=true/false, указателю - атрибут Paged=true/false, переменной - ConcurrentAccess=true/false, и так далее.
ровно использование атрибутов в компиляторе и было реквестировано в исходном посте:
ОтветитьУдалить"нужна некоторая подсказка компилятору - если мы не возвращаем значение из этой ф-ции, то любая ветка code flow ниже до return должна уменьшить счетчик ссылок"