Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
4 / 4 / 1
Регистрация: 23.01.2015
Сообщений: 330

Перехват MessageBox в dll

10.08.2017, 22:45. Показов 3693. Ответов 4

Студворк — интернет-сервис помощи студентам
Недавно нашёл исходник dll перехватывающей ф-цию MessageBoxW:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <Windows.h>
#include <string> 
#define SIZE 6
 
typedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);
int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT);
void BeginRedirect(LPVOID);
pMessageBoxW pOrigMBAddress = NULL;
BYTE oldBytes[SIZE] = { 0 };
BYTE JMP[SIZE] = { 0 };
DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE;
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
 
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH: 
    {
        std::wstring s = L"I hook MessageBox! PID: ";
        s = s += (std::to_wstring(GetCurrentProcessId()));
        s = s += L" .";
 
        MessageBoxW(NULL, (LPCWSTR)s.c_str(), L"Hello", MB_OK);
 
        // Идем адрес MessageBox
        pOrigMBAddress = (pMessageBoxW)GetProcAddress(GetModuleHandleW(L"user32.dll"), "MessageBoxW");
        if (pOrigMBAddress != NULL)
        {
            BeginRedirect(MyMessageBoxW);
        }
 
        break;
    }
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
 
void BeginRedirect(LPVOID newFunction)
{
    // Массив-маска для записи команды перехода
    BYTE tempJMP[SIZE] = { 0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3 };
    memcpy(JMP, tempJMP, SIZE);
    // Вычисляем смещение относительно оригинальной функции
    DWORD JMPSize = ((DWORD)newFunction - (DWORD)pOrigMBAddress - 5);
    // Получаем доступ к памяти
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, PAGE_EXECUTE_READWRITE, &oldProtect);
    // Запоминаем старые байты
    memcpy(oldBytes, pOrigMBAddress, SIZE);
    // Пишем 4байта смещения. Да, код рассчитан только на x86
    memcpy(&JMP[1], &JMPSize, 4);
    // Записываем вместо оригинальных
    memcpy(pOrigMBAddress, JMP, SIZE);
    // Восстанавливаем старые права доступа
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
}
 
int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType)
{
    // Получаем доступ к памяти
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL);
    // Возвращаем старые байты (иначе будет переполнение стека)
    memcpy(pOrigMBAddress, oldBytes, SIZE);
    // Зовем оригинальную функцию, но подменяем заголовок
    int retValue = MessageBoxW(hWnd, lpText, L"Перехвачено!_W", uiType);
    // Снова ставим хук
    memcpy(pOrigMBAddress, JMP, SIZE);
    // Восстанавливаем старые права доступа
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
    return retValue;
}

Всё хорошо работает, но как только я попытался криво, но добавить перехват ещё и MessageBoxA, то стал работать только перехват MessageBoxA, а при вызове MessageBoxW программа вылетает.

Вопрос: как в эту длл добавить ещё один хук на MessageBoxA?

Добавлено через 3 часа 55 минут
Кстати, попытался изменить на:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <Windows.h>
#include <string> 
#define SIZE 6
// Объявления функций и кастомных типов
typedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);
int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT);
typedef int (WINAPI *pMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
int WINAPI MyMessageBoxA(HWND, LPCSTR, LPCSTR, UINT);
void BeginRedirect(LPVOID);
pMessageBoxW pOrigMBAddressW = NULL;
pMessageBoxA pOrigMBAddressA = NULL;
FARPROC pOrigMBAddress = NULL;
BYTE oldBytes[SIZE] = { 0 };
BYTE JMP[SIZE] = { 0 };
DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE;
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
 
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH: 
    {
        std::wstring s = L"I hook MessageBox! PID: ";
        s = s += (std::to_wstring(GetCurrentProcessId()));
        s = s += L" .";
 
        MessageBoxW(NULL, (LPCWSTR)s.c_str(), L"Hello", MB_OK);
 
        pOrigMBAddressW = (pMessageBoxW)GetProcAddress(GetModuleHandleW(L"user32.dll"), "MessageBoxW");
        if (pOrigMBAddressW != NULL)
        {
            pOrigMBAddress = GetProcAddress(GetModuleHandleW(L"user32.dll"), "MessageBoxW");
            BeginRedirect(MyMessageBoxW);
        }
 
        pOrigMBAddressA = (pMessageBoxA)GetProcAddress(GetModuleHandleW(L"user32.dll"), "MessageBoxA");
        if (pOrigMBAddressA != NULL)
        {
            pOrigMBAddress = GetProcAddress(GetModuleHandleW(L"user32.dll"), "MessageBoxA");
            BeginRedirect(MyMessageBoxA);
        }
 
        break;
    }
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
 
void BeginRedirect(LPVOID newFunction)
{
    // Массив-маска для записи команды перехода
    BYTE tempJMP[SIZE] = { 0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3 };
    memcpy(JMP, tempJMP, SIZE);
    // Вычисляем смещение относительно оригинальной функции
    DWORD JMPSize = ((DWORD)newFunction - (DWORD)pOrigMBAddress - 5);
    // Получаем доступ к памяти
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, PAGE_EXECUTE_READWRITE, &oldProtect);
    // Запоминаем старые байты
    memcpy(oldBytes, pOrigMBAddress, SIZE);
    // Пишем 4байта смещения. Да, код рассчитан только на x86
    memcpy(&JMP[1], &JMPSize, 4);
    // Записываем вместо оригинальных
    memcpy(pOrigMBAddress, JMP, SIZE);
    // Восстанавливаем старые права доступа
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
}
 
