Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
| Помогли мы вам |
Теперь нырнем в пучины интернета и поищем кастомную реализацию GetProcAddress(. Я выбрал самый аккуратный и милый вариант.
FARPROC myGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + dosHeader->e_lfanew); PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hModule + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); DWORD* addressOfFunctions = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfFunctions); WORD* addressOfNameOrdinals = (WORD*)((BYTE*)hModule + exportDirectory->AddressOfNameOrdinals); DWORD* addressOfNames = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfNames); for (DWORD i = 0; i < exportDirectory->NumberOfNames; ++i) { if (strcmp(lpProcName, (const char*)hModule + addressOfNames[i]) == 0) {return (FARPROC)((BYTE*)hModule + addressOfFunctions[addressOfNameOrdinals[i]]); } } return NULL;}Функция достаточно проста: принимает базовый адрес загрузки библиотеки, а также имя функции, адрес которой надо получить. Работает так, как нам и нужно, — путем парсинга EAT.
Помнишь, мы отключили CRT? Поэтому использование функции strcmp( из этого кода невозможно. К счастью, сравнение двух строк — базовый алгоритм, который пишут еще на паскале в седьмом классе. На C++ я вынес его в отдельную функцию custom_strcmp(.
int custom_strcmp(const char* str1, const char* str2) { while (*str1 || *str2) {if (*str1 < *str2) {return -1;}else if (*str1 > *str2) {return 1;}str1++;str2++; } return 0;}Разобравшись, как и что делать, получаем следующий код.
#include <Windows.h>#include <winternl.h>typedef int (WINAPI* MessageBoxWFunc)( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType );int custom_strcmp(const char* str1, const char* str2) { while (*str1 || *str2) {if (*str1 < *str2) {return -1;}else if (*str1 > *str2) {return 1;}str1++;str2++; } return 0;}FARPROC myGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + dosHeader->e_lfanew); PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hModule +ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); DWORD* addressOfFunctions = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfFunctions); WORD* addressOfNameOrdinals = (WORD*)((BYTE*)hModule + exportDirectory->AddressOfNameOrdinals); DWORD* addressOfNames = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfNames); for (DWORD i = 0; i < exportDirectory->NumberOfNames; ++i) {if (custom_strcmp(lpProcName, (const char*)hModule + addressOfNames[i]) == 0) {return (FARPROC)((BYTE*)hModule + addressOfFunctions[addressOfNameOrdinals[i]]);} } return NULL;}int main() { HMODULE user32Module = LoadLibrary(L"user32.dll"); MessageBoxWFunc MessageBoxWPtr = (MessageBoxWFunc)(myGetProcAddress(user32Module, "MessageBoxW")); MessageBoxWPtr(NULL, L"HI", L"HI", MB_OK); return 0;}Компилируем, запускаем. Видим, что остался лишь один импорт.
Чем же заменить LoadLibrary(? Если мы глянем на последовательность вызовов функций, то увидим, что LoadLibrary( вызывает LdrLoadDll(, она — LdrpLoadDll(, а та — еще одну функцию... Процесс, скажу честно, достаточно сложный. Вот картинка, которая хорошо описывает последовательность вызовов при загрузке DLL.
|
|
|