├── .gitattributes ├── .gitignore ├── CTemplate ├── CTemplate.vcxproj ├── CTemplate.vcxproj.filters ├── dllmain.cpp ├── framework.h ├── ijl15.cpp ├── ijl15.h ├── pch.cpp └── pch.h ├── Common ├── Common.h ├── Common.vcxproj ├── Common.vcxproj.filters ├── TSecType.h ├── ZArray.h ├── ZList.h ├── ZMap.h ├── ZRecycleable.h ├── ZRef.h ├── ZXString.h ├── commonconfig.h ├── detours.h ├── detours.lib ├── hooker.h ├── logger.h ├── memedit.h └── winhooks.h ├── GenericLauncher ├── GenericLauncher.vcxproj ├── GenericLauncher.vcxproj.filters └── main.cpp ├── MapleClientCollection.sln └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /CTemplate/CTemplate.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {d2c48f68-c2b4-41c4-a581-550603163363} 25 | CTemplate 26 | 10.0 27 | CTemplate 28 | 29 | 30 | 31 | DynamicLibrary 32 | true 33 | v142 34 | Unicode 35 | 36 | 37 | DynamicLibrary 38 | false 39 | v142 40 | true 41 | Unicode 42 | 43 | 44 | DynamicLibrary 45 | true 46 | v142 47 | Unicode 48 | 49 | 50 | DynamicLibrary 51 | false 52 | v142 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | $(SolutionDir)$(Configuration)\$(ProjectName) 77 | LEN 78 | $(SolutionDir)Common;$(LibraryPath) 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | $(SolutionDir)Common;$(LibraryPath) 86 | 87 | 88 | false 89 | 90 | 91 | 92 | Level3 93 | true 94 | WIN32;_DEBUG;CTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 95 | true 96 | Use 97 | pch.h 98 | $(SolutionDir)Common;%(AdditionalIncludeDirectories) 99 | 100 | 101 | Windows 102 | true 103 | false 104 | 105 | 106 | 107 | 108 | Level3 109 | true 110 | true 111 | true 112 | WIN32;NDEBUG;CTemplate_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 113 | true 114 | Use 115 | pch.h 116 | 117 | 118 | Windows 119 | true 120 | true 121 | true 122 | false 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | _DEBUG;CTemplate_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 130 | true 131 | Use 132 | pch.h 133 | $(SolutionDir)Common;%(AdditionalIncludeDirectories) 134 | 135 | 136 | Windows 137 | true 138 | false 139 | 140 | 141 | 142 | 143 | Level3 144 | true 145 | true 146 | true 147 | NDEBUG;CTemplate_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 148 | true 149 | Use 150 | pch.h 151 | 152 | 153 | Windows 154 | true 155 | true 156 | true 157 | false 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | Create 170 | Create 171 | Create 172 | Create 173 | 174 | 175 | 176 | 177 | {3eb29228-1f83-4dd3-b3c5-0f284fd50f39} 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /CTemplate/CTemplate.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {ee34f9f8-3892-447c-8cee-869a00197983} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Proxy 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Proxy 40 | 41 | 42 | -------------------------------------------------------------------------------- /CTemplate/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | // BE AWARE ===v 4 | // in order to reference other projects you need to add: 5 | // $(SolutionDir)Common;%(AdditionalIncludeDirectories) 6 | // to project properties -> c/c++ -> additional include directories 7 | #include "memedit.h" 8 | #include "hooker.h" 9 | #include "Common.h" 10 | #include "winhooks.h" 11 | 12 | // BE AWARE ===v 13 | // in order to fix the detours.lib link error you need to replace 14 | // project properties -> vc++ directories -> library directories 15 | // with $(SolutionDir)Common;$(LibraryPath) 16 | 17 | /// ================ \\\ 18 | 19 | // executed after the client is unpacked 20 | VOID MainFunc() 21 | { 22 | Log(__FUNCTION__); 23 | 24 | // paste all your edits in here 25 | } 26 | 27 | // prolly don't edit this region if youre a noob 28 | #pragma region EntryThread 29 | 30 | // windows hooks are stored in here -> no need to mess with this normally 31 | static Common* CommonHooks; 32 | 33 | // main thread 34 | VOID MainProc() 35 | { 36 | Log(__FUNCTION__); 37 | 38 | if (MAPLE_INSTAJECT) 39 | { 40 | MainFunc(); 41 | } 42 | else 43 | { 44 | CommonHooks = new Common( 45 | TRUE, // true if you want to hook windows libraries (besides mutex) 46 | // set this to false if you already edited your IP into the client (eg v83 localhosts) 47 | &MainFunc, // function to be executed after client is unpacked 48 | "127.0.0.1", // IP to connec to (your server IP) 49 | "127.0.0.1"); // IP to redirect from (nexon IP) 50 | } 51 | } 52 | 53 | // dll entry point 54 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 55 | { 56 | switch (ul_reason_for_call) 57 | { 58 | case DLL_PROCESS_ATTACH: 59 | { 60 | Log("DLL_PROCESS_ATTACH"); 61 | 62 | DisableThreadLibraryCalls(hModule); 63 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&MainProc, NULL, 0, 0); 64 | break; 65 | } 66 | case DLL_PROCESS_DETACH: 67 | { 68 | Log("DLL_PROCESS_DETACH"); 69 | CommonHooks->~Common(); 70 | break; 71 | } 72 | } 73 | return TRUE; 74 | } 75 | 76 | #pragma endregion -------------------------------------------------------------------------------- /CTemplate/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | // Windows Header Files 5 | #include 6 | -------------------------------------------------------------------------------- /CTemplate/ijl15.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef MAPLE_INJECT_USE_IJL 4 | 5 | #include "ijl15.h" 6 | 7 | #define LIB_NAME "ijl15.dll.bak" 8 | #define LIB_EXPORT extern "C" __declspec(dllexport) 9 | 10 | DWORD ijlErrorStr_Proc; 11 | DWORD ijlFree_Proc; 12 | DWORD ijlGetLibVersion_Proc; 13 | DWORD ijlInit_Proc; 14 | DWORD ijlRead_Proc; 15 | DWORD ijlWrite_Proc; 16 | 17 | BOOL InitializeIjl15() 18 | { 19 | DWORD dw; 20 | HANDLE hOrg = CreateFileA(LIB_NAME, (GENERIC_READ | GENERIC_WRITE), NULL, NULL, CREATE_ALWAYS, NULL, NULL); 21 | 22 | if (hOrg) 23 | { 24 | WriteFile(hOrg, g_Ijl15_Raw, sizeof(g_Ijl15_Raw), &dw, NULL); 25 | CloseHandle(hOrg); 26 | } 27 | else 28 | { 29 | OutputDebugStringA("ijl15: Unable to write " LIB_NAME " to disk"); 30 | } 31 | 32 | HMODULE SeData_Base = LoadLibraryA(LIB_NAME); 33 | 34 | if (SeData_Base) 35 | { 36 | ijlErrorStr_Proc = (DWORD)GetProcAddress(SeData_Base, "ijlErrorStr"); 37 | ijlFree_Proc = (DWORD)GetProcAddress(SeData_Base, "ijlFree"); 38 | ijlGetLibVersion_Proc = (DWORD)GetProcAddress(SeData_Base, "ijlGetLibVersion"); 39 | ijlInit_Proc = (DWORD)GetProcAddress(SeData_Base, "ijlInit"); 40 | ijlRead_Proc = (DWORD)GetProcAddress(SeData_Base, "ijlRead"); 41 | ijlWrite_Proc = (DWORD)GetProcAddress(SeData_Base, "ijlWrite"); 42 | 43 | return TRUE; 44 | } 45 | 46 | return FALSE; 47 | } 48 | 49 | BOOL g_InitIjl15 = InitializeIjl15(); //This is the static initializer !!! 50 | 51 | LIB_EXPORT void ijlGetLibVersion() 52 | { 53 | __asm jmp dword ptr[ijlGetLibVersion_Proc] 54 | } 55 | 56 | LIB_EXPORT void ijlInit() 57 | { 58 | __asm jmp dword ptr[ijlInit_Proc] 59 | } 60 | 61 | LIB_EXPORT void ijlFree() 62 | { 63 | __asm jmp dword ptr[ijlFree_Proc] 64 | } 65 | 66 | LIB_EXPORT void ijlRead() 67 | { 68 | __asm jmp dword ptr[ijlRead_Proc] 69 | } 70 | 71 | LIB_EXPORT void ijlWrite() 72 | { 73 | __asm jmp dword ptr[ijlWrite_Proc] 74 | } 75 | 76 | LIB_EXPORT void ijlErrorStr() 77 | { 78 | __asm jmp dword ptr[ijlErrorStr_Proc] 79 | } 80 | 81 | #endif -------------------------------------------------------------------------------- /CTemplate/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /CTemplate/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | #include "commonconfig.h" 13 | 14 | #pragma comment(lib, "detours.lib") 15 | 16 | #endif //PCH_H 17 | -------------------------------------------------------------------------------- /Common/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "hooker.h" 4 | #include "logger.h" 5 | #include "winhooks.h" 6 | 7 | struct Common 8 | { 9 | public: 10 | Common(BOOL bHookWinLibs, PostMutexFunc_t pMutexFunc, const char* sIP, const char* sOriginalIP) 11 | { 12 | Log("Common created => Hook winsock libs: %s || IP: %s || Original IP: %s", (bHookWinLibs ? "Yes" : "No"), sIP, sOriginalIP); 13 | 14 | if (!pMutexFunc) 15 | { 16 | Log("Invalid function pointer passed to Common constructor."); 17 | return; 18 | } 19 | 20 | // set pointer to function that is executed after client unpacks itself 21 | g_PostMutexFunc = pMutexFunc; 22 | 23 | // required for proper injection 24 | INITWINHOOK("KERNEL32", "CreateMutexA", CreateMutexA_Original, CreateMutexA_t, CreateMutexA_Hook); 25 | 26 | if (MAPLETRACKING_OPEN_PROC) 27 | { 28 | INITWINHOOK("KERNEL32", "OpenProcess", OpenProcess_Original, OpenProcess_t, OpenProcess_Hook); 29 | } 30 | if (MAPLETRACKING_CREATE_PROCW) 31 | { 32 | INITWINHOOK("KERNEL32", "CreateProcessW", CreateProcessW_Original, CreateProcessW_t, CreateProcessW_Hook); 33 | } 34 | if (MAPLETRACKING_OPEN_MUTEXA) 35 | { 36 | INITWINHOOK("KERNEL32", "OpenMutexA", OpenMutexA_Original, OpenMutexA_t, OpenMutexA_Hook); 37 | } 38 | if (MAPLETRACKING_NT_TERMINATE_PROC) 39 | { 40 | INITWINHOOK("NTDLL", "NtTerminateProcess", NtTerminateProcess_Original, NtTerminateProcess_t, NtTerminateProcess_Hook); 41 | } 42 | if (MAPLE_LOCALE_SPOOF) 43 | { 44 | INITWINHOOK("KERNEL32", "GetACP", GetACP_Original, GetACP_t, GetACP_Hook); 45 | } 46 | if (MAPLE_PATCHER_CLASS) 47 | { 48 | INITWINHOOK("USER32", "CreateWindowExA", CreateWindowExA_Original, CreateWindowExA_t, CreateWindowExA_Hook) 49 | } 50 | 51 | INITWINHOOK("KERNEL32", "RegCreateKeyExA", RegCreateKeyExA_Original, RegCreateKeyExA_t, RegCreateKeyExA_Hook); 52 | 53 | if (!bHookWinLibs) return; 54 | 55 | if (!sIP || !sOriginalIP) 56 | { 57 | Log("Null IP string passed to Common constructor."); 58 | return; 59 | } 60 | 61 | g_sRedirectIP = sIP; 62 | sOriginalIP = sOriginalIP; 63 | 64 | // macro outputs error if hook fails 65 | INITWINHOOK("MSWSOCK", "WSPStartup", WSPStartup_Original, WSPStartup_t, WSPStartup_Hook); 66 | } 67 | 68 | ~Common() 69 | { 70 | Log("Cleaning up common.."); 71 | 72 | if (g_GameSock != INVALID_SOCKET) 73 | { 74 | Log("Closing socket.."); 75 | 76 | g_ProcTable.lpWSPCloseSocket(g_GameSock, NULL); 77 | g_GameSock = INVALID_SOCKET; 78 | } 79 | } 80 | }; 81 | 82 | -------------------------------------------------------------------------------- /Common/Common.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {3eb29228-1f83-4dd3-b3c5-0f284fd50f39} 25 | Common 26 | 10.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) 76 | 77 | 78 | false 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | 88 | Level3 89 | true 90 | WIN32;_DEBUG;COMMON_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 91 | true 92 | NotUsing 93 | pch.h 94 | 95 | 96 | Windows 97 | true 98 | false 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | true 106 | true 107 | WIN32;NDEBUG;COMMON_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 108 | true 109 | Use 110 | pch.h 111 | 112 | 113 | Windows 114 | true 115 | true 116 | true 117 | false 118 | 119 | 120 | 121 | 122 | Level3 123 | true 124 | _DEBUG;COMMON_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 125 | true 126 | Use 127 | pch.h 128 | 129 | 130 | Windows 131 | true 132 | false 133 | 134 | 135 | 136 | 137 | Level3 138 | true 139 | true 140 | true 141 | NDEBUG;COMMON_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 142 | true 143 | Use 144 | pch.h 145 | 146 | 147 | Windows 148 | true 149 | true 150 | true 151 | false 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /Common/Common.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8694bb41-e655-4ee5-8d0d-df08d5e043f4} 18 | 19 | 20 | {99fc11fd-c7ce-4ed7-9985-42a80e654ac2} 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files\MapleTypes 38 | 39 | 40 | Header Files\MapleTypes 41 | 42 | 43 | Header Files\MapleTypes 44 | 45 | 46 | Header Files\MapleTypes 47 | 48 | 49 | Header Files\MapleTypes 50 | 51 | 52 | Header Files\MapleTypes 53 | 54 | 55 | Header Files\MapleTypes 56 | 57 | 58 | Header Files\Tools 59 | 60 | 61 | Header Files\Tools 62 | 63 | 64 | Header Files 65 | 66 | 67 | 68 | 69 | Resource Files 70 | 71 | 72 | -------------------------------------------------------------------------------- /Common/TSecType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // thanks raj 5 | 6 | template 7 | struct TSecData 8 | { 9 | T data; 10 | unsigned char bKey; 11 | unsigned char FakePtr1; 12 | unsigned char FakePtr2; 13 | unsigned short wChecksum; 14 | }; 15 | 16 | template 17 | class TSecType 18 | { 19 | public: 20 | TSecType() 21 | { 22 | this->m_secdata = reinterpret_cast*>(malloc(12)); 23 | 24 | this->FakePtr1 = static_cast(reinterpret_cast(&this[-0x00003FF8]) + rand()); 25 | this->FakePtr2 = static_cast(reinterpret_cast(&this[-0x00003FF8]) + rand()); 26 | 27 | this->m_secdata->FakePtr1 = static_cast(LOBYTE(this->FakePtr1)); 28 | this->m_secdata->FakePtr2 = static_cast(LOBYTE(this->FakePtr2)); 29 | 30 | this->SetData(0); 31 | } 32 | 33 | ~TSecType() 34 | { 35 | if (this->m_secdata) 36 | { 37 | free(this->m_secdata); 38 | this->m_secdata = nullptr; 39 | } 40 | } 41 | 42 | T GetData() 43 | { 44 | T decrypted_data = 0; 45 | unsigned short checksum = 0; 46 | 47 | for (unsigned char i = 0, key = 0; i < (sizeof(T) + 1); i++) 48 | { 49 | key = (i == 0 ? this->m_secdata->bKey : reinterpret_cast(&this->m_secdata->data)[i - 1] + key + 42); 50 | 51 | if (i > 0) 52 | { 53 | checksum = (i > 1 ? ((8 * checksum) | (key + (checksum >> 13))) : ((key + 4) | 0xD328)); 54 | } 55 | 56 | if (i < sizeof(T)) 57 | { 58 | if (!key) 59 | { 60 | key = 42; 61 | } 62 | 63 | reinterpret_cast(&decrypted_data)[i] = reinterpret_cast(&this->m_secdata->data)[i] ^ key; 64 | } 65 | } 66 | 67 | if (this->m_secdata->wChecksum != checksum || LOBYTE(this->FakePtr1) != this->m_secdata->FakePtr1 || LOBYTE(this->FakePtr2) != this->m_secdata->FakePtr2) 68 | { 69 | return 0; //TODO: CxxThrow 70 | } 71 | 72 | return decrypted_data; 73 | } 74 | 75 | void SetData(T data) 76 | { 77 | this->m_secdata->bKey = static_cast(rand()); 78 | this->m_secdata->wChecksum = static_cast(39525); 79 | 80 | for (unsigned char i = 0, key = 0; i < (sizeof(T) + 1); i++) 81 | { 82 | key = (i == 0 ? this->m_secdata->bKey : (key ^ reinterpret_cast(&data)[i - 1]) + key + 42); 83 | 84 | if (i > 0) 85 | { 86 | this->m_secdata->wChecksum = ((8 * this->m_secdata->wChecksum) | (key + (this->m_secdata->wChecksum >> 13))); 87 | } 88 | 89 | if (i < sizeof(T)) 90 | { 91 | if (!key) 92 | { 93 | key = 42; 94 | } 95 | 96 | reinterpret_cast(&this->m_secdata->data)[i] = reinterpret_cast(&data)[i] ^ key; 97 | } 98 | } 99 | } 100 | 101 | private: 102 | unsigned int FakePtr1; 103 | unsigned int FakePtr2; 104 | TSecData* m_secdata; 105 | }; 106 | 107 | struct SECPOINT 108 | { 109 | TSecType y; 110 | TSecType x; 111 | 112 | operator POINT() 113 | { 114 | return { this->x.GetData(), this->y.GetData() }; 115 | } 116 | }; 117 | 118 | struct SECRECT 119 | { 120 | int _ZtlSecureTear_left[2]; 121 | unsigned int _ZtlSecureTear_left_CS; 122 | int _ZtlSecureTear_top[2]; 123 | unsigned int _ZtlSecureTear_top_CS; 124 | int _ZtlSecureTear_right[2]; 125 | unsigned int _ZtlSecureTear_right_CS; 126 | int _ZtlSecureTear_bottom[2]; 127 | unsigned int _ZtlSecureTear_bottom_CS; 128 | }; -------------------------------------------------------------------------------- /Common/ZArray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct ZArray 5 | { 6 | T* a; 7 | }; -------------------------------------------------------------------------------- /Common/ZList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct ZListDataVtbl 4 | { 5 | void* (__thiscall* __vecDelDtor)(unsigned int); 6 | }; 7 | 8 | template 9 | struct ZListData 10 | { 11 | ZListDataVtbl* vfptr; 12 | ZListData* pNext; 13 | ZListData* pPrev; 14 | char aPad[4]; 15 | T data; 16 | }; 17 | 18 | template 19 | class ZList 20 | { 21 | private: 22 | void* vfptr; 23 | void* padding; 24 | 25 | public: 26 | unsigned int m_uCount; 27 | T* m_pHead; 28 | T* m_pTail; 29 | 30 | ZList() 31 | { 32 | vfptr = 0; 33 | padding = 0; 34 | 35 | m_uCount = 0; 36 | m_pHead = 0; 37 | m_pTail = 0; 38 | } 39 | 40 | T* GetNext(T** ppPosition) 41 | { 42 | T* pResult = *ppPosition; 43 | 44 | ZListData* pData = reinterpret_cast*>(reinterpret_cast(pResult) - 16); 45 | 46 | if (pData->pNext) 47 | *ppPosition = &pData->pNext->data; 48 | else 49 | *ppPosition = nullptr; 50 | 51 | return pResult; 52 | } 53 | 54 | void RemoveAll() 55 | { 56 | auto pPosition = this->m_pHead; 57 | 58 | while (pPosition) 59 | { 60 | T* pItem = this->GetNext(&pPosition); 61 | 62 | ZListData* pData = reinterpret_cast*>(reinterpret_cast(pItem) - 16); 63 | 64 | pData->vfptr->__vecDelDtor(1); 65 | 66 | } 67 | 68 | this->m_pTail = 0; 69 | this->m_pHead = 0; 70 | this->m_uCount = 0; 71 | } 72 | }; -------------------------------------------------------------------------------- /Common/ZMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ZRecycleable.h" 3 | 4 | template 5 | class ZMap 6 | { 7 | public: 8 | struct _PAIR : ZRecyclable::_PAIR, int, ZMap::_PAIR> 9 | { 10 | private: 11 | char aPad[0x4]; // vfptr 12 | public: 13 | ZMap::_PAIR* pNext; 14 | T key; 15 | U value; 16 | }; 17 | 18 | private: 19 | char aPad[0x4]; 20 | 21 | public: 22 | //ZMapVtbl* vfptr; 23 | ZMap::_PAIR** _m_apTable; 24 | unsigned int _m_uTableSize; 25 | unsigned int _m_uCount; 26 | unsigned int _m_uAutoGrowEvery128; 27 | unsigned int _m_uAutoGrowLimit; 28 | 29 | U* GetAt(const T* key) 30 | { 31 | ZMap::_PAIR** v3; // esi 32 | ZMap::_PAIR* v5; // esi 33 | 34 | v3 = this->_m_apTable; 35 | 36 | if (!v3) return 0; 37 | 38 | v5 = v3[_rotr(*key, 5) % this->_m_uTableSize]; 39 | 40 | if (!v5) return 0; 41 | 42 | while (v5->key != *key) 43 | { 44 | v5 = v5->pNext; 45 | 46 | if (!v5) return 0; 47 | } 48 | 49 | // we are gonna skip the copying for now 50 | //if (value) ZRef::operator=(value, &v5->value); 51 | 52 | return &v5->value; 53 | } 54 | }; -------------------------------------------------------------------------------- /Common/ZRecycleable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "logger.h" 3 | 4 | template 5 | class ZRecyclable 6 | { 7 | private: 8 | char aPad[0x4]; 9 | }; 10 | 11 | assert_size(sizeof(ZRecyclable), 0x4); -------------------------------------------------------------------------------- /Common/ZRef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ZRecycleable.h" 3 | 4 | template 5 | struct ZRef 6 | { 7 | private: 8 | char aPad[4]; 9 | public: 10 | T* p; 11 | }; 12 | 13 | class ZRefCounted 14 | { 15 | public: 16 | 17 | ZRefCounted() 18 | { 19 | this->m_nRef = 0; 20 | this->m_pPrev = 0; 21 | } 22 | 23 | virtual ~ZRefCounted() 24 | { 25 | //TODO: ? 26 | } 27 | 28 | union 29 | { 30 | long m_nRef; 31 | ZRefCounted* m_pNext; 32 | }; 33 | 34 | ZRefCounted* m_pPrev; 35 | }; 36 | 37 | template 38 | class ZRefCountedDummy : public ZRefCounted, public ZRecyclable, int, T> 39 | { 40 | public: 41 | T pData; 42 | }; 43 | 44 | assert_size(sizeof(ZRef), 0x08); 45 | assert_size(sizeof(ZRefCounted), 0x0C); 46 | assert_size(sizeof(ZRefCountedDummy), 0x14); -------------------------------------------------------------------------------- /Common/ZXString.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "logger.h" 3 | 4 | // good reference: https://en.cppreference.com/w/cpp/language/operators 5 | 6 | template 7 | struct ZXString 8 | { 9 | T* m_pStr; 10 | 11 | ZXString() 12 | { 13 | m_pStr = 0; 14 | } 15 | ZXString(T* val) 16 | { 17 | m_pStr = &val; 18 | } 19 | }; 20 | 21 | assert_size(sizeof(ZXString), 0x04) -------------------------------------------------------------------------------- /Common/commonconfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | global settings config file 5 | try not to add version-specific settings in here 6 | */ 7 | 8 | #define MAPLE_INJECT_USE_IJL // comment this line out to use other injection methods (not ijl15 trojan) 9 | #define MAPLE_INJECT_DLLNAME "LEN.dll" // name of dll to inject if above line is commented out 10 | #define MAPLE_EXE_NAME "MapleStory.exe" // name of executable to start 11 | #define MAPLE_STARTUP_ARGS " GameLaunching 127.0.0.1 8484" // maple exe arguments to use on startup (usually needs a space first) 12 | #define MAPLE_UNSUSPEND TRUE // false to stay suspended after exe is started and dll is injected (normally should be true) 13 | 14 | // GameLaunching 127.0.0.1 15 | 16 | #define MAPLE_INSTAJECT FALSE // if true dll will immediately edit memory after injecting (when target exe is unvirtualized) 17 | #define MAPLE_FORCE_WINDOWED TRUE // force windowed login screen 18 | #define MAPLE_WINDOW_CLASS "MapleStoryClass" // maple window class name -- don't need to change in most cases -- used to force minimized startup window 19 | #define MAPLE_PATCHER_CLASS "StartUpDlgClass" // name of patcher dialog window to skip -- set to null if none or don't want to skip 20 | #define MAPLE_MUTEX "WvsClientMtx" // name of client mutex -- this is usually WvsClientMtx but might be different in higher versions 21 | #define MAPLE_LOCALE_SPOOF 874 // region/locale ID to spoof -- set to 0 to skip spoofing locale 22 | 23 | // below are used for debug logging 24 | #define MAPLETRACKING_WSPCONN_PRINT FALSE // print all wspconnect requests -- useful for finding maple IPs 25 | #define MAPLETRACKING_NT_TERMINATE_PROC TRUE // hook and log NtTerminateProc 26 | #define MAPLETRACKING_OPEN_PROC TRUE // hook and log OpenProcess 27 | #define MAPLETRACKING_CREATE_PROCW TRUE // hook and log CreateProcessW 28 | #define MAPLETRACKING_OPEN_MUTEXA TRUE // hook, log, and spoof OpenMutexA 29 | #define MAPLETRACKING_SLEEP_ON_MUTEX 0 // number of seconds to sleep when mutex is triggered (0 for nothing) -------------------------------------------------------------------------------- /Common/detours.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Core Detours Functionality (detours.h of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 2.1. 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #pragma once 11 | #include 12 | 13 | #ifndef _DETOURS_H_ 14 | #define _DETOURS_H_ 15 | 16 | #define DETOURS_VERSION 20100 // 2.1.0 17 | 18 | ////////////////////////////////////////////////////////////////////////////// 19 | // 20 | 21 | #if (_MSC_VER < 1299) 22 | typedef LONG LONG_PTR; 23 | typedef ULONG ULONG_PTR; 24 | #endif 25 | 26 | #ifndef __in_z 27 | #define __in_z 28 | #endif 29 | 30 | ////////////////////////////////////////////////////////////////////////////// 31 | // 32 | #ifndef GUID_DEFINED 33 | #define GUID_DEFINED 34 | typedef struct _GUID 35 | { 36 | DWORD Data1; 37 | WORD Data2; 38 | WORD Data3; 39 | BYTE Data4[8]; 40 | } GUID; 41 | 42 | #ifdef INITGUID 43 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 44 | const GUID name \ 45 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 46 | #else 47 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 48 | const GUID name 49 | #endif // INITGUID 50 | #endif // !GUID_DEFINED 51 | 52 | #if defined(__cplusplus) 53 | #ifndef _REFGUID_DEFINED 54 | #define _REFGUID_DEFINED 55 | #define REFGUID const GUID & 56 | #endif // !_REFGUID_DEFINED 57 | #else // !__cplusplus 58 | #ifndef _REFGUID_DEFINED 59 | #define _REFGUID_DEFINED 60 | #define REFGUID const GUID * const 61 | #endif // !_REFGUID_DEFINED 62 | #endif // !__cplusplus 63 | 64 | // 65 | ////////////////////////////////////////////////////////////////////////////// 66 | 67 | #ifdef __cplusplus 68 | extern "C" { 69 | #endif // __cplusplus 70 | 71 | /////////////////////////////////////////////////// Instruction Target Macros. 72 | // 73 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) 74 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 75 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 76 | 77 | extern const GUID DETOUR_EXE_RESTORE_GUID; 78 | 79 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 80 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, * PDETOUR_TRAMPOLINE; 81 | 82 | /////////////////////////////////////////////////////////// Binary Structures. 83 | // 84 | #pragma pack(push, 8) 85 | typedef struct _DETOUR_SECTION_HEADER 86 | { 87 | DWORD cbHeaderSize; 88 | DWORD nSignature; 89 | DWORD nDataOffset; 90 | DWORD cbDataSize; 91 | 92 | DWORD nOriginalImportVirtualAddress; 93 | DWORD nOriginalImportSize; 94 | DWORD nOriginalBoundImportVirtualAddress; 95 | DWORD nOriginalBoundImportSize; 96 | 97 | DWORD nOriginalIatVirtualAddress; 98 | DWORD nOriginalIatSize; 99 | DWORD nOriginalSizeOfImage; 100 | DWORD cbPrePE; 101 | 102 | DWORD nOriginalClrFlags; 103 | DWORD reserved1; 104 | DWORD reserved2; 105 | DWORD reserved3; 106 | 107 | // Followed by cbPrePE bytes of data. 108 | } DETOUR_SECTION_HEADER, * PDETOUR_SECTION_HEADER; 109 | 110 | typedef struct _DETOUR_SECTION_RECORD 111 | { 112 | DWORD cbBytes; 113 | DWORD nReserved; 114 | GUID guid; 115 | } DETOUR_SECTION_RECORD, * PDETOUR_SECTION_RECORD; 116 | 117 | typedef struct _DETOUR_CLR_HEADER 118 | { 119 | // Header versioning 120 | ULONG cb; 121 | USHORT MajorRuntimeVersion; 122 | USHORT MinorRuntimeVersion; 123 | 124 | // Symbol table and startup information 125 | IMAGE_DATA_DIRECTORY MetaData; 126 | ULONG Flags; 127 | 128 | // Followed by the rest of the header. 129 | } DETOUR_CLR_HEADER, * PDETOUR_CLR_HEADER; 130 | 131 | typedef struct _DETOUR_EXE_RESTORE 132 | { 133 | ULONG cb; 134 | 135 | PIMAGE_DOS_HEADER pidh; 136 | PIMAGE_NT_HEADERS pinh; 137 | PULONG pclrFlags; 138 | DWORD impDirProt; 139 | 140 | IMAGE_DOS_HEADER idh; 141 | IMAGE_NT_HEADERS inh; 142 | ULONG clrFlags; 143 | } DETOUR_EXE_RESTORE, * PDETOUR_EXE_RESTORE; 144 | 145 | #pragma pack(pop) 146 | 147 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ 148 | { \ 149 | sizeof(DETOUR_SECTION_HEADER),\ 150 | DETOUR_SECTION_HEADER_SIGNATURE,\ 151 | sizeof(DETOUR_SECTION_HEADER),\ 152 | (cbSectionSize),\ 153 | \ 154 | 0,\ 155 | 0,\ 156 | 0,\ 157 | 0,\ 158 | \ 159 | 0,\ 160 | 0,\ 161 | 0,\ 162 | 0,\ 163 | } 164 | 165 | ///////////////////////////////////////////////////////////// Binary Typedefs. 166 | // 167 | typedef BOOL(CALLBACK* PF_DETOUR_BINARY_BYWAY_CALLBACK)(PVOID pContext, 168 | PCHAR pszFile, 169 | PCHAR* ppszOutFile); 170 | 171 | typedef BOOL(CALLBACK* PF_DETOUR_BINARY_FILE_CALLBACK)(PVOID pContext, 172 | PCHAR pszOrigFile, 173 | PCHAR pszFile, 174 | PCHAR* ppszOutFile); 175 | 176 | typedef BOOL(CALLBACK* PF_DETOUR_BINARY_SYMBOL_CALLBACK)(PVOID pContext, 177 | ULONG nOrigOrdinal, 178 | ULONG nOrdinal, 179 | ULONG* pnOutOrdinal, 180 | PCHAR pszOrigSymbol, 181 | PCHAR pszSymbol, 182 | PCHAR* ppszOutSymbol); 183 | 184 | typedef BOOL(CALLBACK* PF_DETOUR_BINARY_COMMIT_CALLBACK)(PVOID pContext); 185 | 186 | typedef BOOL(CALLBACK* PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(PVOID pContext, 187 | ULONG nOrdinal, 188 | PCHAR pszName, 189 | PVOID pCode); 190 | 191 | typedef VOID* PDETOUR_BINARY; 192 | typedef VOID* PDETOUR_LOADED_BINARY; 193 | 194 | //////////////////////////////////////////////////////////// Detours 2.1 APIs. 195 | // 196 | 197 | LONG WINAPI DetourTransactionBegin(); 198 | LONG WINAPI DetourTransactionAbort(); 199 | LONG WINAPI DetourTransactionCommit(); 200 | LONG WINAPI DetourTransactionCommitEx(PVOID** pppFailedPointer); 201 | 202 | LONG WINAPI DetourUpdateThread(HANDLE hThread); 203 | 204 | LONG WINAPI DetourAttach(PVOID* ppPointer, 205 | PVOID pDetour); 206 | 207 | LONG WINAPI DetourAttachEx(PVOID* ppPointer, 208 | PVOID pDetour, 209 | PDETOUR_TRAMPOLINE* ppRealTrampoline, 210 | PVOID* ppRealTarget, 211 | PVOID* ppRealDetour); 212 | 213 | LONG WINAPI DetourDetach(PVOID* ppPointer, 214 | PVOID pDetour); 215 | 216 | VOID WINAPI DetourSetIgnoreTooSmall(BOOL fIgnore); 217 | 218 | ////////////////////////////////////////////////////////////// Code Functions. 219 | // 220 | PVOID WINAPI DetourFindFunction(PCSTR pszModule, PCSTR pszFunction); 221 | PVOID WINAPI DetourCodeFromPointer(PVOID pPointer, PVOID* ppGlobals); 222 | 223 | PVOID WINAPI DetourCopyInstruction(PVOID pDst, PVOID pSrc, PVOID* ppTarget); 224 | PVOID WINAPI DetourCopyInstructionEx(PVOID pDst, 225 | PVOID pSrc, 226 | PVOID* ppTarget, 227 | LONG* plExtra); 228 | 229 | ///////////////////////////////////////////////////// Loaded Binary Functions. 230 | // 231 | HMODULE WINAPI DetourEnumerateModules(HMODULE hModuleLast); 232 | PVOID WINAPI DetourGetEntryPoint(HMODULE hModule); 233 | ULONG WINAPI DetourGetModuleSize(HMODULE hModule); 234 | BOOL WINAPI DetourEnumerateExports(HMODULE hModule, 235 | PVOID pContext, 236 | PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); 237 | 238 | PVOID WINAPI DetourFindPayload(HMODULE hModule, REFGUID rguid, DWORD* pcbData); 239 | DWORD WINAPI DetourGetSizeOfPayloads(HMODULE hModule); 240 | 241 | ///////////////////////////////////////////////// Persistent Binary Functions. 242 | // 243 | 244 | PDETOUR_BINARY WINAPI DetourBinaryOpen(HANDLE hFile); 245 | PVOID WINAPI DetourBinaryEnumeratePayloads(PDETOUR_BINARY pBinary, 246 | GUID* pGuid, 247 | DWORD* pcbData, 248 | DWORD* pnIterator); 249 | PVOID WINAPI DetourBinaryFindPayload(PDETOUR_BINARY pBinary, 250 | REFGUID rguid, 251 | DWORD* pcbData); 252 | PVOID WINAPI DetourBinarySetPayload(PDETOUR_BINARY pBinary, 253 | REFGUID rguid, 254 | PVOID pData, 255 | DWORD cbData); 256 | BOOL WINAPI DetourBinaryDeletePayload(PDETOUR_BINARY pBinary, REFGUID rguid); 257 | BOOL WINAPI DetourBinaryPurgePayloads(PDETOUR_BINARY pBinary); 258 | BOOL WINAPI DetourBinaryResetImports(PDETOUR_BINARY pBinary); 259 | BOOL WINAPI DetourBinaryEditImports(PDETOUR_BINARY pBinary, 260 | PVOID pContext, 261 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 262 | PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 263 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 264 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); 265 | BOOL WINAPI DetourBinaryWrite(PDETOUR_BINARY pBinary, HANDLE hFile); 266 | BOOL WINAPI DetourBinaryClose(PDETOUR_BINARY pBinary); 267 | 268 | /////////////////////////////////////////////////// Create Process & Load Dll. 269 | // 270 | typedef BOOL(WINAPI* PDETOUR_CREATE_PROCESS_ROUTINEA) 271 | (LPCSTR lpApplicationName, 272 | LPSTR lpCommandLine, 273 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 274 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 275 | BOOL bInheritHandles, 276 | DWORD dwCreationFlags, 277 | LPVOID lpEnvironment, 278 | LPCSTR lpCurrentDirectory, 279 | LPSTARTUPINFOA lpStartupInfo, 280 | LPPROCESS_INFORMATION lpProcessInformation); 281 | 282 | typedef BOOL(WINAPI* PDETOUR_CREATE_PROCESS_ROUTINEW) 283 | (LPCWSTR lpApplicationName, 284 | LPWSTR lpCommandLine, 285 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 286 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 287 | BOOL bInheritHandles, 288 | DWORD dwCreationFlags, 289 | LPVOID lpEnvironment, 290 | LPCWSTR lpCurrentDirectory, 291 | LPSTARTUPINFOW lpStartupInfo, 292 | LPPROCESS_INFORMATION lpProcessInformation); 293 | 294 | BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName, 295 | __in_z LPSTR lpCommandLine, 296 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 297 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 298 | BOOL bInheritHandles, 299 | DWORD dwCreationFlags, 300 | LPVOID lpEnvironment, 301 | LPCSTR lpCurrentDirectory, 302 | LPSTARTUPINFOA lpStartupInfo, 303 | LPPROCESS_INFORMATION lpProcessInformation, 304 | LPCSTR lpDetouredDllFullName, 305 | LPCSTR lpDllName, 306 | PDETOUR_CREATE_PROCESS_ROUTINEA 307 | pfCreateProcessA); 308 | 309 | BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName, 310 | __in_z LPWSTR lpCommandLine, 311 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 312 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 313 | BOOL bInheritHandles, 314 | DWORD dwCreationFlags, 315 | LPVOID lpEnvironment, 316 | LPCWSTR lpCurrentDirectory, 317 | LPSTARTUPINFOW lpStartupInfo, 318 | LPPROCESS_INFORMATION lpProcessInformation, 319 | LPCSTR lpDetouredDllFullName, 320 | LPCSTR lpDllName, 321 | PDETOUR_CREATE_PROCESS_ROUTINEW 322 | pfCreateProcessW); 323 | 324 | #ifdef UNICODE 325 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW 326 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 327 | #else 328 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA 329 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 330 | #endif // !UNICODE 331 | 332 | BOOL WINAPI DetourCopyPayloadToProcess(HANDLE hProcess, 333 | REFGUID rguid, 334 | PVOID pvData, 335 | DWORD cbData); 336 | BOOL WINAPI DetourRestoreAfterWith(); 337 | BOOL WINAPI DetourRestoreAfterWithEx(PVOID pvData, DWORD cbData); 338 | 339 | // 340 | ////////////////////////////////////////////////////////////////////////////// 341 | #ifdef __cplusplus 342 | } 343 | #endif // __cplusplus 344 | 345 | //////////////////////////////////////////////// Detours Internal Definitions. 346 | // 347 | #ifdef __cplusplus 348 | #ifdef DETOURS_INTERNAL 349 | 350 | #ifndef __deref_out 351 | #define __deref_out 352 | #endif 353 | 354 | #ifndef __deref 355 | #define __deref 356 | #endif 357 | 358 | ////////////////////////////////////////////////////////////////////////////// 359 | // 360 | #if (_MSC_VER < 1299) 361 | #include 362 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 363 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 364 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 365 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 366 | 367 | static inline 368 | LONG InterlockedCompareExchange(LONG* ptr, LONG nval, LONG oval) 369 | { 370 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 371 | } 372 | #else 373 | #include 374 | #endif 375 | 376 | #ifdef IMAGEAPI // defined by DBGHELP.H 377 | typedef LPAPI_VERSION(NTAPI* PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion); 378 | 379 | typedef BOOL(NTAPI* PF_SymInitialize)(IN HANDLE hProcess, 380 | IN LPCSTR UserSearchPath, 381 | IN BOOL fInvadeProcess); 382 | typedef DWORD(NTAPI* PF_SymSetOptions)(IN DWORD SymOptions); 383 | typedef DWORD(NTAPI* PF_SymGetOptions)(VOID); 384 | typedef DWORD64(NTAPI* PF_SymLoadModule64)(IN HANDLE hProcess, 385 | IN HANDLE hFile, 386 | IN PSTR ImageName, 387 | IN PSTR ModuleName, 388 | IN DWORD64 BaseOfDll, 389 | IN DWORD SizeOfDll); 390 | typedef BOOL(NTAPI* PF_SymGetModuleInfo64)(IN HANDLE hProcess, 391 | IN DWORD64 qwAddr, 392 | OUT PIMAGEHLP_MODULE64 ModuleInfo); 393 | typedef BOOL(NTAPI* PF_SymFromName)(IN HANDLE hProcess, 394 | IN LPSTR Name, 395 | OUT PSYMBOL_INFO Symbol); 396 | 397 | typedef struct _DETOUR_SYM_INFO 398 | { 399 | HANDLE hProcess; 400 | HMODULE hDbgHelp; 401 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 402 | PF_SymInitialize pfSymInitialize; 403 | PF_SymSetOptions pfSymSetOptions; 404 | PF_SymGetOptions pfSymGetOptions; 405 | PF_SymLoadModule64 pfSymLoadModule64; 406 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 407 | PF_SymFromName pfSymFromName; 408 | } DETOUR_SYM_INFO, * PDETOUR_SYM_INFO; 409 | 410 | PDETOUR_SYM_INFO DetourLoadDbgHelp(VOID); 411 | 412 | #endif // IMAGEAPI 413 | 414 | #ifndef DETOUR_TRACE 415 | #if DETOUR_DEBUG 416 | #define DETOUR_TRACE(x) printf x 417 | #define DETOUR_BREAK() DebugBreak() 418 | #include 419 | #include 420 | #else 421 | #define DETOUR_TRACE(x) 422 | #define DETOUR_BREAK() 423 | #endif 424 | #endif 425 | 426 | #ifdef DETOURS_IA64 427 | __declspec(align(16)) struct DETOUR_IA64_BUNDLE 428 | { 429 | public: 430 | union 431 | { 432 | BYTE data[16]; 433 | UINT64 wide[2]; 434 | }; 435 | 436 | public: 437 | struct DETOUR_IA64_METADATA; 438 | 439 | typedef BOOL(DETOUR_IA64_BUNDLE::* DETOUR_IA64_METACOPY) 440 | (const DETOUR_IA64_METADATA* pMeta, DETOUR_IA64_BUNDLE* pDst) const; 441 | 442 | enum { 443 | A_UNIT = 1u, 444 | I_UNIT = 2u, 445 | M_UNIT = 3u, 446 | B_UNIT = 4u, 447 | F_UNIT = 5u, 448 | L_UNIT = 6u, 449 | X_UNIT = 7u, 450 | UNIT_MASK = 7u, 451 | STOP = 8u 452 | }; 453 | struct DETOUR_IA64_METADATA 454 | { 455 | ULONG nTemplate : 8; // Instruction template. 456 | ULONG nUnit0 : 4; // Unit for slot 0 457 | ULONG nUnit1 : 4; // Unit for slot 1 458 | ULONG nUnit2 : 4; // Unit for slot 2 459 | DETOUR_IA64_METACOPY pfCopy; // Function pointer. 460 | }; 461 | 462 | protected: 463 | BOOL CopyBytes(const DETOUR_IA64_METADATA* pMeta, DETOUR_IA64_BUNDLE* pDst) const; 464 | BOOL CopyBytesMMB(const DETOUR_IA64_METADATA* pMeta, DETOUR_IA64_BUNDLE* pDst) const; 465 | BOOL CopyBytesMBB(const DETOUR_IA64_METADATA* pMeta, DETOUR_IA64_BUNDLE* pDst) const; 466 | BOOL CopyBytesBBB(const DETOUR_IA64_METADATA* pMeta, DETOUR_IA64_BUNDLE* pDst) const; 467 | BOOL CopyBytesMLX(const DETOUR_IA64_METADATA* pMeta, DETOUR_IA64_BUNDLE* pDst) const; 468 | 469 | static const DETOUR_IA64_METADATA s_rceCopyTable[33]; 470 | 471 | public: 472 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 473 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. 474 | 475 | // 00 476 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. 477 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] 478 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] 479 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] 480 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] 481 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] 482 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] 483 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] 484 | BYTE GetTemplate() const; 485 | BYTE GetInst0() const; 486 | BYTE GetInst1() const; 487 | BYTE GetInst2() const; 488 | BYTE GetUnit0() const; 489 | BYTE GetUnit1() const; 490 | BYTE GetUnit2() const; 491 | UINT64 GetData0() const; 492 | UINT64 GetData1() const; 493 | UINT64 GetData2() const; 494 | 495 | public: 496 | BOOL IsBrl() const; 497 | VOID SetBrl(); 498 | VOID SetBrl(UINT64 target); 499 | UINT64 GetBrlTarget() const; 500 | VOID SetBrlTarget(UINT64 target); 501 | VOID SetBrlImm(UINT64 imm); 502 | UINT64 GetBrlImm() const; 503 | 504 | BOOL IsMovlGp() const; 505 | UINT64 GetMovlGp() const; 506 | VOID SetMovlGp(UINT64 gp); 507 | 508 | VOID SetInst0(BYTE nInst); 509 | VOID SetInst1(BYTE nInst); 510 | VOID SetInst2(BYTE nInst); 511 | VOID SetData0(UINT64 nData); 512 | VOID SetData1(UINT64 nData); 513 | VOID SetData2(UINT64 nData); 514 | BOOL SetNop0(); 515 | BOOL SetNop1(); 516 | BOOL SetNop2(); 517 | BOOL SetStop(); 518 | 519 | BOOL Copy(DETOUR_IA64_BUNDLE* pDst) const; 520 | }; 521 | #endif // DETOURS_IA64 522 | 523 | ////////////////////////////////////////////////////////////////////////////// 524 | 525 | #endif // DETOURS_INTERNAL 526 | #endif // __cplusplus 527 | 528 | #endif // _DETOURS_H_ 529 | // 530 | //////////////////////////////////////////////////////////////// End of File. 531 | -------------------------------------------------------------------------------- /Common/detours.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oung/MapleClientEditTemplate/87ceface2e95f942aef87457f2dccd7c9068c9fa/Common/detours.lib -------------------------------------------------------------------------------- /Common/hooker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "detours.h" 4 | 5 | #pragma comment(lib, "detours.lib") 6 | 7 | #pragma region Macros 8 | 9 | /// Sets hook and outputs result to debug window (pass/fail) 10 | #define INITWINHOOK(sModName, sFuncName, pOrigFunc, Func_t, pNewFunc) \ 11 | pOrigFunc = (Func_t)GetFuncAddress(sModName, sFuncName); \ 12 | if (SetHook(TRUE, reinterpret_cast(&pOrigFunc), pNewFunc)) \ 13 | { Log("Hooked %s", sFuncName); } \ 14 | else \ 15 | { Log("Failed to hook %s", sFuncName); } // end macro 16 | 17 | #define INITMAPLEHOOK(pOrigFunc, Func_t, pNewFunc, dwAddress) \ 18 | pOrigFunc = reinterpret_cast(dwAddress); \ 19 | if (!SetHook(TRUE, reinterpret_cast(&pOrigFunc), pNewFunc)) \ 20 | { /*Log("Failed to hook maple func at address %d", dwAddress);*/ } // end macro 21 | 22 | #define HOOKDEF(retType, callConv, defName, typeName, funcName, ...) \ 23 | typedef retType (callConv* typeName)(__VA_ARGS__); \ 24 | typeName defName = nullptr; \ 25 | retType callConv funcName(__VA_ARGS__); 26 | 27 | #pragma endregion 28 | 29 | static bool SetHook(bool bInstall, void** ppvTarget, void* pvDetour) 30 | { 31 | if (DetourTransactionBegin() != NO_ERROR) 32 | { 33 | return FALSE; 34 | } 35 | 36 | HANDLE pCurThread = GetCurrentThread(); 37 | 38 | if (DetourUpdateThread(pCurThread) == NO_ERROR) 39 | { 40 | auto pDetourFunc = bInstall ? DetourAttach : DetourDetach; 41 | 42 | if (pDetourFunc(ppvTarget, pvDetour) == NO_ERROR) 43 | { 44 | if (DetourTransactionCommit() == NO_ERROR) 45 | { 46 | return TRUE; 47 | } 48 | } 49 | } 50 | 51 | DetourTransactionAbort(); 52 | return FALSE; 53 | } 54 | 55 | static DWORD GetFuncAddress(const char* lpModule, const char* lpFunc) 56 | { 57 | HMODULE hMod = LoadLibraryA(lpModule); 58 | 59 | return !hMod ? 0 : (DWORD)GetProcAddress(hMod, lpFunc); 60 | } -------------------------------------------------------------------------------- /Common/logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #define assert_size(x, y) static_assert(x == y, "Static size assert failed."); 6 | 7 | //void Log(const char* format, ...); 8 | //void PrintStackTrace(unsigned long dwSize); 9 | 10 | /// 11 | /// Prints to windows debug output. 12 | /// 13 | static void Log(const char* format, ...) 14 | { 15 | char buf[1024] = { 0 }; 16 | 17 | va_list args; 18 | va_start(args, format); 19 | vsprintf_s(buf, format, args); 20 | 21 | OutputDebugStringA(buf); 22 | 23 | va_end(args); 24 | } 25 | 26 | /// 27 | /// Print call stack information to debug output 28 | /// 29 | static void PrintStackTrace(unsigned long dwSize = 10) 30 | { 31 | // TODO 32 | } -------------------------------------------------------------------------------- /Common/memedit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #define relative_address(frm, to) (int)(((int)to - (int)frm) - 5) 7 | 8 | #define x86XOR 0x33 9 | #define x86EAXEAX 0xC0 10 | #define x86RET 0xC3 11 | #define x86JMP 0xE9 12 | #define x86CALL 0xE8 13 | #define x86NOP 0x90 14 | 15 | static VOID PatchRetZero(DWORD dwAddress) 16 | { 17 | *(BYTE*)(dwAddress + 0) = x86XOR; 18 | *(BYTE*)(dwAddress + 1) = x86EAXEAX; 19 | *(BYTE*)(dwAddress + 2) = x86RET; 20 | } 21 | 22 | static VOID PatchJmp(DWORD dwAddress, PVOID pDestination) 23 | { 24 | *(BYTE*)(dwAddress + 0) = x86JMP; 25 | *(DWORD*)(dwAddress + 1) = relative_address(dwAddress, pDestination); 26 | } 27 | 28 | static VOID PatchCall(DWORD dwAddress, PVOID pDestination) 29 | { 30 | *(BYTE*)(dwAddress + 0) = x86CALL; 31 | *(DWORD*)(dwAddress + 1) = relative_address(dwAddress, pDestination); 32 | } 33 | 34 | static VOID PatchNop(DWORD dwAddress, UINT nCount) 35 | { 36 | for (int i = 0; i < nCount; i++) 37 | *(BYTE*)(dwAddress + i) = x86NOP; 38 | } 39 | 40 | template 41 | static VOID WriteValue(DWORD dwAddress, T pValue) 42 | { 43 | *((T*)dwAddress) = pValue; 44 | } 45 | 46 | static VOID WriteBytes(DWORD dwAddress, const char* pData, UINT nCount) 47 | { 48 | memcpy((PVOID)dwAddress, pData, nCount); 49 | } 50 | 51 | static PCHAR ReadBytes(DWORD dwAddress, UINT nLen) 52 | { 53 | char* aRet = (char*)malloc(nLen); 54 | 55 | memcpy(aRet, (PVOID)dwAddress, nLen); 56 | 57 | return aRet; 58 | } -------------------------------------------------------------------------------- /Common/winhooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "commonconfig.h" 4 | #include 5 | #include 6 | #include 7 | #include "hooker.h" 8 | #include "logger.h" 9 | 10 | // fix returnaddress func 11 | // https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress?view=msvc-160 12 | #pragma intrinsic(_ReturnAddress) 13 | 14 | // link socket library 15 | #pragma comment(lib, "WS2_32.lib") 16 | 17 | // deprecated api call warning 18 | #pragma warning(disable : 4996) 19 | 20 | /// 21 | /// Gets called when mutex hook is triggered. 22 | /// 23 | typedef VOID(*PostMutexFunc_t)(); 24 | PostMutexFunc_t g_PostMutexFunc; 25 | 26 | // ignore this region if you arent sure what you are doing 27 | #pragma region LibraryDefs 28 | 29 | /// 30 | /// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa 31 | /// 32 | typedef HANDLE(WINAPI* CreateMutexA_t)(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName); 33 | CreateMutexA_t CreateMutexA_Original; 34 | 35 | /// 36 | /// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-openmutexw 37 | /// Please note: there is no microsoft doc for OpenMutexA, but OpenMutexW is the same except for the type of string passed (LPCSTR vs LPCWSTR) 38 | /// 39 | typedef HANDLE(WINAPI* OpenMutexA_t)(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName); 40 | OpenMutexA_t OpenMutexA_Original; 41 | 42 | /// 43 | /// https://docs.microsoft.com/en-us/windows/win32/api/ws2spi/nf-ws2spi-wspstartup 44 | /// 45 | typedef int(WSPAPI* WSPStartup_t)(WORD wVersionRequested, LPWSPDATA lpWSPData, LPWSAPROTOCOL_INFOW lpProtocolInfo, WSPUPCALLTABLE UpcallTable, LPWSPPROC_TABLE lpProcTable); 46 | WSPStartup_t WSPStartup_Original; 47 | /// 48 | /// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclassexa 49 | /// 50 | typedef ATOM(WINAPI* RegisterClassExA_t)(const WNDCLASSEXA* lpWc); 51 | RegisterClassExA_t RegisterClassExA_Original; 52 | 53 | /// 54 | /// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw 55 | /// 56 | typedef BOOL(WINAPI* CreateProcessW_t)( 57 | LPCWSTR lpApplicationName, 58 | LPWSTR lpCommandLine, 59 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 60 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 61 | BOOL bInheritHandles, 62 | DWORD dwCreationFlags, 63 | LPVOID lpEnvironment, 64 | LPCWSTR lpCurrentDirectory, 65 | LPSTARTUPINFOW lpStartupInfo, 66 | LPPROCESS_INFORMATION lpProcessInformation 67 | ); 68 | CreateProcessW_t CreateProcessW_Original; 69 | 70 | /// 71 | /// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess 72 | /// 73 | typedef HANDLE(WINAPI* OpenProcess_t)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId); 74 | OpenProcess_t OpenProcess_Original; 75 | 76 | /// 77 | /// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread 78 | /// 79 | typedef HANDLE(WINAPI* CreateThread_t)( 80 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 81 | SIZE_T dwStackSize, 82 | LPTHREAD_START_ROUTINE lpStartAddress, 83 | __drv_aliasesMem LPVOID lpParameter, 84 | DWORD dwCreationFlags, 85 | LPDWORD lpThreadId 86 | ); 87 | CreateThread_t CreateThread_Original; 88 | 89 | /// 90 | /// https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getacp 91 | /// 92 | typedef UINT(WINAPI* GetACP_t)(); 93 | GetACP_t GetACP_Original; 94 | 95 | /// 96 | /// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa 97 | /// 98 | typedef HWND(WINAPI* CreateWindowExA_t)( 99 | DWORD dwExStyle, 100 | LPCSTR lpClassName, 101 | LPCSTR lpWindowName, 102 | DWORD dwStyle, 103 | int X, 104 | int Y, 105 | int nWidth, 106 | int nHeight, 107 | HWND hWndParent, 108 | HMENU hMenu, 109 | HINSTANCE hInstance, 110 | LPVOID lpParam 111 | ); 112 | CreateWindowExA_t CreateWindowExA_Original; 113 | 114 | /// 115 | /// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FProcess%2FNtTerminateProcess.html 116 | /// 117 | typedef LONG(NTAPI* NtTerminateProcess_t)(HANDLE hProcHandle, LONG ntExitStatus); 118 | NtTerminateProcess_t NtTerminateProcess_Original; 119 | 120 | /// 121 | /// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeyexa 122 | /// 123 | /// 124 | typedef LSTATUS(WINAPI* RegCreateKeyExA_t)( 125 | HKEY hKey, 126 | LPCSTR lpSubKey, 127 | DWORD Reserved, 128 | LPSTR lpClass, 129 | DWORD dwOptions, 130 | REGSAM samDesired, 131 | const LPSECURITY_ATTRIBUTES lpSecurityAttributes, 132 | PHKEY phkResult, 133 | LPDWORD lpdwDisposition 134 | ); 135 | RegCreateKeyExA_t RegCreateKeyExA_Original; 136 | 137 | #pragma endregion 138 | 139 | bool g_bMutexTriggered = false; 140 | 141 | SOCKET g_GameSock; 142 | WSPPROC_TABLE g_ProcTable; 143 | 144 | const char* g_sRedirectIP; 145 | const char* g_sOriginalIP; 146 | 147 | /// 148 | /// CreateMutexA is the first Windows library call after the executable unpacks itself. 149 | /// We hook this function to do all our memory edits and hooks when it's called. 150 | /// 151 | static HANDLE WINAPI CreateMutexA_Hook( 152 | LPSECURITY_ATTRIBUTES lpMutexAttributes, 153 | BOOL bInitialOwner, 154 | LPCSTR lpName 155 | ) 156 | { 157 | if (!CreateMutexA_Original) 158 | { 159 | Log("Original CreateMutex pointer corrupted. Failed to return mutex value to calling function."); 160 | 161 | return nullptr; 162 | } 163 | else if (lpName && strstr(lpName, MAPLE_MUTEX)) 164 | { 165 | if (MAPLETRACKING_SLEEP_ON_MUTEX) 166 | { 167 | Log("Mutex triggered => sleeping for %d milliseconds.", MAPLETRACKING_SLEEP_ON_MUTEX); 168 | Sleep(MAPLETRACKING_SLEEP_ON_MUTEX); 169 | } 170 | 171 | Log("Mutex spoofed, unhooking.."); 172 | 173 | g_PostMutexFunc(); 174 | 175 | g_bMutexTriggered = true; 176 | 177 | if (!SetHook(FALSE, reinterpret_cast(&CreateMutexA_Original), CreateMutexA_Hook)) 178 | { 179 | Log("Failed to unhook mutex."); 180 | } 181 | 182 | return CreateMutexA_Original(lpMutexAttributes, bInitialOwner, lpName); 183 | } 184 | 185 | return CreateMutexA_Original(lpMutexAttributes, bInitialOwner, lpName); 186 | } 187 | 188 | /// 189 | /// In some versions, Maple calls this library function to check if the anticheat has started. 190 | /// We can spoof this and return a fake handle for it to close. 191 | /// 192 | static HANDLE WINAPI OpenMutexA_Hook( 193 | DWORD dwDesiredAccess, 194 | BOOL bInitialOwner, 195 | LPCSTR lpName 196 | ) 197 | { 198 | Log("Opening mutex %s", lpName); 199 | 200 | if (strstr(lpName, "Global")) // make sure we only override hackshield 201 | { 202 | // return handle to a spoofed mutex so it can close the handle 203 | return CreateMutexA_Original(NULL, TRUE, "FakeMutex1"); 204 | } 205 | else // TODO add second mutex handling 206 | { 207 | return OpenMutexA_Original(dwDesiredAccess, bInitialOwner, lpName); 208 | } 209 | } 210 | 211 | /// 212 | /// Used to track what maple is trying to start (mainly for anticheat modules). 213 | /// 214 | static BOOL WINAPI CreateProcessW_Hook( 215 | LPCWSTR lpApplicationName, 216 | LPWSTR lpCommandLine, 217 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 218 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 219 | BOOL bInheritHandles, 220 | DWORD dwCreationFlags, 221 | LPVOID lpEnvironment, 222 | LPCWSTR lpCurrentDirectory, 223 | LPSTARTUPINFOW lpStartupInfo, 224 | LPPROCESS_INFORMATION lpProcessInformation 225 | ) 226 | { 227 | if (lpApplicationName) 228 | { 229 | Log("CreateProcessW -> %s", lpApplicationName); 230 | } 231 | else 232 | { 233 | Log("CreateProcessW -> Null Application Name"); 234 | } 235 | 236 | return CreateProcessW_Original(lpApplicationName, lpCommandLine, 237 | lpProcessAttributes, lpThreadAttributes, bInheritHandles, 238 | dwCreationFlags, lpEnvironment, lpCurrentDirectory, 239 | lpStartupInfo, lpProcessInformation); 240 | } 241 | 242 | /// 243 | /// Same as CreateProcessW 244 | /// 245 | static HANDLE WINAPI CreateThread_Hook( 246 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 247 | SIZE_T dwStackSize, 248 | LPTHREAD_START_ROUTINE lpStartAddress, 249 | __drv_aliasesMem LPVOID lpParameter, 250 | DWORD dwCreationFlags, 251 | LPDWORD lpThreadId 252 | ) 253 | { 254 | return CreateThread_Original(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); 255 | } 256 | 257 | /// 258 | /// Used to track what processes Maple opens. 259 | /// 260 | static HANDLE WINAPI OpenProcess_Hook( 261 | DWORD dwDesiredAccess, 262 | BOOL bInheritHandle, 263 | DWORD dwProcessId 264 | ) 265 | { 266 | Log("OpenProcess -> PID: %d - CallAddy: %08X", dwProcessId, _ReturnAddress()); 267 | 268 | return OpenProcess_Original(dwDesiredAccess, bInheritHandle, dwProcessId); 269 | } 270 | 271 | /// 272 | /// This library call is used by nexon to determine the locale of the connecting clients PC. We spoof it. 273 | /// 274 | /// 275 | static UINT WINAPI GetACP_Hook() // AOB: FF 15 ?? ?? ?? ?? 3D 6A 03 00 00 74 276 | { 277 | if (MAPLE_LOCALE_SPOOF == 0) return GetACP_Original(); // should not happen cuz we dont hook if value is zero 278 | 279 | if (g_bMutexTriggered) 280 | { 281 | Log("Locale spoofed, unhooking. Calling address: %02x", _ReturnAddress()); 282 | 283 | if (!SetHook(FALSE, reinterpret_cast(&GetACP_Original), GetACP_Hook)) 284 | { 285 | Log("Failed to unhook GetACP."); 286 | } 287 | } 288 | 289 | const UINT uiNewLocale = MAPLE_LOCALE_SPOOF; // thai 290 | 291 | return uiNewLocale; 292 | } 293 | 294 | /// 295 | /// Blocks the startup patcher "Play!" window and forces the login screen to be minimized 296 | /// 297 | static HWND WINAPI CreateWindowExA_Hook( 298 | DWORD dwExStyle, 299 | LPCSTR lpClassName, 300 | LPCSTR lpWindowName, 301 | DWORD dwStyle, 302 | int X, 303 | int Y, 304 | int nWidth, 305 | int nHeight, 306 | HWND hWndParent, 307 | HMENU hMenu, 308 | HINSTANCE hInstance, 309 | LPVOID lpParam 310 | ) 311 | { 312 | if (MAPLE_PATCHER_CLASS && strstr(lpClassName, MAPLE_PATCHER_CLASS)) 313 | { 314 | Log("Bypassing patcher window.."); 315 | return NULL; 316 | } 317 | else 318 | { 319 | if (MAPLE_FORCE_WINDOWED && MAPLE_WINDOW_CLASS && strstr(lpClassName, MAPLE_WINDOW_CLASS)) 320 | { 321 | dwExStyle = 0; 322 | dwStyle = 0xCA0000; 323 | } 324 | 325 | return CreateWindowExA_Original(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); 326 | } 327 | } 328 | 329 | /// 330 | /// We use this function to track what memory addresses are killing the process. 331 | /// There are more ways that Maple kills itself, but this is one of them. 332 | /// 333 | static LONG NTAPI NtTerminateProcess_Hook( 334 | HANDLE hProcHandle, 335 | LONG ntExitStatus 336 | ) 337 | { 338 | Log("NtTerminateProcess: %08X", unsigned(_ReturnAddress())); 339 | 340 | return NtTerminateProcess_Original(hProcHandle, ntExitStatus); 341 | } 342 | 343 | /// 344 | /// Maplestory saves registry information (config stuff) for a number of things. This can be used to track that. 345 | /// 346 | static LSTATUS WINAPI RegCreateKeyExA_Hook( 347 | HKEY hKey, 348 | LPCSTR lpSubKey, 349 | DWORD Reserved, 350 | LPSTR lpClass, 351 | DWORD dwOptions, 352 | REGSAM samDesired, 353 | const LPSECURITY_ATTRIBUTES lpSecurityAttributes, 354 | PHKEY phkResult, 355 | LPDWORD lpdwDisposition 356 | ) 357 | { 358 | //Log("Return address: %d", _ReturnAddress()); 359 | 360 | return RegCreateKeyExA_Original(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); 361 | } 362 | 363 | /// 364 | /// 365 | /// 366 | static int WSPAPI WSPConnect_Hook( 367 | SOCKET s, 368 | const struct sockaddr* name, 369 | int namelen, 370 | LPWSABUF lpCallerData, 371 | LPWSABUF lpCalleeData, 372 | LPQOS lpSQOS, 373 | LPQOS lpGQOS, 374 | LPINT lpErrno 375 | ) 376 | { 377 | char szAddr[50]; 378 | DWORD dwLen = 50; 379 | WSAAddressToStringA((sockaddr*)name, namelen, NULL, szAddr, &dwLen); 380 | 381 | sockaddr_in* service = (sockaddr_in*)name; 382 | 383 | if (MAPLETRACKING_WSPCONN_PRINT) 384 | { 385 | Log("WSPConnect IP Detected: %s", szAddr); 386 | } 387 | 388 | if (strstr(szAddr, g_sRedirectIP)) 389 | { 390 | Log("Detected and rerouting socket connection to IP: %s", g_sOriginalIP); 391 | service->sin_addr.S_un.S_addr = inet_addr(g_sOriginalIP); 392 | g_GameSock = s; 393 | } 394 | 395 | return g_ProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno); 396 | } 397 | 398 | /// 399 | /// 400 | /// 401 | static int WSPAPI WSPGetPeerName_Hook( 402 | SOCKET s, 403 | struct sockaddr* name, 404 | LPINT namelen, 405 | LPINT lpErrno 406 | ) 407 | { 408 | int nRet = g_ProcTable.lpWSPGetPeerName(s, name, namelen, lpErrno); 409 | 410 | if (nRet != SOCKET_ERROR) 411 | { 412 | char szAddr[50]; 413 | DWORD dwLen = 50; 414 | WSAAddressToStringA((sockaddr*)name, *namelen, NULL, szAddr, &dwLen); 415 | 416 | sockaddr_in* service = (sockaddr_in*)name; 417 | 418 | USHORT nPort = ntohs(service->sin_port); 419 | 420 | if (s == g_GameSock) 421 | { 422 | char szAddr[50]; 423 | DWORD dwLen = 50; 424 | WSAAddressToStringA((sockaddr*)name, *namelen, NULL, szAddr, &dwLen); 425 | 426 | sockaddr_in* service = (sockaddr_in*)name; 427 | 428 | u_short nPort = ntohs(service->sin_port); 429 | 430 | service->sin_addr.S_un.S_addr = inet_addr(g_sOriginalIP); 431 | 432 | Log("WSPGetPeerName => IP Replaced: %s -> %s", szAddr, g_sOriginalIP); 433 | } 434 | else 435 | { 436 | Log("WSPGetPeerName => IP Ignored: %s:%d", szAddr, nPort); 437 | } 438 | } 439 | else 440 | { 441 | Log("WSPGetPeerName Socket Error: %d", nRet); 442 | } 443 | 444 | return nRet; 445 | } 446 | 447 | /// 448 | /// 449 | /// 450 | /// 451 | /// 452 | /// 453 | static int WSPAPI WSPCloseSocket_Hook( 454 | SOCKET s, 455 | LPINT lpErrno 456 | ) 457 | { 458 | int nRet = g_ProcTable.lpWSPCloseSocket(s, lpErrno); 459 | 460 | if (s == g_GameSock) 461 | { 462 | Log("Socket closed by application.. (%d). CallAddr: %02x", nRet, _ReturnAddress()); 463 | g_GameSock = INVALID_SOCKET; 464 | } 465 | 466 | return nRet; 467 | } 468 | 469 | /// 470 | /// 471 | /// 472 | static int WSPAPI WSPStartup_Hook( 473 | WORD wVersionRequested, 474 | LPWSPDATA lpWSPData, 475 | LPWSAPROTOCOL_INFOW lpProtocolInfo, 476 | WSPUPCALLTABLE UpcallTable, 477 | LPWSPPROC_TABLE lpProcTable 478 | ) 479 | { 480 | int nRet = WSPStartup_Original(wVersionRequested, lpWSPData, lpProtocolInfo, UpcallTable, lpProcTable); 481 | 482 | if (nRet == NO_ERROR) 483 | { 484 | Log("Overriding socket routines.."); 485 | 486 | g_GameSock = INVALID_SOCKET; 487 | g_ProcTable = *lpProcTable; 488 | 489 | lpProcTable->lpWSPConnect = WSPConnect_Hook; 490 | lpProcTable->lpWSPGetPeerName = WSPGetPeerName_Hook; 491 | lpProcTable->lpWSPCloseSocket = WSPCloseSocket_Hook; 492 | } 493 | else 494 | { 495 | Log("WSPStartup Error Code: %d", nRet); 496 | } 497 | 498 | return nRet; 499 | } -------------------------------------------------------------------------------- /GenericLauncher/GenericLauncher.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {6e0b10d1-1a13-4c13-9f00-1525a7e53019} 25 | GenericLauncher 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | MultiByte 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | $(SolutionDir)Common;%(AdditionalIncludeDirectories) 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | Level3 101 | true 102 | true 103 | true 104 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | true 118 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | true 120 | 121 | 122 | Console 123 | true 124 | 125 | 126 | 127 | 128 | Level3 129 | true 130 | true 131 | true 132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | true 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /GenericLauncher/GenericLauncher.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /GenericLauncher/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "commonconfig.h" 5 | 6 | __declspec(dllimport) void ord1(int hash); 7 | 8 | void ErrorBox(const char* format, ...) 9 | { 10 | char szMessage[1024]; 11 | 12 | va_list args; 13 | va_start(args, format); 14 | 15 | vsnprintf(szMessage, 1023, format, args); 16 | MessageBoxA(NULL, szMessage, "Launch Error", MB_ICONERROR); 17 | 18 | va_end(args); 19 | } 20 | 21 | #define ErrorBoxWithCode(msg) ErrorBox(msg" Error code: %d", GetLastError()); 22 | 23 | int main() 24 | { 25 | OutputDebugStringA("Launcher entrypoint."); 26 | 27 | // additional information 28 | STARTUPINFO siMaple; 29 | PROCESS_INFORMATION piMaple; 30 | 31 | // Initialize the startup structures 32 | ZeroMemory(&siMaple, sizeof(siMaple)); 33 | ZeroMemory(&piMaple, sizeof(piMaple)); 34 | 35 | siMaple.cb = sizeof(siMaple); 36 | 37 | // Start the child process. 38 | BOOL bCreateProc = CreateProcess( 39 | MAPLE_EXE_NAME, // name of application 40 | const_cast(MAPLE_STARTUP_ARGS), // Command line args 41 | NULL, // Process handle not inheritable 42 | NULL, // Thread handle not inheritable 43 | FALSE, // Set handle inheritance to FALSE 44 | CREATE_SUSPENDED, // Creation flags 45 | NULL, // Use parent's environment block 46 | NULL, // Use parent's starting directory 47 | &siMaple, // Pointer to STARTUPINFO structure 48 | &piMaple // Pointer to PROCESS_INFORMATION structure 49 | ); 50 | 51 | if (bCreateProc) 52 | { 53 | const char* szDllName = MAPLE_INJECT_DLLNAME; 54 | const size_t nLoadDllStrLen = strlen(szDllName); 55 | 56 | HMODULE hKernel = GetModuleHandleA("Kernel32.dll"); 57 | 58 | if (!hKernel) 59 | { 60 | ErrorBoxWithCode("Unable to get Kernel32 handle."); 61 | } 62 | 63 | LPVOID lpLoadLibAddr = (LPVOID)GetProcAddress(hKernel, "LoadLibraryA"); 64 | 65 | if (!lpLoadLibAddr) 66 | { 67 | ErrorBoxWithCode("Unable to get address for library call."); 68 | } 69 | 70 | LPVOID lpRemoteStr = VirtualAllocEx(piMaple.hProcess, NULL, nLoadDllStrLen, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 71 | 72 | if (!lpRemoteStr) 73 | { 74 | ErrorBoxWithCode("Unable to allocate memory."); 75 | } 76 | 77 | BOOL bWriteProc = WriteProcessMemory(piMaple.hProcess, lpRemoteStr, szDllName, nLoadDllStrLen, NULL); 78 | 79 | if (!bWriteProc) 80 | { 81 | ErrorBoxWithCode("Unable to attach to MapleStory process."); 82 | } 83 | 84 | HANDLE hRemThread = CreateRemoteThread(piMaple.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)lpLoadLibAddr, lpRemoteStr, 0, NULL); 85 | 86 | if (!hRemThread) 87 | { 88 | ErrorBoxWithCode("Unable to create remote thread."); 89 | } 90 | 91 | if (MAPLE_UNSUSPEND) 92 | { 93 | DWORD dwRet = ResumeThread(piMaple.hThread); 94 | 95 | if (dwRet == -1) 96 | { 97 | ErrorBoxWithCode("Unable to resume thread."); 98 | } 99 | } 100 | 101 | // close handle for injected dll 102 | CloseHandle(hRemThread); 103 | 104 | // Close process and thread handles. 105 | CloseHandle(piMaple.hProcess); 106 | CloseHandle(piMaple.hThread); 107 | 108 | OutputDebugStringA("End launcher"); 109 | 110 | return TRUE; 111 | } 112 | else 113 | { 114 | ErrorBoxWithCode("Make sure you're running as Administrator and that the launcher is in the same folder as MapleStory.exe."); 115 | return FALSE; 116 | } 117 | 118 | return TRUE; 119 | } -------------------------------------------------------------------------------- /MapleClientCollection.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30320.27 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenericLauncher", "GenericLauncher\GenericLauncher.vcxproj", "{6E0B10D1-1A13-4C13-9F00-1525A7E53019}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "Common\Common.vcxproj", "{3EB29228-1F83-4DD3-B3C5-0F284FD50F39}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CTemplate", "CTemplate\CTemplate.vcxproj", "{D2C48F68-C2B4-41C4-A581-550603163363}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Debug|x64.ActiveCfg = Debug|Win32 21 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Debug|x64.Build.0 = Debug|Win32 22 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Debug|x86.ActiveCfg = Debug|Win32 23 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Debug|x86.Build.0 = Debug|Win32 24 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Release|x64.ActiveCfg = Release|x64 25 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Release|x64.Build.0 = Release|x64 26 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Release|x86.ActiveCfg = Release|Win32 27 | {6E0B10D1-1A13-4C13-9F00-1525A7E53019}.Release|x86.Build.0 = Release|Win32 28 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Debug|x64.ActiveCfg = Debug|Win32 29 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Debug|x64.Build.0 = Debug|Win32 30 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Debug|x86.ActiveCfg = Debug|Win32 31 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Debug|x86.Build.0 = Debug|Win32 32 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Release|x64.ActiveCfg = Release|x64 33 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Release|x64.Build.0 = Release|x64 34 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Release|x86.ActiveCfg = Release|Win32 35 | {3EB29228-1F83-4DD3-B3C5-0F284FD50F39}.Release|x86.Build.0 = Release|Win32 36 | {D2C48F68-C2B4-41C4-A581-550603163363}.Debug|x64.ActiveCfg = Debug|x64 37 | {D2C48F68-C2B4-41C4-A581-550603163363}.Debug|x64.Build.0 = Debug|x64 38 | {D2C48F68-C2B4-41C4-A581-550603163363}.Debug|x86.ActiveCfg = Debug|Win32 39 | {D2C48F68-C2B4-41C4-A581-550603163363}.Debug|x86.Build.0 = Debug|Win32 40 | {D2C48F68-C2B4-41C4-A581-550603163363}.Release|x64.ActiveCfg = Release|x64 41 | {D2C48F68-C2B4-41C4-A581-550603163363}.Release|x64.Build.0 = Release|x64 42 | {D2C48F68-C2B4-41C4-A581-550603163363}.Release|x86.ActiveCfg = Release|Win32 43 | {D2C48F68-C2B4-41C4-A581-550603163363}.Release|x86.Build.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {321069B6-E641-4B0F-9523-415E55A7A91F} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MapleClientCollection 2 | 3 | A (increasingly generic) framework that is intended to be used when crafting new MapleStory client redirectors/edits. 4 | This should work pretty much out of the box and all that is required is potential anticheat and crc bypasses. These are version dependant. 5 | This solution contains all the Windows library hooks that are required for a MapleStory localhost enabler and is configured to be as noob friendly as possible. 6 | The Windows hooks are abstracted away (as best as I could) and can be toggled on/off depending on need. For example, if using this with an unvirtualized localhost (eg v83), the WinSock hooks can be disabled with a simple switch and memory editing can be done immediately on injection rather than waiting for the client to be unpacked (since it's already unpacked no need to wait). 7 | 8 | ### Current Status 9 | This project is in active development by myself (Minimum Delta). Issue/feature requests are appreciated. 10 | The project is in alpha stage, so do not expect it to work perfectly (even though it should work pretty well). 11 | 12 | ### Credits 13 | Darter (aka Moozi) - Very helpful mentor 14 | Ez - Another mentor and friend 15 | SunCat - Great insight from this friendly fellow 16 | The Muffin Man - Always staying positive 17 | DAVHEED - BUTT JUICE GANG GANG GANG 18 | 19 | ### Setup 20 | I'm going to expand this at some point, but there's a few things that need to be configured in order for the project to work: 21 | * Put detours.lib into your Debug folder (folder generated on compilation in main folder) 22 | * Paste: $(SolutionDir)Common;%(AdditionalIncludeDirectories) in your (CTemplate) project properties -> c/c++ -> additional include directories. This will let the project see the other files for proper compilation. It will not compile unless this is done properly. 23 | * Sometimes VS defaults to x64 which is incorrect and will not work. Make sure you're compiling in Debug x86 -> if you try to compile in x64 it'll give detour linker errors. 24 | 25 | ### Config settings 26 | All generic config settings are in commonconfig.h. More information on the specifics of this will come at a later point (documentation is always last, eh). However, I've commented reasonbly well so it should be pretty apparent what each setting does. 27 | 28 | ### Compiling for proxy vs regular injection 29 | Ijl15 proxy injection (auto injection on Maple start rather than using a launcher) can be turned on/off by defining MAPLE_INJECT_USE_IJL in commonconfig.h. 30 | You'll need to rename the compiled DLL to ijl15.dll instead of LEN.dll in order for it to be auto injected. 31 | 32 | ### GenericLauncher 33 | Regular injection can be done with the GenericLauncher project exe. This program will boot up MapleStory and inject LEN.dll. It's very simple, but works very well. 34 | 35 | ### Common Project 36 | The Common project contains all the Windows library hooks that are not version specific. 37 | These can be used by any version and are already configured to be hooked on injection. They can be toggled on/off in the commonconfig file. 38 | 39 | ### When does hooking and memory editing happen? 40 | Windows functions are hooked immediately after injection which happens directly after MapleStory is launched (for ijl proxy and regular GenericLauncher injection). 41 | Unlike MapleStory function hooks, outside API hooks (winhooks) do not need to wait for the client to be unpacked. Assuming that the MAPLE_INSTAJECT config option is disabled, when the WinAPI CreateMutexA hook is triggered by MapleStory then MainFunc in dllmain is triggered and any hooks or editing called from that function will be executed. 42 | It is recommended to keep all hooking and memory editing inside (or called from) that function. 43 | 44 | ### MapleAPI Hooking Examples 45 | MapleStory function hook examples will be added in the future -- currently there is support to add them but there are none added yet. 46 | These will be more or less version specific which is why I excluded it from the initial template upload. 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | --------------------------------------------------------------------------------