int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType)
{
    // Получаем доступ к памяти
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL);
    // Возвращаем старые байты (иначе будет переполнение стека)
    memcpy(pOrigMBAddress, oldBytes, SIZE);
    // Зовем оригинальную функцию, но подменяем заголовок
    int retValue = MessageBoxW(hWnd, lpText, L"Перехвачено!_W", uiType);
    // Снова ставим хук
    memcpy(pOrigMBAddress, JMP, SIZE);
    // Восстанавливаем старые права доступа
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
    return retValue;
}
 
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uiType)
{
    // Получаем доступ к памяти
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL);
    // Возвращаем старые байты (иначе будет переполнение стека)
    memcpy(pOrigMBAddress, oldBytes, SIZE);
    // Зовем оригинальную функцию, но подменяем заголовок
    int retValue = MessageBoxA(hWnd, lpText, "Перехвачено!_W", uiType);
    // Снова ставим хук
    memcpy(pOrigMBAddress, JMP, SIZE);
    // Восстанавливаем старые права доступа
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
    return retValue;
}

Скажите, где ошибка...
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.08.2017, 22:45
Ответы с готовыми решениями:

Инжектор dll, не выполняется вызов MessageBox
имеется код: #include &lt;windows.h&gt; #include &lt;TlHelp32.h&gt; #include &lt;iostream&gt; using namespace std; DWORD func(const char...

При загрузке Dll MessageBox срабатывает 2 раза
создаю такую тестевую dll #include &lt;windows.h&gt; BOOL WINAPI DllMain (HANDLE hInst,DWORD dwReason, LPVOID IpReserved) { ...

Перехват WindowMessage для окна, создаваемого DLL
Суть проблемы: есть окно, создаваемое средствами подключенной DLL, я могу менять положение и размеры, но винда не позволяет ставить размеры...

4
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
11.08.2017, 08:12
Zagadohnik37, дак у тебе между твоими хуками глобальные переменные используются. Конечно будет падать. Т.е. к примеру ты ставишь хук на Func1 (oldBytes, JMP, etc инциализируются), затем на Func2 (oldBytes, JMP, etc затираются новыми данными). Затем вызываешь Func1 и программа падает, т.к. в переменных данные для Func2.

И вообще код ужасный. Где ты его взял? Как так можно, патчить, вызывать оригинал, и опять патчить. В многопоточном приложении, с таким кодом, будут вызовы мимо хука и падения. Да и, многопоточность, это не единственная проблема при перехватах. Лучше возьми, что-нибудь готовое (MinHook etc).
0
4 / 4 / 1
Регистрация: 23.01.2015
Сообщений: 330
11.08.2017, 12:57  [ТС]
Цитата Сообщение от jupman Посмотреть сообщение
И вообще код ужасный
А это про какой код?
Мой код конечно ужасный, т.к. я раньше не работал с хуками, да и вообще на с++ недавно перешёл.
А код, который я взял за основу вроде-как норм... С minHook я ещё посмотрю, а вот как к этому коду(тот что был изначально) добавить ещё один хук?
Только что-бы всё норм работало...

Добавлено через 2 минуты
Или если всё криво, то можно пример перехвата двух апи (MessageBoxW и MessageBoxA), только с MinHook плиз
Ну что-бы можно было выбирать, что изменять, а что нет, как в первом примере, где result = Mess... .

Добавлено через 1 час 30 минут
И я уже 2 часа не могу понять, как впихнуть этот minhook в мой проект! Кстати, может кто-нибудь знает видео, или сайт, где написано, как это сделать?
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
11.08.2017, 17:16
Цитата Сообщение от Zagadohnik37 Посмотреть сообщение
Или если всё криво, то можно пример перехвата двух апи (MessageBoxW и MessageBoxA), только с MinHook плиз
Ну что-бы можно было выбирать, что изменять, а что нет, как в первом примере, где result = Mess... .
В ссылке что я дал сразу же пример идет с перехватом MessageBoxW. Делай по аналогии.
0
4 / 4 / 1
Регистрация: 23.01.2015
Сообщений: 330
11.08.2017, 18:08  [ТС]
Пока вы отвечали, я уже всё нашёл и сделал А теперь мини-вопрос: C MessageBox и MessageBoxEx всё легко, а вот как быть с MessageBoxIndirect?
Вот пример перехвата простых msgBox'ов:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
int WINAPI DetourMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
    std::wstring s = lpText;
    s = s += L"\n_(HOOK)";
    return fpMessageBoxW(hWnd, (LPCWSTR)s.c_str(), lpCaption, uType);
}
 
int WINAPI DetourMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    std::string s = lpText;
    s = s + "\n_(HOOK)";
    return fpMessageBoxA(hWnd, (LPCSTR)s.c_str(), lpCaption, uType);
}
Не перевхата, а подменяемой ф-ции если быть точнее.
Просто вдруг загорелась идея перехватывать все виды MsgBox'ов.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.08.2017, 18:08
Помогаю со студенческими работами здесь

Dll в MessageBox
Помогите пожалуйста написать dll. Использовать данную dll в консольном и оконном приложении. В консольном приложении вывести сообщение с...

MessageBox.Show из dll
Всем привет ) Как мне сделать чтобы dll могла сделать MessageBox.Show ? А то у меня System.Console.WriteLine работает, а MessageBox.Show...

Перехват сообщения от DLL
Доброго времени суток! Есть такая проблема: В dll имеется функция c тремя аргументами, которая описана так: procedure MyFunc(var...

Перехват Send(ws2_32.dll)
Создаю программу для ограничения доступа юзеров к определенным сайтам . Использую библиотеки для перехвата ExtendedAPIFunctions и...

как заHOOKать MessageBox в другом приложение из моего DLL?
Привет форум... Пожалуйста напишите маленкий пример для hook а MessageBox -а в другом приложение. Знаю что надо использовать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru