- 51
- 2
plugin.hpp:
#ifndef PLUGIN_HPP
#define PLUGIN_HPP
#include <windows.h>
#include <kthook/kthook.hpp>
#include <RakHook/rakhook.hpp>
#include "overlay.hpp"
using namespace std::placeholders;
class c_plugin {
public:
c_plugin() = default;
~c_plugin() { rakhook::destroy(); render::destroy(); overlay::destroy(); };
kthook::kthook_simple<void(__cdecl*)()> update_hook { reinterpret_cast<void*>(0x561B10), std::bind(&c_plugin::update_hooked, this, _1) };
void update_hooked(const decltype(update_hook)& hook);
kthook::kthook_simple<HRESULT(__stdcall*)(HWND, UINT, WPARAM, LPARAM)> wnd_proc_hook{ reinterpret_cast<void*>(0x747EB0), std::bind(&c_plugin::wnd_proc_hooked, this, _1, _2, _3, _4, _5) };
HRESULT wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
};
#endif // PLUGIN_HPP
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP
#include <filesystem>
#include "include/cef_app.h"
#include "render.hpp"
class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
c_overlay() = default;
~c_overlay() = default;
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override { this->browser = browser; }
void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) override;
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 840, 660); };
CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };
private:
CefRefPtr<CefBrowser> browser;
IMPLEMENT_REFCOUNTING(c_overlay);
DISALLOW_COPY_AND_ASSIGN(c_overlay);
};
namespace overlay {
inline static c_overlay* cef;
inline LPDIRECT3DTEXTURE9 texture;
void initialize();
void create_browser(std::string url = "https://url.com");
bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
void destroy();
}
#endif // !OVERLAY_HPP
plugin.cpp:
#include "plugin.hpp"
void c_plugin::update_hooked(const decltype(update_hook)& hook) {
static bool inited = false;
if (!inited && c_chat().reference() && rakhook::initialize()) {
inited = true;
overlay::initialize();
render::initialize();
render::on_present += []() {
if (!overlay::texture || !render::device)
return;
render::device->SetTexture(0, overlay::texture);
render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
render::device->SetRenderState(D3DRS_LIGHTING, FALSE);
struct CUSTOMVERTEX {
FLOAT x, y, z, rhw;
FLOAT u, v;
};
CUSTOMVERTEX vertices[] = {
{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },
{ 840.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f },
{ 0.0f, 660.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ 840.0f, 660.0f, 0.0f, 1.0f, 1.0f, 1.0f }
};
render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));
};
}
return hook.call_trampoline();
}
HRESULT c_plugin::wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
overlay::wnd_proc(hwnd, umsg, wp, lp);
return hook.call_trampoline(hwnd, umsg, wp, lp);
}
overlay.cpp:
#include "overlay.hpp"
void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
if (!overlay::texture)
D3DXCreateTexture(render::device, width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &overlay::texture);
D3DLOCKED_RECT locked_rect;
overlay::texture->LockRect(0, &locked_rect, nullptr, 0);
memcpy(locked_rect.pBits, buffer, width * height * 4);
overlay::texture->UnlockRect(0);
}
void overlay::create_browser(std::string url) {
CefWindowInfo window_info;
CefBrowserSettings browser_settings;
window_info.SetAsWindowless(nullptr);
CefBrowserHost::CreateBrowser(window_info, cef, url.c_str(), browser_settings, nullptr, nullptr);
}
void overlay::initialize() {
cef = new c_overlay();
std::string work_path = std::filesystem::current_path().string();
std::filesystem::create_directories(work_path + "\\cache");
CefSettings settings;
CefString(&settings.browser_subprocess_path).FromASCII(std::string(work_path + "\\cef-sub-process.exe").c_str());
CefString(&settings.log_file) = work_path + "\\cef-log.log";
CefString(&settings.cache_path).FromASCII(std::string(work_path + "\\cache").c_str());
CefString(&settings.locales_dir_path).FromASCII(std::string(work_path + "\\locales").c_str());
CefString(&settings.resources_dir_path) = work_path;
CefString(&settings.locale).FromASCII("ru");
CefString(&settings.accept_language_list).FromASCII("en-US,en,ru-RU,ru");
settings.no_sandbox = 1;
settings.multi_threaded_message_loop = 1;
settings.windowless_rendering_enabled = 1;
settings.background_color = 0;
settings.log_severity = LOGSEVERITY_DEBUG;
settings.command_line_args_disabled = 1;
CefMainArgs main_args;
CefInitialize(main_args, settings, nullptr, nullptr);
create_browser();
}
bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
if (cef && cef->GetBrowser()) {
CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();
if (umsg >= WM_MOUSEMOVE && umsg <= WM_MBUTTONUP || umsg == WM_MOUSEWHEEL) {
POINT point = { LOWORD(lp), HIWORD(lp) };
ScreenToClient(hwnd, &point);
CefMouseEvent mouse_event;
mouse_event.x = point.x;
mouse_event.y = point.y;
mouse_event.modifiers = 0;
switch (umsg) {
case WM_LBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); break;
case WM_LBUTTONUP: host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1); break;
case WM_RBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1); break;
case WM_RBUTTONUP: host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1); break;
case WM_MBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_MIDDLE, false, 1); break;
case WM_MBUTTONUP: host->SendMouseClickEvent(mouse_event, MBT_MIDDLE, true, 1); break;
case WM_MOUSEWHEEL: {
int delta = GET_WHEEL_DELTA_WPARAM(wp);
host->SendMouseWheelEvent(mouse_event, 0, delta);
break;
}
default: {
host->SendMouseMoveEvent(mouse_event, false);
break;
}
}
return true;
}
if (umsg >= WM_KEYDOWN && umsg <= WM_CHAR) {
int keycode = static_cast<int>(wp);
int modifiers = 0;
if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= EVENTFLAG_SHIFT_DOWN;
if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
if (GetKeyState(VK_MENU) & 0x8000) modifiers |= EVENTFLAG_ALT_DOWN;
CefKeyEvent event;
event.windows_key_code = keycode;
event.native_key_code = static_cast<int>(lp);
event.modifiers = modifiers;
if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) { event.type = KEYEVENT_RAWKEYDOWN; }
else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) { event.type = KEYEVENT_KEYUP; }
else if (umsg == WM_CHAR) { event.type = KEYEVENT_CHAR; }
host->SendKeyEvent(event);
return true;
}
}
return false;
}
void overlay::destroy() {
CefShutdown();
if (texture)
texture->Release();
delete cef;
}
main.cpp:
#include "plugin.hpp"
c_plugin* plugin;
int __stdcall DllMain(HMODULE instance, DWORD call_reason, LPVOID reserved) {
if (call_reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(instance);
plugin = new c_plugin();
}
else if (call_reason == DLL_PROCESS_DETACH)
delete plugin;
return TRUE;
}
render.hpp:
#ifndef RENDER_HPP
#define RENDER_HPP
#include <imgui_impl_dx9.h>
#include <imgui_impl_win32.h>
#include <imgui_internal.h>
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
#include "kthook/kthook.hpp"
#include "samp.hpp"
namespace render {
template <typename T>
struct on_event : public std::vector<std::function<T>> {
on_event& operator+=(std::function<T> func) {
this->push_back(func);
return *this;
}
};
inline on_event<void()> on_present;
inline bool initialized = false;
inline IDirect3DDevice9* device;
void initialize();
void destroy();
}
#endif // !RENDER_HPP
render.cpp:
#include "render.hpp"
#include "overlay.hpp"
kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, const RECT*, const RECT*, HWND, const RGNDATA*)> present_hook;
kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*)> reset_hook;
std::optional<HRESULT> d3d9_present_hooked(const decltype(present_hook)& hook, IDirect3DDevice9* device, CONST RECT* src_rect, CONST RECT* dest_rect, HWND dest_window, CONST RGNDATA* dirty_region) {
if (!render::initialized) {
render::device = device;
render::initialized = true;
}
else {
for (auto& f : render::on_present) {
if (f) f();
}
}
return std::nullopt;
}
std::optional<HRESULT> d3d9_lost_hooked(const decltype(reset_hook)& hook, LPDIRECT3DDEVICE9 device, D3DPRESENT_PARAMETERS* present_params) {
return std::nullopt;
}
uintptr_t find_device(uint32_t length) {
static uintptr_t base = [](size_t length) {
std::string path(MAX_PATH, '\0');
if (auto size = GetSystemDirectoryA(path.data(), MAX_PATH)) {
path.resize(size);
path += "\\d3d9.dll";
uintptr_t object_base = reinterpret_cast<uintptr_t>(LoadLibraryA(path.c_str()));
while (object_base++ < object_base + length) {
if (*reinterpret_cast<uint16_t*>(object_base + 0x00) == 0x06C7 && *reinterpret_cast<uint16_t*>(object_base + 0x06) == 0x8689 && *reinterpret_cast<uint16_t*>(object_base + 0x0C) == 0x8689) {
object_base += 2;
break;
}
}
return object_base;
}
return uintptr_t(0);
}(length);
return base;
}
void* get_function_address(int virtual_table_index) {
return (*reinterpret_cast<void***>(find_device(0x128000)))[virtual_table_index];
}
void render::initialize() {
present_hook.set_dest(get_function_address(17));
present_hook.install();
reset_hook.set_dest(get_function_address(16));
reset_hook.install();
present_hook.before.connect(&d3d9_present_hooked);
reset_hook.before.connect(&d3d9_lost_hooked);
}
void render::destroy() {
}
Увидел как-то на форуме CEF который отрисовывается на imgui, решил переделать в отрисовку через directx9, но плохо рендерится(текст, мыло и все пикселится, появляется черная обводка которой нет) и ломает ESC.