Алекс Jenter - Программирование на Visual C++. Архив рассылки

Здесь есть возможность читать онлайн «Алекс Jenter - Программирование на Visual C++. Архив рассылки» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Жанр: Программирование, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Программирование на Visual C++. Архив рассылки: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Программирование на Visual C++. Архив рассылки»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ
, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Программирование на Visual C++. Архив рассылки — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Программирование на Visual C++. Архив рассылки», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule);

if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) {

return E_INVALIDARG;

}

PIMAGE_NT_HEADERS pNTHeaders = MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew);

if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) || IMAGE_NT_SIGNATURE != pNTHeaders->Signature) {

return E_INVALIDARG;

}

HRESULT hr = E_UNEXPECTED;

// Locate the victim

IMAGE_DATA_DIRECTORY& impDir =

pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

PIMAGE_IMPORT_DESCRIPTOR pImpDesc =

MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress),

pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1;

while (pImpDesc < pEnd) {

if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim)) {

if (0 == pImpDesc->OriginalFirstThunk) {

// no import names table

return E_UNEXPECTED;

}

// Locate the entry

PIMAGE_THUNK_DATA pNamesTable =

MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk);

if (IS_INTRESOURCE(szEntry)) {

// By ordinal

while(pNamesTable->u1.AddressOfData) {

if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) && WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal)) {

hr = S_OK;

break;

}

pNamesTable++;

}

} else {

// By name

while(pNamesTable->u1.AddressOfData) {

if (!IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal)) {

PIMAGE_IMPORT_BY_NAME pName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pNamesTable->u1.AddressOfData);

if (0 == ::lstrcmpiA(LPSTR(pName->Name), szEntry)) {

hr = S_OK;

break;

}

}

pNamesTable++;

}

}

if (SUCCEEDED(hr)) {

// Get address

LPVOID *pProc = MakePtr(LPVOID *, pNamesTable, pImpDesc->FirstThunk - pImpDesc->OriginalFirstThunk);

// Save original handler

if (ppOrig) *ppOrig = *pProc;

// write to write-protected memory

return WriteProtectedMemory(pProc, &pHijacker, sizeof(LPVOID));

}

break;

}

pImpDesc++;

}

return hr;

}

HRESULT WriteProtectedMemory(LPVOID pDest, LPCVOID pSrc, DWORD dwSize) {

// Make it writable

DWORD dwOldProtect = 0;

if (::VirtualProtect(pDest, dwSize, PAGE_READWRITE, &dwOldProtect)) {

::MoveMemory(pDest, pSrc, dwSize);

// Restore protection

::VirtualProtect(pDest, dwSize, dwOldProtect, &dwOldProtect);

return S_OK;

}

return HRESULT_FROM_WIN32(GetLastError());

}

Впрочем, такой способ не будет работать если используется позднее связывание (delay load) или связывание во время исполнения (run-time load) с помощью ::GetProcAddress(). Это можно побороть если перехватить саму ::GetProcAddress(), и подменять возвращяемое значение при необходимости. А можно и подправить таблицу экспорта аналогичным способом:

HRESULT ApiHijackExports(HMODULE hModule, LPSTR szEntry, LPVOID pHijacker, LPVOID *ppOrig) {

// Check args

if ((!IS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) || ::IsBadCodePtr(FARPROC(pHijacker))) {

return E_INVALIDARG;

}

PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule);

if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) {

return E_INVALIDARG;

}

PIMAGE_NT_HEADERS pNTHeaders =

MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew);

if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) || IMAGE_NT_SIGNATURE != pNTHeaders->Signature) {

return E_INVALIDARG;

}

HRESULT hr = E_UNEXPECTED;

IMAGE_DATA_DIRECTORY& expDir =

pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

PIMAGE_EXPORT_DIRECTORY pExpDir =

MakePtr(PIMAGE_EXPORT_DIRECTORY, hModule, expDir.VirtualAddress);

LPDWORD pdwAddrs = MakePtr(LPDWORD, hModule, pExpDir->AddressOfFunctions);

LPWORD pdwOrd = MakePtr(LPWORD, hModule, pExpDir->AddressOfNameOrdinals);

DWORD dwAddrIndex = -1;

if (IS_INTRESOURCE(szEntry)) {

// By ordinal

dwAddrIndex = WORD(szEntry) - pExpDir->Base;

hr = S_OK;

} else {

// By name

LPDWORD pdwNames = MakePtr(LPDWORD, hModule, pExpDir->AddressOfNames);

for (DWORD iName = 0; iName < pExpDir->NumberOfNames; iName++) {

if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pdwNames[iName]), szEntry)) {

dwAddrIndex = pdwOrd[iName];

hr = S_OK;

break;

}

}

}

if (SUCCEEDED(hr)) {

if (pdwAddrs[dwAddrIndex] >= expDir.VirtualAddress && pdwAddrs[dwAddrIndex] < expDir.VirtualAddress + expDir.Size) {

// We have a redirection

LPSTR azRedir = MakePtr(LPSTR, hModule, pdwAddrs[dwAddrIndex]);

ATLASSERT(!IsBadStringPtrA(azRedir, -1));

LPSTR azDot = strchr(azRedir, '.');

int nLen = azDot - azRedir;

LPSTR azModule = (LPSTR)alloca(nLen);

memcpy(azModule, azRedir, nLen);

azModule[nLen] = '\x0';

// Try to patch redirected function

return ApiHijackExports(

::GetModuleHandle(azModule), azDot + 1, pHijacker, ppOrig);

}

if (ppOrig)

*ppOrig = MakePtr(LPVOID, hModule, pdwAddrs[dwAddrIndex]);

DWORD dwOffset = DWORD_PTR(pHijacker) - DWORD_PTR(hModule);

// write to write-protected memory

hr = WriteProtectedMemory(pdwAddrs + dwAddrIndex, &dwOffset, sizeof(LPVOID));

}

return hr;

}

Имейте в виду, под Windows9x нельзя честно подменить экспорты для разделяемых библиотек, таких как user32.dll, kernel32.dll и gdi32.dll. Это связано с тем, что область памяти начиная с адреса 7FC00000h и выше совместно используестя всеми процессами в системе, и модификация сказалась бы на каждом из них. А это нежелательно, поскольку память, занимаемая нашей функцией-перехватчиком, наоборот, принадлежит только нашему процессу. Во всех остальных процессах в системе ::GetProcAddress(), после подмены таблицы экспорта, вернула бы неправильный указатель. Тем не менее, если нельзя, но очень хочется, то можно. Для этого нам придется вручную создать новый дескриптор в GDT (вот тут-то у Windows9x проблем не возникает) и используя этот дескриптор произвести необходимые изменения. Но будьте готовы к тому, что понадобится написать свою разделяемую библиотеку, установить ее в системе и проверять ID процесса при каждом обращении. Рабочий пример есть на internals.com.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Программирование на Visual C++. Архив рассылки»

Представляем Вашему вниманию похожие книги на «Программирование на Visual C++. Архив рассылки» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Алексей Макеев - Смертельный архив
Алексей Макеев
libcat.ru: книга без обложки
Алексей Апухтин
Отзывы о книге «Программирование на Visual C++. Архив рассылки»

Обсуждение, отзывы о книге «Программирование на Visual C++. Архив рассылки» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x