Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
Zagadohnik37
0 / 0 / 1
Регистрация: 23.01.2015
Сообщений: 307
1

Перехват MessageBox в dll

10.08.2017, 22:45. Просмотров 496. Ответов 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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.08.2017, 22:45
Ответы с готовыми решениями:

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

При загрузке Dll MessageBox срабатывает 2 раза
создаю такую тестевую dll #include &lt;windows.h&gt; BOOL WINAPI DllMain...

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

MessageBox: Как сделать так, чтобы если окно модальное, при клике на родительское окно MessageBox мигал?
Здравия всем! Никак не найду нужный MB_*, как можно сделать так, чтобы если...

Кто может поделиться файлами ogg.dll, vorbis.dll и vorbisfile.dll - 32-х и 64-битными версиями?
Движок перевожу на платформу Win64 и нужно, чтобы разрядность ЕХЕ и DLL...

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

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

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

Добавлено через 1 час 30 минут
И я уже 2 часа не могу понять, как впихнуть этот minhook в мой проект! Кстати, может кто-нибудь знает видео, или сайт, где написано, как это сделать?
0
jupman
230 / 133 / 19
Регистрация: 10.11.2015
Сообщений: 305
11.08.2017, 17:16 4
Цитата Сообщение от Zagadohnik37 Посмотреть сообщение
Или если всё криво, то можно пример перехвата двух апи (MessageBoxW и MessageBoxA), только с MinHook плиз
Ну что-бы можно было выбирать, что изменять, а что нет, как в первом примере, где result = Mess... .
В ссылке что я дал сразу же пример идет с перехватом MessageBoxW. Делай по аналогии.
0
Zagadohnik37
0 / 0 / 1
Регистрация: 23.01.2015
Сообщений: 307
11.08.2017, 18:08  [ТС] 5
Пока вы отвечали, я уже всё нашёл и сделал А теперь мини-вопрос: 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
11.08.2017, 18:08
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.08.2017, 18:08

Точка входа в процедуру InitializeConditionVariable не найдена в библиотеке DLL KERNEL32.dll
Добрый день, товарищи! Помогите, пожалуйста, советом в решении следующией...

Как узнать какие dll Загружает процесс или dll
Проблема вот в чем: Нужно определить какие dll загружает процесс. Есть ли...

Как из DLL, в котором есть только DllGetClassObject, обратиться к методу, который должен быть в этой DLL?
Есть метод ITaskbarList3::SetProgressState, он предназначен для того, чтобы в...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru