initial commit

This commit is contained in:
Ryuku 2020-01-24 10:46:05 +11:00
parent c735a44047
commit 89edb2948a
9 changed files with 463 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
empires/
/obj
/.vs
src/.vs
*.zip

View File

@ -1,2 +1,24 @@
# empires-assert-patcher
## Usage
* extract the latest release to your `Empires Dedicated Server` folder
* edit `run_patched_server.bat` with your favourite text editor
* make necessary changes to `SET "ARGS=-console -toconsole -insecure +map emp_arid +sv_lan 1 +maxplayers 32 -nobreakpad"`
* start `run_patched_server.bat` to patch and run the server
### original run_patched_server
```
:: DO NOT MODIFY
@ECHO OFF
SETLOCAL
:: MODIFY AS NECESSARY
SET "ARGS=-console -toconsole -insecure +map emp_arid +sv_lan 1 +maxplayers 32 -nobreakpad"
:: DO NOT MODIFY
empires\bin\empires-assert-patcher.exe
IF %ERRORLEVEL% 1 (
PAUSE
EXIT /B
)
start "" srcds.exe -game "empires" %ARGS%
```

14
run_patched_server.bat Normal file
View File

@ -0,0 +1,14 @@
:: DO NOT MODIFY
@ECHO OFF
SETLOCAL
:: MODIFY AS NECESSARY
SET "ARGS=-console -toconsole -insecure +map emp_arid +sv_lan 1 +maxplayers 32 -nobreakpad"
:: DO NOT MODIFY
empires\bin\empires-assert-patcher.exe
IF %ERRORLEVEL% 1 (
PAUSE
EXIT /B
)
start "" srcds.exe -game "empires" %ARGS%

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "empires-assert-patcher", "empires-assert-patcher.vcxproj", "{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Debug|x64.ActiveCfg = Debug|x64
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Debug|x64.Build.0 = Debug|x64
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Debug|x86.ActiveCfg = Debug|Win32
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Debug|x86.Build.0 = Debug|Win32
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Release|x64.ActiveCfg = Release|x64
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Release|x64.Build.0 = Release|x64
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Release|x86.ActiveCfg = Release|Win32
{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {34AC155B-66F3-4F18-9C85-36D2D0B870CF}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{9E17EDBC-F74F-452C-9D53-1047CB0FEBC5}</ProjectGuid>
<RootNamespace>empiresassertpatcher</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)..\empires\bin\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(Configuration)-$(Platform)\</IntDir>
<TargetName>$(ProjectName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)..\empires\bin\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(Configuration)-$(Platform)\</IntDir>
<TargetName>$(ProjectName)</TargetName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

204
src/main.cpp Normal file
View File

@ -0,0 +1,204 @@
/* empires-assert-patcher created by ryuku@ennui.software - license can be found in included LICENSE file */
#define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <Windows.h>
#include <string>
#include <filesystem>
/*
server.dll+30C90 - 68 80915917 - push server.dll+3C9180 { ("i:\git-runner\builds\e2c1ae76\0\empires_code\empires_main\mp\sr") }
server.dll+30C95 - 8B F0 - mov esi,eax
server.dll+30C97 - FF 15 ECF15817 - call dword ptr [server.dll+3BF1EC] { ->tier0.CallAssertFailedNotifyFunc }
server.dll+30C9D - 83 C4 20 - add esp,20 { 32 }
server.dll+30CA0 - 85 F6 - test esi,esi
server.dll+30CA2 - 75 20 - jne server.dll+30CC4 { patch to EB 20 }
server.dll+30CA4 - FF 15 F4F15817 - call dword ptr [server.dll+3BF1F4] { ->tier0.ShouldUseNewAssertDialog }
server.dll+30CAA - 84 C0 - test al,al
server.dll+30CAC - 74 15 - je server.dll+30CC3
server.dll+30CAE - 57 - push edi
server.dll+30CAF - 6A 1C - push 1C { 28 }
server.dll+30CB1 - 68 80915917 - push server.dll+3C9180 { ("i:\git-runner\builds\e2c1ae76\0\empires_code\empires_main\mp\sr") }
server.dll+30CB6 - FF 15 F0F15817 - call dword ptr [server.dll+3BF1F0] { ->tier0.DoNewAssertDialog }
server.dll+30CBC - 83 C4 0C - add esp,0C { 12 }
server.dll+30CBF - 84 C0 - test al,al
server.dll+30CC1 - 74 01 - je server.dll+30CC4
server.dll+30CC3 - CC - int 3
server.dll+30CC4 - 5F - pop edi
83 C4 20 85 F6 75 20 FF 15 F4 F1 58 17 84 C0 74 15
83 C4 20 85 F6 75 20 FF 15 ?? ?? ?? ?? 84 C0 74 15
*/
// comment for better performance
#define WORKING_INDICATOR
const std::wstring fileName = L"server.dll";
const char* mask = "xxxxx?xxx????xxxx";
const char* aob = "\x83\xC4\x20\x85\xF6\x75\x20\xFF\x15\xF4\xF1\x58\x17\x84\xC0\x74\x15";
const DWORD aobSize = 17;
int DoPatch(const BYTE* pMapped, const DWORD& offset)
{
*(BYTE*)(pMapped + offset + 5) = '\xEB';
wprintf(L"patched: ");
for (DWORD i = 0; i < aobSize; i++) wprintf(L"%02x ", (BYTE)*(pMapped + offset + i));
return 0;
}
int lastMatch = 0;
bool VerifyPatch(const BYTE* pMapped, const DWORD& offset, const std::vector<DWORD>& matches)
{
if (matches.size() > lastMatch)
{
if (*(BYTE*)(pMapped + matches[lastMatch] + 5) == (BYTE)'\xEB')
{
wprintf(L"existing patch found, nothing to do\n");
return true;
}
lastMatch++;
}
return false;
}
int SearchFailed(const std::vector<DWORD>& matches)
{
if (matches.size() > 0) wprintf(L"only expected a single match, patch failed\n");
else wprintf(L"patch not found, patch failed\n");
return 1;
}
namespace fs = std::filesystem;
void GetExePath(std::wstring& exePath);
int AOBSearch(const std::wstring filePath);
int main()
{
std::wstring exePath;
GetExePath(exePath);
wprintf(L"%s...", fileName.c_str());
if (!fs::exists(exePath + fileName))
{
wprintf(
L"not found\n"
"this executable needs to be in the same folder as %s", fileName.c_str()
);
return 1;
}
wprintf(L"found\n");
return AOBSearch(exePath + fileName);
}
void GetExePath(std::wstring& exePath)
{
DWORD bufSize = MAX_PATH;
wchar_t* buf = new wchar_t[bufSize];
bufSize = GetModuleFileNameW(NULL, buf, bufSize);
if (bufSize > MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
delete[] buf;
buf = new wchar_t[bufSize];
GetModuleFileNameW(NULL, buf, bufSize);
}
exePath = std::wstring(buf);
exePath = exePath.substr(0, exePath.find_last_of('\\') + 1);
delete[] buf;
}
int AOBSearch(const std::wstring filePath)
{
int exitcode = 0;
HANDLE hFile, hMapped;
DWORD dwSize = 0;
DWORD offset = 0;
BYTE* pMapped;
std::vector<DWORD> matches;
// open file to prepare for mapping
if ((hFile = CreateFileW(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
{
wprintf(L"error: failed to open %s\n", filePath.c_str());
return 1;
}
// get file size, needed to determine when EOF
dwSize = GetFileSize(hFile, NULL);
// map to memory
if ((hMapped = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 0, 0, NULL)) == NULL)
{
wprintf(L"error: failed to create file mapping\n");
goto CLOSE_FILE;
}
if ((pMapped = (BYTE*)MapViewOfFile(hMapped, FILE_MAP_ALL_ACCESS, 0, 0, 0)) == NULL)
{
wprintf(L"error: failed to map view of file\n");
goto CLOSE_MAPPED;
}
#ifndef WORKING_INDICATOR
wprintf(L"searching for aob...\n");
#endif
// iterate through BYTEs of file
for (;offset < dwSize - aobSize; offset++)
{
#ifdef WORKING_INDICATOR
static int dotCount = 0;
dotCount = dotCount == 5 ? 0 : dotCount + 1;
wprintf(L"\rsearching for aob%.*s%*s", dotCount, L".....", 5 - dotCount, L"");
fflush(stdout);
#endif
// perform BYTE compare to find aob
for (DWORD i = 0; i < aobSize; i++)
{
// if not wildcard and not matching BYTE, stop checking from this offset
if (mask[i] != '?' && (BYTE)*(pMapped + offset + i) != (BYTE)*(aob + i)) break;
// if reached expected size, found a matching aob
if (i == aobSize - 1)
{
matches.push_back(offset);
break;
}
}
// if patch has been verified, no need to continue
if (VerifyPatch(pMapped, offset, matches)) goto EXIT;
}
wprintf(L"%llu matches found\n", matches.size());
for (const auto& m : matches)
{
wprintf(L"offset: %x - ", m);
for (DWORD i = 0; i < aobSize; i++) wprintf(L"%02x ", (BYTE)*(pMapped + m + i));
wprintf(L"\n");
}
exitcode = matches.size() == 1 ? DoPatch(pMapped, matches[0]) : SearchFailed(matches);
EXIT:
UnmapViewOfFile(pMapped);
CLOSE_MAPPED:
CloseHandle(hMapped);
CLOSE_FILE:
CloseHandle(hFile);
return exitcode;
}

5
zip_release.bat Normal file
View File

@ -0,0 +1,5 @@
@ECHO OFF
SETLOCAL
IF EXIST empires-assert-patcher.zip DEL empires-assert-patcher.zip
IF EXIST empires-assert-patcher.zip EXIT /B
7z a empires-assert-patcher.zip empires/bin/empires-assert-patcher.exe run_patched_server.bat LICENSE README.md