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!

[Tutorial] Analyzing a MapleStory 2 Client

Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
With all of the resources I have provided, the only thing left to do is show you how to go about analyzing MapleStory 2 clients. I highly recommend relying on this for your packet structures, and then you can sniff the live servers to determine what the values of each byte actually is. This way, you will always have the correct packet data. A very common problem in MapleStory is the lack of using analyzed clients, and thus having to pad your packets with zeroes to prevent your game client from crashing. Let's not repeat past mistakes ;)

Before we get started, I'm only going to say this once - the process of creating, analyzing, and working with IDA is a steep learning curve at first. However, once you've gotten the hang of the basics (which is really just trial and error, and asking questions), then it's really easy from there and will help you out a lot!

In order to analyze a MapleStory 2 client, you're going to need a handful of tools:
- (archive password: tuts4you)
-
- (if running a x64 system)
-
-
- (installation key: qY2jts9hEJGy)
-
- MapleStory 2 Application (and its dependency DLLs)

1a. Installation
If you currently have IDA 7.0 installed, the IDC and Themida unpacking scripts downloaded, OllyDbg previously configured, and a working anti-debugger such as ScyllaHide, StrongOD, or PhantOm already setup, then you may skip to step 2.

First, download and run the installation for IDA Pro 7. When prompted, enter in the installation key to continue and finish. It should setup 32-bit shortcuts on your desktop and/or start where you'll be accessing it later. After that's setup, go ahead and download the MapleStory 2 IDC script, and put it on your desktop or wherever you plan to store your IDA stuff (IDBs, scripts, etc) - we'll be using this later.

Next, download and extract OllyDbg somewhere. Make sure the location is ignored by your antivirus because it'll be deleted, since they don't like us reverse engineering ;). Once you've downloaded and extracted Olly, go ahead and download OllyDumpEx and extract into OllyDbg's "Plugin" folder.

Then, create a new folder called "Scripts" in OllyDbg's "Plugin" folder. Download and move the Themida unpacking script to that "Scripts" folder you just made.

Finally, right-click on OllyDbg and run the program as administrator. Once it's loaded, navigate to Options->Appearance. Move over to the "Directories" tab and verify that these locations are correct. If you are for some reason using remote directories, then browse for their locations. After everything is correct, click OK, and exit out of OllyDbg.

1b. Installation Continued (x64)
If you are NOT running on an x64 based system, then you may skip this step (to step 2) because OllyDbg comes with StrongOD by default. Otherwise, go ahead and download and extract ScyllaHide somewhere.

First, copy over the "HookLibraryx86.dll" and "scylla_hide.ini" files from the ScyllaHide folder, into your OllyDbg's "Plugin" folder. You won't need to configure any of these settings, so don't worry about them.

Next, go into the "plugins" folder, and copy over the "ScyllaHideOlly1Plugin.dll" file into your OllyDbg's "Plugin" folder. These are all the necessary Scylla library plugins needed.

Then, go into the "NtApiTool" folder, and you'll see x64 and x86 folders - select the x86 folder. Now, run the "PDBReaderx86.exe" file, and give it some time. This might take a few moments to finish, so just let it run its course - it'll download PDBs off Microsoft's servers before it processes everything.

Finally, once the program has finished, a "NtApiCollection.ini" file will be generated. All you need to do now is just copy that file into OllyDbg's "Plugin" directory.

2. Unpacking the MapleStory 2 Client
Now that we have configured IDA, Olly, and our anti-debuggers, we're ready to unpack the client! By using an old Themida unpacking script, we can unpack the sections of the client, and then dump the process.

First, open up OllyDbg (run as administrator!) and navigate to File->Open to select the MapleStory2.exe file. It should load the packed application's binary code into Olly without a problem.

Next, right-click anywhere in the main thread window (the window with the assembly code instructions), and navigate to "Run Script". Select "Open", browse to your OllyDbg's Plugin->Scripts folder, and select the Themida unpacking script. Now, a popup will appear asking you to unpack the client, click Yes.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


It will proceed to ask you if you want to run the SetEvent finder, click No.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


