SEOSERVISE - Защита информации.

 
   
 

Главная


 


Однако рассмотрим эти байты подробнее. Первое значение, 0x70786567, является шсстнадиатеричным представлением подстроки рхед, входящей в состав строки hacking exposed . Таким образом, значение счетчика команд можно модифицировать с помощью функции strcpy ()^ А это значит, что можно кардинально изменить ход вы­ полнения программы, разместив в регистре EIP адрес кода, помещенного в память при переполнении. Что произойдет, если в буфере buff разместить машинный код (двоичное представление ассемблерных инструкций) и модифицировать содержимое регистра EIP так, чтобы он на этот код указывал? Остается только надеяться, м i о прак­ тически каждая компания-разработчик программного обеспечения будет уделять вни­ мание вопросам безопасности. В противном случае любую команду на удаленном компьютере можно будет выполнить даже без подбора пароля. Другими словами, мир был бы в наших руках. Пример переполнения буфера Рассмотрим интересный пример, а также проанализируем, как из сложившейся ситуации можно извлечь максимальную выгоду. Есть три возможности поиска изъянов переполнения буфера. Просмотр исходного кода. • Дизассемблирование. Работа в предельном режиме. Если условий переполнения буфера требуется достигнуть в системе Windows (что и рассматривается в данной главе), то действия ограничиваются двумя последними воз­ можностями. Ниже рассматриваются достоинства и недостатки каждой из них. Дизассемблирование Это представление двоичной исполняемой программы (т.е. программного обеспе­ чения) на языке ассемблера или в виде инструкций центрального процессора, выпол­ няемых на компьютере. Если вы всерьез подумываете о подобном обратном проекти­ровании, то стоит воспользоваться единственным лучшим средством — Interactive Dis ­ assembler Professional от компании Datarescue . В мире Windows , в котором исходный код, как правило, недоступен, способность "читать между строк" является невероятно ценным качеством. Чтобы обнаружить изъяны посредством этого метода, необходимо понимать, как высокоуровневые функ­ ции преобразуются в ассемблерный код. Для примера рассмотрим простой фрагмент исходного кода на языке С. int v - jln ( char * user ) Аргумент с заданной пользователем длиной user копируется в буфер ( buffer ) раз­ мером 500 байт. Поскольку количеством передаваемых данных, которые размещаются в буфере, можно управлять, это позволяет выйти за пределы выделенного диапазона и выполнить произвольный код. После дизассемблирования исходный код выглядит следующим образом: Обратите внимание на ряд важных моментов. Параметры помещаются в стек в об­ ратном порядке. С одной стороны, почти каждая инструкция, которая ссылается на область памяти, расположенную выше адреса, заданного в регистре ЕВР (например, [ ebp +8 J ), ссылается на параметр процедуры. С другой стороны, при ссылке на ло­ кальные переменные используется отрицательное смещение относительно адреса ЕВР. Так что же происходит? Параметр, ссылка на который имеет вид [еЪр+8] (пользовательская строка), помещается в регистр еах, а затем проталкивается в стек. Следующим в стек записывается второй аргумент функции sprintf . Здесь Oxlf 4 соот­ ветствует десятичному числу 500 (размеру буфера). После завершения обратного про­ ектирования можно без особых проблем выявить подобные вызовы. Пока в памяти еще свежи полученные сведения, ничто не может помешать анализу низкоуровневого преобразования функций.

 

 

 

 

 

 
 

1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |32 |33 |34 |35 |36 |37 |38 |39 |40 |41 |42 |43 |44 |45 |46 |47 |48 |49 |50 |51 |52 |53 |54 |55 |56 |57 |58 |59 |60 |61 |62 |63 |64 |65 |66 |67 |68 |69 |70 |71 |72 |73 |74 |75 |76 |77 |78 |79 |80 |81 |82 |83 |84 |85 |86 |87 |88 |89 |90 |91 |92 |93 |94 |95 |96 |97 |98 |99 |100 |