Packet Editing

Packets
packet is a set of memory data or byte displayed in a certain format to allow users to view or manipulate it to their liking. Each section of a packet has different kinds of data stored in hexadecimal formats. Packets play a super large role in MapleStory because it can alter the game dramatically in either good or bad way. Packets can never be patched but methods of exploiting them can.

Hexadecimals
In math and computer science, hexadecimals is a number system with a base of 16. Meaning, the number starts at 0 going to 9 (10 numbers) and then from A to F (6 more) totaling 16 numbers. In the game, there's always 2 hexadecimals in every section of a packet.
For example: 88 00 05 C1 2A 55 54 89 00 00 00 00 00 00 00 00 00 FF FF FF FF
In the given, I've chosen a packet with a variety of hexadecimals.

Packet Structures
Packets can be slightly confusing in the beginning if you never worked with them. They possessed a mysterious nature because every packet has its own unique action and therefore they're structured differently from each other.

Example of a portal packet in v0.98:
2A 00 02 FF FF FF FF 06 00 65 61 73 74 30 30 03 0B FF FD 00 00 00

2A is the header of the packet. 2A represents all normal portal packets.
02 is the portal count. 02 means you've entered 2 portals during your game-play.

As for the rest of the packet, they are unknown to me.

A family teleport packet in v0.98:
B3 00 01 00 00 00 0C 00 74 69 6D 65 34 63 68 65 63 6B 75 70 


B3 is the header for family teleport.
01 is the choice option of the family rep system.
0C is the # of characters in a player's IGN.
xx this green portion is an IGN in hexadecimal from string.

There are a whole list of them and each have their own structures. That's your job to find and test what each of their functions mean.

Randomizing Timestamp
There are some packets that have timestamps in them. The reason is that you always use a skill at a different time and that you NEVER reuse the same time. It's literally impossible. If you did reuse the same time, the packet will not work and may d/c you. To avoid this, you randomize the time with **. Timestamps are usually located after the header followed by the first 00.

Dangers of Editing
There are things that can go wrong in the game when you're messing around with packets. You can easily crash: yourself, a channel, or a map. You can auto banned or permanently banned. There was a time where I was messing with an attack packet and I got my main account auto banned. You can get a permanent ban if you use packets to exploit the game, such as using a modified packet to gain scrolls in large amounts in a small amount of time. Packets can be logged in the game servers and GMs can check players' logs when an exploit gets severe in the game.

Popular Icon in Packet Editing
A well known packet editor known in many hacking communities is RiPE (aka R|PE). The author of RiPE is Ryan Cornwall with the alias Riukuzaki. Most, if not all, exploits and game enhancements were done by packets with the help of his PE. He has a VIP PE and the public PE.
Source: http://www.riukuzaki.com/

----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
MapleShark - A Packet Sniffer
Preface: This is an extensive guide on how to sniff a packet, understand what each packet means, what an opcode is, how to update them, and using this to serve your MapleStory private servers.

General Introduction:
Updating takes time and general knowledge of the game. Some creativity might be involved as well. A few basic things must be known beforehand if anyone is interested in updating. These are the very basic definitions and without this, it is quite useless to proceed and further. I will give you an efficient way to packet sniff and update with possibly a few tricks to save time, but it is still up to you to learn the logic behind updating. I am also assuming this is updating for OdinMS source but the same concepts can be applied for Vana and DelphiMS. I haven't ever looked at Titan or the C# sources so I cannot say the same, but packets are the same for the game. I will also use v88 and v99 as I am most familiar with v88 and MapleGlobal is at v99. Still, if you want to update MSEA, this guide will still work. I will also make sure the guide works for both odinms sources using properties files and those that do not.

Why Learn Packets?

