EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Support::Packetcollector (https://www.eqemulator.org/forums/forumdisplay.php?f=602)
-   -   Finding Opcodes (https://www.eqemulator.org/forums/showthread.php?t=25603)

EvoZak 07-11-2008 01:46 PM

This thread delivers.

SEQ should be an excellent source for opcodes, but I wonder about the structures. Would SEQ even be interested in the structures for, say, bazaar or ldon stuff? Isn't SEQ just interested showing you mob pops, loot drops, etc? If that's the case, there's a fair chance they wouldn't implement any of the data structures since they wouldn't have a use for it.

KLS 07-11-2008 05:22 PM

They'd have the hard to find structures like player profile and spawn structures. (They tend to change a lot from patch to patch.) Things like ldon could be figures out via packet collecting and viewing. Though I can't get the packet collector to compile nor the pre-compiled to work. =x Guess I get to keep making mine.

Derision 07-23-2008 03:07 PM

Quote:

Originally Posted by trevius (Post 152306)
I did finally get showeq running on my Debian box, but I need to move both PCs to share a hub so that the packets can be sniffed and I didn't want to do that last night since it would affect my players obviously. I will try to put a hub in the next time I reboot the server. Then, I can get a look at what it shows for Live at least. And see if there is anything useful coming into it.

I found that for the purposes of packet collecting from live, you don't need to use a hub.

What I did was to run Wireshark on my PC, perform the actions I wanted to collect, then stop the capture and save the packets as a .pcap file.

I then transferred the capture file over to my Linux box and ran ShowEQ in replay mode:

showeq --playback-tcpdump-file=/tmp/livecap.pcap --log-zone --zone-log-file=/tmp/livecap.txt

Once the GUI has loaded and processed the capture, quit and you have a text version of the capture in, e.g. /tmp/livecap.txt

Code:

[OPCode: 0x0e98]
[Name: OP_ExpUpdate][Updated: 01/17/08][Type: expUpdateStruct (8) ==]
000 | 42 00 00 00 02 00 00 00                          | B.......

Jul 20 2008 19:58:18:849 [Decoded] [Server->Client] [Size: 12]
[OPCode: 0x4656]
[Name: OP_MobUpdate][Updated: 01/17/08][Type: spawnPositionUpdate (12) ==]
000 | 0f 46 e7 1d 61 f4 bf 4f f7 01 0a 00              | .F..a..O....

<snip>


trevius 07-23-2008 05:41 PM

Oh, nice! I will definitely check that out. I already have wireshark and showeq setup, so that wouldn't take much to get going. I guess I better do it soon before the free live thing stops lol...

I still plan to work on Opcodes, but have been pretty busy the past few weeks with RL stuff. Hopefully I can start going on it again really soon :) I know it could make a big difference for the project if we can get more systems working and things like opcodes and packet structures figured out.

Derision 07-24-2008 06:21 AM

Here is a quick and dirty tutorial on how I found the OP_Charm opcode for Titanium, based on information in the Wiki on
disassembly using IDA.

Requirements: The 6.2 Client, The Titanium Client, and an OpCode that is known for the 6.2 client
but unknown in Titanium (this is what we want to find).

Download IDA Freeware 4.9 from: http://www.hex-rays.com/idapro/idadown.htm

Fire up IDA, Select 'New', Select PE Executable, then navigate to your 6.2 eqgame.exe, then let IDA
analyse it. This will take several minutes. It will say 'Idle' in the status bar when it has finished.

In 6.2, Opcodes are handled in the 'Dispatch' routine at address 45A8B6.

To Jump to this address, press G and enter the address 45A8B6.

The routine looks like this ( I added the comments down near the bottom):

Code:

.text:0045A8B6
.text:0045A8B6 sub_45A8B6      proc near              ; CODE XREF: sub_407D2B+27p
.text:0045A8B6
.text:0045A8B6 var_5980        = dword ptr -5980h
.text:0045A8B6 var_597C        = dword ptr -597Ch
.text:0045A8B6 var_5978        = dword ptr -5978h
.text:0045A8B6 var_5974        = dword ptr -5974h
.text:0045A8B6 var_5970        = dword ptr -5970h
.text:0045A8B6 var_596C        = dword ptr -596Ch
.text:0045A8B6 var_5968        = dword ptr -5968h
.text:0045A8B6 var_5964        = dword ptr -5964h
.text:0045A8B6
.text:0045A8B6                mov    eax, offset loc_5F3AC7
.text:0045A8BB                call    __EH_prolog
.text:0045A8C0                mov    eax, 5954h
.text:0045A8C5                call    __alloca_probe
.text:0045A8CA                mov    eax, dword_75D3D4
.text:0045A8CF                mov    edx, [ebp+0Ch]
.text:0045A8D2                push    ebx
.text:0045A8D3                push    esi
.text:0045A8D4                mov    esi, [ebp+10h]
.text:0045A8D7                mov    [ebp-10h], eax
.text:0045A8DA                push    edi            ; char
.text:0045A8DB                mov    eax, 4665h
.text:0045A8E0                xor    edi, edi
.text:0045A8E2                cmp    edx, eax
.text:0045A8E4                mov    [ebp-58B8h], ecx
.text:0045A8EA                mov    ecx, 5ACh
.text:0045A8EF                mov    ebx, offset byte_95E7B8
.text:0045A8F4                ja      loc_45C52C
.text:0045A8FA                jz      loc_45DA84
.text:0045A900                mov    eax, 2089h    ; The Opcode of the packet being processed is in register edx
.text:0045A905                cmp    edx, eax     
.text:0045A907                ja      loc_45B969    ; If the Opcode > 0x2089, jump to 45B969
.text:0045A90D                jz      loc_45B95E
.text:0045A913                mov    eax, 1336h
.text:0045A918                cmp    edx, eax
.text:0045A91A                ja      loc_45ADB6    ; If the Opcode > 0x1336, jump to 45ADB6
.text:0045A920                jz      loc_45BA1B
.text:0045A926                mov    eax, 0A2Ah
.text:0045A92B                cmp    edx, eax
.text:0045A92D                ja      loc_45AB94    ; If the Opcode > 0x0A2A, jump to 45AB94
.text:0045A933                jz      loc_45AB89

Starting at address 45A900, is where it is checking which routine to jump to, based on the Opcode.

We know that for 6.2, OP_Charm is 0x10A1, so the first test that will pass is, is opcode > 0x0A2A, and
we jump to loc_45AB94.

Move the cursor over the loc_45AB94 in the ja instruction, right click, and select jump to operand, which
takes us to 45AB94:

Code:

.text:0045AB94 loc_45AB94:                            ; CODE XREF: sub_45A8B6+77j
.text:0045AB94                mov    eax, 0F40h
.text:0045AB99                cmp    edx, eax
.text:0045AB9B                ja      loc_45ACAC
.text:0045ABA1                jz      loc_45DB94

There are some more comparisons. In this case, our opcode 0x10A1 is greater than 0x0F40, so we now jump to
loc_45ACAC. (Jump to operand as before).

Code:

.text:0045ACAC loc_45ACAC:                            ; CODE XREF: sub_45A8B6+2E5j
.text:0045ACAC                mov    eax, edx
.text:0045ACAE                sub    eax, 0F66h
.text:0045ACB3                jz      loc_45AD6E
.text:0045ACB9                sub    eax, 9Eh
.text:0045ACBE                jz      loc_45AD63
.text:0045ACC4                sub    eax, 9Dh
.text:0045ACC9                jz      loc_45AD58      ; Jump to Charm Routine
.text:0045ACCF                sub    eax, 5
.text:0045ACD2                jz      short loc_45AD4A
.text:0045ACD4                sub    eax, 4Eh
.text:0045ACD7                jz      loc_45DE25

What it does now is start subtracting values from the opcode, then jumping to a routine if the result is 0.
0x10A1 - F66 - 9E - 9D = 0, so we jump to 45AD58.

Code:

.text:0045AD58 loc_45AD58:                            ; CODE XREF: sub_45A8B6+413j
.text:0045AD58                push    esi
.text:0045AD59                call    sub_457270
.text:0045AD5E                jmp    loc_45B3A0

This just takes us to 457270:

Code:

.text:00457270 sub_457270      proc near              ; CODE XREF: sub_45A8B6+4A3p
.text:00457270
.text:00457270 arg_0          = dword ptr  10h
.text:00457270
.text:00457270                push    ebx
.text:00457271                push    esi
.text:00457272                push    edi
.text:00457273                mov    edi, [esp+arg_0]
.text:00457277                push    dword ptr [edi]
.text:00457279                call    sub_402DD2
.text:0045727E                push    dword ptr [edi+4]
.text:00457281                mov    esi, eax
.text:00457283                call    sub_402DD2
.text:00457288                test    esi, esi
.text:0045728A                pop    ecx
.text:0045728B                pop    ecx
.text:0045728C                mov    ebx, eax
.text:0045728E                jz      short loc_4572EC
.text:00457290                test    ebx, ebx
.text:00457292                jz      short loc_4572EC
.text:00457294                cmp    byte ptr [ebx+1B3h], 0
.text:0045729B                jnz    short loc_4572EC

This is where it seems to start doing some processing, so we guess this is the guts of the charm routine.

Now we need to find the same routine in Titanium. Close IDA and start it up again, this time selecting the
Titanium eqgame.exe. Let it do it's thing for a few minutes.

When IDA is done processing, our goal is to find a routine in the Titanium client that looks the same, or very
similar to the one above. In this case, what I did was search for the 'immediate' value, 0x1B3.

Press Alt-I, and enter 0x1b3 in the search box. After a few seconds, a list of matches will be displayed. What
we are after is one that is:

Code:

cmp    byte ptr [ebx+1B3h], 0
to match the instruction in the 6.2 client. In the list of occurences of 0x1B3 in IDA, the second match is the one we are
after. Double click on it and it will take you to the routine. Scroll up a bit and it looks like this:

Code:

.text:00453D7B sub_453D7B      proc near              ; CODE XREF: sub_45B8F0+D1Dp
.text:00453D7B
.text:00453D7B arg_0          = dword ptr  10h
.text:00453D7B
.text:00453D7B                push    ebx
.text:00453D7C                push    esi
.text:00453D7D                push    edi
.text:00453D7E                mov    edi, [esp+arg_0]
.text:00453D82                push    dword ptr [edi]
.text:00453D84                call    sub_401B28
.text:00453D89                push    dword ptr [edi+4]
.text:00453D8C                mov    esi, eax
.text:00453D8E                call    sub_401B28
.text:00453D93                test    esi, esi
.text:00453D95                pop    ecx
.text:00453D96                pop    ecx
.text:00453D97                mov    ebx, eax
.text:00453D99                jz      short loc_453DF7
.text:00453D9B                test    ebx, ebx
.text:00453D9D                jz      short loc_453DF7
.text:00453D9F                cmp    byte ptr [ebx+1B3h], 0

As you can see, this looks like the right routine, as it is identical in all ways that matter to the 6.2 code.

Now we need to work our way backwards. Click on the 'Sub_453D7B' which precedes 'proc near', and then press
the X key.

This will produce a list of locations that this subroutine is called from. There is only one place, so double
click it, and it takes us to:

Code:

.text:0045C60C loc_45C60C:                            ; CODE XREF: sub_45B8F0+BD0j
.text:0045C60C                push    ebx
.text:0045C60D                call    sub_453D7B
.text:0045C612                jmp    loc_45F673

Nothing interesting here, so click on loc_45C60C, press X. This will produce a list of where 45C60C is called
from (just the one location). Double click on it in the result dialog box.

This looks more interesting.

Code:

.text:0045C4BA loc_45C4BA:                            ; CODE XREF: sub_45B8F0+B6Fj
.text:0045C4BA                sub    ecx, 12E5h
.text:0045C4C0                jz      loc_45C60C
.text:0045C4C6                sub    ecx, 21h
.text:0045C4C9                jz      short loc_45C517
.text:0045C4CB                sub    ecx, 171h
.text:0045C4D1                jnz    loc_45F674

Here the code is subtracting 12E5 from ecx (which is the opcode), and following a jump which leads to the
charm routine if the result is zero.

We could continue moving back through the call tree to find if there are any other subtractions being done
on the opcode value, but in this case there isn't, 0x12e5 is the opcode for OP_Charm in Titanium.

trevius 07-24-2008 07:59 AM

Very nice! Much better info than what I was seeing in the Wiki itself lol. So, by using that same logic, I imagine that the known opcodes in Titanium could be used to find opcodes for anniversary or even live. It sounds a bit involved and I don't know much about looking at the IDA output yet, but I think If I can get the hang of it that it might start getting easier.

I guess we would still need to figure out packet structure, and other than packet sniffing, I haven't seen it done really. SOE just needs to give us a peak at their source hehe :P

MNWatchdog 07-25-2008 12:50 AM

As long as Sony doesnt change compilers or their C code for handling Opcodes, you could make what ya might call templates that could easily find any opcodes.

You take the current client, look at the hex before and after the opcode and build these templates to quickly search for new opcodes.

Template for a opcode would be like HH HH HH ?? ?? HH HH, where HHs are the common hex codes and the ?? are the unknown/possible opcodes.

Then you search the new client using these templates.

AndMetal 09-19-2008 09:52 PM

Quote:

Originally Posted by AndMetal (Post 152299)
Looking at the source (different files of course) from the same time, we should be able to find out at least some of the structures, if we don't know them already. However, taking a quick peek myself, I wasn't able to find any clear cut "structures" file, so it's probably all spread out through the source.

Found them: showeq/src/everquest.h. Maybe some of the later changes to the structs might provide some insight on what the unknown values may be...


All times are GMT -4. The time now is 02:12 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.