Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
 Аватар для uhx
60 / 60 / 19
Регистрация: 11.07.2013
Сообщений: 305

Не получается поставить хук на функцию через запись в код

22.02.2015, 03:02. Показов 2503. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Прошу помочь, сижу уже несколько часов.
До этого нормально писал такой хук, только на один раз, так сказать. Без обратной записи (ну я тогда просто тестил) старого опкода.
Короче, сабж: в опкоде адрес прыжка пишется криво. Постоянно. Когда я вывожу в концольку адрес - все нормально. Через калькулятор посчитал - все сходится. А в опкоде херота какая-то, даже не связана с моим адресом...
Весь код:
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
#include <Windows.h>
#include <conio.h>
#include <stdio.h>
 
#define newThread(Function, lParam) CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Function, lParam, 0, 0);
 
HINSTANCE hDLL;
 
 
 
class HookFunction{
    DWORD relativeAddress; // 
    BYTE old[5]; // Старые пять байт, вместо которых мы пишем наш прыжок
    void *org, *hk; // Адреса
public:
    HookFunction(void *Original, void *Hook){
        hk = Hook; // Запоминаем адреса наших функций
        org = Original;
        relativeAddress = (DWORD)org - (DWORD)hk - 5; // Считаем прыжок
        memcpy(old, Original, 5); // Запоминаем старые 5 байт, чтобы восстановить функцию.
    }
    void Hook(){ // Ставим хук
        DWORD dwProtect = PAGE_READWRITE;
        VirtualProtect(org, 5, dwProtect, &dwProtect); // Включаем запись
        memset(org, 0xE9, 1); // Ставим прыжок
        memset((char*)org + 1, relativeAddress, 4); // И длину прыжка
        VirtualProtect(org, 5, dwProtect, &dwProtect);
        printf("0x%X hooked to 0x%X!\nRelAddr: 0x%X\n", org, hk, relativeAddress); // Выводим некоторую информацию
    }
    void unHook(){ // Убираем хук
        DWORD dwProtect = PAGE_READWRITE;
        VirtualProtect(org, 5, dwProtect, &dwProtect);
        for(int i = 0; i < 5; i++)
            memset((char*)org + i, old[i], 1); // Возвращаем старые 5 байт
        VirtualProtect(org, 5, dwProtect, &dwProtect);
    }
}*mBox;
 
int MessageB(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType){
    mBox->unHook(); // Снимаем хук
    int ret = MessageBox(hWnd, "Text", "Caption", uType); // Вызываем оригинальную функцию уже с нажими параметрами
    mBox->Hook(); // Ставим обратно
    return ret; 
}
 
 
void Main()
{
    // Юзаем конструктор
    mBox = new HookFunction((void*)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA"), MessageB);
    mBox->Hook(); // Ставим хук
    Sleep(5000); // Ждем 5 сек (Временно, чтобы глянуть в CE че изменилось
    FreeLibraryAndExitThread(hDLL, 1); // Вытаскиваем свою либу, чтобы потом подключить более новую (задолбался в CE процесс открывать :D)
}
 
int __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
    switch(fdwReason){
    case DLL_PROCESS_ATTACH:
        hDLL = hinstDLL;
        Beep(1000, 100);
        newThread(Main, 0); // Создаем поток
        break;
    case DLL_PROCESS_DETACH:
        mBox->unHook(); // Снимаем хук при детаче
        Beep(1000, 100); // Прощальный *ПИП*
    }
    return 1;
}
Вроде нормально все выглядит. Перепроверил все сто раз, в чем ошибка - не пойму. Ща ниже еще скрины прилеплю, чтоб нагляднее было.
Инжектор, а так же подопытная программа - всё мое, но там все ровно.
Уже мозг не варит, обычно пишу сюда только на крайняк. Может я и тему не в том разделе создал, но по моему все правильно.
Адрес не меняется никогда, не смотря на то что адреса функций меняются. В чем проблема - не пойму. Тип вроде нужный - DWORD. Или не тот? Явно с ним что-то не то, но я уже не соображаю. 1 байт прыжка, 4 байта адрес. В чем беда-то, блин?!
Миниатюры
Не получается поставить хук на функцию через запись в код  
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.02.2015, 03:02
Ответы с готовыми решениями:

Поставить хук на клавиатуру
Ребят , как сделать ? хук клавы ? Тоесть если я нажму F5 начнется какоет-то действие ... Спасибо !

Работа с процессами, как поставить хук..
такая проблема: Есть программа &quot;1&quot; она использует библиотеку &quot; Sim.dll &quot;. Есть ещё программа &quot;2&quot; которая постоянно вырубает...

