Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Modern OS Support (Win8/8.1/10 'Fix')

Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
**If you're trying to fix the "process hang" issue on higher version clients, read my below post.

As most if not all of you have already read my documentation thread regarding this problem, many weren't able to follow what I was doing and explaining. Thus, I've decided to quickly review what I was talking about and showing you how to fix it.

In the initial post, I was trying to fix the issue by bypassing the client's ZAPILoader checks that look if "dinput8.dll" is present and displays a korean error, and then placing a dinput8.dll into your MapleStory folder. The purpose of this was to "override" the dinput8 module that your operating system is loading from system32, and patch it by injecting the old windows 7 library that works for everyone. As a result, this fixed the problem for a lot of my friends who had tested it for me. Furthermore, for people whose clients were receiving the "CoInitialize failed" error (caused from the thread sleep workaround), this had fixed that problem because it wasn't delaying thread startup anymore.

However, after posting the thread, people were continuing to have problems even after patching dinput8 itself. So, if it wasn't from their OS's dinput8 library, then the exception itself is coming from outside the module itself. This is where a few posts later I tracked down after several AoB breakpoints, the function in dinput8 that was throwing the exception to the client. In order to confirm this was the true cause, I posted a modified dll that would throw a custom exception code instead of incorrect parameter.

Then, a day later, I had gotten a reply from PrinceReborn that had confirmed the location of the problem at hand was exactly what I had suggested -- the _hresValidInstanceVer_ function was throwing the exception. Thus, I had officially posted the source of the problem and continued digging deeper into WINAPI to figure out why this was happening with later operating systems. The issue at hand is because of the function GetModuleFileNameW in WINAPI failing. Therefore, if you were to figure out and fix the function that's failing, you would fix the incorrect parameter error.

My solution that I had done for Orion originally to fix not only the errors happening with this function in dinput8, but a handful of others as well, was to write a dinput8 wrapper (this way I didn't have to involve hooking). This had solved all the problems for me, and is the go-to method for fixing it on a lot of other games as well. While this way takes a lot more time and doesn't physically make any difference (the backend functions being fixed aren't all used by MapleStory in the first place), the alternative method was to hook the GetModuleFileNameW function and fix its return value. Since I never officially posted my wrapper fix, anhtanh95 had posted how he hooked GetModuleFileNameW in order to fix it.

So now that I've broken down how we got to the cause, how do we fix it?

Well, if you wish to hook GetModuleFileNameW to fix this problem, then I'll expect you to know what you're doing with detours enough to be able to implement the below function into your DLL.
Code:
/* GetModuleFileNameW hook used to fix the "Incorrect parameter" error within the DirectInput8 library */
bool Orion::Hook_GetModuleFileNameW(bool bEnable) {
	static decltype(&GetModuleFileNameW) _GetModuleFileNameW = &GetModuleFileNameW;

	decltype(&GetModuleFileNameW) GetModuleFileNameW_Hook = [](HMODULE hModule, LPWSTR lpFileName, DWORD dwSize) -> DWORD {
		auto len = _GetModuleFileNameW(hModule, lpFileName, dwSize);

		/* Check to see if the length is invalid (zero) */
		if (!len) {
			/* Try again without the provided module for a fixed result */
			len = _GetModuleFileNameW(NULL, lpFileName, dwSize);
		}
		
		return len;
	};

	return SetHook(bEnable, reinterpret_cast<void**>(&_GetModuleFileNameW), GetModuleFileNameW_Hook);
}

Example Usage (DllMain):
Code:
/* Initiate the GetModuleFileNameW hook to fix DirectInput8 exceptions. */
if (!Orion::Hook_GetModuleFileNameW(true)) {
	NotifyMessage("Failed to hook GetModuleFileNameW", Orion::NotifyType::Error);
	return FALSE;
}

Alright, so if you're not so advanced with C++ and detour hooking, then I advise you to use Orion's solution instead because no hooking is involved. First, you're going to need to jump the ZAPILoader checks in the client (time to get your OllyDbg game on!). Below are the client addresses for the common versions:
Code:
v62 -> 00672F10 (JE to JMP)
v75 -> 006DF82D (JE to JMP)
v83 -> 00796357 (JE to JMP)
v90 -> 00864A34 (JMP 00864BCA)
v111 -> 0085EC08 (JMP 0085EE88)

Once you've jumped the check, simply place into your MapleStory folder. If done correctly (on either solution), you will no longer have any incorrect parameter problems.

Hope this helps!

- Eric
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
Yess tysm :)

You're very welcome <3

UPDATED: How to patch the infamous "process hang => crash" problem that (can) occur on v7x~v11x clients.
I completely forgot to mention this! On the same thread regarding all my modern OS support fixes, I had additionally explained how to fix the process hang bug. If you recall back when v90/v111/v117 were popular years back, many users on modern OS's would run the client and it'd do nothing.

This problem is because the process starts => executes WinMain => executes CWvsApp::SetUp => begins WinSock IP checks(*). When the client reaches the portion where it does it's first set of IP checks, it calls a function named HideDll. Below is the code in which this happens:
Code:
szWs232dll[0] = 'w';
szWs232dll[1] = 's';
szWs232dll[2] = '2';
szWs232dll[3] = '_';
szWs232dll[4] = '3';
szWs232dll[5] = '2';
szWs232dll[6] = '.';
szWs232dll[7] = 'd';
szWs232dll[8] = 'l';
szWs232dll[9] = 'l';
szWs232dll[10] = 0;
hWs2_32Dll = GetModuleHandleA(szWs232dll);
dwImageSize = 0;
pDosHeader = (char *)hWs2_32Dll;
if ( LOWORD(hWs2_32Dll->unused) == 23117 )
{
	pNTHeader = &pDosHeader[*((_DWORD *)pDosHeader + 15)];
    if ( *(_DWORD *)pNTHeader == 17744 )
      dwImageSize = *((_DWORD *)pNTHeader + 20);
}
memcpy(&g_hSafeWs232AdrList, (char *)loc_401231 + 3, 0x200u);
for ( i = 64; i < 74; ++i )
    *(&g_hSafeWs232AdrList + i) = (int)InitSafeDll();
num = rand() % 10 + 64;
fnWSAStartup = MyGetProcAddress((HINSTANCE__ *)*(&g_hSafeWs232AdrList + num), "WSAStartup");
szgetpeername[0] = 'g';
szgetpeername[1] = 'e';
szgetpeername[2] = 't';
szgetpeername[3] = 'p';
szgetpeername[4] = 'e';
szgetpeername[5] = 'e';
szgetpeername[6] = 'r';
szgetpeername[7] = 'n';
szgetpeername[8] = 'a';
szgetpeername[9] = 'm';
szgetpeername[10] = 'e';
szgetpeername[11] = 0;
if ( fnWSAStartup
    && !((int (__stdcall *)(signed int, WSAData *))fnWSAStartup)(2, &wsadata)
    && (unsigned __int8)wsadata.wVersion == 2 )
{
    g_fnSafeGetPeerName = MyGetProcAddress((HINSTANCE__ *)*(&g_hSafeWs232AdrList + num), szgetpeername);
    if ( !g_fnSafeGetPeerName )
      g_fnSafeGetPeerName = GetProcAddress(hWs2_32Dll, szgetpeername);
}
else
{
    g_fnSafeGetPeerName = GetProcAddress(hWs2_32Dll, szgetpeername);
}
hideStart = rand() % 5 + 64;
for ( j = 0; j < 6; ++j )
    [b]HideDll((HINSTANCE__ *)*(&g_hSafeWs232AdrList + hideStart++));[/b]
pbAddr = g_fnSafeGetPeerName;
dwStart = g_fnSafeGetPeerName;

Now, in order to fix the problem we need to strip this block. However, since any localhost that isn't v90 happens to be VMed here, and for versions where we don't have the luxury of a localhost, this is going to be very difficult. Thus, instead of stripping this out, we just patch the HideDll function so that it does nothing and ends there.

Alright, so let's get started by finding the HideDll function! Unfortunately, I've been unable to get an accurate AoB that works on all client versions (Themida VM makes it veri veri hard). So, the next best thing is finding the function above it through AoBs :).

Make sure you have an IDB made for whatever version you're trying to do this for. It doesn't matter if it's a memory dump or your imports table is destroyed, as long as you got a working IDB. Open up IDA, and use the hotkey ALT + B. When it asks to enter a binary string (an AoB -- "Array of Bytes" for those who aren't aware), input the following: 55 8B EC 81 EC ?? 03 00 00. Ensure that the direction is set to Search Down, the base is set to Hex, and "Find all occurrences" is checkmarked.
Eric - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums

Once you're sure everything is correct, click OK and a occurrences window will appear in a new tab. A handful of functions will appear depending on your client version, but it'll always be the first function. Go ahead and double-click to move to the function in IDA view.
Eric - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums

The name of this function is called "DeleteNstSafeDll" (feel free to name it if you wish), and if the AoB worked yours should looks similar to mine.

Now that you've found the DeleteNstSafeDll function, right below it (always!) is the obfuscated (Themida VM) HideDll function. So, simply put, just scroll down to the next function (where the base pointer is pushed onto the stack) like so:
Eric - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums

Once you've found it, click (select) the address of the "push ebp" instruction, and use the hotkey P. This will create the HideDll function that simply calls a JUMPOUT to the VM table. Feel free to psuedo-code (F5 hotkey of course) and name it if you wish.

Finally, take note of the address that contains the "push ebp" instruction. This is the address that we'll be modifying. At this address, you're going to want to clear the register and return:
Code:
33 C0     xor eax, eax
C3        ret

...and voila, you're done! This will patch the HideDll function, and as a result the client should open without any issues.

It should be noted that while HideDll exists in almost every client version basically, that it isn't a problem because it's unused up until IP checks were introduced. Thus, this is irrelevant on versions at least up to v62 that I'm aware of.
 
Newbie Spellweaver
Joined
Apr 9, 2008
Messages
17
Reaction score
0
Hello! I'm trying to follow the instructions for fixing the hang issue on a v117 client dumped with ollydbg but when searching 55 8B EC 81 EC ?? 03 00 00 and clicking the first function im not finding the "DeleteNstSafeDll" think you could help me out with this?
Finally, take note of the address that contains the "push ebp" instruction. This is the address that we'll be modifying. At this address, you're going to want to clear the register and return:
Code:
33 C0     xor eax, eax
C3        ret

Also you completely lost me here. im not sure what "clear the register and return:" means. D=

Thanks so much for your time!
-Your friendly neighborhood leecher
 
Junior Spellweaver
Joined
Sep 16, 2017
Messages
156
Reaction score
36
I don't have a v117 client so I can't help you with the first part of your question, but as for this:

im not sure what "clear the register and return:" means. D=
"xor eax, eax" is a way to zero the register EAX, which is what Eric intended.
"ret" is the final return of the function, that makes the code jump back to where that very function was called from. (Well, to the address right after* the one the function was called from, to be precise)
 
Newbie Spellweaver
Joined
Apr 9, 2008
Messages
17
Reaction score
0
I guess i should have said that not only do i not know what it means but i don't know how to do it either xD got a good link to learn some basics on how to use ida?
 
Junior Spellweaver
Joined
Sep 16, 2017
Messages
156
Reaction score
36
I guess i should have said that not only do i not know what it means but i don't know how to do it either xD got a good link to learn some basics on how to use ida?
This link offers a nice guide to start moving some steps in IDA, so it should help. c:

By the way, I guess I didn't properly read your question at first, since I missed it: you can't find the function DeleteNstSafeDll because it's not named yet, the renaming is suggested by Eric for clarity and future reference.
The important part is that, right under it (aka after the "endp" mention), you'll find those 5 instructions highlighted in the screenshot, and followed by that block of multiple "dd" lines.

~
On another note, I'd have a question for Eric .
I tried to apply the fix on my v83 server, but a Staff member of mine still had troubles launching the game.

While I wasn't much into client development yet, when the first Incorrect parameter error fixes were showing up, I believe this was the only edit that requires reverting:
1nAmrQi - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums

(which was basically just ignoring potential invalid values from DirectInput8Create I guess)

We don't have the old Sleep() trick implemented, so that should be all.

However, after reverting it and applying a hook/detour from a dll injected via ijl15, the missed CoInitialize call still laughs at us:
8b4efab5ad89e8bbfd4f4c9295045f5b - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums
Judging by that debug text I left, the function seems to get correctly called and re-called in case of failure, which definitely gets rid of any parameter error messages.

Is it possible that there's other required edits, to get the client not to mess up CoInitialize?

Also worth noting, after including the HideDll fix (with all the above still in place ofcourse), the client launched in Win10 started experiencing a different error,
d5f30eb47775fa54705313d39b2cd36f - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums
, which should be related to Direct3D initialization, although the user never had any issues like that before.
No more CoInitialize error messages, although this might be due to the Direct3D error happening prior to that.

Results after applying the fix with your dinput8.dll wrapper instead of the dll hook fix are the same, with this "new" error code showing up.

Is it possible that I missed some old "anti-parameter error" applied workaround to revert? As far as I'm aware, the most common one was the Sleep one, but, were there others I might need to check for?

Thanks for your releases by the way c: and thanks to anhtanh95 for the hook information aswell.
 

Attachments

You must be registered for see attachments list
Junior Spellweaver
Joined
Mar 16, 2013
Messages
167
Reaction score
19
Thanks for sharing!
Can you upload this lib without console?
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
@Pipotron Well for starters, I wasn't even aware that the HideDll issue had been occurring on v83.. I know that it's an issue on v90, v92, and v97, but thought it didn't affect v83 users. Also, the HideDll fix (if done right) should have no change in outcome regarding DirectX. This is simply to make Nexon's ws2_32 checks stfu and continue. So, if by clearing the register and returning is causing this issue, it could be because v83 might use HideDll for more than just one thing, or something was changed in CWvsApp::SetUp already (Spudgy could have altered this within the vm to bypass IP checks).

In regards to CoInitialize, I haven't yet had this issue happen to me on v83 (it does with the "sleep-workaround" still in the localhost, but not with the hooks on a clean client). Your debug logged that it was called twice, but iirc that function should only have been executed once (unless the other call was external and I don't remember, my bad then). You can try doing and just hook both GetModuleFileNameW and DirectInput8Create as well. Then, within the DirectInput8Create hook, do a Sleep(2000) and then return the call. This is replicating the "sleep-workaround", but with a cleaner use of hooks. Maybe with the two combined it will fix your issues? To be honest though, I'm starting to think that the additional problems being caused with v83 is just because it's a poorly constructed localhost..

EDIT:
Thanks for sharing!
Can you upload this lib without console?

 
Last edited:
Experienced Elementalist
Joined
Feb 10, 2008
Messages
249
Reaction score
161
v95

Code:
const DWORD		g_HideDll = 0x0045EBD0;
//Extras
const DWORD		g_AhnHS_HSUpdateA = 0x00A23926;const DWORD		g_AhnHS_InitializeA = 0x00A20A02;const DWORD		g_AhnHS_StartService = 0x00A20B7C;const DWORD		g_TSingleton_CSecurityClient__IsInstantiated = 0x004AD020;const DWORD		g_TSingleton__CSecurityClient__ms_pInstance = 0x00C68E30;const DWORD		g_CSecurityClient__Update = 0x00A1A730;const DWORD		g_CSecurityClient__InitModule = 0x00A1A9C0;const DWORD		g_CSecurityClient__ClearModule = 0x00A1AD70;const DWORD		g_CSecurityClient__StartModule = 0x00A1ABA0;const DWORD		g_CSecurityClient__StopModule = 0x00A1AE10;const DWORD		g_SendHSLog = 0x009BF799;const DWORD		g_DR_check = 0x004AB900;const DWORD		g_CeTracer__Run = 0x009BF370;const DWORD		g_ShowStartUpWndModal = 0x009BF390;
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
@Pipotron Okay, so I decided to test this out more. Normally I could care less about v83, but after having those errors as well it peeked my interest.

So, for starters, I tried doing numerous different "fix" attempts on your public v83 localhost that everyone here is using. After applying the GetModuleFileNameW hook I would no longer get an incorrect parameter, but it would fail to start sometimes. The first error that I had experienced was CoInitialize was not called, and this happened a few times but was not consistent. Then, the next error I had got was the one you had mentioned after bypassing HideDll. Unlike the former, this error was consistent -- it would sometimes take me 10 tries to start the client because of this error. Even after hooking into DirectInput8Create and sleeping the thread, that error would still occur and crash the client.

It wasn't until the next morning that I realized the problem I was having with the d3d error was because of my HideDll bypass. More specifically, it was because my HideDll bypass is meant for v90+ clients (I use my own personal AoB for the newer function entry point). What was happening as a result was the v83 client AoB'd some other function and force-returned that instead. Whooops.. I memed myself there :( However, even after I had fixed that issue, the CoInitialize errors were still happening for some reason.

This is where my theory of it being a problem because v83's localhost is a meme came to the test. I ended up making my own v83 localhost (well, a LEN at least) and after having spent some time tackling my HS and MSCRC bypasses, I was able to get everything working. Just the same, I hooked GetModuleFileNameW (but completely ignored DirectInput8 cause that's useless here) and with my MSCRC bypass I was able to force-return HideDll. As a result, my own v83 localhost starts up (faster too lmfao) without any CoInitialize or d3d error codes. I've tested this on MapleMS, Dream-MS, and Serenity to confirm, having ran the client almost a hundred different times with 100% success rate.

