Protocol documentation

Discussion in 'RuneScape 3 Cheating' started by super_, Aug 20, 2009.

Protocol documentation
  1. Unread #1 - Aug 20, 2009 at 2:10 AM
  2. super_
    Joined:
    Dec 20, 2008
    Posts:
    91
    Referrals:
    0
    Sythe Gold:
    0

    super_ Member

    Protocol documentation

    the runescape protocol is split up into raw data (bare) or what many call frames (header).

    Every change of the RuneScape 2 protocol comes with 2 new arrays holding lengths for every frame used. One is used on the server, the other on the client.
    Examples:

    RS2 #317:
    Code:
        public static final int[] packetSizes = {
                0, 0, 0, 0, 6, 0, 0, 0, 4, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
                0, 0, 0, 0, -2, 4, 3, 0, 0, 0,
                0, 0, 0, 0, 5, 0, 0, 6, 0, 0,
                9, 0, 0, -2, 0, 0, 0, 0, 0, 0,
                -2, 1, 0, 0, 2, -2, 0, 0, 0, 0,
                6, 3, 2, 4, 2, 4, 0, 0, 0, 4,
                0, -2, 0, 0, 7, 2, 0, 6, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 2, 0, 1,
                0, 2, 0, 0, -1, 4, 1, 0, 0, 0,
                1, 0, 0, 0, 2, 0, 0, 15, 0, 0,
                0, 4, 4, 0, 0, 0, -2, 0, 0, 0,
                0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
                0, 0, 2, 0, 0, 0, 0, 14, 0, 0,
                0, 4, 0, 0, 0, 0, 3, 0, 0, 0,
                4, 0, 0, 0, 2, 0, 6, 0, 0, 0,
                0, 3, 0, 0, 5, 0, 10, 6, 0, 0,
                0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
                4, 0, 0, 0, 0, 0, 3, 0, 2, 0,
                0, 0, 0, 0, -2, 7, 0, 0, 2, 0,
                0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
                8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                2, -2, 0, 0, 0, 0, 6, 0, 4, 3,
                0, 0, 0, -1, 6, 0, 0
        };
    RS2 #508:
    Code:
        static int[] packetSizes = { 0, 3, 0, 0, 0, 0, 6, 0, 2, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 5, 0, 0, 0, 15, 4, 0, 0, 0, 0, 10, 0, 2, 0, 0, 4, 6, 4, 0, 0, 0, 0, -1, 0, 10, 7, 0, 0, 0, 0, 24, 0, 3, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 3, 4, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 15, 0, 0, 1, 0, -2, 8, 5, 8, -1, 0, 0, -2, 0, 0, 0, 0, 0, 8, 0, -1, 0, 0, -2, 0, 20, 0, -2, 10, 0, -2, 0, -1, 0, 2, 0,
                0, -1, 0, 0, -2, 4, -1, 0, 8, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, -2, 1, 4, -2, 8, 0, -1, 2, -1, -2, 0, 0, 0, 0, 6, 0, 3, 0, 0, 0, 2, -1, 0, 6, 0, 7, 2, 0, 0, 0, 0, 3, 0, 0, 0, -1, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, -2, 6, -1, 4, 0, 0, -2, 12, 0, 0, 1, 9, 0, -1, 0, 0, 5, 0, -1, 0, 0, 0, 0, 3, -2, 0, 0, 0, 0, 6, 4, 5, 6, 2, 0, 5, -1, 0, 0, -2 };
    
    The table of lengths is indexed by a frame's opcode, type, or id. These tell the client what type of frame the current is. The opcode of a frame is the first field in a frame's header, and is an unsigned 1-byte integer.

    As you see, some of the frame sizes in these lists are negative, and it's impossible for a frame to be negatively sized.. these frames are variable-sized. With variable sized frames, an extra field is put into the frame's header which denotes the frame's payload's size.
    There are two types of variable-sized frames: short and byte. Each are depicted in the packet lengths lists by a -2 and -1, respectively.
    Their names come from the type of datatype and size they are written as in the header; a short variable-sized frame has the payload size written as an unsigned 2-byte short integer, while the byte variable-sized frame has the payload size written as an unsigned 1-byte integer.

    Code:
    Code:
            if (Class49.packetOpcode == -1)
            {
                avail--;
                PlayerDefinition.connection.read(1, 0, Class68_Sub13_Sub8.incomingVector.data);
                Class68_Sub13_Sub8.incomingVector.position = 0;
                Class49.packetOpcode = Class68_Sub13_Sub8.incomingVector.getPacketOpcode();
                Class106.packetSize = Class9.packetSizes[Class49.packetOpcode];
            }
            if (Class106.packetSize == -1)
            {
                if (avail <= 0)
                    return false;
                PlayerDefinition.connection.read(1, 0, Class68_Sub13_Sub8.incomingVector.data);
                Class106.packetSize = 0xff & Class68_Sub13_Sub8.incomingVector.data[0];
                avail--;
            }
            if (Class106.packetSize == -2)
            {
                if (avail > 1)
                {
                    avail -= 2;
                    PlayerDefinition.connection.read(2, 0, Class68_Sub13_Sub8.incomingVector.data);
                    Class68_Sub13_Sub8.incomingVector.position = 0;
                    Class106.packetSize = Class68_Sub13_Sub8.incomingVector.readUShort();
                } else
                    return false;
            }
    Frame structures:

    A statically sized frame has the structure:
    Code:
    {
        ubyte opcode;
        byte payload[size];
    }
    where size is equivalent to the packet's size in the packet lengths list.

    A short variable-sized frame:
    Code:
    {
        ubyte opcode;
        ushort size;
        byte payload[size];
    }
    And lastly, a byte variable-sized frame:
    Code:
    {
        ubyte opcode;
        ubyte size;
        byte payload[size];
    }
    After the client has successfully read a frame, it then checks against it's opcode to discover what type of data lies in the payload, and then begins to read.

    JaGeX employs several different types of datatypes in their Buffer, Stream, Packet, etc. class.

    They also employ several types of encryption. Among them include two methods: RSA and ISAAC ciphering.

    RSA:

    JaGeX only uses RSA upon the login block, which contains the ISAAC cipher seed, username, and password, among other things. This helps stop people from packet sniffing to steal passwords, as well as to kill proxy bots (like AutoRune).
    Code:
    RS2 #508:
    Code:
                        int[] seed = new int[4];
                        seed[1] = (int) (9.9999999E7 * Math.random());
                        seed[0] = (int) (9.9999999E7 * Math.random());
                        seed[2] = (int) (Class68_Sub13_Sub11.serverSessionKey >> 32);
                        ((ByteVector) CRCFileReader.outputVector).position = 0;
                        seed[3] = (int) Class68_Sub13_Sub11.serverSessionKey;
                        CRCFileReader.outputVector.writeByte(10);
                        CRCFileReader.outputVector.writeInteger(seed[0]);
                        CRCFileReader.outputVector.writeInteger(seed[1]);
                        CRCFileReader.outputVector.writeInteger(seed[2]);
                        CRCFileReader.outputVector.writeInteger(seed[3]);
                        CRCFileReader.outputVector.writeLong(Class68_Sub28_Sub2.username.toLong(10908));
                        CRCFileReader.outputVector.writeString(Class68_Sub28_Sub2.password);
                        CRCFileReader.outputVector.encodeRSABlock(Class68_Sub4.RSA_PUBLIC_KEY, Class68_Sub22.RSA_MODULUS);
    RSC #204:
    Code:
                int seed[] = new int[4];
                seed[0] = (int) (Math.random() * 99999999D);
                seed[1] = (int) (Math.random() * 99999999D);
                seed[2] = (int) (serverSessionKey >> 32);
                seed[3] = (int) serverSessionKey;
                EncodedBlock loginBlock = new EncodedBlock(new byte[500]);
                loginBlock.offset = 0;
                loginBlock.writeByte(10);
                loginBlock.writeInt(seed[0]);
                loginBlock.writeInt(seed[1]);
                loginBlock.writeInt(seed[2]);
                loginBlock.writeInt(seed[3]);
                loginBlock.writeInt(getUserId());
                loginBlock.writeString(username);
                loginBlock.writeString(password);
                loginBlock.encodeRSA(d, m);
    RS2 #317:
    Code:
                    int isaacRandomGenSeed[] = new int[4];
                    isaacRandomGenSeed[0] = (int) (Math.random() * 99999999D);
                    isaacRandomGenSeed[1] = (int) (Math.random() * 99999999D);
                    isaacRandomGenSeed[2] = (int) (serverSessionKey >> 32);
                    isaacRandomGenSeed[3] = (int) serverSessionKey;
                    outputStream.currentOffset = 0;
                    outputStream.addByte(10);
                    outputStream.addInt(isaacRandomGenSeed[0]);
                    outputStream.addInt(isaacRandomGenSeed[1]);
                    outputStream.addInt(isaacRandomGenSeed[2]);
                    outputStream.addInt(isaacRandomGenSeed[3]);
                    outputStream.addInt(signlink.uid);
                    outputStream.addString(username);
                    outputStream.addString(password);
                    outputStream.rsaEncodeBuffer();
    ISAAC ciphering:

    Once the login procedure occurs, the RuneScape client and server use the 4 integer seed from the login block to seed two ISAAC ciphers on both sides: one for ciphering, and one for deciphering. The ISAAC ciphers are used to mask and demask each frame's opcode. This was most likely created to stop AutoRune-like bots that worked by injecting data into the intercepted stream.
    Code:

    RS2 #317:
    Code:
                if (packetOpcode == -1) {
                    socketStream.flushInputStream(inStream.buffer, 1);
                    packetOpcode = inStream.buffer[0] & 0xff;
                    if (encryption != null)
                        packetOpcode = packetOpcode - encryption.nextInt() & 0xff;
                    packetSize = SizeConstants.packetSizes[packetOpcode];
                    dataAvailable--;
                }
    Code:
        public void addPacketId(int i) {
            buffer[currentOffset++] = (byte) (i + encryption.nextInt());
        }
    RS2 #508:
    Code:
            if (Class49.packetOpcode == -1)
            {
                avail--;
                PlayerDefinition.connection.read(1, 0, Class68_Sub13_Sub8.incomingVector.data);
                Class68_Sub13_Sub8.incomingVector.position = 0;
                Class49.packetOpcode = Class68_Sub13_Sub8.incomingVector.getPacketOpcode();
                Class106.packetSize = Class9.packetSizes[Class49.packetOpcode];
            }
    Code:
        final int getPacketOpcode()
        {
            return (data[position++] - randomNumberGenerator.next()) & 0xff;
        }
    
    Code:
        final void writeOpcode(int opcode)
        {
            data[position++] = (byte) (opcode + randomNumberGenerator.next());
        }
    
    RSC #204:
    Code:
            opcode = connection.decodeOpcodeISAAC(opcode);
    Code:
            if (outgoingISAACGen != null) {
                int packetId = buffer[packetStartOffset + 2] & 0xff;
                buffer[packetStartOffset + 2] = (byte) (packetId + outgoingISAACGen.next());
            }
    This is by far not that in depth or anything of that sort, just a small introduction to show how the RuneScape protocol worked.

    If you have anything to add that is valid, feel free to ask.
     
  3. Unread #2 - Aug 20, 2009 at 9:38 PM
  4. Badger191
    Joined:
    Mar 22, 2006
    Posts:
    3,533
    Referrals:
    4
    Sythe Gold:
    2,263
    Vouch Thread:
    Click Here
    Discord Unique ID:
    299558299874099200
    Discord Username:
    BadgerBadger#5233
    Pokémon Trainer Two Factor Authentication User

    Badger191 Degenerate
    Badger191 Donor

    Protocol documentation

    Opened, he showed proof he wrote this.
     
  5. Unread #3 - Aug 22, 2009 at 7:27 PM
  6. super_
    Joined:
    Dec 20, 2008
    Posts:
    91
    Referrals:
    0
    Sythe Gold:
    0

    super_ Member

    Protocol documentation

    Tisk tisk.
     
  7. Unread #4 - Aug 23, 2009 at 5:53 AM
  8. PennyRoyal
    Joined:
    Jul 23, 2008
    Posts:
    1,755
    Referrals:
    2
    Sythe Gold:
    37
    Sythe's 10th Anniversary

    PennyRoyal Guru

    Protocol documentation

    Indepth. So thats how the stop sniffers.. Have people been asking about this or something>?
     
  9. Unread #5 - Aug 24, 2009 at 3:19 PM
  10. super_
    Joined:
    Dec 20, 2008
    Posts:
    91
    Referrals:
    0
    Sythe Gold:
    0

    super_ Member

    Protocol documentation

    Asking? Not really... prolly because they are all idiots.
     
< Www.Purescape101.Com | Autofighter.org - Your Opinions >

Users viewing this thread
1 guest


 
 
Adblock breaks this site