The script will execute and eventually pause, opening a Log data window. Feel free to move them off to the right or something, these aren't important. Anywho, after the execution is paused, right-click once again and navigate to "Script Functions". In the sub-menu, select "Resume" to continue execution. If you're on an x64 OS, you're going to get a popup below, but don't worry - just click OK and ignore this.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


After execution was resumed, you should get a new popup regarding your configuration. Click OK so we can configure what it's asking. Navigate to Plugins->StrongOD, and in the sub-menu select "Options". Toggle "KernelMode" so that it's enabled, and click save. Now, navigate to Plugins->PhantOm, and in the sub-menu select "Options". Toggle "Protect DRx" so that it's enabled, and click save. Once you're done, exit out of OllyDbg completely, and re-run it (again, as admin).

After you've successfully restarted OllyDbg, navigate back to Plugins->StrongOD->Options, and make sure "KernelMode" is enabled. If it is, click cancel. Now navigate back to Plugins->PhantOm->Options, and make sure "Protect DRx" is enabled. If it is, click cancel and we're good to go. Since our configuration has been updated, we must repeat our previous steps again. Run the script, and answer the prompts until you get back to where you were. When you've gotten to the previous point, your window should be correctly configured on the prompt:
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


This time, click OK, and afterwards you can continue script execution (right-click, Script Functions->Resume). Another prompt will appear regarding the magic jumps, click Yes.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Directly after, a nopper check prompt will come up, click No here.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Give it a few moments to breakpoint some things, and then you'll get a prompt regarding the VM OEP Turbo finding method. You'll click Yes to this one.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


This will take a bit of time to process, maybe a minute or two. Watch the progress at the bottom left of OllyDbg carefully, and it'll eventually log "No API in eax register!!". We don't really care because all we're using this for is basically just a memory dump. Nonetheless, once you see this (and at the top-left of Olly it says "Paused"), navigate to Plugins->OllyDumpEx, and in the sub-menu select "Dump process".

After you've opened OllyDumpEx, a window should appear with an active base module, an image base at 0x400000, and the sections within the PE. It should look like this below.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Finally, select "Dump", and save the target file as "MapleStory2_dump" somewhere. Once it finishes dumping and it lets you know, close out of OllyDumpEx (click "Finish"), and close the process by navigating to Debug->Close. After it unloads the process, you can exit out of OllyDbg. Now you've got yourself a unpacked dump of the MapleStory 2 client! If done correctly, the size of the dump file should be between 34~40MB.

3. Analyzing the Client -> IDB
If you've gotten this far, then the complicated and annoying part is over with! All we've got to do now is analyze the application and let IDA construct an IDB file for us to use.

First, open up IDA Pro 7.0 and click OK on the about screen. Navigate to File->Open, and browse for the "MapleStory2_dump.exe" file that you just made. A window will pop up, just keep the default settings and make sure Portable Executable is selected. Click OK when you're done.

Next, you'll receive a popup regarding the image base not being loaded into the database. Simply click Yes to load the image base into the database, and continue parsing. If a warning regarding the imports section being destroyed pops up, just click OK to continue.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Then, we wait! IDA will begin to analyze the client and construct an IDB. Depending on your computer specs, this might take a LONG TIME. For me, I can analyze the client in less than an hour (averaging ~30min), so it'll vary for you. Just give it time and let it do its thing! Once it's done, it'll ding and display a graph view. Right-click anywhere in the graph view, and select "Text View" to return to disassembly view.

Finally, to get us started with our IDB, we can use my MapleStory 2 IDC script. This will be a very useful script for you to use because it'll work for almost every version, naming the important functions needed to update your packets automagically for you. To run a IDC script, navigate to File->Script File, and select the script you've downloaded. It will run and name the important functions for you. It should output that it's found functions, like so:
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


4. Setting up your IDB
So you've finally got your IDB ready to go, and now you're wondering how to get started. Before we can do anything, we first want to setup our IDB. The first thing I do after executing my IDC scripts and clicking "Function name" in the Functions window to sort my functions alphabetically is the hotkey CTRL + W. This will write your current data to your IDB file so that you won't lose stuff if IDA or your PC crashes. I recommend doing this every so often when naming a lot of functions in your IDB. Then, I load the Strings Window so that I can use them to my advantage for finding things. Right-click on the toolbar, and checkmark "Lists" if it isn't already checked. A new group of icons will appear on the toolbar, and you're going to want to select the one with the icon of 's'. This will generate all strings within the application.

Once you've got your windows setup, we need to add type information (structures) so that we can read the packet calls. Unlike in MapleStory where packet calls are actual functions (CInPacket::Decode4, for example), MapleStory 2 uses virtual calls everywhere. This means, in order to know what function is being called, we need to have a structure loaded that can be assigned to a variable. Use the hotkey SHIFT + F1 to open up a Local Types window. Within the Local Types window, we're going to need to add a few structures:

1. The CInPacket vftable
2. The CInPacket class
3. The COutPacket vftable
4. The COutPacket class

To insert a new structure into IDA's Local Types window, you can use the hotkey INS, or right-click and select Insert. Here are the structures you're going to need, in order. Do not place all of them in one struct and click OK. You must repeat the process for EACH structure!
PHP:
struct CInPacket_reader_vtbl
{
  int (__thiscall *Decodeb)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode1)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode2)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode4)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode8)(CInPacket_reader_vtbl *);
  int (__thiscall *Decodef)(CInPacket_reader_vtbl *);
  int (__thiscall *DecodeWstrA)(CInPacket_reader_vtbl *);
  int (__thiscall *DecodeStrA)(CInPacket_reader_vtbl *);
  int (__thiscall *DecodeStrW)(CInPacket_reader_vtbl *);
  int (__thiscall *DecodeBuffer)(CInPacket_reader_vtbl *);
  int (__thiscall *DecodeCoordsf)(CInPacket_reader_vtbl *);
  int (__thiscall *DecodeCoords2)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode2ft10)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode2ft100)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode2ftx)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode2ftp1)(CInPacket_reader_vtbl *);
  int (__thiscall *Decode2fdx)(CInPacket_reader_vtbl *);
};
PHP:
struct CInPacket
{
  CInPacket_reader_vtbl *iPacket;
};
PHP:
struct COutPacket_writer_vtbl
{
  int (__thiscall *Encodeb)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode1)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode2)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode4)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode8)(COutPacket_writer_vtbl *);
  int (__thiscall *Encodef)(COutPacket_writer_vtbl *);
  int (__thiscall *EncodeWstrA)(COutPacket_writer_vtbl *);
  int (__thiscall *EncodeStrA)(COutPacket_writer_vtbl *);
  int (__thiscall *EncodeStrW)(COutPacket_writer_vtbl *);
  int (__thiscall *EncodeBuffer)(COutPacket_writer_vtbl *);
  int (__thiscall *EncodeCoordsf)(COutPacket_writer_vtbl *);
  int (__thiscall *EncodeCoords2)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode2ft10)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode2ft100)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode2ftx)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode2ftp1)(COutPacket_writer_vtbl *);
  int (__thiscall *Encode2fdx)(COutPacket_writer_vtbl *);
};
PHP:
struct COutPacket
{
  COutPacket_writer_vtbl *oPacket;
};

Once you've added all of these into your Local Types window, you'll now be able to successfully assign variables to these structures to see their calls.

5. Assigning Variables to CInPacket/COutPacket References
So now that your IDB is all set up, you just need to know how to read the packet calls! When you're working with standard decodes (Decode1/2/4/etc), things aren't that bad. However, just wait until you hit a virtual object decode (CItem::Decode, for example). Finding those is a lot more painful.

Alright, so let's start off by naming Nexon's CClientPlatformNexonAmerica::OnSendLoginResult function. Just like you would with any other IDB, double-click on the function in IDA and use the hotkey F5 to decompile the function into C pseudo-code. If you scroll down a little, the function will look like this:
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Notice the highlighted function? The "v4" variable that was assigned from a2 (iPacket) is your CInPacket reference. For anyone who isn't experienced with these MapleStory class names, the client's CInPacket is when the client is decoding a packet from the server. The client's COutPacket is when the client encodes a packet to send to the server. Furthermore, double-click on the highlighted function present to view its pseudo. At first, it'll look pretty scary because it's a CInPacket with no structure, so we have absolutely no clue what is being called.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Let's clean this up, shall we? If you're picky and prefer not to have typecasting enabled (which may help you in the future), you can use the hotkey Tab to disable all of the casting. Now, to convert this into readable function calls, right-click on the "v3" variable, and select "Convert to struct".
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


It will open a window of available structures. Select the CInPacket structure that we just added, and click OK to watch the magic happen. After assigning it into a structure, your pseudo should now look like this:
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Perfect! Now, when we setup those calls in the packet on our server, it would look something like this:
PHP:
public static OutPacket onSendLoginResult(ClientSocket socket, int loginState, int blockType) {
    OutPacket packet = new OutPacket(LoopbackPacket.SendLoginResult);
    packet.encodeByte(loginState);
    packet.encodeInt(50);//Unknown
    packet.encodeStringW(socket.getPassport());
    packet.encodeLong(socket.getAccountSN());
    packet.encodeLong(socket.getSyncTime());
    packet.encodeInt(socket.getSyncTicks());//Unknown
    packet.encodeByte(socket.getSyncTimeZone());
    packet.encodeByte(blockType);
    packet.encodeInt(10);//Unknown (this is a static constant that xrefs to UGC-related poop)
    packet.encodeLong(123456789);//Unknown (this is a static constant that xrefs to UGC-related poop)
    if (blockType == 1) {
        packet.encodeLong(socket.getBlockDate());//Unknown
    } else if (blockType == 2) {
        packet.encodeLong(socket.getBlockDate());//Unknown
        packet.encodeLong((System.currentTimeMillis() / 1000) + 1000);//Unknown
    }
    packet.encodeInt(3);//Unknown (client checks if this is 3 in multiple locations)
    return packet;
}

I hope this gives you a good basic understanding on how exactly packets will look like throughout the client. Before I go over the OnPacket functions, let me give you a quick overview of what each type of Decode call means in MapleStory 2.

  • Decodeb - This decodes a boolean (internally this is just Decode1() != 0)
  • Decode1 - This decodes a single byte (e.g 1 -> 01)
  • Decode2 - This decodes a 2-byte short (e.g 1 -> 01 00)
  • Decode4 - This decodes a 4-byte integer (e.g 1 -> 01 00 00 00)
  • Decode8 - This decodes a 8-byte long (e.g 1 -> 01 00 00 00 00 00 00 00)
  • Decodef - This decodes a 4-byte floating point value
  • DecodeWStrA - This decodes a wide-character (unicode) string and converts it into ANSI
  • DecodeStrA - This decodes an ANSI string (short size, byte[] characters) (e.g 'Eric' -> 04 00 45 72 69 63)
  • DecodeStrW - This decodes a wide-character string (short size, ushort[] characters)
  • DecodeBuffer - This decodes a given amount of bytes provided as a parameter (usually decodes structs)
  • DecodeCoordsf - This decodes a 3D coordinate set (x, y, z) as floats.
  • DecodeCoords2 - This decodes a 3D coordinate set (x, y, z) as shorts.
  • Decode2ft10 - This decodes a short and multiplies it by 10.0 (mainly used for movement)
  • Decode2ft100 - This decodes a short and multiplies it by 100.0 (mainly used for movement)
  • Decode2ftx - This decodes a short and multiplies it by a given floating-point value.
  • Decode2ftp1 - This decodes a short and multiplies it by 0.1 (mainly used for movement)
  • Decode2fdx - This decodes a short and divides it by a given floating-point value.

In addition to the given list, is CInPacket::DecodeHeader. This calls CInPacket::SetOffset(6) which is the end of the packet header, and then decodes a short which is the opcode. This function is used in several places and is named by my IDC script. By xrefing this, you'll always be able to find the major OnPacket functions all around the client.

6a. Understanding MapleStory 2 Functions
Diving right into MapleStory 2 clients isn't going to be too simple at first, but you'll get a better understanding over time. To help make it easier, I'll try my best to explain some of the important functions.

Alright, so I'm going to assume a majority of you have been around the MapleStory scene. In the MapleStory sections, a leaked v95 GMS PDB exists, and we have used this for years to reference what specific functions should look like. In MapleStory 2, I use the same principle, but without a fully-named PDB. You're probably wondering how this would be possible if we have nothing to go by since there's no debug info or names yet.

Your unpacked MapleStory 2 clients will actually include type names. Remember when I showed you how to enable the Lists in the toolbar? Two icons to the left of the Strings Window ('s'), or in the center of the section, is a Names Window. As I mentioned previously, Nexon uses virtual calls everywhere because they use a whole ton of abstraction. Take a look at my names window, and you'll notice that theres a base class called CClientPlatformNexonAmerica, just like I used to name the OnSendLoginResult function. This is Nexon's actual class names, and just like the process from MapleStory, I name my IDBs the same names Nexon uses.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


Cool, huh? So now we know what the classes are, but we need to know the names of the functions. How can we go upon doing that? Well, up until MapleStory 2 v100 (latest client), Nexon has had a debug function in the client. This function would create two giant mappings of every Send opcode (ks_PACKET), and every Receive opcode (kc_PACKET). Using this function, we can get the name of the opcode that Nexon uses, and apply it to the class name to construct our OnPacket functions! This is exactly how CClientPlatformNexonAmerica::OnSendLoginResult was formed. We take the name of the class, and then from the opcode form the function name: "ks_send_login_result" -> SendLoginResult -> OnSendLoginResult.

As a reference, you can head over to my Library of MapleStory 2 IDBs thread and download the Version 70 IDB. Then, you can reference to name functions not already named in that IDB. From there, if you're having trouble confirming an opcode in v100, you can take a look at the function from v70 and see if they look the same. If they are the same function, then you've found the function for your opcode in your new client.