So basically, as I had expected, the v83 people are just having problems because of the localhost everyone is using. That, or I just have absolutely horrible luck when it comes to getting the v83 client to start. Anywho, just to confirm, make sure you're doing 33 C0 C3 at address 0044EC9C for v83. If that's not the address you have for HideDll, then that's definitely why you're getting weird d3d errors.
 
Junior Spellweaver
Joined
Sep 16, 2017
Messages
156
Reaction score
36
@Eric thank you so much for testing! It looks like I'll go ahead and work on making a localhost of my own.

Anywho, just to confirm, make sure you're doing 33 C0 C3 at address 0044EC9C for v83. If that's not the address you have for HideDll, then that's definitely why you're getting weird d3d errors.
Yep, 0044EC9C is exactly the address I had reached following your guide, so that one atleast should be good to go: I found it as first occurrence with the AoB you had provided.
 
Junior Spellweaver
Joined
Sep 2, 2016
Messages
102
Reaction score
2
@Pipotron Okay, so I decided to test this out more. Normally I could care less about v83, but after having those errors as well it peeked my interest.

So, for starters, I tried doing numerous different "fix" attempts on your public v83 localhost that everyone here is using. After applying the GetModuleFileNameW hook I would no longer get an incorrect parameter, but it would fail to start sometimes. The first error that I had experienced was CoInitialize was not called, and this happened a few times but was not consistent. Then, the next error I had got was the one you had mentioned after bypassing HideDll. Unlike the former, this error was consistent -- it would sometimes take me 10 tries to start the client because of this error. Even after hooking into DirectInput8Create and sleeping the thread, that error would still occur and crash the client.

It wasn't until the next morning that I realized the problem I was having with the d3d error was because of my HideDll bypass. More specifically, it was because my HideDll bypass is meant for v90+ clients (I use my own personal AoB for the newer function entry point). What was happening as a result was the v83 client AoB'd some other function and force-returned that instead. Whooops.. I memed myself there :( However, even after I had fixed that issue, the CoInitialize errors were still happening for some reason.

This is where my theory of it being a problem because v83's localhost is a meme came to the test. I ended up making my own v83 localhost (well, a LEN at least) and after having spent some time tackling my HS and MSCRC bypasses, I was able to get everything working. Just the same, I hooked GetModuleFileNameW (but completely ignored DirectInput8 cause that's useless here) and with my MSCRC bypass I was able to force-return HideDll. As a result, my own v83 localhost starts up (faster too lmfao) without any CoInitialize or d3d error codes. I've tested this on MapleMS, Dream-MS, and Serenity to confirm, having ran the client almost a hundred different times with 100% success rate.

So basically, as I had expected, the v83 people are just having problems because of the localhost everyone is using. That, or I just have absolutely horrible luck when it comes to getting the v83 client to start. Anywho, just to confirm, make sure you're doing 33 C0 C3 at address 0044EC9C for v83. If that's not the address you have for HideDll, then that's definitely why you're getting weird d3d errors.

Do you use discord?
 
Newbie Spellweaver
Joined
Dec 12, 2017
Messages
10
Reaction score
0
can you explain how to jump another destination too?
this part 0085EC08 (JMP 0085EE88)

 
Junior Spellweaver
Joined
Sep 16, 2017
Messages
156
Reaction score
36
can you explain how to jump another destination too?
this part 0085EC08 (JMP 0085EE88)


If you're asking what that line means, it's that, at address 0085EC08 of your client, you will need to insert the instruction "JMP 0085EE88".
 
Newbie Spellweaver
Joined
May 24, 2019
Messages
26
Reaction score
2
HI.

I see you tutorial @Eric, but in version 111, this oab 55 8B EC 81 EC ?? 03 00 00 i see function in picture. But it's not a function for my shange.


Eric - Modern OS Support (Win8/8.1/10 'Fix') - RaGEZONE Forums
 
Back
Top