Здравствуйте! Не получается перехватить MessageBox (перевожу на C пример AdvBox Ms-Rem). Помогите, пожалуйста, разобраться, что не так. В случае вызова функции - текст сообщения должен записаться в файл, но файл постоянно пуст Это первый мой перехват в режиме пользователя (до этого в ядре работал). Заранее благодарен. Код (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; MYPROCA MbaAdr; MYPROCW MbwAdr; far_jmp JmpMba, JmpMbw; BOOL WINAPI TrueMessageBoxExA(HWND hwnd, LPCSTR text, LPCSTR hdr, UINT utype,WORD wLanguageId) { DWORD written; CHAR stdPath[30] = "C:\\tmp.txt"; DWORD d; HANDLE hOut = CreateFile(stdPath, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); WriteFile(hOut, &text, sizeof(text), &d, NULL ); WriteFile(hOut, &hdr, sizeof(hdr), &d, NULL ); CloseHandle(hOut); WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)MbaAdr, (void*)&OldMba, sizeof(OldCode), &written); MessageBoxExA(hwnd, text, hdr, utype, wLanguageId); WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)MbaAdr, (void*)&JmpMba, 6,&written); return true; } BOOL WINAPI TrueMessageBoxExW(HWND hwnd, LPCWSTR text, LPCWSTR hdr, UINT utype,WORD wLanguageId) { DWORD written; CHAR stdPath[30] = "C:\\tmp.txt"; DWORD d; HANDLE hOut = CreateFile(stdPath, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); WriteFile(hOut, &text, sizeof(text), &d, NULL ); WriteFile(hOut, &hdr, sizeof(hdr), &d, NULL ); CloseHandle(hOut); WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)MbwAdr, (void*)&OldMbw, sizeof(OldCode), &written); MessageBoxExW(hwnd, text, hdr, utype, wLanguageId); WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)MbwAdr, (void*)&JmpMbw, 6,&written); return true; } BOOL WINAPI NewMessageBoxExA(HWND hwnd, LPCSTR text, LPCSTR hdr, UINT utype,WORD wLanguageId) { TrueMessageBoxExA(hwnd, text, hdr, utype, wLanguageId); return TRUE; } BOOL WINAPI NewMessageBoxExW(HWND hwnd, LPCWSTR text, LPCWSTR hdr, UINT utype,WORD wLanguageId) { 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 = (MYPROCA) GetProcAddress(hUser32, "MessageBoxExA"); MbwAdr = (MYPROCW) GetProcAddress(hUser32, "MessageBoxExW"); ReadProcessMemory(INVALID_HANDLE_VALUE, &MbaAdr, &OldMba, sizeof(OldCode), &Bytes); ReadProcessMemory(INVALID_HANDLE_VALUE, &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(INVALID_HANDLE_VALUE, &MbaAdr, &JmpMba, sizeof(far_jmp), &Bytes); WriteProcessMemory(INVALID_HANDLE_VALUE, &MbwAdr, &JmpMbw, sizeof(far_jmp), &Bytes); return 0; } DWORD UnHook() { ULONG Bytes; WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)MbaAdr, (void*)&OldMba, sizeof(OldCode), &Bytes); WriteProcessMemory(INVALID_HANDLE_VALUE, (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(); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: UnHook(); break; } return TRUE; }
ksu_ant Зря, вы рема упомянули... сейчас явиться клерк и будет орать, что он, вы и ваша родня до седьмого колена гуано....
Да гуано. Создан топик для таких вопросов http://wasm.ru/forum/viewtopic.php?id=38110. Копипаст в любой форме зло, более того мне чисто неохота разбирать гуанокод ТС.
Clerk Вас никто сюда не звал. Не хотите помочь - не нужно грубить. Я явно указал, что в юзер-моде никогда не делал перехватов и сейчас учу данный вопрос. Так что кто гуано - не Вам, любезный, судить. P.S.: Свои топики рекламировать таким образом - Ваша маркетинговая находка?
ksu_ant Я и не думал вам грубить нисколько, напротив это вы грубите. То что вы не заюзали поиск с таким вопросом величайшая наглость. А про ядро вы наверно шутите. Учитесь формулировать вопросы.
Clerk Поиск юзал. На C я не нашел нормально работающего кода, поэтому решил попробовать перевести с Delphi (только этот пример работал именно так, как мне было нужно), но, к сожалению, хуки не устанавливаются... С целью определить причину этого, я обратился на данный форум, где Вы начали бросаться грубыми словами в адрес человека, которого совсем не знаете. В kernel mode я работаю довольно давно и все, что мне бывает необходимо, я пытаюсь решать сам. Насчет копипаста: во-первых- я явно указал авторство, во-вторых, не думаю, что существует программист, который за всю жизнь ни разу не воспользовался готовым алгоритмом, а если он об этом заявляет об этом, то, скорее всего, лукавит. Предлагаю вернуть топик в конструктивное русло и, если нет желания помочь разобраться в проблеме, не мешать делать этого тем, кто знает в чем проблема и хочет подсказать решение.
ksu_ant Судя по вашим ответам вы тут недавно зарегались и есчо ничего не знаете. И не нужно в меня гуан кидать. Ваша проблема в незнании машинных команд и в не желании юзать отладчик. Вы считаете что ваше решение тру и идеально, реально это грубая ошибка, в частности тупое решение в лоб которое нарушает целостность системных модулей, тоесть идёт наперекос защите.
Clerk Дата регистрации, насколько я понимаю, есть в профиле. Никто в Вас ничего не кидал. Я НЕ считал, что мое решение идеально - это Ваши догадки, если Вы видите явные проблемы и Вас заботит этот топик - гораздо продуктивнее было бы подсказать ошибку. Если Вам это не интересно, прошу прекратить бесполезную дискуссию.
ksu_ant Как бы мне это не нравилось, но я опишу. o Многозадачность. Необходим енум всех тредов и проверка вхождения их Ip в модифицируемый код, в частности в весь изменяемый диапазон и он должен быть выравнен на адрес последней инструкции. Для этого необходим LDE. o Динамическое формирование кода. Выполняется копирование линейного кода(без ветвлений) в буфер или с поправкой их. Для оригинального пролога это не нужно, но проверка необходима. o Атомарная модификация кода, иначе вызов из другого треда завершится крахом. Это основные нюансы. Ваш скрипт мне лень разбирать. Кстате я не вижу пролога в вашем хэндлере, вобще код отвратительный.
Пройдитесь отладчиком. Не совсем понимаю как это должно работать. Почему там к примеру везде INVALID_HANDLE_VALUE? И зачем Ms-Rem везде юзал WinAPI, тоже не совсем понятно.
Booster Это от подного незнания системы. Просто числовое значение именованных констант совпадает NtCurrentProcess = INVALID_HANDLE_VALUE = THREAD_BASE_PRIORITY_IDLE = INFINITE.. не имеющих между собой смысла.
Booster INVALID_HANDLE_VALUE меня тоже удивил, т.к. везде в похожих кодах используется GetCurrentProcess, но я подумал (возможно ошибаюсь), что так сделано для внедрения во все процессы. Delphi вариант работает, код взят отсюда: http://www.wasm.ru/pub/21/files/adwarebox.rar.
Booster Это документированно, вы ведь знаете как ждать на обьекте без указания таймаута - вы передаёте константу INFINITE = -1, значение которой совпадает с псевдохэндлом текущего процесса и кодом ошибки и есчо с сотнями тыщами констант имеющих тоже значение.
Booster Да, сейчас в Delphi варианте исправил на GetCurrentProcess - также работает (нормально). Видимо, действительно совпадают значения...
Clerk При чём здесь INFINITE? Покажи где написано, что можно вместо GetCurrentProcess юзать -1. А использовать левые названия констант это конечно стиль тру хакеров.
Booster Почему же нельзя, значение константы одинаково. Своего рода обфускация. И я не говорил что это верно, но в скомпилированном коде будет всё тоже -1. Так что имена только для скрипта.)
Clerk Автор кода хотел обфусцировать? У программистов правда это называет говнокодом, ну да ладно. ^)
Booster Вы забываете что этот код копипаст без понимания сути его работы. Незачем спорить по этому поводу.
> Покажи где написано, что можно вместо GetCurrentProcess юзать -1 в msdn наверно? http://msdn.microsoft.com/en-us/library/ms683179(VS.85).aspx