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!

Getting packet structures/opcodes using IDA

Experienced Elementalist
Joined
Oct 25, 2008
Messages
224
Reaction score
315
Like I've promised I've created a little tutorial on how to get packets/opcodes out of an unpacked client using IDA.

Requirements:
  • IDA Pro 6.1:
  • An unpacked binary you want to analyze
  • KMST leak (IDA database included):
  • The ability to learn yourself. Trial and Error is a very important concept for this.

If you are going to analyze v90, you can download a pre-made IDA database It has some common functions like CInPacket/COutPacket methods already named.

To start IDA, best use idaq.exe - That's the new QT version and it just looks much better than the old version.

If the quick-start comes up, select Go and then open the KMST IDB. Run IDA again and do the same for the v90 IDB.

On the left, you'll see a list of all methods (usually ordered by address), in the middle there is an assembly view of the current function (the tab is called IDA View). Of course there are more tabs like Hex View, Imports, Exports and later Pseudo Code.

Some important shortcuts:
F5: Decompile the current method into pseudo C code.
X: Find all references to the method you have marked with your cursor in asm/pseudocode.
ALT + ?: Start searching.
CTRL + ?: Continue searching.
Where ? can be:
T: Search a text string. This works in almost all sub-windows of IDA (method list, assembly, pseudocode...)
B: Search for a sequence of bytes (you may know it as AoB, but unlike CE this doesn't support variable bytes, sth. like E8 ? ? ? FF will not work :( )
I: Search for an integer value in assembly. This is much faster than text-search.

What we'll be doing is basically:
1) Locating the packet you need in the KMST client. Getting used to the names Nexon uses might take some time.
2) Looking for that method in the client you're analyzing.

Finding send-packets (which the client will receive) is not that hard. Nexon handles all of them in mainly 2 methods:
CWvsContext::OnPacket for most opcodes < 140 (decimal).
CField::OnPacket for everything above.
These two methods are already named in my v90 IDB. Just go in there and check where it goes for a specific opcode you need a packet structure for.

An example: I want the exact strucutre of the SpawnMonster packet and know that the opcode is 276 in v90.

In CField::OnPacket I see:
Code:
    if ( a2 < 177 || a2 > 275 )
    {
      if ( a2 < 276 || a2 > 302 )
      {
        if ( a2 < 303 || a2 > 310 )
        {
As my opcode is 276, it will go into the else-clause of that second if-statement. I set my cursor before that second if and press down until I see else directly before the cursor. That has to be the packet handler for monster packets. Doing the same in KMST reveals: It is indeed CMobPool::OnPacket.

The next thing I'd do is name that method I've found. In most cases I copy the name from KMST - there are 2 methods of doing that: Either, you copy only the visible part (CMobPool::OnPacket), or you mark that name and press N. It will then show you ?OnPacket@CMobPool@@QAEXJAAVCInPacket@@@Z. This string contains advanced information about the method like parameters and if you use this name, you'll also see the parameters in the function list on the left later on. A disadvantage is that it looks quite ugly in the assembly view.

So when I double click that OnPacket method, I'll get to a switch statement which happens to have the opcode I looked for. It passes the packet on to CMobPool::OnMobEnterField. Inside, it will actually start reading data from the packet.

Decode1: Read byte (mplew.write())
Decode2: Read short
Decode4: Read int
DecodeStr: Read string
DecodeBuffer: Read everything that is longer than 4 bytes and not a string. This is often used for longs (8), names with static length, or buff-stats.

In this method, it'll only read the first few bytes of the packet though. Mark the packet parameter (the on that's passed on to the Decode calls) and you'll directly see where else it is used. In this case, it is passed on to two other methods. One reads the buff stats which the monster currently has (Nexon calls buffs TemporaryStat or SecondaryStat) and the other reads the rest of the packet (position, foothold and that stuff).

Now you might ask: I see THAT it reads ints and what not, but how do I know WHAT it is?
That is indeed a problem. Sometimes it's obvious what it is, e.g. ints at the beginning of a packet are often object IDs, or for receive packets (which the client sends) timestamps. Sometimes it's also becomes obvious when the client passes the value it read on to another method, e.g. is_skill_need_master_level.

In most cases, you don't know what is though. Then you can only sniff in GMS and perhaps it'll become clear to you, or you'll hardcode the value GMS uses without knowing what it does, OR you just set it to 0. Note that this last possibility sometimes has unwanted side effects which you can't explain until you find out it was caused by that 0, that has already cost me hours of time.


Finding packets which the client sends:
This isn't need that often - the client sends all data you need to you and you just need to interpret them - you can't really break anything.
Sometimes you just can't find out what a certain value in a packet means though, and then the client might give you a hint.

Unfortunately, the client doesn't send it packets in once place, but they are scattered throughout the executable.

Useful methods for finding a packet-send method:
1) The method references a method that you have already named in your unpacked client and which is NOT used by many other methods. StringPool::GetInstance e.g. would be a bad choice, as it used 9000 times :p:

2) There is some unique value, e.g. a skill ID in the packet - simply used it in ALT+I. This can also be done for the opcode, but make sure to tick "Find all occurences" - if it is low, that value will be used very often by all kinds of asm-opcodes. You need to look out for a push, followed by COutPacket::COutPacket_0.


That's it for now, I think.
 
Custom Title Activated
Loyal Member
Joined
Jun 30, 2008
Messages
3,451
Reaction score
1,616
That's a great guide. But where can I find the "OnPacket" File and those others?
In the v95 database it's easy to find. At the huge list with methods press alt+T and search for 'OnPacket'. If you want CWvsContext you should search for 'CWvsContext__OnPacket', if you search something you never write '::', but '__'.

If you are on a higher version, it won't always show this method. Just try to search for a method that's used in there, like CWvsContext__OnStatChanged.

Good luck :)
 
Newbie Spellweaver
Joined
Feb 24, 2010
Messages
98
Reaction score
2
Thanks Kevin! But where should I find it? I mean, in the Hex View-A ?
Btw I'm using IDa 5.0 because the 6.1 one is evolution version and I can use it (And I can't understand how to use the 6.1 that Hendi gave here).
 
Custom Title Activated
Loyal Member
Joined
Jun 30, 2008
Messages
3,451
Reaction score
1,616
Thanks Kevin! But where should I find it? I mean, in the Hex View-A ?
Btw I'm using IDa 5.0 because the 6.1 one is evolution version and I can use it (And I can't understand how to use the 6.1 that Hendi gave here).
First, use IDA 6.1
Second, the 'Function Window' on the left.
 
Newbie Spellweaver
Joined
Feb 24, 2010
Messages
98
Reaction score
2
I found nothing close to "CWvsContext__OnStatChanged", only "sub" things...
By the way, what's the difference with those versions? And how can I use v6.1 if it's not opening it (Getting a message that says this is evolution version and I've to buy it in order to use).
 
Custom Title Activated
Loyal Member
Joined
Jun 30, 2008
Messages
3,451
Reaction score
1,616
Did you use this link?

And are you opening idaq.exe ?

If you cannot find anything related to that, either in IDA view use ALT+I to search an immediate value (opcode) or search for CWvsContext in the Function Window.

If there are only sub's then you are pretty much duck'd as you won't be able to fix it from there.
 
Initiate Mage
Joined
Oct 27, 2012
Messages
1
Reaction score
0
Would this still work? Just wondering might make me a nice little program
 
Newbie Spellweaver
Joined
Aug 13, 2009
Messages
29
Reaction score
24
Can you re-upload 'KMST Mistake.7z' file for me? I can't download that file.. :O:
 
Back
Top