Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #91, ИЮЛЬ 2006 г.

Обзор эксплойтов

Крис Касперски ака мыщъх

Хакер, номер #091, стр. 091-060-6


.text:67B8CF4B n2k_vulnerably endp ; конец процедуры

Как мы видим, эта процедура (назовем ее n2k_vulnerably) принимает два аргумента: указатель на строку и длину этой строки, которая затем сравнивается со знаковой операцией и константой 1000h, в результате чего допустимые диапазоны длин строки оказываются равны [0, 1000h) и (7FFFFFFFh, FFFFFFFFh]. Затем эта строка копируется внутрь какой-то структуры (по всей видимости, объекта, поскольку присутствуют вызовы типа this call), которая передается функции sub_67B8CD10 для обработки.

Очевидно, что, передав строку размером 2 Гб или выше, мы затрем добрую половину адресного пространства приложения, отчего ему станет очень нехорошо. В лучшем случае дело кончится крэшем, в худшем - передачей shell-кода и захватом управления. Вот только передать такую длинную строку по сети очень проблематично. Даже если жертва сидит на DSL, атака растянется на несколько часов, и пользователь, скорее всего, просто закроет Оперу, или соединение будет выбито по тайм-ауту.

Но к счастью для хакеров, разработчики Оперы допустили двойную ошибку, использовав расширение слова до двойного слова. Со знаком, разумеется. Куда же без него! (По правде говоря, за разработчиков это сделал компилятор — они лишь использовали неправильное преобразование типов, но пользователям Оперы от этого ничуть не легче). Причем, это преобразование осуществляется в функции, вызывающей n2k_vulnerably!

Ниже приведен ее ключевой фрагмент с некоторыми сокращениями:

Листинг 7: уязвимый код, вызывающий функцию n2k_vulnerably и передающий ей в качестве arg_len знаковое слово, расширенное (со знаком!) до двойного слова

.text:67B8AF5D loc_67B8AF5D: ; CODE XREF: sub_67B8AE6E+F8?j

.text:67B8AF5D 89 46 2C mov [esi+2Ch], eax

.text:67B8AF60 EB 16 jmp short loc_67B8AF78

.text:67B8AF62

.text:67B8AF62 loc_67B8AF62: ; CODE XREF: sub_67B8AE6E+E2?j

.text:67B8AF62 0F BF 45 EC movsx eax, [ebp+ var_length_ovfl]

.text:67B8AF62 ; вот оно! расширение слова, хранящего длину копируемой

.text:67B8AF62 ; строки, до двойного слова со знаком

.text:67B8AF62 ; если длина строки превышает 7FFFh байт,

.text:67B8AF62 ; то и результат превышает 7FFFFFFFh

.text:67B8AF62

…

.text:67B8B012 FF 76 08 push dword ptr [esi+8] ; передаем arg_src функции

.text:67B8B015 8B 0D 18 EF F9 mov ecx, dword_67F9EF18 ; this

.text:67B8B01B 8D 85 B0 FD FF lea eax, [ebp+var_250] ; получаем arg_len

.text:67B8B021 50 push eax ; передаем arg_len функции

.text:67B8B022 E8 D7 1E 00 00 call n2k_vulnerably ; вызываем функцию

Код функции довольно громоздкий и потому приведен не полностью. Под сокращение, в частности, попала передача расширенного EAX в переменную [EBP+var+250], но тот факт, что она передается, сокращает длину переполняемой строки всего до 8000h байт или 32 Кб, что вполне приемлемо для атаки.

Остается выяснить, что же это за строка такая и как она связана с пользовательским вводом (и связана ли вообще). Ответ дает функция sub_67B8CD10, вызываемая из n2k_vulnerably.

Вот ее дизассемблерный текст:

Назад на стр. 091-060-5  Содержание  Вперед на стр. 091-060-7