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

Мастерская бравого хакера

Крис Касперски

Хакер, номер #091, стр. 091-116-4


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

Яркий тому пример — milw0rm.com/shellcode/656 (прилагается к статье под именем beta.cpp). Пропускаем его через gcc и получаем следующий список ошибок (не считая варнингов):

Список ошибок, выдаваемый компилятором gcc, при попытке трансляции файла beta.cpp

beta.cpp:34:21: windows.h: No such file or directory

beta.cpp: In function `int main(int, char**, char**)':

beta.cpp:165: error: `stricmp' undeclared (first use this function)

beta.cpp:185: error: `strnicmp' undeclared (first use this function)

beta.cpp:245: error: `isalnum' undeclared (first use this function)

beta.cpp:250: error: `isprint' undeclared (first use this function)

beta.cpp:339: error: invalid conversion from `void*' to `char*'

beta.cpp:356: error: `O_BINARY' undeclared (first use this function)

beta.cpp:361: error: `lseek' undeclared (first use this function)

beta.cpp:377: error: invalid conversion from `void*' to `char*'

beta.cpp:384: error: `read' undeclared (first use this function)

beta.cpp:398: error: `close' undeclared (first use this function)

С ошибкой 34 все понятно — программа усиленно косит под форточки, прихватив с собой файл <windows.h>, но тут же использует стандартные POSIX-вызовы: open() со странным флагом O_BINARY, lseek(), read() и close(), которых ни в самом Windows, ни в одном из win32-компиляторов никогда не существовало (см. ошибки 356, 361, 384 и 398). Убираем строку «#include <windows.h>», меняя ее на «#include <unistd.h>», и удаляем глупый флаг O_BINARY, поскольку по умолчанию файл уже является двоичным (узнать, какие заголовочные файлы соответствуют данной функции, можно из man'а, например, «man 2 open»). Чтобы избавиться от предупреждения «this file include <malloc.h> which is deprecated, use <stdlib.h> instead», удаляем и «#include <malloc.h>».

Ошибки 245 и 250 устраняются подключением их «родного» заголовочного файла, в котором они были объявлены «#include <ctype.h>» (см. «man isalnum»). А вот функций stricmp() и strnicmp() в gcc действительно нет, однако они могут быть заменены на аналогичные им strcmp() и strncmp() даже без коррекции аргументов!

Ошибки 339 и 377 исправляются еще проще: достаточно взять строку «buffer = malloc(MAX_BUFFER_SIZE)» и добавить явное преобразование типов, также называемое кастингом «buffer = (char *)malloc(MAX_BUFFER_SIZE)».

Исправленный вариант лежит в файле beta-fixed.cpp и компилируется без всяких нареканий.

Будем считать, что с идентификацией транслятора мы разобрались, и exploit откомпилировался нормально, но... это еще не конец, а только начало. Ведь программный листинг - это только оболочка, образно говоря, «тетива», а разящие острие — загадочный и таинственный shell-код, помещенный в строковый «иероглифический» массив вроде «\x29\xc9\x83...\xe9\xb0\xd9». Что делать, если он не работает или работает не так, как нам этого хочется?

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