Благодарен всем заранее за ответы.
Встала задача об отлове копирования файлов. Решений конечно много: хуки, журнал файловой системы, замена самой функции копированя. Вот я и решил выбрать последний вариант... В 2005 году была опубликована статья Перехват API-функций в Windows NT_2000_XP, вот в ней расказывался метод внедрения DLL в процесс с последующей заменой почти любой функции на свою(храняшуюся в той же dll). Как бы с этим проблем нет, dll внедряется, функции заменяются(Замена нужна бля того, чтобы перед началом копированя показать диалог с запросом пароля, и если пароль верен продолжить копирование), всё как бы работает, если учесть что внедрение происходит в процесс мной написаной программы

. Но появилась проблема внедрения в процесс explorer.exe(ибо как я понимаю, за копирование файлов в Windows отвечает именно этот процесс) т.к. этот процесс не содержит .idata.
Вопросы:
1) Что я делаю нетак?
2) Есть ли какие нибудь другие методы отлова и замены копированя файлов?
Код Dll
//------------DLL----------------------
#define _WIN32_WINNT 0x4000
// Dll_for_hook.cpp : Defines the entry point for the DLL application.
//
#define RASSWORD "111"
#include "StdAfx.h"
#include "resource.h"
char szPass[MAX_PATH]; //Буфер для пароля
DWORD adr_i_CopyFileExA;
HINSTANCE hInstance = NULL;
BOOL CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL WINAPI i_CopyFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
LPVOID lpData OPTIONAL, LPBOOL pbCancel OPTIONAL, DWORD dwCopyFlags );
void InterceptFunctions(void);
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hInstance = (HINSTANCE)hModule;
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
InterceptFunctions();
return TRUE;
}
// Эта функция ищет в таблице импорта - .idata нужный адрес и меняет на
// адрес процедуры-двойника
void InterceptFunctions(void)
{
// Начало отображения в памяти процесса
BYTE *pimage = (BYTE*)GetModuleHandle(NULL);
BYTE *pidata;
// Стандартные структуры описания PE заголовка
IMAGE_DOS_HEADER *idh;
IMAGE_OPTIONAL_HEADER *ioh;
IMAGE_SECTION_HEADER *ish;
IMAGE_IMPORT_DESCRIPTOR *iid;
DWORD *isd; //image_thunk_data dword
// Получаем указатели на стандартные структуры данных PE заголовка
idh = (IMAGE_DOS_HEADER*)pimage;
ioh = (IMAGE_OPTIONAL_HEADER*)(pimage + idh->e_lfanew
+ 4 + sizeof(IMAGE_FILE_HEADER));
ish = (IMAGE_SECTION_HEADER*)((BYTE*)ioh + sizeof(IMAGE_OPTIONAL_HEADER));
//если не обнаружен магический код, то у этой программы нет PE заголовка
if (idh->e_magic != 0x5A4D)
{
MessageBox(NULL, "Not exe hdr", "Error!", 0);
return;
}
//ищем секцию .idata
for(int i=0; i<16; i++)
if(strcmp((char*)((ish+ i)->Name) , ".idata") == 0) break;
if(i==16)
{
MessageBox(NULL, "Unable to find .idata section", "Error!", 0);
return;
}
// Получаем адрес секции .idata(первого элемента IMAGE_IMPORT_DESCRIPTOR)
iid = (IMAGE_IMPORT_DESCRIPTOR*)(pimage + (ish +i)->VirtualAddress );
// Получаем абсолютный адрес функции для перехвата
adr_i_CopyFileExA = (DWORD)GetProcAddress(
GetModuleHandle("KERNEL32.dll"), "CopyFileExA");
if(adr_i_CopyFileExA == 0)
{
MessageBox(NULL, "Can`t get adr_i_CopyFileExA", "Error!", 0);
return;
}
// В таблице импорта ищем соответствующий элемент для
// библиотеки user32.dll
while(iid->Name) //до тех пор пока поле структуры не содержит 0
{
if(strcmp((char*)(pimage + iid->Name), "KERNEL32.dll") ==0 ) break;
iid++;
}
// Ищем в IMAGE_THUNK_DATA нужный адрес
isd = (DWORD*)(pimage + iid->FirstThunk);
while(*isd!=adr_i_CopyFileExA && *isd!=0) isd++;
if(*isd == 0)
{
MessageBox(NULL, "CopyFileExA not found in .idata", "Error!", 0);
return;
}
// Заменяем адрес на свою функцию
DWORD buf = (DWORD)&i_CopyFileExA;
DWORD op, writen;
// Обычно страницы в этой области недоступны для записи
// поэтому принудительно разрешаем запись
VirtualProtect((void*)(isd),4,PAGE_READWRITE, &op);
// Пишем новый адрес
WriteProcessMemory(GetCurrentProcess(), (void*)(isd),
(void*)&buf,4,&writen);
//восстанавливаем первоначальную защиту области по записи
VirtualProtect((void*)(isd),4,op, &op);
//если записать не удалось – увы, все пошло прахом…
if(writen!=4)
{
MessageBox(NULL, "Unable rewrite address", "Error!", 0);
return;
}
}
BOOL CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg){
case WM_INITDIALOG:
SetDlgItemText(hDlg, IDC_EDIT1, "Enter_Pass");
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDC_BUTTON1:
GetDlgItemText(hDlg, IDC_EDIT1, szPass, MAX_PATH);
if(szPass != "111"){ // Знаю что эта стока в данном случае не несёт никакого смысла
MessageBox(hDlg, "Пароль не верен, копирование прекращёно", "Error", MB_OK);
EndDialog(hDlg, TRUE);
return false;
}
else return true;
}
}
return 0;
}
BOOL WINAPI i_CopyFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
LPVOID lpData OPTIONAL, LPBOOL pbCancel OPTIONAL, DWORD dwCopyFlags)
{
//здесь вы выполняете любые свои действия
//-----------------------------------------------------------------------------------------------
// if( !DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ) return TRUE;
//-----------------------------------------------------------------------------------------------
// вызываем оригинальную функцию через указатель
MessageBox(NULL, "Пароль не верен, копирование прекращёно", "Error", MB_OK);
((BOOL (__stdcall*)(LPCSTR, LPCSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD))adr_i_CopyFileExA)(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags);
return TRUE;
}