Давно уже использую такую методику: если нужно вставить свой код в какой-то .exe или .dll, то я просто пишу свою .dll на VC++, подключаю ее в таблицу импорта исправляемого .exe (например при помощи утилитки SnippetCreator), а в секции инициализации моей .dll прописываю в нужные места (там где хочу перепавить управление на себя) в память процесса JMP или СALL на некую процедуру в моей .dll, которая и выполняет нужные действия. Естественно в заголовке .exe нужно разрешить запись в исправляемые секции. А теперь собственно вопрос. Под Win98 все работает замечательно. А под XP работает все за исключением файловых операций. То есть ReadFile или WriteFile (а так же всякие надстройки над ними в виде fwrite или CFile:Write) работает только если его вызывать в секции инициализации или финализации. А вот из процедуры в моей .dll, на которую передается вызов, эти функции нельзя заставить работать - возвращают код ошибки. Пока что выкручиваюсь тем, что все нужно загружаю вначале работы при инициализации, а записываю при окончании работы в секции финализации. Но хочется читать и писать в любое время. Ткните носом, куда смотреть.
Вот пример такой .dll - этот кусок выдран из эмулятора Sentinel'а, но аналогичные проблемы возникают всегда под XP при перехвате функций. #include <afxwin.h> #include <afx.h> #include <assert.h> //--------------------------- const ADDR_sproInitialize=0x15740; const offsCONT_sproInitialize=0x15748; DWORD CONT_sproInitialize; WORD _declspec(naked) OLD_sproInitialize(PBYTE packet) { __asm { mov ax,[0x4724f8]//это - те команды, которые затер наш JMP cmp ax,0 jmp [CONT_sproInitialize] } } WORD NEW_sproInitialize(PBYTE packet) { WORD Res; Res=OLD_sproInitialize(packet); //ТУТ НЕЛЬЗЯ РАБОТАТЬ С ФАЙЛАМИ в WinXP/2000- ФУНКЦИИ ВОЗВРАЩАЮТ ОШИБКУ //В Win95 - можно Res=0; return(Res); } //--------------------------- class CMyDll:public CWinApp { public: CMyDll() {}; virtual BOOL InitInstance(); virtual int ExitInstance(); } MyDll; const CALL_CODE=0xE8; const JMP_CODE=0xE9; const JMP_IMPORT_CODE=0xE9; struct TJmpOp { BYTE OpCode; DWORD Offs; }; typedef TJmpOp *PJmpOp; void DoHookJmpOverride(DWORD HookPoint,DWORD NewAddr) { TJmpOp JmpOp; JmpOp.OpCode=JMP_CODE; JmpOp.Offs=NewAddr-HookPoint-5; WriteProcessMemory(GetCurrentProcess(),(LPDWORD)HookPoint,&JmpOp,5,NULL); } HINSTANCE LibAddr; BOOL CMyDll::InitInstance() { LogBuf=""; LibAddr=LoadLibrary("target.exe"); if(!LibAddr) return(FALSE); //ТУТ МОЖНО РАБОТАТЬ С ФАЙЛАМИ DoHookJmpOverride((DWORD)LibAddr+ADDR_sproInitialize,(DWORD)NEW_sproIn itialize); CONT_sproInitialize=offsCONT_sproInitialize+(DWORD)LibAddr; return(TRUE); } int CMyDll::ExitInstance() { //ТУТ МОЖНО РАБОТАТЬ С ФАЙЛАМИ return(0); } __declspec(dllexport) void WINAPI AddDllProc() { }
Бред какой-то - сколько раз так делал, с файлами проблем не замечал ни разу. > WriteProcessMemory(GetCurrentProcess(),(LPDWORD)HookPoint,&JmpOp,5,NULL); Гы, забавная замена memcpy() =)
Просто memcpy() при попытке записи в read-only память вызовет exception, а WriteProcessMemory возвратит ошибку, которая у меня выводится в log-файл и я знаю, что нужно править аттрибуты секций. Просто вывод в отладочный файл в этом примере вырезан. А баг все-таки случается на всех NT-системах.
Извиняюсь за беспокойство. Вопрос снимается. Оказалось, что проблема происходит из-за недостатка прав доступа и не связана с перехватом функций.