Packet capture/decrypt lib menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Packet capture/decrypt lib

    (Edit: almost forgot; you need SharpPcap and SharpZipLib for this to work. Both are freely available on the net.)

    A lot of this is stolen from other locations. Basically I took an idea from snoke originally to use SharpPcap to do managed promiscuous packet capturing and assembly. Then I swiped the sniffitzt java code as well as some of my own reversing to get the decryption of the reassembled packet headers working. Finally, I took a liberal helping of Mangos code to get all the opcodes and so forth.

    I have another large body of code that is just handling the individual opcodes, but this should be enough to get someone started, say, just snagging the Warden traffic -- or whatever you want. In reality, it's the core of a fairly full-featured OOP bot.

    Note that you need to plug in your own OOP memory reader in ClientConnection.cs (it will throw an app exception right now to force you to deal with it ) Also, to limit the amount of uninteresting packets I deal with, I throw away everything except realm server packets to-from predefined realms (in ClientConnectionManager.cs). As the code stands, it's filtering out only traffic to-from Baelgun (the last server I was testing a trial character against). Obviously, you need to change this to your appropriate realm server. One of the early auth server packets has a full realm list (with IP's) in it, if you aren't sure of "your" realm server's IP.

    I can't seem to get MMOwned's upload feature to work, so here's a mediafire share: WoWPacketSniffer.zip

    Yes, I know my code is far from perfect, but it works as-is to capture large streams of decrypted packets from multiple simultaneous WoW sessions.

    Here's a quick-n-dirty console packet sniffer/dumper using this lib:

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using WoWLib.PacketCapture;
    
    namespace Sniffer.Net
    {
        class Program
        {
            static void Main(string[] args)
            {
                // this may not work on your machine -- instead, use some sane way of picking 
                // the right cap device from AllDevices (look at the Description to figure out 
                // what's what)
                var wpd = ClientConnectionManager.AllDevices.First();
                ClientConnectionManager ccm = new ClientConnectionManager(wpd);
                ccm.ClientConnected += new ClientConnectionEstablishedDelegate(ccm_ClientConnected);
                ccm.ClientConnectionCreated += new ClientConnectionCreatedDelegate(ccm_ClientConnectionCreated);
                ccm.ClientDisconnected += new ClientConnectionDisconnectedDelegate(ccm_ClientDisconnected);
                ccm.StartedCapturing += new StartedCapturingDelegate(ccm_StartedCapturing);
                ccm.StoppedCapturing += new StoppedCapturingDelegate(ccm_StoppedCapturing);
                ccm.Run();
                while (true)
                {
                }
            }
    
            static void ccm_StoppedCapturing(IClientConnectionManager manager)
            {
                Console.WriteLine("Stopped capturing on {0}", manager.Description);
            }
    
            static void ccm_StartedCapturing(IClientConnectionManager manager)
            {
                Console.WriteLine("Started capturing on {0}", manager.Description);
            }
    
            static void ccm_ClientDisconnected(IClientConnectionManager manager, IClientConnectionInfo connection, MessageDirection initiator)
            {
                Console.WriteLine("Client id {0} disconnected on {1}", connection.Id, manager.Description);
            }
    
            static void ccm_ClientConnectionCreated(IClientConnectionManager manager, IClientConnectionInfo connection)
            {
                Console.WriteLine("Client connection id {0} (remote addr: {1}) created on {2}", connection.Id, connection.RemoteAddress.ToString(), manager.Description);
            }
    
            static void ccm_ClientConnected(IClientConnectionManager manager, IClientConnectionInfo connection, MessageDirection initiator)
            {
                Console.WriteLine("Client connection id {0} (remote addr: {1}) connected on {2}", connection.Id, connection.RemoteAddress.ToString(), manager.Description);
                connection.LogicalPacketDecoded += new LogicalPacketDecodedDelegate(connection_LogicalPacketDecoded);
            }
    
            static void connection_LogicalPacketDecoded(IClientConnectionInfo connection, LogicalPacket packet)
            {
                Console.WriteLine("[{0} conn {1}] {2}_{3}",
                    DateTime.Now,
                    connection.Id,
                    packet.Direction.ToString(),
                    packet.Opcode.ToString());
            }
        }
    }
    Here's (arguably) the most important opcode parser -- SMSG_UPDATE_OBJECT. This (obviously) won't compile, since you'd need the rest of my GameContext code (the object that abstracts away one connection's "view" of the game world), but it should help anyone interested get started parsing these critical packets. The original was ripped from the sniffitzt sources, but keeping it up-to-date is nontrivial.

    Note that this is probably the most dynamic packet structure. It took a couple hours of reversing to get this to work from 3.1.2 to 3.1.3 (they added a bunch of new spline code).

    Code:
    using System;
    using System.Linq;
    using WoWLib.Logging;
    using WoWLib.Constants;
    using WoWLib.PacketCapture;
    
    namespace WoWLib.GameStateManager
    {
        public enum InstancedObjectType : byte
        {
            TYPEID_OBJECT=0,
    	    TYPEID_ITEM=1,
    	    TYPEID_CONTAINER=2,
    	    TYPEID_UNIT=3,
    	    TYPEID_PLAYER=4,
    	    TYPEID_GAMEOBJECT=5,
    	    TYPEID_DYNAMICOBJECT=6,
    	    TYPEID_CORPSE=7,
    	    TYPEID_AIGROUP=8,
    	    TYPEID_AREATRIGGER=9
        }
    
        public enum ObjectUpdateType : byte
        {
            UPDATETYPE_VALUES = 0,
            UPDATETYPE_MOVEMENT = 1,
            UPDATETYPE_CREATE_OBJECT = 2,
            UPDATETYPE_CREATE_OBJECT2 = 3,
            UPDATETYPE_OUT_OF_RANGE_OBJECTS = 4,
            UPDATETYPE_NEAR_OBJECTS = 5
        }
    
        [Opcode(Opcodes.SMSG_DESTROY_OBJECT, MessageDirection.StoC)]
        public class S2C_SMSG_DESTROY_OBJECT : IOpcodeHandler
        {
            public void Decode(GameContext ctx, LogicalPacket packet)
            {
                var buffer = new ProcessByteBuffer(packet.Buffer);
                ulong guid = buffer.ReadWoWGuid();
                System.Diagnostics.Debug.Assert(guid != ctx.LocalPlayer.guid);
                ctx.Data.RemoveObjectByGuid(guid);
            }
        }
    
        [Opcode(Opcodes.SMSG_UPDATE_OBJECT, MessageDirection.StoC)]
        public class S2C_SMSG_UPDATE_OBJECT : IOpcodeHandler
        {
            public void Decode(GameContext ctx, LogicalPacket packet)
            {
                ProcessByteBuffer buffer = new ProcessByteBuffer(packet.Buffer);
    		    uint blockcount = buffer.Read<uint>();
    		
                for (int i = 0; i < blockcount; i++)
                {
                    ObjectUpdateType type = (ObjectUpdateType)buffer.Read<byte>();
    
                    switch (type)
                    {
                        case ObjectUpdateType.UPDATETYPE_VALUES:
                            {
                                InstancedObject obj = ctx.Data.GetObjectByGuid(buffer.ReadPackedGuid());
                                UpdateObjectFields(obj, ctx, buffer, packet.Timestamp);
                                break;
                            }
                        case ObjectUpdateType.UPDATETYPE_MOVEMENT:
                            {
                                InstancedObject obj = ctx.Data.GetObjectByGuid(buffer.ReadPackedGuid());
                                UpdateObjectPosition(obj, ctx, buffer, packet.Timestamp);
                                break;
                            }
                        case ObjectUpdateType.UPDATETYPE_CREATE_OBJECT2:
                        case ObjectUpdateType.UPDATETYPE_CREATE_OBJECT:
                            {
                                CreateObject(ctx, buffer, packet.Timestamp);
                                break;
                            }
                        case ObjectUpdateType.UPDATETYPE_NEAR_OBJECTS:
                            {
                                long nsize = buffer.ReadUInt32();
                                for (long j = 0; j < nsize; j++)
                                {
                                    ulong guid = buffer.ReadPackedGuid();
                                    // what do we do with it?
                                }
                                break;
                            }
                        case ObjectUpdateType.UPDATETYPE_OUT_OF_RANGE_OBJECTS:
                            {
                                uint size = buffer.Read<uint>();
                                for (long j = 0; j < size; j++)
                                {
                                    ulong guid = buffer.ReadPackedGuid();
                                    System.Diagnostics.Debug.Assert(guid != ctx.LocalPlayer.guid); // the local player is out of range??
                                    ctx.Data.RemoveObjectByGuid(guid);
                                 }
                                break;
                            }
                        default:
                            throw new ApplicationException("Error: unknown updatetype " + type);
                    }
                }
            }
    
            private InstancedObject CreateObject(GameContext ctx, ProcessByteBuffer buffer, DateTime timeStamp)
            {
                ulong guid = buffer.ReadPackedGuid();
    
                WoWObjectType objectType = (WoWObjectType)buffer.ReadByte();
                InstancedObject existing = ctx.Data.GetObjectByGuid(guid);
                if (existing != null)
                {
                    Logger.Log(Level.Warning, "Warning, creating already-existing object guid {0:x16}, type {1}", guid, objectType);
                }
                else
                {
                    existing = ctx.Data.GetOrInitializeObject(guid, objectType, timeStamp);
                }
    
                UpdateObjectPosition(existing, ctx, buffer, timeStamp);
                UpdateObjectFields(existing, ctx, buffer, timeStamp);
    
                return existing;
            }
    
            private void UpdateObjectFields(InstancedObject obj, GameContext ctx, ProcessByteBuffer buffer, DateTime timeStamp)
            {
                int blockCount = (int)buffer.ReadByte();
    
                if (blockCount > 0)
                {
                    int masksize = blockCount << 2;
                    UpdateMask umask = buffer.ReadUpdateMask(masksize);
                    int limit = blockCount * 32;
    
                    for (int i = 0; i < limit; ++i)
                    {
                        if (umask.IsVisibleBit(i))
                        {
                            uint value = buffer.ReadUInt32();
    
                            switch (i)
                            {
                                case UpdateFields.UNIT_FIELD_TARGET + 1:
                                    {
                                        obj.setUInt32Value(i, value);
                                        Logger.Log(Level.Trace, "{0} set target to {1}",
                                            obj.getName(),
                                            ctx.Data.SafeGetObjectName(obj.getValuesArray().GetGuid(UpdateFields.UNIT_FIELD_TARGET)));
                                    }
                                    break;
    
                                case UpdateFields.OBJECT_FIELD_TYPE:
                                    {
                                        WoWObjectType oldType = (WoWObjectType)obj.getValue(UpdateFields.OBJECT_FIELD_TYPE);
                                        WoWObjectType newType = (WoWObjectType)value;
                                        if ((oldType != newType) && (oldType != (WoWObjectType)0))
                                        {
                                            Logger.Log(Level.Trace, "Object {0} changing type from {1} to {2}...",
                                                ctx.Data.SafeGetObjectName(obj.guid),
                                                oldType,
                                                newType); // does this ever happen?
                                        }
                                    }
                                    break;
    
                                case UpdateFields.OBJECT_FIELD_ENTRY:
                                    obj.SetTemplate((int)value, ctx.Data);
                                    break;
    
                                case UpdateFields.UNIT_FIELD_CHARM + 1:
                                case UpdateFields.UNIT_FIELD_CHARMEDBY + 1:
                                case UpdateFields.UNIT_FIELD_CREATEDBY + 1:
                                case UpdateFields.UNIT_FIELD_SUMMON + 1:
                                case UpdateFields.UNIT_FIELD_SUMMONEDBY + 1:
                                    {
                                        if (obj is InstancedUnit) // useful to track changes in these fields; comment for general use
                                        {
                                            obj.setUInt32Value(i, value);
                                            Logger.Log(Level.Trace, "{0} set {1} to {2}",
                                                obj.getName(),
                                                i - 1,
                                                ctx.Data.SafeGetObjectName(obj.getGuid(i - 1)));
                                        }
                                    }
                                    break;
    
                                case UpdateFields.UNIT_FIELD_FLAGS:
                                    {
                                        UnitFlags oldFlags = (UnitFlags)obj.getValue(UpdateFields.UNIT_FIELD_FLAGS);
                                        UnitFlags newFlags = (UnitFlags)value;
                                    }
    
                                    break;
    
                                case UpdateFields.UNIT_FIELD_HEALTH:
                                    {
                                        uint oldValue = (uint)obj.getValue(UpdateFields.UNIT_FIELD_HEALTH);
                                        uint newValue = (uint)value;
    
                                        if ((oldValue != newValue) && (oldValue != 0))
                                        {
                                            if (newValue == 0)
                                            {
                                                Logger.Log(Level.Trace, "!!! {0} died !!!",
                                                    ctx.Data.SafeGetObjectName(obj.guid)); // is there a cleaner way to detect unit death?
                                            }
                                            else
                                            {
                                                Logger.Log(Level.Trace, "{0} changing health from {1} to {2}...",
                                                    ctx.Data.SafeGetObjectName(obj.guid),
                                                    oldValue,
                                                    newValue);
                                            }
                                        }
                                    }
                                    break;
                            }
    
                            obj.setUInt32Value(i, value);
                        }                    
                    }
                }
            }
    
            [Flags]
            public enum UpdateFlags : ushort
            {
                NONE = 0x00,
                SELF = 0x01,
                TRANSPORT = 0x02,
                TargetGuid = 0x04,
                LowGuid = 0x08,
                HighGuid = 0x10,
                Living = 0x20,
                HasPosition = 0x40,
                UNKNOWN1 = 0x80,
                UNKNOWN2 = 0x100,
                UNKNOWN3 = 0x200
            }
    
            private void UpdateObjectPosition(InstancedObject obj, GameContext ctx, ProcessByteBuffer buffer, DateTime movementTime)
            {
                UpdateFlags updateFlags = (UpdateFlags)buffer.ReadInt16();
    
    
                MovementFlags movementFlags;
                int timeStamp = 0;
                short unknown1 = 0;
    
                if ((updateFlags & UpdateFlags.Living) != 0)
                {
                    { // in 3.1.3, this block is held in 0x7a24d0
                        { // in 3.1.3, this entire block is held in the function at 0x7A21C0                        
                            movementFlags = (MovementFlags)buffer.ReadInt32();
                            unknown1 = buffer.ReadInt16();
                            timeStamp = buffer.ReadInt32();
    
                            ((InstancedWorldObject)obj).Position.Read(buffer, false);                        
                            ((InstancedWorldObject)obj).Position.Timestamp = movementTime;
    
                            if ((movementFlags & MovementFlags.OnTransport) != 0)
                            {
                                ulong transportGuid = buffer.ReadPackedGuid(); // packed as of 3.1.3, see 0x7A222D
                                Position transportPos = new Position(0f, 0f, 0f, 0f);
                                transportPos.Read(buffer, false);
                                int transportTime = buffer.ReadInt32();
                                byte transportUnk = buffer.ReadByte();
                                ((InstancedWorldObject)obj).IsOnTransport = true;
                            }
                            else
                            {
                                ((InstancedWorldObject)obj).IsOnTransport = false;
                            }
    
                            if ((movementFlags & MovementFlags.Swimming) != 0)
                            {
                                ((InstancedWorldObject)obj).IsSwimming = true;
                            }
                            else
                            {
                                ((InstancedWorldObject)obj).IsSwimming = false;
                            }
    
                            // 3.1.3:  0x7a228a
                            if (((movementFlags & (MovementFlags.Swimming | MovementFlags.FLYING2)) != 0) ||
                                ((unknown1 & 0x20) != 0))
                            {
                                float swimPitch = buffer.ReadFloat();
                            }
    
                            // 3.1.3:  0x7A22BA
                            int fallTime = buffer.ReadInt32();
    
                            if ((movementFlags & MovementFlags.Jumping) != 0)
                            {
                                ((InstancedWorldObject)obj).IsJumping = true;
                                float jumpUnk1 = buffer.ReadFloat();
                                float jumpSinAngle = buffer.ReadFloat();
                                float jumpCosAngle = buffer.ReadFloat();
                                float jumpXYSpeed = buffer.ReadFloat();
                            }
                            else
                            {
                                ((InstancedWorldObject)obj).IsJumping = false;
                            }
    
                            if ((movementFlags & MovementFlags.Spline) != 0)
                            {
                                float splineUnknown = buffer.ReadFloat();
                            }
                        }
    
                        for (int i = 0; i < 9; ++i)
                        {
                            buffer.ReadFloat(); // movementspeeds[i]
                        }
    
                        if ((movementFlags & MovementFlags.SPLINE2) != 0)
                        {
                            // 3.1.3: see sub 0x7A1FD0 (ProcessSplineFlags)
                            SplineFlags splineFlags = (SplineFlags)buffer.ReadInt32();
                            
                            if ((splineFlags & SplineFlags.Target) != 0)
                            {
                                buffer.ReadFloat();
                            }
                            else
                            {
                                if ((splineFlags & SplineFlags.Point) != 0)
                                {
                                    buffer.ReadWoWGuid();
                                }
                                else if ((splineFlags & SplineFlags.Unk1) != 0)
                                {
                                    Position pos = new Position(0f, 0f, 0f, 0f);
                                    pos.Read(buffer, true);
                                }
                            }
    
                            // 3.1.3: see 0x7a2028 thru end of func
                            buffer.ReadInt32();
                            buffer.ReadInt32();
                            buffer.ReadInt32();
                            buffer.ReadFloat();
                            buffer.ReadFloat();
                            buffer.ReadFloat();
                            buffer.ReadInt32();
                            int val = buffer.ReadInt32();
                            buffer.ReadBytes(12 * val);
                            buffer.ReadByte();
                            buffer.ReadFloat();
                            buffer.ReadFloat();
                            buffer.ReadFloat();
                        }
                    }
                }
                else // 0x7BC9EB
                {
                    // this flag and check is new from 3.1.2->3.1.3 afaik
                    if ((updateFlags & UpdateFlags.UNKNOWN2) == 0)
                    {
                        if ((updateFlags & UpdateFlags.HasPosition) != 0)
                        {
                            ((InstancedWorldObject)obj).Position.Read(buffer, false);
                            ((InstancedWorldObject)obj).Position.Timestamp = movementTime;
                        }
                    }
                    else
                    {
                        // in 3.1.3, see the block at 0x7BC9F2
                        ulong guid2 = buffer.ReadPackedGuid();
                        for (int i = 0; i < 8; ++i)
                        {
                            buffer.ReadFloat(); // what is this??
                        }
                    }
                }
    
                if ((updateFlags & UpdateFlags.LowGuid) != 0)
                {
                    uint lowGuid = buffer.ReadUInt32();
                }
    
                if ((updateFlags & UpdateFlags.HighGuid) != 0)
                {
                    uint highGuid = buffer.ReadUInt32();
                }
    
                if ((updateFlags & UpdateFlags.TargetGuid) != 0)
                {
                    ulong targetGuid = buffer.ReadPackedGuid(); // 3.1.3:  0x7BCADA
                }
    
                if ((updateFlags & UpdateFlags.TRANSPORT) != 0)
                {
                    buffer.ReadInt32(); // 3.1.3:  0x7BCB01
                }
    
                if ((updateFlags & UpdateFlags.UNKNOWN1) != 0)
                {
                    int wotlkUnk1 = buffer.ReadInt32();
                    float wotlkUnk2 = buffer.ReadFloat();
                }
    
                if ((updateFlags & UpdateFlags.UNKNOWN3) != 0)
                {
                    buffer.ReadWoWGuid();
                }
            }
        }
    }
    Edit: currently the problems I'm having with my bot are all higher-level abstractions. It's relatively easy to detect, for instance, who's attacking me (I can just enumerate threat lists). But a trickier task is how to normalize 2, 3, or 5 different "views" of the WoW gameworld so that my bot can get a clear idea of what's going on.

    It's certainly not an impossible task. Just tricky; I have to think about what data is private per client, and what is shared with the world via packets, and then correctly combine those two sources of information into a coherent picture.

    Once I have that, it's time to start writing my more complicated behavior tree rules!
    Last edited by amadmonk; 06-24-2009 at 04:45 PM.
    Don't believe everything you think.

    Packet capture/decrypt lib
  2. #2
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry to reply to my own thread. Do you guys think we can move this to the regular memedit section (if that's the right place for it)? Lanman asked me if I was gonna release it; I won't release the full bot, but it seems like it might be useful for someone (making a radar or something else OOP) and would be a shame to waste the hours I put into it...
    Don't believe everything you think.

  3. #3
    BoogieManTM's Avatar Active Member
    Reputation
    52
    Join Date
    May 2008
    Posts
    193
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cool stuff. nice share.

  4. #4
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for this, amadmonk. +rep

  5. #5
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're welcome; enjoy. I've moved on to injection-based bots, but the decryptor lib still works fine (until the next patch, when someone will need to update the encryption key offset).
    Don't believe everything you think.

  6. #6
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by amadmonk View Post
    You're welcome; enjoy. I've moved on to injection-based bots, but the decryptor lib still works fine (until the next patch, when someone will need to update the encryption key offset).

    We converted you to the dark side.

  7. #7
    Sel3n's Avatar Member
    Reputation
    10
    Join Date
    Jul 2009
    Posts
    115
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice! Thx for this :hap:

  8. #8
    barthen's Avatar Contributor Authenticator enabled
    Reputation
    94
    Join Date
    Apr 2007
    Posts
    112
    Thanks G/R
    4/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Great post! Thanks for sharing.

  9. #9
    bouh2's Avatar Active Member
    Reputation
    28
    Join Date
    Mar 2008
    Posts
    83
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice !

    +rep for you =)

  10. #10
    dook123's Avatar Active Member
    Reputation
    21
    Join Date
    Oct 2008
    Posts
    115
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    nice

    Very nice job here. A few months back when i decided to start working on creating my own bot I figured there were two ways, memory or networking. I am bettering with networking so i thought that would be the best way but there are a lot more people doing it with injection.

    I may use this though so thank you for sharing

    -Duke

  11. #11
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Someone wanna update the SRP key for 3.2.0? Otherwise I'll do it... when I get to it (bot dev keeping me kinda busy lately)
    Don't believe everything you think.

  12. #12
    Cromon's Avatar Legendary


    Reputation
    840
    Join Date
    Mar 2008
    Posts
    714
    Thanks G/R
    0/7
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey!

    Thats a great thing! Worked a bit on that to get it for 3.2.0 but facing some problems

    The packets from the client getting decrypted correctly also the first serverpacket (0x492) but after that the next serverpacket comes with a raw size of 6 bytes what actually cannot be, cause after 0x493 from the client the server sends 0x494 which is at least 15 bytes... also all of the 6 bytes are 0. And after that the tcp-Acknowledges get out of sync (the sequence of the packets first are 6 less than the next sequence and after much higher...).

  13. #13
    Cromon's Avatar Legendary


    Reputation
    840
    Join Date
    Mar 2008
    Posts
    714
    Thanks G/R
    0/7
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    [edit: browser hung up -> posted twice...]

    [edit2: ill use this accidental post for some updates ]
    Solved that, there are some 6 byte packets that seem to be strange. The next packet has the same sequence-number so if you increase the expected number by 6 when the packet arrives it gets out of sync. Also you should avoid to decrypt those packets cause they dont seem to be encrypted (they dont have any purpose at all) and you **** up the encryption.

    For some "hackfix" im ignoring all 6-byte standalone packets and it works now til the server sends a 6 byte standalone packet which is not one of those crappy packets and so i get out of sync in the encryption. Need to find a better way of avoiding those senseless packets :P
    Last edited by Cromon; 08-10-2009 at 01:34 AM.

  14. #14
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If so, this must be new, since I captured hours and hours of traffic with this lib with no sync issues.

    There is a known problem when packets arrive out of order, but the solution to the problem -- which doesn't occur often on a good net connection -- was complex enough that I didn't bother to implement it.
    Don't believe everything you think.

  15. #15
    Cromon's Avatar Legendary


    Reputation
    840
    Join Date
    Mar 2008
    Posts
    714
    Thanks G/R
    0/7
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Its very strange! If i use a test-DK lvl 80 capturing i get out of sync just some seconds after login. If i use any other char everything works great...


    EDIT:
    Very, very, very strange! It gets out of sync allways after CMSG_MSG_MOVE_HEARTBEAT...
    Last edited by Cromon; 08-10-2009 at 01:04 PM.

Page 1 of 2 12 LastLast

Similar Threads

  1. ESO Packet Decrypt/Encrypt. Close, but cannot determine key
    By jarjar1 in forum Elder Scrolls Online General
    Replies: 3
    Last Post: 10-06-2013, 12:19 PM
  2. [Question] What packets are not encrypted/decrypted?
    By adapa in forum WoW Memory Editing
    Replies: 10
    Last Post: 09-28-2011, 09:03 AM
  3. Packet capture/decrypt lib
    By SinnerG in forum WoW Memory Editing
    Replies: 7
    Last Post: 03-24-2010, 05:00 PM
  4. [C] WoW packet decryption
    By pendra in forum WoW Memory Editing
    Replies: 12
    Last Post: 03-06-2010, 12:39 AM
All times are GMT -5. The time now is 09:53 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search