test dll changes

This commit is contained in:
Jettford 2024-12-04 18:53:04 +00:00
parent 80d3baa886
commit 983a5ec634
22 changed files with 522 additions and 9 deletions

View File

@ -343,6 +343,10 @@ add_subdirectory(dAuthServer)
add_subdirectory(dChatServer)
add_subdirectory(dMasterServer) # Add MasterServer last so it can rely on the other binaries
if (WIN32 AND LOCAL_SERVEr)
add_subdirectory(dLocalServer)
endif()
target_precompile_headers(
dZoneManager PRIVATE
${HEADERS_DZONEMANAGER}

View File

@ -30,3 +30,6 @@ OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
# Whether or not to cache the entire CDClient Database into memory instead of lazy loading.
# 0 means to lazy load, all other values mean load the entire database.
CDCLIENT_CACHE_ALL=0
# Build a local client running server instead of a production server.
LOCAL_SERVER=1

View File

@ -38,7 +38,7 @@ namespace Game {
void HandlePacket(Packet* packet);
int main(int argc, char** argv) {
int start(int argc, char** argv) {
constexpr uint32_t authFramerate = mediumFramerate;
constexpr uint32_t authFrameDelta = mediumFrameDelta;
Diagnostics::SetProcessName("Auth");
@ -161,6 +161,43 @@ int main(int argc, char** argv) {
return EXIT_SUCCESS;
}
#ifdef LOCAL_SERVER
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
start(0, nullptr);
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr) {
break; // do not do cleanup if process termination scenario
}
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#else
int main(int argc, char** argv) {
return start(argc, argv);
}
#endif
void HandlePacket(Packet* packet) {
if (packet->length < 4) return;

View File

@ -1,4 +1,9 @@
add_executable(AuthServer "AuthServer.cpp")
if (WIN32 AND LOCAL_SERVER)
add_library(AuthServer SHARED "AuthServer.cpp")
else()
add_executable(AuthServer "AuthServer.cpp")
endif()
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)

View File

@ -4,7 +4,13 @@ set(DCHATSERVER_SOURCES
"PlayerContainer.cpp"
)
add_executable(ChatServer "ChatServer.cpp")
if (WIN32 AND LOCAL_SERVER)
add_library(ChatServer SHARED "ChatServer.cpp")
else()
add_executable(ChatServer "ChatServer.cpp")
endif()
target_include_directories(ChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dChatFilter")
add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")

View File

@ -41,7 +41,7 @@ namespace Game {
void HandlePacket(Packet* packet);
int main(int argc, char** argv) {
int start(int argc, char** argv) {
constexpr uint32_t chatFramerate = mediumFramerate;
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
Diagnostics::SetProcessName("Chat");
@ -178,6 +178,43 @@ int main(int argc, char** argv) {
return EXIT_SUCCESS;
}
#ifdef LOCAL_SERVER
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
start(0, nullptr);
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr) {
break; // do not do cleanup if process termination scenario
}
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#else
int main(int argc, char** argv) {
return start(argc, argv);
}
#endif
void HandlePacket(Packet* packet) {
if (packet->length < 1) return;
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {

View File

@ -0,0 +1,7 @@
set(DLOCAL_SERVER_SOURCES
"dllmain.cpp"
)
add_library(dLocalServer OBJECT ${DLOCAL_SERVER_SOURCES})
target_link_libraries(dLocalServer)

32
dLocalServer/dllmain.cpp Normal file
View File

@ -0,0 +1,32 @@
#include <windows.h>
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr) {
break; // do not do cleanup if process termination scenario
}
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}

View File

@ -1,11 +1,23 @@
set(DMASTERSERVER_SOURCES
"InstanceManager.cpp"
"PersistentIDManager.cpp"
"Start.cpp"
"StartLocal.cpp"
)
if(WIN32 AND LOCAL_SERVER)
set(DMASTERSERVER_SOURCES ${DMASTERSERVER_SOURCES} "StartLocal.cpp")
else()
set(DMASTERSERVER_SOURCES ${DMASTERSERVER_SOURCES} "Start.cpp")
endif()
add_library(dMasterServer ${DMASTERSERVER_SOURCES})
add_executable(MasterServer "MasterServer.cpp")
if (WIN32 AND LOCAL_SERVER)
add_library(MasterServer SHARED "MasterServer.cpp")
else()
add_executable(MasterServer "MasterServer.cpp")
endif()
target_compile_definitions(MasterServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
target_include_directories(dMasterServer PUBLIC "."
"${PROJECT_SOURCE_DIR}/dZoneManager" # InstanceManager.h uses dZMCommon.h

View File

@ -62,7 +62,7 @@ std::map<uint32_t, std::string> activeSessions;
SystemAddress authServerMasterPeerSysAddr;
SystemAddress chatServerMasterPeerSysAddr;
int main(int argc, char** argv) {
int start(int argc, char** argv) {
constexpr uint32_t masterFramerate = mediumFramerate;
constexpr uint32_t masterFrameDelta = mediumFrameDelta;
Diagnostics::SetProcessName("Master");
@ -429,6 +429,44 @@ int main(int argc, char** argv) {
return ShutdownSequence(EXIT_SUCCESS);
}
#ifdef LOCAL_SERVER
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
AllocConsole();
start(0, nullptr);
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr) {
break; // do not do cleanup if process termination scenario
}
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#else
int main(int argc, char** argv) {
return start(argc, argv);
}
#endif
void HandlePacket(Packet* packet) {
if (packet->length < 1) return;
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION) {

View File

@ -0,0 +1,121 @@
#include <windows.h>
#include <iostream>
#include <string>
#include "Start.h"
#include "Logger.h"
#include "dConfig.h"
#include "Game.h"
#include "BinaryPathFinder.h"
// Function to create a process and execute a DLL
bool RunDLLAsApplication(const char* dllPath) {
STARTUPINFOA si = { sizeof(STARTUPINFOA) };
PROCESS_INFORMATION pi = { 0 };
// Path to a dummy executable
const char* dummyProcessPath = "C:\\Windows\\System32\\notepad.exe";
// Create a suspended dummy process
if (!CreateProcessA(
dummyProcessPath,
NULL,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
NULL,
&si,
&pi)) {
std::cerr << "Failed to create dummy process. Error: " << GetLastError() << std::endl;
return false;
}
// Get the address of LoadLibraryA in the current process
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
if (!kernel32) {
std::cerr << "Failed to get handle for kernel32.dll. Error: " << GetLastError() << std::endl;
TerminateProcess(pi.hProcess, 1);
return false;
}
void* loadLibraryAddr = (void*)GetProcAddress(kernel32, "LoadLibraryA");
if (!loadLibraryAddr) {
std::cerr << "Failed to get address of LoadLibraryA. Error: " << GetLastError() << std::endl;
TerminateProcess(pi.hProcess, 1);
return false;
}
// Allocate memory in the target process for the DLL path
void* remoteMemory = VirtualAllocEx(pi.hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!remoteMemory) {
std::cerr << "Failed to allocate memory in target process. Error: " << GetLastError() << std::endl;
TerminateProcess(pi.hProcess, 1);
return false;
}
// Write the DLL path into the allocated memory
if (!WriteProcessMemory(pi.hProcess, remoteMemory, dllPath, strlen(dllPath) + 1, NULL)) {
std::cerr << "Failed to write DLL path to target process. Error: " << GetLastError() << std::endl;
VirtualFreeEx(pi.hProcess, remoteMemory, 0, MEM_RELEASE);
TerminateProcess(pi.hProcess, 1);
return false;
}
// Create a remote thread in the target process to load the DLL
HANDLE remoteThread = CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddr, remoteMemory, 0, NULL);
if (!remoteThread) {
std::cerr << "Failed to create remote thread. Error: " << GetLastError() << std::endl;
VirtualFreeEx(pi.hProcess, remoteMemory, 0, MEM_RELEASE);
TerminateProcess(pi.hProcess, 1);
return false;
}
// Wait for the remote thread to complete
WaitForSingleObject(remoteThread, INFINITE);
CloseHandle(remoteThread);
// Free the allocated memory
VirtualFreeEx(pi.hProcess, remoteMemory, 0, MEM_RELEASE);
// Resume the main thread of the process
ResumeThread(pi.hThread);
// Clean up process and thread handles
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return true;
}
void StartChatServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Chat will not be restarted.");
return;
}
RunDLLAsApplication("ChatServer.dll");
}
void StartAuthServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Auth will not be restarted.");
return;
}
RunDLLAsApplication("AuthServer.dll");
}
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
RunDLLAsApplication("WorldServer.dll");
//cmd.append(std::to_string(mapID));
//cmd.append(" -port ");
//cmd.append(std::to_string(port));
//cmd.append(" -instance ");
//cmd.append(std::to_string(lastInstanceID));
//cmd.append(" -maxclients ");
//cmd.append(std::to_string(maxPlayers));
//cmd.append(" -clone ");
//cmd.append(std::to_string(cloneID));
}

View File

@ -5,7 +5,12 @@ set(DWORLDSERVER_SOURCES
add_library(dWorldServer OBJECT ${DWORLDSERVER_SOURCES})
target_link_libraries(dWorldServer PUBLIC dGameBase dCommon)
add_executable(WorldServer "WorldServer.cpp")
if (WIN32 AND LOCAL_SERVER)
add_library(WorldServer SHARED "WorldServer.cpp")
else()
add_executable(WorldServer "WorldServer.cpp")
endif()
target_include_directories(WorldServer PRIVATE "${PROJECT_SOURCE_DIR}/dChatFilter")
add_compile_definitions(WorldServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")

View File

@ -120,7 +120,8 @@ uint32_t instanceID = 0;
uint32_t g_CloneID = 0;
std::string databaseChecksum = "";
int main(int argc, char** argv) {
int start(int argc, char** argv) {
Diagnostics::SetProcessName("World");
Diagnostics::SetProcessFileName(argv[0]);
Diagnostics::Initialize();
@ -526,10 +527,50 @@ int main(int argc, char** argv) {
Metrics::AddMeasurement(MetricVariable::CPUTime, (1e6 * (1000.0 * (std::clock() - metricCPUTimeStart))) / CLOCKS_PER_SEC);
Metrics::EndMeasurement(MetricVariable::Frame);
}
FinalizeShutdown();
return EXIT_SUCCESS;
}
#ifdef LOCAL_SERVER
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
start(0, nullptr);
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr) {
break; // do not do cleanup if process termination scenario
}
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#else
int main(int argc, char** argv) {
return start(argc, argv);
}
#endif
void HandlePacketChat(Packet* packet) {
if (packet->length < 1) return;
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {

View File

@ -31,6 +31,10 @@ endif()
target_include_directories(bcrypt INTERFACE "libbcrypt/include")
target_include_directories(bcrypt PRIVATE "libbcrypt/src")
if (WIN32)
add_subdirectory(hijackkit)
endif()
# Source code for sqlite
add_subdirectory(SQLite)

2
thirdparty/hijackkit/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.vs/
out/

11
thirdparty/hijackkit/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,11 @@
cmake_minimum_required (VERSION 3.8)
project (HijackKit)
add_library(HijackKit "include/utils.h" "include/memory.h" "include/tricks.h" "source/memory.cpp" "source/utils.cpp")
target_include_directories(HijackKit PUBLIC "include/")
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET HijackKit PROPERTY CXX_STANDARD 20)
endif()
set_target_properties(HijackKit PROPERTIES LINKER_LANGUAGE CXX)

1
thirdparty/hijackkit/README.txt vendored Normal file
View File

@ -0,0 +1 @@
https://github.com/Jettford/HijackKit

18
thirdparty/hijackkit/include/memory.h vendored Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <cstdlib>
#include <functional>
namespace hijack {
namespace memory {
inline void Protect(size_t address, size_t size, std::function<void()> function);
inline void* Read(size_t address, size_t size);
inline void Patch(size_t address, size_t size, void* data);
template<class T>
inline void Patch(size_t address, T data) {
hijack::memory::Patch(address, sizeof(T), &data);
}
}
}

46
thirdparty/hijackkit/include/tricks.h vendored Normal file
View File

@ -0,0 +1,46 @@
#pragma once
#include <Windows.h>
#include <winnt.h>
#include <ntifs.h>
#include <vector>
namespace hijack {
namespace tricks {
struct ModuleInfo {
wchar_t* m_ModuleName;
size_t m_ModuleBase;
};
template<class T>
inline T* GetVFunc(void* instance, size_t index) {
return (T*)*(size_t*)((size_t)instance + index * sizeof(size_t));
}
inline std::vector<ModuleInfo> LookupDLL() {
size_t pedAddr = __readgsqword(0x60);
size_t ldrData = *(size_t*)(pedAddr + 0x18);
size_t firstEntry = *(size_t*)(ldrData + 0x10);
size_t currentEntry = firstEntry;
std::vector<ModuleInfo> modules;
while (*(DWORD*)(currentEntry + 0x60) != NULL) {
wchar_t* dllName = (wchar_t*)(currentEntry + 0x60);
size_t dllBase = *(size_t*)(currentEntry + 0x30);
ModuleInfo info;
info.m_ModuleName = dllName;
info.m_ModuleBase = dllBase;
modules.push_back(info);
currentEntry = *(size_t*)currentEntry;
}
return modules;
}
}
}

10
thirdparty/hijackkit/include/utils.h vendored Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
namespace hjiack {
namespace utils {
uintptr_t GetModuleBaseAddress(const wchar_t* moduleName);
void AllocateConsole();
}
}

28
thirdparty/hijackkit/source/memory.cpp vendored Normal file
View File

@ -0,0 +1,28 @@
#include "memory.h"
#include <Windows.h>
void hijack::memory::Protect(size_t address, size_t size, std::function<void()> function) {
DWORD oldProtect;
VirtualProtect((void*)address, size, PAGE_EXECUTE_READWRITE, &oldProtect);
function();
VirtualProtect((void*)address, size, oldProtect, &oldProtect);
}
void* hijack::memory::Read(size_t address, size_t size) {
void* returnData = malloc(size);
Protect(address, size, [&]() {
memcpy(returnData, (void*)address, size);
});
return returnData;
}
void hijack::memory::Patch(size_t address, size_t size, void* data) {
Protect(address, size, [&]() {
memcpy((void*)address, data, size);
});
}

45
thirdparty/hijackkit/source/utils.cpp vendored Normal file
View File

@ -0,0 +1,45 @@
#include "utils.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <string>
#include <cstdlib>
uintptr_t hjiack::utils::GetModuleBaseAddress(const wchar_t* moduleName) {
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, GetCurrentProcessId());
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
auto a = std::wstring((wchar_t*)modEntry.szModule);
if (!_wcsicmp(a.c_str(), moduleName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
void hjiack::utils::AllocateConsole() {
AllocConsole();
freopen_s((FILE**)__acrt_iob_func(1), "CONOUT$", "w", __acrt_iob_func(1));
freopen_s((FILE**)__acrt_iob_func(2), "CONOUT$", "w", __acrt_iob_func(2));
freopen_s((FILE**)__acrt_iob_func(0), "CONIN$", "r", __acrt_iob_func(0));
}