Skip to content

Instantly share code, notes, and snippets.

@GregLando113
Last active October 18, 2016 09:38
Show Gist options
  • Save GregLando113/eed2ab3529252e68851dfd0a9101951e to your computer and use it in GitHub Desktop.
Save GregLando113/eed2ab3529252e68851dfd0a9101951e to your computer and use it in GitHub Desktop.
DLL for multi client launching Guild Wars clients. use cl.exe to compile with /O1 flag
#include <Windows.h>
#include <stdio.h>
#define GWML_NO_DATFIX 1
#define GWML_KEEP_SUSPENDED 2
#define ERROR(msg) { printf("ERROR: "##msg##"\n"); return FALSE; }
#define ASSERT(action) if(!(##action##)) ERROR( #action )
__declspec(dllexport) BOOL MCPatch(HANDLE hProcess) {
const BYTE sig_patch[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x2C, 0x01, 0x00,
0x00, 0x53, 0x56, 0x8B, 0xDA, 0x8B, 0xF1, 0x57 };
BYTE* buffer = malloc(0x49a000);
BYTE* mcpatch = NULL;
if (!ReadProcessMemory(hProcess, (void*)0x401000, buffer, 0x49a000, NULL)) {
free(buffer);
return FALSE;
}
for (DWORD i = 0; i < 0x49a000; ++i) {
if (!memcmp(buffer + i, sig_patch, sizeof(sig_patch))) {
mcpatch = (BYTE*)(0x401000 + i);
break;
}
}
free(buffer);
if (!mcpatch)
return FALSE;
printf("mcpatch = %X\n",mcpatch);
const BYTE payload[] = { 0x31, 0xC0, 0x90, 0xC3 };
if (!WriteProcessMemory(hProcess, mcpatch, payload, sizeof(payload), NULL))
ERROR("WriteProcessMemory mcpatch");
return TRUE;
}
__declspec(naked) void stub_patchdat(void)
{
__asm {
push ecx
push edx
push eax
xor edx,edx
xor eax,eax
getlen:
mov ax, word ptr ds:[ecx + edx]
cmp ax, 0
je getbackslash
add edx, 2
jmp getlen
getbackslash:
sub edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L'\\'
je checkifdat
jmp getbackslash
checkifdat:
add edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L'G'
jne exitwithoutset
add edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L'w'
jne exitwithoutset
add edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L'.'
jne exitwithoutset
add edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L'd'
jne exitwithoutset
add edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L'a'
jne exitwithoutset
add edx, 2
mov ax, word ptr ds : [ecx + edx]
cmp ax, L't'
jne exitwithoutset
jmp setpermissions
setpermissions:
pop eax
pop edx
pop ecx
mov edx, 0x80000000
mov dword ptr ss : [esp + 0x4], 3
mov dword ptr ss : [esp + 0x10], 1
jmp end
exitwithoutset:
pop eax
pop edx
pop ecx
end:
push ebp
mov ebp, esp
sub esp, 0x104
}
}
__declspec(naked) void stubend_patchdat(void) {}
#define ENCODE_REL(from,to) (uintptr_t)((uintptr_t)(##to##) - (uintptr_t)(##from##) - 5)
__declspec(dllexport) BOOL DATFix(HANDLE hProcess)
{
const BYTE sig_datfix[] = { 0x56, 0x85, 0xC0, 0x8B, 0xF2, 0x74, 0x3B };
BYTE jmpencoding[5] = { 0xE9, 0, 0, 0, 0 };
BYTE* buffer = malloc(0x49a000);
BYTE* datfix = NULL;
if (!ReadProcessMemory(hProcess, (void*)0x401000, buffer, 0x49a000, NULL)) {
free(buffer);
return FALSE;
}
for (DWORD i = 0; i < 0x49a000; ++i) {
if (!memcmp(buffer + i, sig_datfix, sizeof(sig_datfix))) {
datfix = (BYTE*)(0x401000 + i - 0xE);
break;
}
}
free(buffer);
if (!datfix)
return FALSE;
printf("datfix = %X\n",datfix);
void* asmbuffer = VirtualAllocEx(hProcess,NULL,
(uintptr_t)stubend_patchdat - (uintptr_t)stub_patchdat,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
DWORD oldprot;
ASSERT(VirtualProtect(stub_patchdat,(uintptr_t)stubend_patchdat - (uintptr_t)stub_patchdat,PAGE_EXECUTE_READWRITE,&oldprot));
ASSERT(WriteProcessMemory(hProcess, asmbuffer, (void*)stub_patchdat, (uintptr_t)stubend_patchdat - (uintptr_t)stub_patchdat + 5, NULL));
*(DWORD*)(jmpencoding + 1) = ENCODE_REL((uintptr_t)asmbuffer + ((uintptr_t)stubend_patchdat - (uintptr_t)stub_patchdat),(uintptr_t)datfix + 9);
ASSERT(WriteProcessMemory(hProcess, (void*)((uintptr_t)asmbuffer + ((uintptr_t)stubend_patchdat - (uintptr_t)stub_patchdat)), jmpencoding, sizeof(jmpencoding), NULL));
*(DWORD*)(jmpencoding + 1) = ENCODE_REL(datfix,asmbuffer);
ASSERT(WriteProcessMemory(hProcess, datfix, jmpencoding, sizeof(jmpencoding), NULL));
return TRUE;
}
__declspec(dllexport) DWORD LaunchClient(LPCWSTR path,LPCWSTR args, DWORD flags,DWORD* out_hThread)
{
WCHAR commandLine[0x100];
swprintf(commandLine, 0x100, L"\"%s\" %s", path, args);
STARTUPINFOW startinfo;
PROCESS_INFORMATION procinfo;
memset(&procinfo,0,sizeof(PROCESS_INFORMATION));
memset(&startinfo,0,sizeof(STARTUPINFO));
if(!CreateProcessW(NULL,commandLine,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&startinfo,&procinfo))
ERROR("CreateProcessW");
if(!MCPatch(procinfo.hProcess))
ERROR("MCPatch");
if((flags & GWML_NO_DATFIX) == 0)
if(!DATFix(procinfo.hProcess))
ERROR("DATFix");
if((flags & GWML_KEEP_SUSPENDED) == 0)
ResumeThread(procinfo.hThread);
else
if (out_hThread != NULL)
*out_hThread = (DWORD)procinfo.hThread;
return procinfo.dwProcessId;
}
BOOL WINAPI DllMain(HMODULE hMod,DWORD dwReason, LPVOID lpReserve) { return TRUE; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment