процедура MyGetProcAddress, возвращающая адрес API-функции по хэш-сумме его имени
Зная базовый адрес загрузки KERNEL32.DLL (он передается функции через стек и лежит по смещению 24h байта от вершины — остальное пространство занимают регистры, сохраненные командой PUSHA), программа получает указатель на PE-заголовок, откуда извлекает указатель на таблицу экспорта, считывая общее количество экспортируемых имен (numberOfNamePointers) и RVA-указатель на массив с именами, который тут же преобразуется в эффективный виртуальный адрес путем сложения с базовым адресом загрузки KERNEL32.DLL.
А вот дальше… дальше начинается самое интересное! Для каждого из экспортируемых имен функция вычисляет хэш, сравнивая его с тем "загадочным" числом. Если они совпадают, искомая API-функция считается найденной и возвращается ее виртуальный адрес. Таким образом, данный код представляет собой аналог функции GetProcAddress, только с той разницей, что он принимает не ASCII-имя функции, а его 32-битный хэш. Условимся называть эту процедуру MyGetProcAddress.
Можно ли восстановить имя функции по ее хэшу? С математической точки зрения — навряд ли, но что мешает нам запустить shell-код под отладчиком (см. одноименную врезку) и "подсмотреть" возвращенный виртуальный адрес, по которому имя определяется без проблем!
Сказано сделано! Немного протрассировав программу до строки 82h, мы обнаруживаем в регистре EAX число 79450221h (зависит от версии системы на вашей машине наверняка будет иным). Нормальные отладчики (типа OllyDbg) тут же покажут имя функции LoadLibraryA. Как вариант, можно воспользоваться утилитой DUMPBIN из Platform SDK, запустив ее со следующими ключами: "dumpbin KERNEL32.DLL /EXPORTS >
kernel32", только помните, что она показывает относительные RVA-адреса, поэтому необходимо либо добавить к ним базовый адрес загрузки KERNEL32.DLL, либо вычесть его из адреса искомой функции.
seg000:00000082 66 53 push bx ; \
seg000:00000084 66 68 33 32 push small 3233h ; + - "ws2_32"
seg000:00000088 68 77 73 32 5F push 5F327377h ; /
seg000:0000008D 54 push esp ; &"ws2_32"
seg000:0000008E FF D0 call eax ; LoadLibraryA
seg000:00000090 68 CB ED FC 3B push 3BFCEDCBh ; WSAStartup
seg000:00000095 50 push eax ;
seg000:00000096 FF D6 call esi ; MyGetProcAddress