If you actually want to run a successful server with no competition, updating to the latest version is important. Now you ask me why I haven't done this for MoongraMS (according to Flav, I "don't know how to"). I simply don't have the time and energy for this stuff anymore as even though I have done it before, I have no motivation or time to do it anymore. If you're going to "aim for #1" you're going to have to keep up with the competition that is going on. True, custom features and the site are "almost as important" as the game itself, but this is the easiest way to get players quickly and not being labeled as a terrible server who is only top because of insane rates.

Definitions and Basic Information:

-Byte: 1 byte
-Short: 2 bytes
-Int: 4 bytes
-Long: 8 bytes
-The packets on Maplestory are in little endian format, which means the once converted to hex, they are reversed. This means that if something was 0x12345678, once converted to little endian, it would be 78 56 34 12.
-Packets are sent between the server and client to transfer data and information. The GUI is a projection of it, in a way.
-Actions that are handled by packets on Maplestory are defined by a short (2 bytes) in the beginning of the packet. Some actions may share the same short. We will call this short an opcode. Both packets sent and received by the server have opcodes. Naming these opcodes will help a lot.
-This will be done in hexadecimal so it is base 16. It is useful to have calculators for hex to dec and dec to hex at the ready. It is also useful to know some basics such as 0xA = 10, 0xB = 11, and possible some multiples of 16. It is useful to also know how to multiply and add in your head. Since I can do that, for all bytes I can calculate the values pretty fast by doing it in my head.
-Handlers are for receive packets. MaplePacketCreator is for send packets.


Other Misc Information:
-Levels, item slots are bytes
-Jobs, stats are shorts
-Mesos, exp, map id are ints
-Buffstats are saved into longs


Updating Opcodes:
Introduction
Updating opcodes is the first step to updating a version from one to another. This step takes either a lot of time, or a bit of time and some logic.

The first thing to know is to know about common things Nexon does. The most important thing is to know that Nexon usually keeps the opcodes between versions in order. This is not always true as some opcodes are moved around in some versions, but for the most part, most of the opcodes stay in order. Knowledge of what is added and removed is somewhat important as well. For example in v88 there were monster books, but by big bang patch they were removed. It is possible that the opcodes were removed as well, causing the values of the opcodes to go down.

How to Work a Packet Sniffer:
After knowing this, it is time to go and grab some packets from the game. I personally favor SnowSniffer solely due to the ASCII printout, but I currently use MapleShark and will be writing a guide about it. It is googleable and just look for the latest version, which I believe is 1013. If you don't have .net framework, get that as MapleShark needs it. Download and install WinPCap while you're at it since this is needed for packet sniffing.

I have gotten some questions on MapleShark not working for a few people, so I will also include a small guide. Open up the executable and set the settings. If you are on wireless, choose wireless. If you are on ethernet, use local area connection when it asks for it. Sometimes you have to pick option number 2 of these sections.

[Image: 2guclt1.png]
MapleShark also asks you for the ports you want to sniff. Set those from 7575-8888. The ports don't quite reach 8888, but use 8888 for simplicity. When you have this open, you can change channels or log into the game and packets will start being logged.


How to Packet Sniff Efficiently:
Good packet sniffing isn't just mindless moving around and training on monsters, contrary to popular belief due to released packets. No, those packets are pretty useless and so are the people thanking them. When you packet sniff, you need to get what you want, quickly and clearly. To packet sniff efficiently, do one function at a time. Look through the receive packets and send packets and find the ones you want to sniff. The most important part is to say what you want to sniff before sniffing the exact action. For example if you want to sniff meso drop, don't just drop mesos and move on, say DROPPING MESOS and then drop mesos. Also know how many mesos you dropped. Saying something like DROPPING 256 MESOS is better than saying DROPPING MESOS. However, if you say you're dropping 256 mesos, you better drop 256 mesos. Otherwise you'll be confused. This will be useful later on when you look at your log. once you have a sizeable log with many things sniffed, you can stop sniffing. If this is your first time updating and you have little experience, then sniff a bunch of things so you can fill in the unknown opcodes later on.
Analyzing Packet Logs and Updating First Opcode:
Now that you have packet logs, log off of MapleStory. You don't want more packets coming. Now go back to the MapleShark GUI and scroll down each packet that is logged. The packets received by the server will be outbound, and the packets sent by the server will be inbound. The names are counter-intuitive but if you think about it the other way around by replacing server with client, then it would make sense (receive by client = inbound). The opcode is given at the side as well along with the packet length. This will be useful later on. Now it is the time to find when you talked. Scroll down each packet until you find where you talked. The textbox to the bottom right of MapleShark gives you an ASCII printout.
[Image: 2d9r9s3.png]

Basically, scroll down until you see what you said in plain text. If it is outbound, then that packet will be for receive packets. Get the opcode that MapleShark says it is. In v88 it is 0x31. In v99 it is 0x37. Navigate to the file where the receive packets are stored. Get the old value of GENERAL_CHAT and change that to the new value. Example: v88 is 0x31, v99 = 0x37. Change 0x31 to 0x37. Since 0x37-0x31 = 6, note that it is +6. This will come in handy later. If you are experienced or very good at mental math, you may skip this step. You have updated your first opcode. Next go back to MapleShark and look at the inbound packet containing the words you have said. This is also GENERAL_CHAT, but in send opcodes. Go to where your opcodes are stored and change that for CHATTEXT as well. In v88 it is 0xA2. In 0x99 it is 0xAF.

Opcode Naming:

Now you may be thinking, how did I know it was CHATTEXT and GENERAL_CHAT for send and receive packets respectively? Perhaps you may be thinking, how would you know what the packet names are right off the bat? There is no simple answer to this. I just know because I've done this many times. Although the packets are not badly named, some are a bit confusing. For example, in my source I have ARAN_COMBO for receive packet but the handler is named DamageMonsterHandler for some stupid reason. Oftentimes figuring out this for the first time may take a while. Here are some helpful tips though: Remember that packet opcodes stay in order for the most part. In v88, ARAN_COMBO comes before CS_OPERATION (doing things with cash shop). If you got something like ARAN_COMBO and it is 0x9999, then it is way too high since it's greater than the value of cash shop (when you sniff that later on) and you're probably doing it wrong. However, if you got something like ARAN_COMBO being 0xBA, then it may be reasonable. There are many ways to verify if it is correct and this will be gone more in depth in the Looking At Packet Structures section of this guide.


Analyzing Packet Logs Continued:
So you have just found the GENERAL_CHAT opcode. This is a very important step. To make things easier for yourself, at any GENERAL_CHAT packet, right click it and name it GENERAL_CHAT (RECV). The good thing about MapleShark is that it can search for the packets you have logged based on opcode. No one wants to read through a list of hexidecimal numbers like Outbound 0x37, so naming it something in English will help. After this is done, scroll down to the next few packets. Remember we only updated chatting, and we have not even updated what we were trying to update, which is the function of what you said. While doing updates, I sometimes drop mesos first. Now it's time to use your brain. Find the old opcode for dropping mesos. Start in the Recv handler. Now the question is how did I know it was receive? There are two reasons. One, experience, and I know that it is receive, and it sends a DROP_ITEM_FROM_MAPOBJECT packet. Secondly, think back and remember those exploits on GMS about duping mesos. Also think about the meso hacks back in the older versions through packet editing negative values. Packet editing is done completely in receive handlers since clients send a custom packet that will be received by the server. Anyways now that you have the packet opcode from the old version, remember that most of the time opcodes go up, but not at a crazy rate. In v88, it was 0x5E. Now search for packets that around around that area and outbound. If you need more help, look at the mesodrophandler, and figure out what the packet length should be around (more indepth in analyzing packet structures). Since this is not covered yet, you will not know the exact length from v88, but think about it. Does a lot of data need to be transmitted for dropping mesos? Probably not. The meso count is needed, possibly what dropped it matters, and possibly when it dropped matters, and even perhaps the location of the drop. This means the packet will not be insanely long. So look around for a short packet.