duck u auto save, will rewrite the rest of this again later :(

6b. Finding MapleStory 2 Functions
I'll wrap everything up by going over how to find some important functions in the client from the ones already provided to you by my IDC script.

I will finish the rest of this later~
 
Last edited:
Newbie Spellweaver
Joined
Sep 21, 2014
Messages
13
Reaction score
0
how should I handle patch stuffs at the very beginning of launching
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
Can you explain how you got the structures of the virtual calls please?

Of course. While I was originally given different structures from a friend when we first started, I realized the order and what all the functions truly were shortly after. Anywho, in the Strings Window find "Decode1", and simply double-click it. Then, it'll take you to an IDA disassembly view with the names of most CInPacket functions:
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


If you scroll up, you'll find right above it is the CInPacket vftable.
Eric - [Tutorial] Analyzing a MapleStory 2 Client - RaGEZONE Forums


If you view a few of the functions, you'll be able to determine which is which. For example, the second function will call a += function -- this function is the one which contains the string "Decode1". The one after it was Decode2, then Decode4, and so on and so forth. Since we know which is which within this vftable, we just have to create a structure that represents this vftable. Thus, the CInPacket/COutPacket virtual calls were formed. From there, assuming you have a C++ understanding, you'd know how the structures would be defined as.

In regards to finding the structures of the other virtual calls, I haven't really. I can find which specific function is being called somewhere and determine whether or not a function is a Decode and the other an Encode, but that's about it. When it comes to tracing back where the virtual call outside of a CInPacket/COutPacket reference came from, it's extremely difficult to do in IDA. For this reason, tracing back class decodes is done by breakpointing the address in Cheat Engine and following the stacktrace to see where the next location is. Unfortunately, that's the best way upon doing so since we have no PDB to rely on to get us there any faster. I'll show an example on how exactly this is done when I finish writing the last two sections of the thread.
 
Newbie Spellweaver
Joined
Jan 28, 2015
Messages
5
Reaction score
1
Some useful signatures.
Game use lua5.1.4, but I had what I had and wasn't in the mood to make a new one.
Gamebryo probably the same as game uses, you can find sources leaked by our chinese friends on the internets.
gamebryo:
lua5.1.5.sig:
zlib1.2.8.sig:
 
Joined
Jun 11, 2008
Messages
588
Reaction score
45
If you view a few of the functions, you'll be able to determine which is which. For example, the second function will call a += function -- this function is the one which contains the string "Decode1". The one after it was Decode2, then Decode4, and so on and so forth. Since we know which is which within this vftable, we just have to create a structure that represents this vftable. Thus, the CInPacket/COutPacket virtual calls were formed. From there, assuming you have a C++ understanding, you'd know how the structures would be defined as.

In regards to finding the structures of the other virtual calls, I haven't really. I can find which specific function is being called somewhere and determine whether or not a function is a Decode and the other an Encode, but that's about it. When it comes to tracing back where the virtual call outside of a CInPacket/COutPacket reference came from, it's extremely difficult to do in IDA. For this reason, tracing back class decodes is done by breakpointing the address in Cheat Engine and following the stacktrace to see where the next location is. Unfortunately, that's the best way upon doing so since we have no PDB to rely on to get us there any faster. I'll show an example on how exactly this is done when I finish writing the last two sections of the thread.
Looking forward to it, thanks for the breakdown.
 
Newbie Spellweaver
Joined
Feb 21, 2016
Messages
30
Reaction score
3
did nexon remove opcode information in v101? i can't find any of them (kc_blah, ks_blah).
if so, can you upload idb of v101?
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
did nexon remove opcode information in v101? i can't find any of them (kc_blah, ks_blah).
if so, can you upload idb of v101?

Did you read the thread?
Eric said:
Cool, huh? So now we know what the classes are, but we need to know the names of the functions. How can we go upon doing that? Well, up until MapleStory 2 v100 (latest client), Nexon has had a debug function in the client.

According to Tachi Orz MS2 clients after v74 no longer have them, and Nexon has changed/added quite a few opcodes in between now cause they're annoying like that. I'll go ahead and upload v100 to my library, but the point of this thread is to help you guys be able to do it on your own. Following this tutorial step-by-step should allow you to make a functional IDB for v101 without a problem. Are you stuck somewhere in the tutorial? If so, just let me know; I'm here to help.

EDIT: Oh, apparently I already made a v101 IDB. Guess I was using it to confirm the crypto index formula, so I'll upload that one as well. Still, though, try to follow this tutorial next time so that you can make and update these IDB's yourself :p

You can find the v100 and v101 IDB's here: http://forum.ragezone.com/f1005/library-maplestory-2-client-idbs-1156517/
 
Last edited:
Newbie Spellweaver
Joined
Feb 21, 2016
Messages
30
Reaction score
3
Did you read the thread?


According to @Tachi Orz MS2 clients after v74 no longer have them, and Nexon has changed/added quite a few opcodes in between now cause they're annoying like that. I'll go ahead and upload v100 to my library, but the point of this thread is to help you guys be able to do it on your own. Following this tutorial step-by-step should allow you to make a functional IDB for v101 without a problem. Are you stuck somewhere in the tutorial? If so, just let me know; I'm here to help.

EDIT: Oh, apparently I already made a v101 IDB. Guess I was using it to confirm the crypto index formula, so I'll upload that one as well. Still, though, try to follow this tutorial next time so that you can make and update these IDB's yourself :p

You can find the v100 and v101 IDB's here: http://forum.ragezone.com/f1005/library-maplestory-2-client-idbs-1156517/
Thanks Eric!
now i'm working on the real server.
but how should i handle 'BypassKey'?
it seems like the server keeps sending it

And do you know why the client disconnects form server after few seconds at character list?
 
Last edited:
Skilled Illusionist
Joined
Apr 26, 2015
Messages
302
Reaction score
77
I still wonder why nexon kept those information in client in first place. Where are their security team that are supposed to analyse the binary before sending to production...

Anyways, very good job Eric!
 
Initiate Mage
Joined
Jan 24, 2016
Messages
1
Reaction score
0
I still wonder why nexon kept those information in client in first place. Where are their security team that are supposed to analyse the binary before sending to production...

Anyways, very good job @Eric!

Not really what a security team is suppose to know. They would need knowledge of the language and their entire source code which seems to be a waste of money. Usually these stuff are easily excluded from the build process with macros (easier imo) or just using a compile-time constant and letting the compiler optimize it away if DEBUG is false or true. Former is safer obviously.

Also the reason the game has RTTI is due to their HEAVY use of dynamic casting which needs RTTI info. So they either need to redo lots of stuff and disable RTTI compiler settings or just let it be how C++ is.
 
Last edited:
Initiate Mage
Joined
Jan 25, 2019
Messages
1
Reaction score
0
Hi, I am Korean.
I came across it while surfing the Internet to analyze Maple Story 2's client.
This process is very interesting and creates a challenging spirit.
However, there are some problems.
The site linked to ScylaHide disappeared. So I got another file from the Internet and replaced it. So an error(Distrom err - I_MOV, GetSysCallIndex32 -> not found) occurred during the unpacking process of MS2.exe. I'd like to ask you what caused this error and how to solve it.
I also want to ask if I can save Themeda Unpacking Script in Notepad format.
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
Thanks Eric!
now i'm working on the real server.
but how should i handle 'BypassKey'?
it seems like the server keeps sending it

And do you know why the client disconnects form server after few seconds at character list?

Nice! I personally don't use BypassKey, so I'm not sure how you should handle it. I've never needed it before to get anywhere. If you've figured it out by now, feel free to share~ As for disconnecting, are you sure your crypto is properly updating? If one of the crypto indexes was incorrect, you can disconnect from a single random packet. This shouldn't happen anymore now that I released the formula for it, though.

Hi, I am Korean.
I came across it while surfing the Internet to analyze Maple Story 2's client.
This process is very interesting and creates a challenging spirit.
However, there are some problems.
The site linked to ScylaHide disappeared. So I got another file from the Internet and replaced it. So an error(Distrom err - I_MOV, GetSysCallIndex32 -> not found) occurred during the unpacking process of MS2.exe. I'd like to ask you what caused this error and how to solve it.
I also want to ask if I can save Themeda Unpacking Script in Notepad format.

I've updated the link to Scylla, it seems the snapshots are actively maintained so you'll have to download the .7z file there yourself. I'm not aware of that error, so I'll assume it's because you replaced files with something else online that caused the error to occur. Try installing Scylla again and setting that up first, then replace all the DLLs in Olly like I explained, and try unpacking again. Also, yes you can save it in notepad format - that's the point of it; you right-click on the page, click Save As, and save it as the unpacking script.txt to be loaded from Olly.
 
Newbie Spellweaver
Joined
Oct 17, 2018
Messages
12
Reaction score
3
hi just wondering if this guide can possibly work for unpacking MS1 clients? or even possibly getting nexon op/class names that aren't in the leaked idbs?

This was good stuff and a real nice read. thank you for it!
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
hi just wondering if this guide can possibly work for unpacking MS1 clients? or even possibly getting nexon op/class names that aren't in the leaked idbs?

This was good stuff and a real nice read. thank you for it!

In regards to unpacking the client, this is just standard reverse engineering skills that apply to any game who uses Themida. While you can't unpack the application completely here, you could use this on older Themida versions to complete the whole process.

When it comes to getting opcodes or class names, this was just a rare mistake on Nexon's part and they quickly removed it. You won't be able to get names for opcodes in MS1 clients unless you have a PDB, and you also won't be able to get class names because MS1 is not heavy on dynamic casting and using RTTI type information. However, there is definitely other Nexon games that are like that where you can get their type names and apply the same process as I did here.

Also, it's worth noting that instead of doing a complex unpacking process, you can alternatively perform a memory dump and use that instead (could probably fix imports with this method, too). I just personally prefer to unpack.
 
Back
Top