Подскажите, как правильно поставить хук?
Написал такой код: Option Explicit Public Declare Function CallNextHookEx Lib 'user32' (ByVal hHook As Long, ByVal nCode As Long, ByVal...

8
 Аватар для uhx
60 / 60 / 19
Регистрация: 11.07.2013
Сообщений: 305
22.02.2015, 03:24  [ТС]
А, и в 19 строчке ошибка
C++
1
relativeAddress = (DWORD)org - (DWORD)hk - 5;
надо поменять на
C++
1
relativeAddress = (DWORD)hk - (DWORD)org - 5;
Но тут все еще ошибка, скорее всего)) Потому что адрес поменялся, но так же не меняется как и предыдущий. А почему адрес в опкоде так и не меняется - я вообще не понимаю. Ведь relativeAddress меняется постоянно, так как адрес нашей функции при новой инъекции дллки оказывается в другом месте.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
22.02.2015, 12:33
uhx, хотите добрый совет ? Выбросьте этот код.
Все равно полноценно ставить хуки таким "кустарным" способом
не получится, ну разве что в каких-то частных случаях.

Здесь, например, не учитывается, что тело функции может занимать меньше 5 байт.
Не учитывается, что в момент установки или снятия хука функцию могут вызывать
другие потоки. Не учитывается, что в x64 mode принципы jmp-адресации другие.
И т.д. И для полноценного сплайсинга нужен хороший дизассемблер длин, а здесь
этого нет. Лучше возьмите какой-нибудь EasyHook или (я рекомендую) MinHook и
получите надежное, отточенное и переносимое между версиями и разрядностями
Windows решение.
1
 Аватар для uhx
60 / 60 / 19
Регистрация: 11.07.2013
Сообщений: 305
22.02.2015, 20:53  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
uhx, хотите добрый совет ? Выбросьте этот код.
Все равно полноценно ставить хуки таким "кустарным" способом
не получится, ну разве что в каких-то частных случаях.
Здесь, например, не учитывается, что тело функции может занимать меньше 5 байт.
Не учитывается, что в момент установки или снятия хука функцию могут вызывать
другие потоки. Не учитывается, что в x64 mode принципы jmp-адресации другие.
И т.д. И для полноценного сплайсинга нужен хороший дизассемблер длин, а здесь
этого нет. Лучше возьмите какой-нибудь EasyHook или (я рекомендую) MinHook и
получите надежное, отточенное и переносимое между версиями и разрядностями
Windows решение.
Ждал чего-то подобного. Я знаю, метод далек от идеала, но я все же хочу его доковырять. Да и на кой мне хукать функцию, которая меньше пяти байт?)) Я хукаю то, что мне нужно. Вот например мессейджбокс, но у меня не получается.

Добавлено через 11 минут
Я просто хочу разобраться, что у меня не так в коде, и где кроется ошибка. Если бы я хотел взять готовую библиотеку, где с помощью строчки кода хукается функция - я воспользовался бы гуглом Но все равно спасибо за совет, буду иметь ввиду.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
22.02.2015, 21:17
Лучший ответ Сообщение было отмечено uhx как решение

Решение

Давайте попробуем разложить "по полочкам:

1.
C++
1
relativeAddress = (DWORD)org - (DWORD)hk - 5; // Считаем прыжок
Здесь, как уже было написано, должно быть наоборот:
C++
1
relativeAddress = (DWORD)hk - (DWORD)org - 5; // Считаем прыжок
2.
C++
1
2
3
4
5
6
7
8
void Hook(){ // Ставим хук
    DWORD dwProtect = PAGE_READWRITE;
    VirtualProtect(org, 5, dwProtect, &dwProtect); // Включаем запись
    memset(org, 0xE9, 1); // Ставим прыжок
    memset((char*)org + 1, relativeAddress, 4); // И длину прыжка
    VirtualProtect(org, 5, dwProtect, &dwProtect);
    printf("0x%X hooked to 0x%X!\nRelAddr: 0x%X\n", org, hk, relativeAddress); // Выводим некоторую информацию
}
Во-первых, вместо PAGE_READWRITE следует ставить PAGE_EXECUTE_READWRITE.
И в unHook тоже. Во-вторых, результат вызова VirtualProtect, хотя бы первого, нужно проверять.
Вдруг FALSE ? В-третьих, не
C++
1
memset((char*)org + 1, relativeAddress, 4); // И длину прыжка
а
C++
1
memset((char*)org + 1, &relativeAddress, 4); // И длину прыжка
3.
C++
1
2
3
4
5
6
int MessageB(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType){
    mBox->unHook(); // Снимаем хук
    int ret = MessageBox(hWnd, "Text", "Caption", uType); // Вызываем оригинальную функцию уже с нажими параметрами
    mBox->Hook(); // Ставим обратно
    return ret; 
}
Здесь не хватает явного указания calling convention, т.е. _stdcall.
Ну и сама идея снимать хук на время вызова оригинала, а затем восстанавливать -
она как бы "не очень".