When you find a decent sized packet around the old opcode, time to check if it is correct. This is where remembering how much you dropped comes in. Drag your mouse and highlight 4 consecutive bytes in the packet. You may highlight it in the bottom of the GUI and the integer provided will be calcuated into decimal on the righthand side of the GUI. If that doesn't match the amount of mesos you dropped, keep going. Keep going until the end and if none of the ints match the amount of mesos you dropped, you have the wrong packet. The question is now how is it an int. There are again 2 ways I know it's an int. One, through experience and the second through looking at the packet handler (more info to come). Anyways after a few trials, the meso drop opcode should be found to be 0x69 for v99. Replace the old one with this one. The old opcode was 0x5E, and 0x69-0x5E = 11 so add a +11 tag next to it. Now it's time to check the send packet. Because you know the receive opcode is MESO_DROP, find the handler that corresponds to it.

Obviously it is MesoDropHandler, but if the opcode was named badly, there must be another way to find the handler. The foolproof way to do it is through searching an IDE. I will assume Netbeans here, but those that use Eclipse have a very similar feature. Right click the variable called MESO_DROP and select the option find usages. In Eclipse it is similar. Select the default choice and it will find you the usages of the variable. Double click the line of code that uses it. This will take you to PacketProcessor.java (in odinms) and next to the line of the code will be the name of the file. Press ctrl, and then click on the name of the file. This will take you straight to the file (IDE Shortcuts!). In the handler, sometimes there will be a c.getSession().write(MaplePacketCreator.stuff); line of code. This tells the server what packet to send back to the player. In some handlers, more than one of these will be used and in others, there will not be an packets sent at all. This is where code reading needs to take place. Remember what you did and navigate to the correct section of code. Find the packet that the server sends (if any) and go to that method (hold down the control key and click on the method). The method will be something like public static MaplePacket blah() {MaplePacketLittleEndianWriter mplew = stuff; mplew.writeShort(<OPCODE HERE>);/*code omitted*/}. Find the opcode in <OPCODE HERE>. In the case of meso dropping, it would be DROP_ITEM_FROM_MAPOBJECT. Go back to where the send opcodes are located and get the old opcode for DROP_ITEM_FROM_MAPOBJECT.

Now go back to MapleShark and find the packet sent after MESO_DROP. If the packet opcode is reasonably near the old one, this may be the correct packet (to be verified later on). For now replace the old opcode (v88 = 0x10C) with the new one you have found. Calculate the difference and make note of it for future checking. This whole procedure needs to be continued for everything you have sniffed. If you are too lazy but this is your first time doing this, then stop right now. It is not worth continuing as this is one of the easier parts and the part that really takes the least amount of work. Updating is not for the weak.


Guessing Opcodes (theoretical examples):
Now after a good size of opcodes are updated in this tedious manner, a few other tricks can be utilized. The most important one is guessing opcodes. This is where the adding the packet increases and decreases such as +11 for meso dropping. Unfortunately, I have not done this in v99 so I cannot show any clear examples, but I will show an example here that is completely theoretical.

Your opcodes look something like:
ACTION_1 = 0x50 // +4
ACTION_2 = ?
ACTION_3 = ?
ACTION_4 = 0x53 // +4

Now logically action_2 and action_3 are 0x51 and 0x52. Of course we do not know for sure (who knows, Nexon might have removed ACTION_2 and added a completely new opcode in the middle), but it is a good guess.

Here is a more advanced example for guessing. This is what you'll be seeing for the most part
ACTION_1 = 0x78 // +8, was 0x70
ACTION_2 = ? // was 0x75
ACTION_3 = 0x8F // +8

So between ACTION_1 and ACTION_3, opcodes increased by a value of 8. It is a good guess that all opcodes between also increased by 8. This has worked around 95% (low estimate) for me. ACTION_2 can be found as 0x75+8 = 0x7D. See, this is why documenting the opcode increases is helpful. Even though I do not code every version, I do keep an updated opcode for many versions, and I do this pretty often.


Additional Tips:
Because of the guessing strategy, opcodes can easily be filled up pretty fast. There are a few ways to make your life easier. Firstly, don't sniff everything in the same area. True, you may get completely perfect opcodes in that section, but usually you can guess those. Spread the packet sniffing throughout the opcodes list. Maybe sniff MESO_DROP, then sniff going into cash shop, then perhaps sniff some MTS actions.

Sometimes guessing with certainty isn't purely enough and you get something like
ACTION_1 = 0x55 //+4, was 0x51
ACTION_2 = ? // was 0x52
ACTION_3 = 0x65 //+5 was 0x60

For these examples, look at what the actions are. If action_1 is scrolling, and action_2 is like enhancement scrolling, and action_3 is something to do with moving items, then it is more likely for the ACTION_2 to get the +4 than the +5. Another way to know this is that 0x52 is closer to 0x51 (looking at old values).


Summary for Opcodes:
1. Sniff the easy opcodes but with efficiency and clarity.
2. Update the easy opcodes, go from RECV to SEND if you are not experienced although this doesn't really matter
3. Guess the opcodes that you can guess with high certainty.
4. Go back and sniff the ones that are missing and repeat #2-3 until a good list is done for send and receive packets.


Reading and Updating Packet Structures

Introduction:

So now that you have a good list of correct opcodes, sniffing packets should be no problem at all (especially with snow sniffer, and MapleShark if you name your packets like I do). Now it's the time to update packet structures that are incorrect. Before updating packet structures, you must know how to read the packets and how to make sense of them.

Requirements:

-Basic Java knowledge (including for/while, arrays, and basic data structures)
-Reading the above
-Knowing how to follow directions

Starting out:

Just as a reminder, a byte = 1 byte, a short = 2 bytes, an int = 4 bytes, and a long = 8 bytes. A few of the common variables that take on these data types are listed above (i.e. job id is saved as a short). A byte is the pair of hexadecimal digits. Of course it has a deeper definition, but this is all you really have to know. In a packet 13 00 00 00 00 00 00, each pair would be a byte. Also, hexadecimal notation is 0x followed by a number 0-9 or a letter A-F. Having the 0x symbolizes that it's hexadecimal.


Checking packets for Outbound:
Now we take a packet, and check if it is correct. If you cannot log into the game, this is the only way to update packets as you have no clear way of testing. Let's take the packet that is sent when you move into the cash shop. The packet in v99 is 13 00 00 00 00 00 00. From working with opcodes, you should have an idea of what packet this is in MaplePacketCreator (enableCSUse0 or something, depending on source). Now the job is to check if it works correctly.

Writing/Reading packets have methods in the source. To add a byte to a packet (send), use write, to read (receive), use read. write(number) will write a byte, writeShort(number) will write a short, and writeInt(number) will write an int. The same principles can be applied to the other ones. However, there are a few special methods. One of the most important ones to understand is readMapleAsciiString and writeMapleAsciiString, which will be explained later as it's slightly more advanced.

So let's go analyze a packet. First we need to combine the opcode with the packet itself since MapleShark gives opcode, and then the rest of the packet separate. The opcode of the packet we will be looking at is 0x00FA = FA 00 (outbound). The packet is 2A 00 00 00 52 00 00 00 47 00 00 00 49 00 00 00 1D 00 00 00 53 00 00 00 4F 00 00 00 51 00 00 00. Combined this will be Outbound FA 00 2A 00 00 00 52 00 00 00 47 00 00 00 49 00 00 00 1D 00 00 00 53 00 00 00 4F 00 00 00 51 00 00 00.

This packet is for quickslots (in v99) but in case this is not obvious, take the first 2 bytes and find the opcode referring to that. It is in little endian form so when you put the short together, you have to reverse the bytes, so the opcode will be 0x00FA. Browse through your receive opcodes and find the receive opcode corresponding to the value, which in this case is 0xFA. Find the handler that corresponds to that opcode and open it up.

