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

Недетский трюк от Криса

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

Хакер, номер #092, стр. 092-122-2


Создадим простейшую программу test.c и откомпилируем ее компилятором Microsoft Visual C++ с настройками по умолчанию.

#include <stdio.h>

main()

{

printf("hello, world!\n");

}

Образовавшийся файл test.exe пропустим через утилиту dumpbin, входящую в состав MS VC (dumpbin /IMPORTS test.exe > out), и посмотрим, что хорошего она нам скажет:

Dump of file test.exe

KERNEL32.dll

405000 Import Address Table

4054AC Import Name Table

0 time date stamp

0 Index of first forwarder reference

2DF WriteFile

174 GetVersion

7D ExitProcess

...

Ага, таблица адресов располагается по адресу 405000h, а lookup-таблица — по 4054ACh. Заглянув туда hiew'ом, мы увидим следующее (RVA-адреса имен импортируемых функций):

.00405000:D8 56 00 00-62 55 00 00-70 55 00 00-7E 55 00 00

.00405010:92 55 00 00-A6 55 00 00-C2 55 00 00-D8 55 00 00

.00405020:F2 55 00 00-0C 56 00 00-22 56 00 00-3A 56 00 00

.004054AC:D8 56 00 00-62 55 00 00-70 55 00 00-7E 55 00 00

.004050DC:92 55 00 00-A6 55 00 00-C2 55 00 00-D8 55 00 00

.004050EC:F2 55 00 00-0C 56 00 00-22 56 00 00-3A 56 00 00

Как видно, обе таблицы полностью совпадают и указывают на массив имен/ординалов импортируемых функций:

.004056D8:DF 02 57 72-69 74 65 46 61 70 41 6C-6C 6F 63 00 ??WriteFile

А теперь пропустим через dumpbin «Блокнот» из стандартной поставки NT (dumpbin /IMPORTS notepad.exe > out) и увидим, в чем состоит разница.

KERNEL32.dll

1001080 Import Address Table

1006784 Import Name Table

FFFFFFFF time date stamp

FFFFFFFF Index of first forwarder reference

77E99F42 1EF LocalUnlock

77E8B7F4 1AE GlobalUnlock

77E8CCA3 1A7 GlobalLock

Таблица адресов еще до загрузки файла в память уже содержит готовые эффективные виртуальные адреса! Если не веришь — смотри hiew'ом:

.010012D4:22 6A AF 76-47 26 AF 76-9E DB AE 76-5F FC AF 76

.010012E4:32 6A AF 76-E2 16 AE 76-71 6F AF 76-C2 AC AF 76

.010012F4:9C 1D AF 76-00 00 00 00-00 00 00 00-00 00 00 00

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

Такая техника импорта функций называется биндингом (binding) и при желании может быть реализована с помощью утилиты editbin, позаимствованной все из того же компилятора (editbin /BIND test.exe). Посмотрим, что она сделала с нашим тестовым файлом? А сделала она с ним вот что:

Dump of file test.exe

KERNEL32.dll

405000 Import Address Table

4054AC Import Name Table

44B17B02 time date stamp Mon Jul 10 01:54:10 2006

Назад на стр. 092-122-1  Содержание  Вперед на стр. 092-122-3