Чтение онлайн

ЖАНРЫ

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

Jenter Алекс

Шрифт:

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)

Поделиться с друзьями: