Appearance
question:необходим ли switch case в DllMain? я не планирую добавлять новый функционал
answer:Если вы не планируете добавлять новый функционал и ваш `DllMain` обрабатывает только событие `DLL_PROCESS_ATTACH`, использование конструкции `switch-case` действительно может показаться избыточным. В таком случае, вы можете упростить реализацию `DllMain`, избегая `switch-case`, если желаете сосредоточиться на четкости и минимализме: ```cpp #include "pch.h" #include <Windows.h> #include <cstdio> void install_hook() { auto current_process = GetCurrentProcess(); auto engine_module_handle = GetModuleHandleW(L"engine.dll"); if (engine_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля engine.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } auto nwindow_module_handle = GetModuleHandleW(L"nwindow.dll"); if (nwindow_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля nwindow.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } uintptr_t nwindow_base = reinterpret_cast<uintptr_t>(nwindow_module_handle); uintptr_t debuff_time_address = nwindow_base + 0x4DCE7; BYTE debuff_time_patch[13] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; if (!WriteProcessMemory(current_process, reinterpret_cast<LPVOID>(debuff_time_address), debuff_time_patch, sizeof(debuff_time_patch), nullptr)) { MessageBoxA(nullptr, "Ошибка при применении debuff_time_patch", "Ошибка", MB_OK | MB_ICONERROR); } uintptr_t engine_base = reinterpret_cast<uintptr_t>(engine_module_handle); uintptr_t bodyblock_address = engine_base + 0x22E207; BYTE bodyblock_patch[1] = {0x00}; if (!WriteProcessMemory(current_process, reinterpret_cast<LPVOID>(bodyblock_address), bodyblock_patch, sizeof(bodyblock_patch), nullptr)) { MessageBoxA(nullptr, "Ошибка при применении bodyblock_patch", "Ошибка", MB_OK | MB_ICONERROR); } } BOOL APIENTRY DllMain(HMODULE h_module, DWORD ul_reason_for_call, LPVOID lp_reserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(h_module); install_hook(); } return TRUE; } ``` В этом коде `DllMain` предполагает, что ваша библиотека будет использоваться только при загрузке в процесс, и никакие дополнительные действия (например, очистка при выгрузке с `DLL_PROCESS_DETACH`) не требуются. Это упрощение подходит для сценариев, где вам нужно минимально вмешиваться в процесс загрузки и выгрузки DLL и ваша главная задача сосредоточена на выполнении некоторых операций при инициализации.
question:Что скажешь по качеству кода DLL? Можно ли его улучшить или лучше оставить как есть? #include "pch.h" #include <Windows.h> #include <stdio.h> void install_hook() { auto current_process = GetCurrentProcess(); auto engine_module_handle = GetModuleHandleW(L"engine.dll"); if (engine_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля engine.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } auto nwindow_module_handle = GetModuleHandleW(L"nwindow.dll"); if (nwindow_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля nwindow.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } uintptr_t nwindow_base = reinterpret_cast<uintptr_t>(nwindow_module_handle); uintptr_t debuff_time_address = nwindow_base + 0x4DCE7; BYTE debuff_time_patch[13] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; if (!WriteProcessMemory(current_process, reinterpret_cast<LPVOID>(debuff_time_address), debuff_time_patch, sizeof(debuff_time_patch), nullptr)) { MessageBoxA(nullptr, "Ошибка при применении debuff_time_patch", "Ошибка", MB_OK | MB_ICONERROR); } uintptr_t engine_base = reinterpret_cast<uintptr_t>(engine_module_handle); uintptr_t bodyblock_address = engine_base + 0x22E207; BYTE bodyblock_patch[1] = { 0x00 }; if (!WriteProcessMemory(current_process, reinterpret_cast<LPVOID>(bodyblock_address), bodyblock_patch, sizeof(bodyblock_patch), nullptr)) { MessageBoxA(nullptr, "Ошибка при применении bodyblock_patch", "Ошибка", MB_OK | MB_ICONERROR); } } BOOL APIENTRY DllMain(HMODULE h_module, DWORD ul_reason_for_call, LPVOID lp_reserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(h_module); install_hook(); } return TRUE; }
answer:В целом, ваш код для DLL демонстрирует ясную цель — установку хуков при загрузке DLL. Тем не менее, существует несколько аспектов, в которых код может быть доработан или улучшен для повышения его читаемости, безопасности и общего качества: 1. **Проверка возвращаемых значений**: Основываясь на текущей логике, вы уже проверяете возвращаемые значения функции `WriteProcessMemory`. Однако, было бы полезно отметить, что проверки результатов работы других функций, таких как `GetModuleHandleW`, также реализованы и обрабатываются корректно. 2. **Использование стандартов C++**: Вы используете `#include <stdio.h>`, хотя фактически нигде не используете функции стандартного ввода-вывода C. Если ваш код полностью ориентирован на C++, включение заголовочных файлов C может быть избыточным. Вместо этого, используйте функционал C++, например `<iostream>`, если нужно будет работать с вводом-выводом. 3. **Обработка ошибок**: Для улучшения процесса обработки ошибок вы можете реализовать логирование или другие механизмы, позволяющие понять, на каком этапе возникает сбой, не ограничиваясь только показом диалоговых окон. 4. **Безопасность при работе с памятью**: Код корректно использует типы данных и касты, однако желательно всегда быть очень внимательными при выполнении операций, которые влияют на память других процессов. Убедитесь, что адреса и размеры патчей точны и не вызовут повреждения или нестабильности в приложении-хосте. 5. **Возврат значения функции `DllMain`**: Всегда явно возвращайте `TRUE` из `DllMain`, чтобы указать успешную загрузку DLL. В вашем случае это уже реализовано корректно. 6. **Использование ресурсов**: Хорошей практикой является освобождение всех захваченных ресурсов перед выгрузкой DLL. В вашем случае, каких-либо захваченных ресурсов, которые нужно явно освободить, не обнаружено, но это полезно иметь в виду для более сложных случаев. 7. **Рефакторинг**: Рассмотрите возможность разделения `install_hook` на более мелкие функции для каждого хука. Это сделает ваш код более читаемым и упростит поддержку. В целом, ваш код хорош для выполняемой задачи, но всегда полезно рассмотреть эти аспекты для повышения качества и безопасности вашего программного обеспечения.
question:Используя свой совет "7. Рефакторинг: Рассмотрите возможность разделения install_hook на более мелкие функции для каждого хука. Это сделает ваш код более читаемым и упростит поддержку." проведи рефакторинг моего кода.
answer:Конечно, давайте разделим функцию `install_hook` на несколько меньших функций для улучшения читаемости кода и облегчения его дальнейшей поддержки. Каждая из этих функций будет отвечать за установку отдельного хука. ```cpp #include "pch.h" #include <Windows.h> #include <cstdio> // Прототипы функций BOOL apply_patch(HANDLE process, HMODULE module_handle, DWORD offset, const BYTE* patch, SIZE_T patch_size); void install_debuff_time_patch(HANDLE current_process, HMODULE nwindow_module_handle); void install_bodyblock_patch(HANDLE current_process, HMODULE engine_module_handle); void install_hook() { auto current_process = GetCurrentProcess(); auto engine_module_handle = GetModuleHandleW(L"engine.dll"); if (engine_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля engine.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } auto nwindow_module_handle = GetModuleHandleW(L"nwindow.dll"); if (nwindow_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля nwindow.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } install_debuff_time_patch(current_process, nwindow_module_handle); install_bodyblock_patch(current_process, engine_module_handle); } BOOL apply_patch(HANDLE process, HMODULE module_handle, DWORD offset, const BYTE* patch, SIZE_T patch_size) { uintptr_t base_address = reinterpret_cast<uintptr_t>(module_handle); uintptr_t patch_address = base_address + offset; return WriteProcessMemory(process, reinterpret_cast<LPVOID>(patch_address), patch, patch_size, nullptr); } void install_debuff_time_patch(HANDLE current_process, HMODULE nwindow_module_handle) { BYTE debuff_time_patch[13] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; if (!apply_patch(current_process, nwindow_module_handle, 0x4DCE7, debuff_time_patch, sizeof(debuff_time_patch))) { MessageBoxA(nullptr, "Ошибка при применении debuff_time_patch", "Ошибка", MB_OK | MB_ICONERROR); } } void install_bodyblock_patch(HANDLE current_process, HMODULE engine_module_handle) { BYTE bodyblock_patch[1] = { 0x00 }; if (!apply_patch(current_process, engine_module_handle, 0x22E207, bodyblock_patch, sizeof(bodyblock_patch))) { MessageBoxA(nullptr, "Ошибка при применении bodyblock_patch", "Ошибка", MB_OK | MB_ICONERROR); } } BOOL APIENTRY DllMain(HMODULE h_module, DWORD ul_reason_for_call, LPVOID lp_reserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(h_module); install_hook(); } return TRUE; } ``` Что было изменено: 1. **`apply_patch`**: Отвечает за непосредственное применение патча к процессу. Принимает HANDLE процесса, HMODULE загруженного модуля, смещение относительно начала модуля, сам патч (массив байт) и его размер. Возвращает BOOL, указывая, было ли применение патча успешным. 2. **`install_debuff_time_patch` и `install_bodyblock_patch`**: Отдельные функции для каждого патча, использующие `apply_patch` для применения соответствующих изменений к памяти процесса. Этот подход делает ваш код более модульным и понятным. Изменение, удаление или добавление новых патчей теперь становится более простым и менее подверженным ошибкам.
question:код стал более массивным и запутанным, плохой рефакторинг
answer:Извините за неудобства. Целью рефакторинга было улучшить структуру кода и повысить его читаемость и поддерживаемость, разделив его на логические блоки. Однако, если вы считаете, что это привело к усложнению кода, мы можем поискать альтернативный подход, который оставит код проще и понятнее. Важно найти баланс между модулярностью и простотой. Давайте попробуем упростить предыдущий рефакторинг, сохраняя при этом разделение на функции для каждого патча, но уберём вспомогательную функцию `apply_patch` для сокращения кода: ```cpp #include "pch.h" #include <Windows.h> #include <cstdio> void install_debuff_time_patch(HANDLE current_process, HMODULE nwindow_module_handle) { uintptr_t nwindow_base = reinterpret_cast<uintptr_t>(nwindow_module_handle); uintptr_t debuff_time_address = nwindow_base + 0x4DCE7; BYTE debuff_time_patch[13] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; if (!WriteProcessMemory(current_process, reinterpret_cast<LPVOID>(debuff_time_address), debuff_time_patch, sizeof(debuff_time_patch), nullptr)) { MessageBoxA(nullptr, "Ошибка при применении debuff_time_patch", "Ошибка", MB_OK | MB_ICONERROR); } } void install_bodyblock_patch(HANDLE current_process, HMODULE engine_module_handle) { uintptr_t engine_base = reinterpret_cast<uintptr_t>(engine_module_handle); uintptr_t bodyblock_address = engine_base + 0x22E207; BYTE bodyblock_patch[1] = { 0x00 }; if (!WriteProcessMemory(current_process, reinterpret_cast<LPVOID>(bodyblock_address), bodyblock_patch, sizeof(bodyblock_patch), nullptr)) { MessageBoxA(nullptr, "Ошибка при применении bodyblock_patch", "Ошибка", MB_OK | MB_ICONERROR); } } void install_hook() { auto current_process = GetCurrentProcess(); auto engine_module_handle = GetModuleHandleW(L"engine.dll"); if (engine_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля engine.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } auto nwindow_module_handle = GetModuleHandleW(L"nwindow.dll"); if (nwindow_module_handle == nullptr) { MessageBoxA(nullptr, "Не удалось получить дескриптор модуля nwindow.dll", "Ошибка", MB_OK | MB_ICONERROR); return; } install_debuff_time_patch(current_process, nwindow_module_handle); install_bodyblock_patch(current_process, engine_module_handle); } BOOL APIENTRY DllMain(HMODULE h_module, DWORD ul_reason_for_call, LPVOID lp_reserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(h_module); install_hook(); } return TRUE; } ``` В этом варианте на каждый патч отправляется отдельная функция, что сохраняет некоторую модульность и читаемость, не усложняя при этом структуру кода. Отказ от дополнительной уровневой функции `apply_patch` уменьшает количество строк кода и делает его более прямолинейным.