Reading and checking a packet requires working from the beginning and going forward. This is little point of starting in the middle unless more experience is gained (tips will be shown later). Anyways, the thing about a outbound packet is that in the source, there is always a short read in the beginning no matter what. This is to identify which handler it should go to. So we can start reading the packet now that we know the structure, at least in the old version. We start with slea.readShort(); to get the handler it calls. The first two bytes are FA 00, and since it's a short it would be 0x00FA. The important thing to remember is the following few steps.

One, after you read them, the bytes won't be looked at during further reading. Because of this, it is useful to keep track of where the packets are, and if it is a byte, short, or any other. So we have read FA 00, so we can put brackets around it to symbolize it is a short. So far, a short has been read and it is looking like [FA 00] 2A 00 00 00 52 00 00 00 47 00 00 00 49 00 00 00 1D 00 00 00 53 00 00 00 4F 00 00 00 51 00 00 00. The second thing to think about while reading through the packets is to make sure the packet values make sense. You cannot go wrong with the packet header (or opcode, or just first two bytes), so you do not need to worry about it here, but in the future this is vital.

Next, look in your handler and you should see something like for (int i = 0; i < 8; i++) {int key = slea.readInt(); /*omitted code*/}. This basically says readInt() 8 times. So we go through the packet again, going through ints each time. An int, as stated before is 4 bytes. The first one will be 2A 00 00 00. As this is little endian, again, the bytes are reversed before being put together. So when it is read, it will be 0x0000002A. Add brackets around the 2A 00 00 00 indicating that it is finished. The packet should now look like [FA 00] [2A 00 00 00] 52 00 00 00 47 00 00 00 49 00 00 00 1D 00 00 00 53 00 00 00 4F 00 00 00 51 00 00 00. The next step would to be making sure the part that was just read made any sense. Is it reasonable to have a key have a value of 42? It seems possible so move onto the next int. Repeating the above will eventually take you to
completing the packet with [FA 00] [2A 00 00 00] [52 00 00 00] [47 00 00 00] [49 00 00 00] [1D 00 00 00] [53 00 00 00] [4F 00 00 00] [51 00 00 00].
Because all the ints make sense, this packet doesn't seem to need updating so we are done here.


Incorrect Packets for Outbound:
Unfortunately having correct packets from one version to another is not always the case. A perfect example is here in this receive packet (opcode already included): 73 00 5F 98 95 02 02 00 00 00 00 02 00 00 00 00 00 00 31 00 00 00 00 01 00 00 00 00 00 00 AB 00 00 00 which was for auto assign for the jump start level 50 Evan. The first step is to once again identify the opcode. The opcode is the first two bytes, reversed so the opcode would be 0x0073. If you have followed the updating opcodes part of the guide and have completed it, this will be found to be AUTO_ASSIGN. Find the handler that uses AUTO_ASSIGN and enter it. We have already analyzed the first 2 bytes so we can skip that already. We go through the first packet reading and see if it makes sense. slea.readInt(); (or slea.skip(4) which basically means read 4 bytes) is the first thing that is read after the header. It is also said to be the timestamp. Again, we have to reverse the bytes when we read it and it is an int so we read 4 bytes. We should get 0x0295985F. Use MapleShark's calculator or a hex to dec calculator to see if this makes sense. It should as timestamp is usually high. Because it makes sense we can move on. So far we have [73 00] [5F 98 95 02] 02 00 00 00 00 02 00 00 00 00 00 00 31 00 00 00 00 01 00 00 00 00 00 00 AB 00 00 00. The next line says slea.readInt(); which is the count of stats updated with auto assign as a comment or the variable name should say. Go through the next 4 bytes as usual and you'll get that the value is 2. Updating 2 stats makes sense so we can go passed this.

