Clerk За перепалками не заметил Вашего сообщения, содержащего конструктивную критику с указанием проблем. Спасибо большое. Постараюсь учесть то, что Вы сказали. Но, справедливости ради, необходимо заметить, что исходный код (ссылку на который я приводил) практически идентичен моему (возможно, я добавил некоторые ошибки перевода)... Это я к тому, что не всегда необходимы грубые слова при общении и оценке чужого кода, т.к. даже проверенные временем и очень уважаемые программисты (Ms-Rem, в данном случае) - не всегда пишут идеальный код (энума тредов и т.д. нет в исходном коде)...
ksu_ant Для конкретных задач это вполне работоспособное решение, Clerk как всегда напускает тумана и поднимает своё ЧСВ. Вы отлаживать умеете или нет? Или натыкайте логов на худой конец.
Booster Как же вы надоели с этим чсв. Я написал как оно есть. Проблема с переопределением ошибочным констант очень распространена между тех, кто юзает дельфи.
Booster Поправил, все, что увидел. Получилось вот это: Код (Text): #include "stdafx.h" #include "windows.h" typedef struct _OldCode { DWORD One; DWORD Two; } OldCode; typedef struct _far_jmp { BYTE PuhsOp; DWORD PushArg; BYTE RetOp; } far_jmp; typedef VOID (*MYPROCA)(HWND, LPCSTR, LPCSTR, UINT,WORD); typedef VOID (*MYPROCW)(HWND, LPCWSTR, LPCWSTR, UINT,WORD); HINSTANCE hDLL; OldCode OldMba, OldMbw; DWORD MbaAdr; DWORD MbwAdr; far_jmp JmpMba, JmpMbw; BOOL WINAPI TrueMessageBoxExA(HWND hwnd, LPCSTR text, LPCSTR hdr, UINT utype,WORD wLanguageId) { DWORD written; CHAR str[5] = "1234"; CHAR stdPath[30] = "C:\\tmp.txt"; DWORD d; HANDLE hOut = CreateFile(stdPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); CloseHandle(hOut); WriteProcessMemory(GetCurrentProcess(), (void*)MbaAdr, (void*)&OldMba, sizeof(OldCode), &written); MessageBoxExA(hwnd, text, hdr, utype, wLanguageId); WriteProcessMemory(GetCurrentProcess(), (void*)MbaAdr, (void*)&JmpMba, 6,&written); return true; } BOOL WINAPI TrueMessageBoxExW(HWND hwnd, LPCWSTR text, LPCWSTR hdr, UINT utype,WORD wLanguageId) { DWORD written; CHAR str[5] = "1234"; CHAR stdPath[30] = "C:\\tmp.txt"; DWORD d; HANDLE hOut = CreateFile(stdPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); CloseHandle(hOut); WriteProcessMemory(GetCurrentProcess(), (void*)MbwAdr, (void*)&OldMbw, sizeof(OldCode), &written); MessageBoxExW(hwnd, text, hdr, utype, wLanguageId); WriteProcessMemory(GetCurrentProcess(), (void*)MbwAdr, (void*)&JmpMbw, 6,&written); return true; } BOOL WINAPI NewMessageBoxExA(HWND hwnd, LPCSTR text, LPCSTR hdr, UINT utype,WORD wLanguageId) { CHAR str[5] = "1234"; CHAR stdPath[30] = "C:\\tmp.txt"; DWORD d; HANDLE hOut = CreateFile(stdPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); CloseHandle(hOut); TrueMessageBoxExA(hwnd, text, hdr, utype, wLanguageId); return TRUE; } BOOL WINAPI NewMessageBoxExW(HWND hwnd, LPCWSTR text, LPCWSTR hdr, UINT utype,WORD wLanguageId) { CHAR str[5] = "1234"; CHAR stdPath[30] = "C:\\tmp.txt"; DWORD d; HANDLE hOut = CreateFile(stdPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); CloseHandle(hOut); TrueMessageBoxExW(hwnd, text, hdr, utype, wLanguageId); return TRUE; } LRESULT CALLBACK MessageProc(int code, WPARAM wParam, LPARAM lParam) { CallNextHookEx(0, code, wParam, lParam); return 0; } DWORD WINAPI SetGlobalHookProc(LPVOID lpParam) { SetWindowsHookEx(WH_GETMESSAGE, &MessageProc, hDLL, 0); Sleep(INFINITE); return 0; } DWORD SetGlobalHook() { HANDLE hMutex; DWORD TrId; hMutex = CreateMutex(NULL, false, "AdvareHook"); if (GetLastError() == 0) { CreateThread(NULL, 0, &SetGlobalHookProc, 0, 0, &TrId); } else { CloseHandle(hMutex); } return 0; } DWORD SetHook() { HINSTANCE hUser32; ULONG Bytes; hUser32 = GetModuleHandle("user32.dll"); MbaAdr = (DWORD) GetProcAddress(hUser32, "MessageBoxExA"); MbwAdr = (DWORD) GetProcAddress(hUser32, "MessageBoxExW"); ReadProcessMemory(GetCurrentProcess(), &MbaAdr, &OldMba, sizeof(OldCode), &Bytes); ReadProcessMemory(GetCurrentProcess(), &MbwAdr, &OldMbw, sizeof(OldCode), &Bytes); JmpMba.PuhsOp = 0x68; JmpMba.PushArg = (DWORD) NewMessageBoxExA; JmpMba.RetOp = 0xC3; JmpMbw.PuhsOp = 0x68; JmpMbw.PushArg = (DWORD) NewMessageBoxExW; JmpMbw.RetOp = 0xC3; WriteProcessMemory(GetCurrentProcess(), &MbaAdr, &JmpMba, sizeof(far_jmp), &Bytes); WriteProcessMemory(GetCurrentProcess(), &MbwAdr, &JmpMbw, sizeof(far_jmp), &Bytes); return 0; } DWORD UnHook() { ULONG Bytes; WriteProcessMemory(GetCurrentProcess(), (void*)MbaAdr, (void*)&OldMba, sizeof(OldCode), &Bytes); WriteProcessMemory(GetCurrentProcess(), (void*)MbwAdr, (void*)&OldMbw, sizeof(OldCode), &Bytes); return 0; } BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: hDLL = hModule; SetGlobalHook(); SetHook(); MessageBoxExA(NULL,"Test me","Test Caption",MB_OK,0); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: UnHook(); break; } return TRUE; } В результате выполнения этого кода длжен создаться файл C:\tmp.txt, но он не создается. По поводу отладки - при отладке в Visual C++ 6.0 - я попадаю на точку входа (DLL_PROCESS_ATTACH), попадаю в SetHook(), вроде хуки устанавливаются, но даже при проверочном вызове MessageBox - я не попадаю в функцию NewMessageBox... Думаю, что проблемы при установке хуков (адреса напутал или еще что)...
увы без матчасти (хотя бы основы - отладки приложений) эту задачу не решить. PS: первая встреченная ошибка в 11 строчке.
Еще нашел: Код (Text): typedef struct _OldCode { DWORD One; DWORD Two; } OldCode; Верно так: Код (Text): typedef struct _OldCode { DWORD One; WORD Two; } OldCode; Раньше были неверные размеры структур... По отладке: попадаю только на DLL_PROCESS_ATTACH, выполняется все, что указано в коде и все . В перехваченные функции не заходит...
n0name Если можно - приведите содержание строки - не понятно как строки считать (с пустыми, с объявлениями структур и т.д.).
Собрал этот чудо код. 1) return CallNextHookEx(0, code, wParam, lParam); 2) Код (Text): #pragma pack(1) typedef struct _OldCode { DWORD One; DWORD Two; } OldCode; #pragma pack(1) typedef struct _far_jmp { BYTE PuhsOp; DWORD PushArg; BYTE RetOp; } far_jmp; 3) Код конечно своеобразно написан. ^)
WriteProcessMemory(GetCurrentProcess(), MbaAdr, &JmpMba, sizeof(far_jmp), &Bytes); WriteProcessMemory(GetCurrentProcess(), MbwAdr, &JmpMbw, sizeof(far_jmp), &Bytes);
Booster punxer Спасибо Вам большое! Все заработало. Мне бы было тяжело найти эти проблемы самостоятельно.
ksu_ant [modnote=Great]Предупреждение, что не юзали поиск.[/modnote] Booster Clerk ksu_ant [modnote=Great]Предупреждение за срач[/modnote]
Great Поиск юзал. Работающего решения в User Mode (на С) - не нашел (хотя нашел множество других, но они не работали). Была попытка перевода того решения, которое работало, на нужный язык... И были, при этом, недопонимания. Про С моей стороны не было никакой агрессии (если это подразумевает Ваше определение), а было противодействие безосновательным нападкам не знающего меня человека.
ksu_ant Формат инструкций не зависит от CPL. Не имеет значения в каком кольце защиты выполняется ваш код. Это тупой патч. Неужеле так трудно просто логически подумать, я на самом деле не понимаю.
попробуй перед каждым вызовом WriteProcessMemory вазвать VirtualProtect а полсе каждого вызова WriteProcessMemory вазвать FlushInstructionCache. С параметрами для VirtualProtect и FlushInstructionCache думаю разберешься, как и с назначением этих функций. Совсем забыл, после вызова FlushInstructionCache желательно вызвать VirtualProtect и вернуть как было до первого вызова VirtualProtect. Код (Text): DWORD dwProtection = 0; DWORD dwWrite = 0; LPVOID pAdress; // адрес, значение которого надо изменить на значение по pNewAdress DWORD dwLength; LPVOID pNewAdress; DWORD dwNewLength; VirtualProtect(pAdress, dwLength, PAGE_READWRITE, &dwProtection); WriteProcessMemory(hProcess, pAdress, pNewAdress, dwNewLength, &dwWrite); VirtualProtect(pAdress, dwLength, dwProtection, &dwProtection); FlushInstructionCache(g_hProcess, pAdress, dwLength);
И набуя в своём процессе юзать WriteProcessMemory - запись в память своего процесса легко делается например через RtlMoveMemory или напрямую асмом, тока VirtualProtect из WinAPI нужен и после модификций памяти не надо забывать выставлять предыдущие флаги для неё. Ещё можно напрямую вызывать NtFlushInstructionCache, но всё равно проблема атомарности и записи при многопоточности остаётся открытой в сплайсинге.