Добавлено через 2 минуты
Короче, вот. На скорую руку (вместо 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
#include <Windows.h>
#include <strsafe.h>
 
 
 
bool SetHook(__in PVOID Function, __in PVOID Hook)
{
    DWORD const JmpOpcodeSize = 5;
    DWORD OldProtect;
 
    if (FALSE == VirtualProtect(Function, JmpOpcodeSize, PAGE_EXECUTE_READWRITE, &OldProtect))
    {
        return false;
    }
 
    byte * pCode = (byte *)Function;
    *pCode = 0xE9;
    *((DWORD *)(pCode + 1)) = (ULONG_PTR)Hook - (ULONG_PTR)Function - (ULONG_PTR)JmpOpcodeSize;
 
    DWORD OldProtect2;
    VirtualProtect(Function, JmpOpcodeSize, OldProtect, &OldProtect2);
    return true;
}
 
 
 
int _stdcall Hooked_MessageBoxW(HWND hWnd, wchar_t const * pText, wchar_t const * pCaption, UINT Type)
{
    size_t const BuffSize = 1000;
    wchar_t Buffer[BuffSize];
 
    StringCchPrintfW(
        Buffer,
        BuffSize,
        L"Hooked MessageBoxW: Text = %s, Caption = %s\r\n",
        pText,
        pCaption
        );
    OutputDebugStringW(&Buffer[0]);
 
    return 0;
}
 
 
 
int main()
{
    if (false == SetHook(MessageBoxW, Hooked_MessageBoxW))
    {
        MessageBoxW(NULL, L"Unable to hook MessageBoxW :(", L"Error", MB_ICONERROR);
    }
 
    else
    {
        MessageBoxW(NULL, L"Hello, World !", L"Info", MB_OK);
    }
 
    return 0;
}
1
 Аватар для uhx
60 / 60 / 19
Регистрация: 11.07.2013
Сообщений: 305
22.02.2015, 22:29  [ТС]
Убежденный, за код - отдельное спасибо. Сами замечания по коду ничего не изменили, а теперь в чем суть ошибки:
C++
1
2
memset(org, 0xE9, 1); // Ставим прыжок
memset((char*)org + 1, relativeAddress, 4); // И длину прыжка
поменял на
C++
1
2
*org = 0xE9;
*((DWORD *)(org + 1)) = relativeAddress;
И сразу все заработало. Спасибо.
Видимо, memset как-то неудачно преобразовывает нашу переменную relativeAddress, и поэтому адрес записывается криво. А по указателям все прошло как надо)
А, и тип указателей на функции поменял на BYTE*. Так правильнее будет, насколько я понял)
Спасибо огромное!
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
22.02.2015, 22:36
C
1
2
3
4
5
6
7
8
9
10
11
12
13
//
// Здесь в org+1 пишется то, что лежит по адресу relativeAddress.
// Но relativeAddress - это не адрес на самом деле, а смещение
// (смотрим конструкцию опкода JMP-E9). Поэтому наиболее вероятный
// результат данного кода - access violation.
//
memset((char*)org + 1, relativeAddress, 4);
 
//
// А здесь в org+1 пишется значение переменной relativeAddress.
// То есть, как раз то самое смещение.
//
memset((char*)org + 1, &relativeAddress, 4);
0
 Аватар для uhx
60 / 60 / 19
Регистрация: 11.07.2013
Сообщений: 305
22.02.2015, 22:47  [ТС]
Убежденный, такой код компилятор не принимает, я пробовал.
Ведь & - это ссылка на адрес переменной, а в САМОЙ переменной лежит смещение, которое мы и вписываем в опкод... Но я может и заблуждаюсь, я уже что-то начал путаться с этими указателями-ссылками.

Добавлено через 4 минуты
C++
1
printf("0x%X hooked to 0x%X!\nRelAddr: 0x%X (0x%X)\n", org, hk, relativeAddress, &relativeAddress);
Такой код выдает
Code
1
2
0x7624FD1E hooked to 0x54901226!
RelAddr: 0xDE6B1503 (0x463730)
Перехожу по адресу 0x463730 и оказываюсь на месте переменной, где хранится наше смещение (0xDE6B1503) только в int.
Мне кажется, Вы тут сами что-то намудрили
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
22.02.2015, 23:38
Цитата Сообщение от uhx Посмотреть сообщение
Убежденный, такой код компилятор не принимает, я пробовал.
Я туплю [иногда. как правило, под вечер ].
Вместо memset должно быть memcpy или RtlCopyMemory, конечно же.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.02.2015, 23:38
Помогаю со студенческими работами здесь

Как поставить хук на нажатие клавиш
Народ подскажите, каким образом можно реализовать перехват на нажатие определенных последовательностей (нужно задавать, может быть одна...

Можно ли поставить хук на MessageBox, CreateFile без драйвера?
Можно ли поставить хук на MessageBox, CreateFile без драйвера?

Не получается передать парметры через функцию
Пожалуйста объясните как передавать параметры через функцию.

Не получается запустить функцию через switch
Не получается запустить функцию через switch, где ошибка? #include &lt;iostream&gt; using namespace std; int const N = 256; void...

Не получается вызвать функцию через onmouseover
В общем нужно передать параметр функции. на странице: &lt;a href='proj.php' onmouseover='showtrail(320,240,image.jpg); count(123);' ...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
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 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru