Jump to content

kennylovecode

Member
  • Posts

    105
  • Joined

  • Last visited

Everything posted by kennylovecode

  1. I just did some basic testing and successfully redrew.
  2. As far as I know, most 2D version game clients are basically based on D3D8. If you have the capability, it can be changed to D3D9 or higher versions through hooking, but this requires deeper research
  3. you can find it from "google", or github.com or anywhere if you search! Even you can ask CHATGPT for the download link to this file, and it can provide it to you completely, which is much better than asking on a forum, waiting, waiting, waiting, and then giving up.
  4. What I am sharing is an idea of how to do it, not a complete project. But this idea is a feasible path that I have fully verified, not a hypothesis. There is an ancient Chinese saying that "teach him how to fish is better then just give a man a fish". I think this is very important.
  5. And Next. how to use your D3D8 hook to render a custom UI inside the game/client. Goal: Render Custom UI Over Game Screen We’ll do this by drawing inside the hkEndScene() function, which runs every frame right before the screen is presented. Prerequisites You must have: Already hooked EndScene (as we did above) Access to the LPDIRECT3DDEVICE8 pointer Initialized DirectX 8 properly in the target context Tools and Libraries (Optional) You can either: Use raw D3D8 drawing functions (simple, less dependency) Or use libraries like: ImGui + D3D8 backend (more complex, but easier to make UIs) D3DXFont / D3DXSprite (from d3dx8.lib) Let’s start with a raw example, then show how to add ImGui. Step-by-Step: Drawing Text and Boxes in hkEndScene 1. Draw Text with D3DXFont LPD3DXFONT pFont = nullptr; HRESULT APIENTRY hkEndScene(LPDIRECT3DDEVICE8 pDevice) { if (!pFont) { D3DXCreateFont(pDevice, 20, 0, FW_NORMAL, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &pFont); } RECT rect = { 10, 10, 300, 300 }; pFont->DrawTextA(NULL, "Hello from Hook!", -1, &rect, DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 0, 0)); return oEndScene(pDevice); } This renders “Hello from Hook!” in red text at the top-left of the screen. 2. Draw a Filled Rectangle (Box) void DrawBox(LPDIRECT3DDEVICE8 pDevice, float x, float y, float width, float height, D3DCOLOR color) { struct Vertex { float x, y, z, rhw; DWORD color; }; Vertex vertices[] = { { x, y, 0.0f, 1.0f, color }, { x + width, y, 0.0f, 1.0f, color }, { x, y + height, 0.0f, 1.0f, color }, { x + width, y + height, 0.0f, 1.0f, color }, }; pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); pDevice->SetRenderState(D3DRS_ZENABLE, FALSE); pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(Vertex)); } // Inside hkEndScene DrawBox(pDevice, 50, 50, 100, 20, D3DCOLOR_ARGB(150, 0, 255, 0)); // semi-transparent green box Bonus: Show Health Bar Above Entity Assuming you know the screen position (x, y) of the entity, you can do: float healthPercent = 0.7f; // 70% health DrawBox(pDevice, x, y - 10, 50, 5, D3DCOLOR_ARGB(150, 0, 0, 0)); // background DrawBox(pDevice, x, y - 10, 50 * healthPercent, 5, D3DCOLOR_ARGB(200, 0, 255, 0)); // foreground Optional: Use ImGui for Modern UI ImGui works with D3D8 too, with slight setup. You’ll need: ImGui D3D8 backend (use imgui_impl_dx8.cpp) Windows message handler (imgui_impl_win32.cpp) In hkEndScene: ImGui_ImplDX8_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); ImGui::Begin("Custom UI"); ImGui::Text("Injected Overlay!"); ImGui::End(); ImGui::Render(); ImGui_ImplDX8_RenderDrawData(ImGui::GetDrawData()); Debug Tips Ensure EndScene is being called (log or breakpoint) Use OutputDebugString or write to file for diagnostics If the overlay doesn’t show: Make sure the render state is correct The game window must be the foreground window (for some methods) Try drawing solid rectangles first (not text) Summary FeatureMethod TextD3DXCreateFont, DrawTextA Box/RectanglesCustom vertex arrays + DrawPrimitiveUP UIImGui (with D3D8 backend) Health BarCombine rectangles and entity coordinates
  6. Here's a full D3D8 Hook Tutorial in English, including all steps from knowledge prerequisites to debugging and logging. 1. Prerequisites Before diving into D3D8 hooking, you should be familiar with the following: TopicDescription C/C++ ProgrammingKnow classes, pointers, function pointers DLL BasicsUnderstand how DLLs work and are injected Windows APIBasic Win32 programming and message loop Assembly & MemoryBasic understanding of memory layout and vtables DirectX 8 ConceptsHow Direct3D8 renders (e.g., EndScene, Reset) 2. Required Tools ToolPurposeRecommendation Visual Studio 2019/2022Build and debug C++ projects DirectX 8 SDKProvides d3d8.h, d3d8.lib, etc. DLL InjectorInject your DLL into the target process[Extreme Injector, Process Hacker, or custom one] Cheat EngineMemory inspection/debugging DebugView or file loggerFor logging without a console 3. Create the Hook DLL Project 3.1 Set up a Visual Studio Project Open Visual Studio → Create New Project → C++ Dynamic-Link Library (DLL) Name it something like D3D8Hook Set Project Properties: C/C++ > General > Additional Include Directories: Add the DirectX SDK Include path Linker > Input > Additional Dependencies: Add d3d8.lib, d3dx8.lib 3.2 Write the Hooking Code // D3D8Hook.cpp // D3D8Hook.cpp #include <Windows.h> #include <d3d8.h> #include <d3dx8.h> typedef HRESULT(APIENTRY* EndScene_t)(LPDIRECT3DDEVICE8 pDevice); EndScene_t oEndScene = nullptr; DWORD WINAPI MainThread(LPVOID); // Hook implementation HRESULT APIENTRY hkEndScene(LPDIRECT3DDEVICE8 pDevice) { static bool once = false; if (!once) { MessageBoxA(0, "D3D8 Hooked!", "Success", MB_OK); once = true; } return oEndScene(pDevice); // Call the original } void HookFunction() { IDirect3D8* pD3D = Direct3DCreate8(D3D_SDK_VERSION); if (!pD3D) return; D3DPRESENT_PARAMETERS d3dpp = {}; d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = GetForegroundWindow(); IDirect3DDevice8* pDevice = nullptr; if (SUCCEEDED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))) { void** vtable = *(void***)pDevice; oEndScene = (EndScene_t)vtable[35]; DWORD oldProtect; VirtualProtect(&vtable[35], sizeof(void*), PAGE_EXECUTE_READWRITE, &oldProtect); vtable[35] = (void*)&hkEndScene; VirtualProtect(&vtable[35], sizeof(void*), oldProtect, &oldProtect); pDevice->Release(); } pD3D->Release(); } DWORD WINAPI MainThread(LPVOID) { HookFunction(); return 0; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID) { if (reason == DLL_PROCESS_ATTACH) CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr); return TRUE; } 3.3 Build the DLL Use Build → Build Solution (Ctrl + Shift + B) and find the DLL in: csharp 复制编辑 [YourProjectFolder]\x86\Debug\D3D8Hook.dll Make sure it's compiled for x86 if the target process is 32-bit. 4. Injecting the DLL Method 1: Use an Injector Tool Start the game or D3D8-based application Open an injector (e.g., Extreme Injector or Process Hacker) Select the target process and inject D3D8Hook.dll Method 2: Write Your Own Injector (optional) cpp 复制编辑 HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); LPVOID addr = VirtualAllocEx(hProc, NULL, len, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProc, addr, dllPath, len, NULL); CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, addr, 0, NULL); 5. Debugging and Logging 5.1 Output to DebugView Use this to see logs: cpp 复制编辑 OutputDebugStringA("D3D8 Hook initialized!"); You can view logs with DebugView by Sysinternals. 5.2 Write Logs to File cpp 复制编辑 void Log(const char* msg) { FILE* f = fopen("C:\\D3D8_Hook_Log.txt", "a+"); if (f) { fprintf(f, "%s\n", msg); fclose(f); } } 5.3 Use Visual Studio Debugger Build your DLL in Debug mode Launch the target app Attach Visual Studio (Debug → Attach to Process) Set breakpoints in hkEndScene or elsewhere Common Issues & Fixes IssuePossible Cause Game crashesWrong vtable index or uninitialized pointers Nothing happensHook not applied or wrong process architecture DLL fails to injectMissing dependencies or wrong platform (x64 vs x86)
  7. I'm also in the process of learning, I've just analyzed its method but haven't gone through the process and results yet. But I've analyzed about 4-5 sample clients, and they are almost all done this way.
  8. Since you have already seen which table the mapping is for, you can certainly try adding this column to the table to test
  9. Some thing for learning .... for long time forget mark D3D8 HOOK: // Typedef of reset and present HRESULT __stdcall nReset ( LPDIRECT3DDEVICE8 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters ); typedef HRESULT ( APIENTRY* Reset_t ) ( LPDIRECT3DDEVICE8 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters ); Reset_t pReset; HRESULT __stdcall nPresent ( LPDIRECT3DDEVICE8 pDevice,CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion ); typedef HRESULT ( APIENTRY* Present_t)( LPDIRECT3DDEVICE8 pDevice,CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion ); Present_t pPresent; HRESULT __stdcall nReset ( LPDIRECT3DDEVICE8 pDevice , D3DPRESENT_PARAMETERS* pPresentationParameters ) { _asm PUSHAD; Tools.AddLog("Hook Reset\n"); _asm POPAD; return pReset(pDevice, pPresentationParameters); } HRESULT __stdcall nPresent ( LPDIRECT3DDEVICE8 pDevice,CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion ) { _asm PUSHAD; Tools.AddLog("Hook Present\n"); _asm POPAD; return pPresent (pDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); } DWORD_PTR * Hook :: FindDevice ( DWORD Base, DWORD Len ) { unsigned long i = 0, n = 0; for( i = 0; i < Len; i++ ) { if(*(BYTE *)(Base+i+0x00)==0xC7)n++; if(*(BYTE *)(Base+i+0x01)==0x06)n++; if(*(BYTE *)(Base+i+0x06)==0x89)n++; if(*(BYTE *)(Base+i+0x07)==0x86)n++; if(*(BYTE *)(Base+i+0x0C)==0x89)n++; if(*(BYTE *)(Base+i+0x0D)==0x86)n++; if( n == 6 ) return ( DWORD_PTR * ) ( Base + i + 2 ); n = 0; } return(0); } int __fastcall StaticHook ( void ) { HMODULE hD3D8Dll; do{ Tools.AddLog("%s - Loading d3d8.dll->",Tools.AddTime()); hD3D8Dll = GetModuleHandle("d3d8.dll"); Sleep(20); Tools.AddLog("OK!\n"); } while(!hD3D8Dll); Tools.AddLog("%s - Enable Device [Metin2]->",Tools.AddTime()); DWORD_PTR * VtablePtr = cHook.FindDevice((DWORD)hD3D8Dll,0x128000); Tools.AddLog("OK!\n"); if ( VtablePtr == NULL ) { MessageBox(NULL,"Device Not Found !! Please try again",0,MB_ICONSTOP); ExitProcess(TRUE); } Tools.AddLog("%s - Type Device->",Tools.AddTime()); DWORD_PTR* VTable = 0; *(DWORD_PTR*)&VTable = *(DWORD_PTR *)VtablePtr; Tools.AddLog("OK!\n"); Tools.AddLog("%s - Hooking Class->",Tools.AddTime()); pPresent = (Present_t) Tools.bDetourA((PBYTE)VTable[15],(LPBYTE)nPresent,6); pReset = (Reset_t) Tools.bDetourA((PBYTE)VTable[14],(LPBYTE)nReset,6); Tools.AddLog("OK!\n"); return(0); } bool __stdcall DllMain ( HMODULE hDll, unsigned long Reason , LPVOID LPReserved ) { DisableThreadLibraryCalls(hDll); switch ( Reason ) { case DLL_PROCESS_ATTACH : CreateThread(0,0,(LPTHREAD_START_ROUTINE)StaticHoo k ,0,0,0); break; case DLL_PROCESS_DETACH : break; } return (1); } d3d9 hook: // Typedef of reset and present HRESULT __stdcall nReset ( LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters ); typedef HRESULT ( APIENTRY* Reset_t ) ( LPDIRECT3DDEVICE8 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters ); Reset_t pReset; HRESULT __stdcall nPresent ( LPDIRECT3DDEVICE9 pDevice,CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion ); typedef HRESULT ( APIENTRY* Present_t)( LPDIRECT3DDEVICE9 pDevice,CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion ); Present_t pPresent; HRESULT __stdcall nReset ( LPDIRECT3DDEVICE9 pDevice , D3DPRESENT_PARAMETERS* pPresentationParameters ) { _asm PUSHAD; Tools.AddLog("Hook Reset\n"); _asm POPAD; return pReset(pDevice, pPresentationParameters); } HRESULT __stdcall nPresent ( LPDIRECT3DDEVICE9 pDevice,CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion ) { _asm PUSHAD; Tools.AddLog("Hook Present\n"); _asm POPAD; return pPresent (pDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); } DWORD_PTR * Hook :: FindDevice ( DWORD Base, DWORD Len ) { unsigned long i = 0, n = 0; for( i = 0; i < Len; i++ ) { if(*(BYTE *)(Base+i+0x00)==0xC7)n++; if(*(BYTE *)(Base+i+0x01)==0x06)n++; if(*(BYTE *)(Base+i+0x06)==0x89)n++; if(*(BYTE *)(Base+i+0x07)==0x86)n++; if(*(BYTE *)(Base+i+0x0C)==0x89)n++; if(*(BYTE *)(Base+i+0x0D)==0x86)n++; if( n == 6 ) return ( DWORD_PTR * ) ( Base + i + 2 ); n = 0; } return(0); } int __fastcall StaticHook ( void ) { HMODULE hD3D9Dll; do{ Tools.AddLog("%s - Loading d3d9.dll->",Tools.AddTime()); hD3D9Dll = GetModuleHandle("d3d9.dll"); Sleep(20); Tools.AddLog("OK!\n"); } while(!hD3D9Dll); Tools.AddLog("%s - Enable Device d3d9->",Tools.AddTime()); DWORD_PTR * VtablePtr = cHook.FindDevice((DWORD)hD3D9Dll,0x128000); Tools.AddLog("OK!\n"); if ( VtablePtr == NULL ) { MessageBox(NULL,"Device Not Found !! Please try again",0,MB_ICONSTOP); ExitProcess(TRUE); } Tools.AddLog("%s - Type Device->",Tools.AddTime()); DWORD_PTR* VTable = 0; *(DWORD_PTR*)&VTable = *(DWORD_PTR *)VtablePtr; Tools.AddLog("OK!\n"); Tools.AddLog("%s - Hooking Class->",Tools.AddTime()); pPresent = (Present_t) Tools.bDetourA((PBYTE)VTable[17],(LPBYTE)nPresent,6); pReset = (Reset_t) Tools.bDetourA((PBYTE)VTable[16],(LPBYTE)nReset,6); Tools.AddLog("OK!\n"); return(0); }
  10. copy map dir from client!
  11. 1. Use Dear ImGui & D3D9Hook 2. Dev Custom client GUI 3. overlay old client gui This is a classic client modification case that uses ImGUI to overwrite a large amount of the original UI
  12. No, it's actually just removing some GUI configurations from the client and changing the GUI to a nostalgic theme. This isn't a lie, because I've also tried it, and it's feasible.
  13. Although I haven't used this source, I seem to have seen its version number somewhere. You can try using the v5517 version client and loader to test.
  14. I've been saving this playlist for a long time, kept looking but never understood it I really don't have a talent for decompilation; assembly code looks like machine code to me 01010101010.... Actually, I've been studying how to modify all player characters in the client with health bars through assembly code... obviously, I failed Because I really don't have a lot of time to spend on studying this, but I've seen many clients do it this way and succeed
  15. On 6/14/2025 at 6:39 AM, Spirited said: Dang, I really need to figure something out for my archive. I have 800GBs of backed up clients across multiple languages... but nowhere to upload them. I'll try and get back in contact with the Gamefront folks... Edit: Oh! I didn't have these. Thank you! Indeed, historical items can be too many, and it requires a lot of time to organize them, while we must wait until we have time.... hahahah
  16. 如果你看得懂中文,就将微信私信给我就可以,当然这是有偿服务。
  17. Recently, I have been looking at some previous source code and found that it has been heavily used ThreadSafeDictionary Of course, you can tell from the name that it is for thread safety Then I discovered in a large amount of code GameState[] array = Server.GamePool.Values; Of course, this is also for thread safety, copying a new copy of the dictionary value into memory first. So I may have found about a hundred sentences of this repetitive code. So I refactored a ThreadSafeDictionary class But I'm not quite sure what problems it might have, so I'm looking at everyone's experience. Here is my code: This is about its calling: public static void Send(IPacket packet, ushort withoutMapId = 0, uint withoutUID = 0) { GameStatePool.ForEachValue((gameState) => { if (gameState.Map.ID == withoutMapId) return; if (gameState.Entity.UID == withoutUID) return; gameState.Send(packet); }); } Haha, I have a code cleanliness obsession. I don't like to write a repetitive code sentence hundreds of times. But I'm not sure what new problems it will bring, anyway it's just a learning code.
  18. If you are struggling with both building a server and fixing bugs, don't think about anything else, learn first and then execute. Wait until you feel that everything is very simple, then you can talk about it again ” aim for a much more stable version“
  19. You can fully use patches to restore the old version of the client, delete some unnecessary things, and get a specified version of the client. I thought they all relied on Conquer.exe
  20. Learning, understanding, and creating Generative artificial intelligence can only provide you with some code suggestions within a limited scope, although sometimes the given code may seem comprehensive, if you analyze it carefully, it is actually full of vulnerabilities. If you are interested in this field, you should spend more time learning the basics instead of spending a lot of time on AI coding and error correction
  21. The encryption algorithm is actually not a big problem for me now, because most sources can be found as references. I mentioned at the beginning about memory based robots, but I am not familiar with assembly language and cannot find the memory base address controlled by the program for CE tools, which stopped me. It may take longer to study and research. But if I use a proxy, I am currently encountering this problem. The automatically sent packets cannot be synchronized to the client. The only way I can think of is to call the client's skip method through memory, which requires finding the skip function address and then calling func This really confuses me, it seems like I can't get around this step
  22. Hello everyone, recently I have compiled all the patches for the Chinese client and shared them on the cloud. Later on, I will organize the introduction of phased patches and compare them with the English version's version numbers Chinese All Client Patch ... Here are the Chinese version names I've compiled from memory; I will add the version number range and English version equivalents later. The Chinese version names will not be translated as they should 1.0 公测版 斧头ICON 1.5 风云天下/风云再起 这两个版本的区别为,风云天下红名会掉装备,风云再起不会。 1.6 双宝奇谋 增加了扇子、塔,装备赎回系统 2.0 暗忍危机 增加了忍者职业 2.0 纵马江湖 增加了马屁、骑术、马鞭等。 2.0 神兵传奇 增加了神魂、淬炼 2.0 降龙武僧 增加了武僧职业 2.0 海盗来袭 增加了海盗职业 End with 6587 .... No last!
  23. 004A5671|004A5688|004A56A8|00481897|0048189C|004818A1|004818A7|00481898|0048189D|0042E7B6|0042E8E4|00462EDC|00464D61|00464D70|00462EE2|0042E7BC|0042E8EA|0048189D|00481898|00462EDD|0042E7B7|0042E8E5|0047B5C3|0047B5CC|6873020000|6800000000|8D8E98070000|90909090|680401000068000100008BCE9090|680401000068000100008BCE9090|689401000068750200008BCF909090909090|004C0848|004C08A8|004C08E2|0047C767|风云天下 When I captured the packet sent from the server and converted it into a string, I could see information containing some memory addresses and server names
×
×
  • Create New...