Now we have [73 00] [5F 98 95 02] [02 00 00 00] 00 02 00 00 00 00 00 00 31 00 00 00 00 01 00 00 00 00 00 00 AB 00 00 00. The loop iterates 2 times, because of the 2 previously, so we go to the next line and it says which stat it updates and that it is an int. The int read is 00 02 00 00 and as that is in little endian, we change it to hex form and it'll be 0x200 (512) = updating luck according to the if statement if (type == 512). This makes sense so we can move on. The next int according to the handler says that the next int would be the amount gained. The next int read is 00 00 00 00. It seems kind of strange that the gained amount is 0, but this is not impossible so we can move on. Had it been more than 1000, then it would have been weird. This is where knowledge of the game comes in though. Auto-assign gives you regular stat build and since this was a stripped level 50 Evan, this should have given some luck.

Next, we reenter the loop due to it being looped twice. Again, it asks for the stat that will be updated. This time it is 31 00 00 00, which is 49. This doesn't make sense though, as there isn't a stat that is 49. There are a mixture of stats that can reach 49, but not a single stat. Something is clearly wrong and doesn't make sense. This is when we notice there is a structure problem. What to do now is to think about what the 49 could be. I said above that the character was a jumpstart Evan which was level 50. Remember that before the luck gain was 0. Would 49 likely be a better luck gain? I had 4 in luck already and luck = 3 + your level for Evans at level 50. Would this be correct? The answer is yes, the 49 would probably be the luck gain. This means that there is a new int between the stat and the stat gain. What you can do now is to add a slea.readInt() after the int type = slea.readInt(); to indicate that it is new. Check the rest of the packet until you reach the end. The newly added int should fix the packet. You have now updated a packet from one version to another.


Additional Words and "Error" Correction:
Note that I knew that it should have given some luck because it was my character so I would have noticed something wrong right away. If it wasn't my character, there would be no easy way to tell if I had the required luck to begin with and would move onto the next line like above. This is another reason why getting other people to post packets they sniffed is not always good. You know your character, but you don't know anyone else's. Also, that "int" that was added is actually a long which was added for all stats. Because of the traits system, the int became a long, but this was not mentioned here as this would be confusing. Auto assign doesn't affect the traits and personality system so it doesn't really matter.


Checking Packets for Inbound - Starting Out:
The concept is the same, and you still trace over the packet as before. However, instead of finding the opcode and skipping over the first 2 bytes to enter a handler, this is not done here. If we want to check a packet like 13 00 00 00 00 00 00, which is the packet apparently to enable a few actions, we would start with checking 13 00. Before we do this, we have to understand what the packet being created in MaplePacketCreator is trying to do. Another difference is instead of reading bytes, we would write bytes instead.

public static MaplePacket enableCS0() {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(0x13); // or SendPacketOpcode.ENABLE_CS_0 or SendPacketOpcode.ENABLE_CS_0.getValue();
mplew.write0(5); // or mplew.writeInt();mplew.write(0);
return mplew.getPacket();
}

The first line is the method definition. It is a public method so it is accessible everywhere. It is static so it's a class method and not called by an object. It returns a MaplePacket. The second line creates an object of type MaplePacketLittleEndianWriter. This is what we "write" our bytes into to make it simple. The next line, we write a short that is 0x13. This means we add 13 00 to the empty packet from line 2. Next we do mplew.write0(5); write0 is like skip for outbound packets. It just writes 0 bytes though. So that line would add 00 00 00 00 00 to the packet (we had 13 00 before). Now it looks like 13 00 00 00 00 00 00. After the 4th line, the 5th line returns the packet, so it will return what we had at the 4th line.


Checking Packets for Inbound - Continued:
One way to check is to just compare the packets from the old version to the new one. Another way is to do the same thing we did for receive packets and check them byte by byte and seeing if it makes sense. The latter method works better during updates since if the packets don't match, we would have to trace it again through anyways to see if anything was incorrect. Refer to the other section to read and go through a packet. Remember that a byte is 1 byte, short is 2 bytes, int is 4 bytes, and a long is 8 bytes. If it is done correctly, the new packet for enabling a few functions will match the old one. The only difference between v88 and v98+ is that the opcode changed from 0x12 to 0x13, but this can be figured out by updating opcodes, which is why opcodes should be updated first.
Notes:
A few terms and sentences were simplified for better understanding. One example is what MaplePacketLittleEndianWriter is. Another example is what the return statement is. The benefit is that understanding this stuff really has no purpose in updating one version to another.

Other Packet Methods in Odin:

There are a few functions that have not been mentioned up until now. One of the most important methods in the source is readMapleAsciiString. This is like 2 functions in one. readMapleAsciiString will first pass over a short to get how long the string will be. Then it will read that length and convert the value to ASCII. For example if you had 08 00 30 30 30 30 30 30 30 30 and applied readMapleAsciiString, it would first read 08 00 (which is 8), then it would read 8 bytes and change that into ASCII. The 30s will become 0s. There is also the write counterpart of readMapleAsciiString, which is writeMapleAsciiString. writeMapleAsciiString("3141") would be 04 00 33 31 34 31. The 04 00 would be the length of the string that is being written.

There is a method called skip for reading bytes (and it has been gone over above). It merely just passes through the bytes in an outbound packet and doesn't do anything with the values excepts "skips" over. The other ones like readInt return an int value of the bytes it has passed. The write counterpart for skip would be write0 which writes 0s a number of times. It is not an exact counterpart, but it is similar.

There is a method for writing packets called writeAsciiString. This is the same as writeMapleAsciiString except the short indicating the length is not there. writeMapleAsciiString("1234") would write 04 00 31 32 33 34 while writeAsciiString("1234") would just be 31 32 33 34.


Summary of Updating Packets:
1. Check the packet
2. If it is incorrect, find out why it is incorrect. If there are new things added, figure out what it is supposed to represent. Barely anything is random, and even if something is always 0, they might have a purpose in later versions.
3. Make changes as necessary. Sometimes bytes are removed.
4. Repeat this for all broken packets between versions.

Efficient Way of Updating:
Of course it is impractical to do the hard packets first and it is pretty dumb to just do the biggest packets with no prior knowledge.

Tips:
-In packets, if it involves items, think about which slot the item is in, item id, and other things to do with items such as item stats. This can help identify the new parts. In new things added in new versions, think about what the value can be. For example in v99 and 0A 00 00 00 was added in some character stat places. What could that be? Think about what has the value 10 in v99.
-Know some common values. The non expiring timestamp long appears in many places including skills, items, and a couple other places. The default map packet used for teleport rocks is used in a couple places too. Know common values to help aid yourself through this long process.
-Learn some packet structures. After doing this for a while, you should know that buffs have 4 longs (or 2 before aftershock, 2.5 in v88) in the beginning, then for every buff stat the buff contains, it does short, int, int. After that it has some other info. Char Info goes from skills to cooldowns, to quests, to completed quests, and to mini-games, and then to rings, and then to teleport rocks, and so on. This makes checking much faster.
-Know some checkpoints for packets. When I do stupid packets like getCharInfo (the super long WARP_TO_MAP one), I start at the teleport rock place and fix those ints, and then work my way up. For all packets containing the addCharLook, I know the structure to have a section with equips showing up and I would do that place first and then work myself up the packet. If you are just starting out though, try to work in order from the top. It is much easier and even though it is slower, you can never go wrong.
-Updating versions takes some sort of experience. Know what to do, remember it, and keep learning on the way. You can never be too good at updating.
-No such thing as "packet triples" so no data type has 3 bytes. I see that a few packet editors talk about things with 3 bytes at a time. This is wrong. Do not fall into the same hole.
-Don't give up right away. Packets take some time to get used to and it really isn't that easy, no matter what people say. I've seen many people say packets are easy end up asking me for packets. There are packets that I have to ask to check as well and if they were really that easy, they would be easy to explain (which is not true at all), and easy to figure out any packet.

Sources: http://mapletalk.net/showthread.php?tid=2813