Arisstath / roblox-dissector

Roblox UDP Protocol Dissector
MIT License
133 stars 16 forks source link

Question #4

Closed ghost closed 5 years ago

ghost commented 5 years ago

Hi, Could you transform this function: func shuffleSlice(src []byte) []byte { ShuffledSrc := make([]byte, 0, len(src)) ShuffledSrc = append(ShuffledSrc, src[:0x10]...) for j := len(src) - 0x10; j >= 0x10; j -= 0x10 { ShuffledSrc = append(ShuffledSrc, src[j:j+0x10]...) } return ShuffledSrc }

In javascript? I have already convert the rest. I don't code Golang and I dont know those operator.. Thanks!

ghost commented 5 years ago

function shuffleSlice(src){

let ShuffledSrc = new Buffer(src.length).fill(0);
ShuffledSrc = append(ShuffledSrc, src[:0x10]...)
for(var j = src.length - 0x10; j >= 0x10; j -= 0x10) {
    ShuffledSrc = append(ShuffledSrc, src[j:j+0x10]...)
}
return ShuffledSrc

};

This is what i have rn. Idk what todo with the append function and the [j:j ...

Gskartwii commented 5 years ago

See the docs for Buffer from node.js: https://nodejs.org/api/buffer.html#buffer_class_method_buffer_concat_list_totallength

You can think of Golang's [start:end] operator like Buffer.slice(start, end) from node.js. So src[j:j+0x10] in Go is the same as src.slice(j, j+0x10), where src is a node.js Buffer.

Golang's builtin append(slice, vars...) function works similarly to Buffer.concat([buf1, buf2]) in node.js. Basically, append(ShuffledSrc, src[:0x10]...) translates to Buffer.concat([ShuffledSrc, src.slice(0, 0x10).

Now let's take a look at what shuffleSlice() is meant to do. Its purpose is to split a byte buffer to blocks of length 128-bits (or 0x10 bytes), which matches the block length for AES-128-CBC. It should then put the first block at the start of the shuffled buffer, but the rest of the blocks should be in reverse order, so the last block goes second, the second to last block goes third, etc. and the originally second block goes last.

On the first line of your function, you're creating a new buffer with a specific length that is filled with 0x00 bytes. You don't actually want to do this, but instead, you need to the shuffled buffer to be empty in the beginning. In fact, you can skip allocating it and just take a slice out of the original buffer, so:

let ShuffledSrc = src.slice(0, 0x10);

The loop then takes a variable j that points to some index within the buffer. The length of the buffer is guaranteed to be a multiple of 0x10, so we can skip a few steps here. The j variable is initially set to point at length - 0x10, and every time the loop processes the chunk from j to j+0x10, so this way the entire src is covered.

Basically, you need to make your code look like this:

function shuffleSlice(src) {
    let ShuffledSrc = src.slice(0, 0x10);
    for (var j = src.length - 0x10; j >= 0x10; j -= 0x10) {
        ShuffledSrc = Buffer.concat([ShuffledSrc, src.slice(j, j+0x10)]);
    }
    return ShuffledSrc;
}

Disclaimer: I didn't actually test this, and I haven't used node.js in a long time.

I hope this was helpful for learning and implementing. Good luck!

ghost commented 5 years ago

Thanks!

ghost commented 5 years ago

Sorry if the code is a bit messy..

const crypto = require('crypto');
let key = new Buffer([0xFE, 0xF9, 0xF0, 0xEB, 0xE2, 0xDD, 0xD4, 0xCF, 0xC6, 0xC1, 0xB8, 0xB3, 0xAA, 0xA5, 0x9C, 0x97]);
const cipherAES = crypto.createCipher('aes-128-cbc', key);

function shuffleSlice(src) {
    let ShuffledSrc = src.slice(0, 0x10);
    for (var j = src.length - 0x10; j >= 0x10; j -= 0x10) {
        ShuffledSrc = Buffer.concat([ShuffledSrc, src.slice(j, j+0x10)]);
    }
    return ShuffledSrc;
}

function calculateChecksum(data){

    var sum = 0
    var r = 55665
    var c1 = 52845
    var c2 = 22719
    for(var i = 0; i < data.length; i++) {
        let char = data[i];
        let cipher = (char ^ (r >> 8)) & 0xFF;
        r = (cipher + r) * c1 + c2;
        sum += cipher;
    }
    return sum

};

let clientTicket = '11/13/2018 7:51:45 PM;TiwZ/CBmI9/2Qu7qtziuFCOX6i5MJlWICsP93d6nBYdY317dVm+G+JVd0sklRNQZkAfpr0O//6I4rEV/Q4OMCKQIxul+/N3gLYTEiNTFoaz2sfoGFj698HHPPrR1E0pg4esKdPqFC/jLrXQd+BmHbvfFq+leeVY24FaCKwNH6EEaV5FIRZ4duABCMVuGQjoZ0w9KO2EecvztY9GO5e92CeJwz/GoFgG/j4LYOL8y9mTcLquoPmCb4bje9I+zPpke6gRJ3MA3E7LgJgQ4s1fc0WTsDgMgA9AYD1DPqeasgTy7gnQoKzfPT4XQY1e23lm8NvYrE/etpmWU3qseR+O1+Q==;A0KT4NC4IpN6+snAicBNluuZA8OeBTRBsohR3qIYYV690U20kluV7Q+LhVK3iiGiODH2aRRukdM+Bhj7VZ9m8EAb0W0uJp205EA5DdVO4oZsiR9/6LvZ0UI66bVY1xL3sZR3g8AUMGpyZGuBSdiwI7TJPofyAADplcEyIIzaMBKl+Y99yW5F4sRHX3BKw1cIoLoO7Z9M/kW+E4QJAFQiAHMhkB7CekwKTeTwMfCp0ilDPiAFiBCfsq08T8K+zMJ0MXeCvU7D3TdJydP+2+NEX9SaKvsBLieske9amdfcuR7ZgADUI3OYcRj8u7rEOhyURCmNgRDIQuJ3KlqYGSjACA==;2';

import bitwiseRotation from 'bitwise-rotation';
const rotationObject = bitwiseRotation(32);
const { ror, rol } = rotationObject;
const XXH = require('xxhashjs');
const xxHash32 = XXH.h32;

function hashClientTicket(ticket) {
    var ecxHash;
    let a = XXH.h32(1);
    a.update(Buffer.from(ticket, 'utf-8'));
    let initHash = a.digest();
    initHash += 0x557BB5D7
    initHash = rol(initHash, -7)
    initHash -= 0x557BB5D7
    initHash *= 0x443921D5
    initHash = rol(initHash, -0xD)
    ecxHash = 0x557BB5D7 - initHash
    ecxHash ^= 0x443921D5
    ecxHash = rol(ecxHash, 0x11)
    ecxHash += 0x664B2854
    ecxHash = rol(ecxHash, -0x17)
    initHash = ecxHash - 0x664B2854
    initHash = rol(initHash, 0x1D)
    initHash ^= 0x557BB5D7
    initHash = -initHash

    return initHash
}

let o = hashClientTicket(clientTicket);

let buf = Buffer.from('0a0201020304050607070080', 'hex');
let length = buf.length;
let paddingSize = 0xF - (length+5)%0x10;
let rawCopy = new Buffer(length+6+paddingSize);
rawCopy[5] = paddingSize & 0xF;
rawCopy = Buffer.concat([rawCopy, buf]);

let checkSum = calculateChecksum(rawCopy.slice(4, rawCopy.length));

rawCopy[3] = (checkSum >> 24 & 0xFF);
rawCopy[2] = (checkSum >> 16 & 0xFF);
rawCopy[1] = (checkSum >> 8 & 0xFF);
rawCopy[0] = (checkSum & 0xFF);
let dest = Buffer(rawCopy.length);
let shuffledEncryptable = shuffleSlice(rawCopy);

let encrypted = new Buffer(0);

cipherAES.on('readable', () => {
  const data = cipherAES.read();
  if (data)
    encrypted = Buffer.concat([encrypted, data]);
});

cipherAES.on('end', () => {
  console.log(shuffleSlice(encrypted));
});

console.log(rawCopy);
console.log(shuffledEncryptable);
cipherAES.write(shuffledEncryptable);
cipherAES.end();

This is the code that I get. I don't think that the return are right... I get that ->

rawCopy: <Buffer 30 03 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 02 01 02 03 04 05 06 07 07 00 80>
shuffledEncryptable: <Buffer 30 03 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 02 01 02 03 04 05 06 07 07 00 80>
shuffleSlice(encrypted): <Buffer 6e 12 9a 11 9d 37 a1 80 32 8c e8 25 37 0b 08 d8 42 3a 59 3f 82 46 b9 50 11 01 6d c5 bb d1 17 3e d0 60 6f 89 bd c3 fc b6 9c 4f 17 7d 7f 70 0f 23>

The encrypted buffer is longer that the 2 other. I know that I did not include the packet but it was just for an exemple.

Also, what you mean with rawStream.writeVarsint64 and rawStream.writeVarLengthString ?

Gskartwii commented 5 years ago

rawCopy = Buffer.concat([rawCopy, buf]); is one of the things making the buffer longer. Unfortunately the Buffer from node.js doesn't seem to have a method similar to how Golang's copy works, but we can work around that by splitting the destination slice to the original part and the overwritten part with slice() and then using Buffer.concat to "overwrite" the remaining bytes:

let rawCopy = new Buffer(length+6+paddingSize);
rawCopy[5] = paddingSize & 0xF;
rawCopy = Buffer.concat([rawCopy.slice(0, 6+paddingSize), buf]);

The second thing is const cipherAES = crypto.createCipher('aes-128-cbc', key);. This creates a cipher that will also try to create padding on its own. We don't need this since we have already padded the buffer to match the AES block length. Also, you need to explicitly specify an IV of all zero because that's how Roblox implements it for some reason. So:

const cipherAES = crypto.createCipheriv('aes-128-cbc', key, Buffer.alloc(0x10, 0));
cipherAES.setAutoPadding(0);

writeVarsint64 and writeVarLengthString can be found somewhere in ExtendedWriter.go and WriteBitstreamPropertyTypes.go.

ghost commented 5 years ago

Thanks! I will give a try.

ghost commented 5 years ago

Hi, I think the packet is malformed. This is the packet that I send: Start at byte 8a

0000   94 10 3e a2 9b 69 80 c5 f2 9e 6a 11 08 00 45 00
0010   03 cb 20 9d 00 00 80 11 78 f6 c0 a8 02 4a ac 53
0020   2e 49 d3 b9 cf 51 03 b7 9b 61 8c 04 00 00 60 1c
0030   60 04 00 00 03 00 00 00 **8a** bf c0 f4 64 cf 0d 12
0040   a9 2d f3 59 9c 91 8f 55 2e 9b cb 16 dc 9e 66 36
0050   24 11 00 3f 92 f4 0e f5 16 c2 83 00 86 21 3a 73
0060   39 a4 4e 6a 73 b1 98 c7 4c d3 b5 ab ee 67 5f 23
0070   20 a7 2c 2a bb 5d e5 fa 23 39 06 d4 9d d6 f6 47
0080   40 bc 86 3f 61 55 b8 c7 0b be 22 07 27 c9 aa 28
0090   ae 04 6a 46 3d cb 05 e2 03 a2 0d 7b 60 ae f9 c7
00a0   e6 3c 15 fa f9 35 5c d9 c6 83 43 82 bb 02 f8 9c
00b0   f9 69 f4 85 31 b7 2a 25 29 34 71 57 48 5d 16 53
00c0   fd 65 65 8e 98 e9 7c 66 af 5b 4e c5 b2 3b 3e d9
00d0   ba 94 60 c9 21 96 09 55 7f 00 9e d7 4a 87 e9 d9
00e0   de d0 a9 00 95 da b4 43 ed 63 bf 0e ec 1c 87 b0
00f0   f8 c5 45 36 c1 f4 7b 7f ce be 78 3c 4f 47 3e b9
0100   94 74 67 b5 3c d5 71 f2 09 cf 68 42 29 1c 3f 25
0110   7e b3 ac 23 ec 08 fc 6e 9b 80 d5 26 a4 f0 14 29
0120   4b 87 c0 04 81 fd b7 de e8 db a2 1e 24 0f 37 70
0130   2c 25 43 f7 d7 ba 50 df 3a 66 db 7b 38 ca 4e 03
0140   bf 6f f2 94 75 bf 47 87 43 99 8e 53 f3 c2 fa 17
0150   66 05 43 9f 08 6f 8e 44 db 68 84 6c 20 22 de 61
0160   bb bc 5d 55 38 9e d8 ad d6 ec 58 5e 9e 45 fe 72
0170   bb 98 38 fa e7 88 f0 ce d8 19 22 61 e2 e5 68 0e
0180   a4 41 91 e2 44 88 04 2e b7 ec f1 6a 50 86 dc 07
0190   b6 43 82 c4 3b 62 6a 81 1d 7b 86 2b 0e 8b 3d c0
01a0   ad cd de 91 d6 51 4b 9a 70 29 4d a7 7d d0 b7 7d
01b0   c7 a3 61 13 08 3f 5e 28 38 3e 76 2f 1e 02 db e7
01c0   d0 6f bb 98 51 6b 64 dc f9 db a8 e7 e2 3b c2 e3
01d0   b6 19 28 b1 24 1f c2 7d 48 b8 ed a8 93 6c a4 db
01e0   aa 16 49 68 fd 96 a2 08 55 58 15 ad 02 80 b7 5a
01f0   01 63 ac 60 a0 9f 4a 13 0f 75 2e 6f 57 c3 17 73
0200   26 1f 8b d4 3c f9 eb 2e 42 ec dc ea 24 01 99 1e
0210   71 aa 24 bf 98 15 fe ff 94 fd 97 5b d5 cd e9 14
0220   21 46 4e 3e 92 4d dd 8f 3d 42 9b e8 d1 30 b7 5e
0230   bc c8 b1 ed 3f 42 47 ec cb d4 a4 6e 8f dc 31 cc
0240   e4 64 3b 44 d3 30 84 75 84 06 57 cf fd d5 1c c4
0250   b6 a4 5b 8c f9 c7 58 46 32 33 2a 1d 80 e3 3f 13
0260   5f b3 e9 0f ea 17 bb 38 27 34 ac 9c 30 9b ef c0
0270   89 b8 28 de 1f ff 14 d3 5f 92 d9 77 bc ee 88 8b
0280   3b dd 0a 0e 80 68 8b c3 91 3a 80 b3 9c e6 dd ad
0290   83 a6 78 d2 b7 c8 aa 28 ab 54 39 b7 94 63 19 32
02a0   b9 46 6b 3a c8 3a c5 9d 6f e5 7f 13 21 11 75 20
02b0   84 f0 92 1c 58 98 92 f5 e4 60 68 7e 7c cb 3b 8e
02c0   8b 5f c5 35 4b e1 69 09 aa 7e 6b bb 08 ba d2 bd
02d0   11 44 62 79 e5 02 fb 2b 6c c8 12 56 3e 22 cf 71
02e0   15 ca 62 c3 98 fa 9c 12 e4 74 c6 51 13 33 ca 0f
02f0   0c 00 e7 d8 ee 0d f8 7c bd 63 b7 6d 8a d6 fd 45
0300   0b 9a 87 eb b0 e9 05 66 3b 32 87 ec a2 7c de 41
0310   9e a7 5c 09 16 bc 45 08 ba 9f 67 0f d1 16 4f a6
0320   25 fd 71 2a 73 6d 5d 7c 48 cd 73 95 ef 9e ba 1f
0330   e9 cb 48 33 03 9f 5e 41 15 4b 9d bc 6c 16 0c a8
0340   42 d1 8c b9 30 12 e6 75 59 2b a0 55 34 cd 58 0d
0350   da 6e 6b 76 e6 9d 1d 12 1c 01 eb 24 bd 66 2c ea
0360   d4 20 eb e4 fa 78 fd 64 06 73 12 8a 30 4d 53 15
0370   d8 c9 79 99 6a 66 5c e7 65 b0 57 05 8a d9 4c 23
0380   2f 88 89 e7 20 32 f9 ea db 86 71 a0 13 6c e0 fc
0390   76 c9 c6 8e bb 80 fc a3 bf 2b 6c e0 c6 12 ae ef
03a0   68 cb b7 1c 2b 26 3e 0a df d0 24 35 18 58 1a d6
03b0   be 33 0a 5f f4 90 a4 77 2b 79 00 ed 3d 01 50 df
03c0   2c 77 74 7a 9f c0 8b 13 43 f2 d7 0a 1a 13 9f 23
03d0   2a d5 62 0a b5 9a 26 31 18

This is what roblox send:

0000   94 10 3e a2 9b 69 80 c5 f2 9e 6a 11 08 00 45 00
0010   05 17 41 dd 00 00 80 11 32 99 c0 a8 02 4a d1 ce
0020   2c 9f f8 e1 d5 b1 05 03 d6 86 8c 04 00 00 60 27
0030   08 04 00 00 03 00 00 00 **8a** 83 20 5e f2 49 1a 62
0040   92 09 bf 7b 91 92 52 46 e4 2d f7 bb b2 27 b6 d5
0050   b2 14 5d 86 d4 e0 7d 88 49 20 e1 48 cf 3c 7f b4
0060   c8 2d 54 b2 a8 f6 41 31 cd b8 f2 f4 44 d8 eb c3
0070   4c 4c f2 25 c5 56 80 cc df e3 af ce 8f 14 6a 21
0080   ff 10 df a7 ac 32 09 10 78 0a 83 dd e0 b9 7d 03
0090   c0 64 ac 74 79 d8 fe 46 db 95 d9 91 a9 4c 7d 54
00a0   9f 73 cd 2d 41 8e ee 4b 70 c3 1b 92 4c 6f 0d 98
00b0   7b f5 10 d1 b6 a7 f8 f6 dd f5 f2 cb 48 a8 25 35
00c0   aa 23 0a 24 17 4d 66 45 d2 37 b0 fb d0 85 67 45
00d0   b4 c9 e5 d6 bc a8 f2 26 29 55 5d 62 f9 e5 6f b5
00e0   af d7 8f f0 50 aa 1e bd 25 c5 ff 76 eb f8 b7 a8
00f0   d3 d4 71 52 24 ba 1d 10 f2 96 8f 09 6b 7c c2 e2
0100   e1 8e 1b 78 61 94 35 92 44 17 c0 3a 10 ee ae 9e
0110   ed 86 48 a1 22 eb 9e bf 5c e0 19 6b 4a 51 3c 19
0120   bd 5c 51 74 7f 62 83 0a cd 65 ed 8f ff 79 6e 5d
0130   9e 61 b5 8d 48 4b eb 83 b3 6b 9f b9 e3 2b 25 da
0140   23 a9 c9 19 cb 94 d6 ef ec db ff d4 0e 43 a5 32
0150   21 94 00 66 58 ee 45 0c 28 c2 26 2c 01 0e c7 76
0160   5a 30 4f a0 ac 75 27 db d0 0e 00 e6 71 4b 6d 7b
0170   76 53 c9 d0 b2 b7 1b 34 81 aa 21 1a 43 0f 2b 0c
0180   da 99 1a 74 b9 a7 0d d6 26 fd 35 99 fb f5 a0 9e
0190   eb 11 80 a5 84 3a 81 a3 78 a7 a9 82 22 ef 9a 68
01a0   66 01 66 fa 9a 72 29 1b 99 ac bc 8b d7 8c a3 c4
01b0   6c e3 13 1c fb 69 1e 7a b8 26 e6 16 e7 3b 35 f6
01c0   50 1f 0d 6a ff 74 17 cc 31 12 76 c2 d6 c8 ee d9
01d0   4f 7b 25 ea 47 ae 1c e9 94 ab 61 7f 52 92 cf bf
01e0   1e 70 11 75 f7 ab 91 41 b1 ea a0 eb fa 19 ff a9
01f0   c9 20 a5 2a de 35 3b 7c c3 29 89 76 3b d3 5c d4
0200   f2 4a 33 db 96 d7 f7 eb d1 d0 ca d5 41 3b 97 96
0210   15 dc d5 fb f3 23 35 53 b3 56 a8 92 c4 ad df ee
0220   04 26 92 dc 32 fa c7 1d d1 37 ca 82 11 b0 b0 0f
0230   e3 d3 da be 1b 51 60 34 21 a2 bc 80 51 0c 12 d6
0240   6a fe 10 c3 52 a8 be af e5 80 98 4a 6a 91 b2 c4
0250   99 61 30 93 9e d7 75 22 fd 80 66 8e b3 d6 48 01
0260   49 35 4d db b3 17 09 52 d8 7d 6a 06 e4 8a d3 ec
0270   01 7a 40 8a af 27 b7 fe a2 02 35 84 8d 7d 4d 18
0280   a5 dc 80 21 6d ee 26 94 73 a2 d3 6d 76 72 59 1a
0290   8c 91 d1 8a 76 8f 66 51 22 6d d9 40 54 91 fc 53
02a0   71 9a 7e e0 72 72 23 bb db a1 e4 d7 e2 ee 61 90
02b0   19 de 2a 22 e4 1a f3 c3 15 0e 25 e7 8e e9 99 15
02c0   fc f5 d6 4f fa 04 20 8c 2c eb f5 25 03 5f b1 15
02d0   c3 54 16 2e b8 79 8d 91 83 d2 cc bb 4c 4f 93 ee
02e0   50 e9 f9 ec 9e 08 5c 45 4c 21 ef 71 94 62 3e a0
02f0   97 67 0d a4 63 b0 ad eb 69 93 36 90 5f 15 1a 41
0300   b2 05 ea 43 06 3f fa b0 28 b3 cc 39 5d 3e 7a e5
0310   21 46 69 72 19 bf 4e 1e 90 f5 59 51 a3 6f 1d 85
0320   15 bb 5b 6b a5 53 82 8d 94 b6 f9 27 41 d0 c9 00
0330   47 3b 1a 73 e2 59 f1 a4 ff 03 69 3a 16 b9 34 6b
0340   9d 38 bb a1 3d 25 59 d6 08 60 cb 6f 35 ad 90 dc
0350   45 85 d1 27 ac aa 6c ba b1 1b 6a 9f 89 3b 26 3e
0360   ed d7 8f 72 bb 26 4a 48 f9 d8 68 6d 1e 73 35 fa
0370   91 27 c0 5b 02 fb d5 03 8b 8f 3f 73 fe 65 74 a6
0380   d1 f8 d2 47 43 6b 61 f1 c4 cb f0 ae 40 5e 49 ce
0390   7e c6 e3 95 2a 52 09 38 77 7f 60 cb 08 3d 44 38
03a0   7a 7b 0c bd cb 61 1a 38 d2 29 85 92 81 d3 11 a1
03b0   bc 5d 52 22 bf 4b 96 39 cb 96 e9 14 eb fc 4b be
03c0   e1 57 8a 8c 40 69 33 59 71 8d 7a 5b 3f 57 17 17
03d0   8f 93 9c c7 55 c6 53 db 33 93 3e 01 2c 90 07 c9
03e0   d1 87 95 d3 68 e5 d4 76 1e fd 49 a5 77 38 70 23
03f0   59 69 69 c3 73 fa 28 d2 c7 03 27 21 43 87 36 e4
0400   39 8d 2d 61 df ea 1e 44 56 98 bc 9e 1e 52 dc 6e
0410   8c 24 aa c9 8b 05 e7 ea 2b 46 f0 a8 a4 26 0b 55
0420   21 a4 05 71 89 37 1d 93 6a 50 10 44 a0 da c5 26
0430   9d 58 11 d0 7e b2 b6 21 f1 bb 17 d4 47 81 d8 fe
0440   92 66 d0 98 70 2b 68 46 34 89 a2 63 e3 c4 da d0
0450   d0 a3 91 2c 81 f7 d5 f7 71 95 7f 0c 95 a1 cd c6
0460   e2 de d6 38 32 f6 8b 10 73 9f ca cd a0 ab e2 39
0470   bd 63 d6 93 11 51 98 32 4d 0e d0 ef c0 fe 7e 27
0480   ee 6b c4 55 e4 62 b5 6e 66 bd 96 84 dc 02 4a 4e
0490   f4 e2 df e8 4f d9 95 7b 32 9e 48 84 e9 bc 20 a1
04a0   26 94 ba 49 3a a4 17 4c 80 f2 d0 ec dc 68 71 ba
04b0   4a cf c2 7a 48 fd b5 19 79 3c 03 27 0b b9 bc 05
04c0   65 56 a7 c2 81 bd a6 8c 2e 15 a5 f1 ef 12 b5 74
04d0   cb bc 28 81 7b 13 0a db 54 09 39 fb 9b 92 64 ac
04e0   b2 c5 22 c3 84 ba e2 af d6 dc 91 83 e8 1f 69 12
04f0   ba 2d 52 64 90 de 3b 03 1c fc 7e c8 d0 5c 36 c3
0500   06 c8 ff 16 f8 f5 b6 9d 26 33 aa a6 2d c8 e1 d9
0510   0a 93 8a ac 15 ab 01 5c c0 60 00 10 05 00 00 04
0520   00 00 00 8f 00

I know that the information are different but, the packet should be the same length?

I think I have also a problem here

function hashClientTicket(ticket) {
    var ecxHash;
    let a = XXH.h32(1);
    a.update(Buffer.from(ticket, 'utf-8'));
    let initHash = a.digest();
    initHash += 0x557BB5D7
    initHash = rol(initHash, -7)
    initHash -= 0x557BB5D7
    initHash *= 0x443921D5
    initHash = rol(initHash, -0xD)
    ecxHash = 0x557BB5D7 - initHash
    ecxHash ^= 0x443921D5
    ecxHash = rol(ecxHash, 0x11)
    ecxHash += 0x664B2854
    ecxHash = rol(ecxHash, -0x17)
    initHash = ecxHash - 0x664B2854
    initHash = rol(initHash, 0x1D)
    initHash ^= 0x557BB5D7
    initHash = -initHash

    return initHash
}

I don't know..

Gskartwii commented 5 years ago

It will be much easier to spot the problem if I can see your code that writes the packet.

hashClientTicket() seems to be correct. Note that in node.js you can use ror(initHash, 0xD) instead of rol(initHash, -0xD). Also note that this implementation of hashClientTicket() is specifically for the Windows 10 App Store version of Roblox. The regular Windows version is secured by VMProtect, making it extremely difficult to figure out. However, the rest of the code should work fine for all versions.

ghost commented 5 years ago

I am trying to make the client in node js. Not the graphic but the protocol.

Gskartwii commented 5 years ago

Is there something you would like help with? If not, feel free to close the issue.

ghost commented 5 years ago

I can't get the auth packet generated correctly. I thing the packet does not have the good length, I copy the code prensent on your hand and recode it on node js. Mine is like 969 of len and the client one is about 1300. I think there is missing information or something.

Gskartwii commented 5 years ago

Apologies for the delay, I forgot about this issue. If you’re still working on this, make sure to check out the newest changes (peer/Packet8ALayer.go and peer/ExtendedWriter.go). Also, it is normal that the RakNet containers have different lengths. This is because Roblox stores multiple packets in one RakNet container. In your example, there is a 0x8F packet (ID_PREFERRED_SPAWN_NAME) that is stored in the last two bytes of the container. There are probably two other packets in there as well, namely 0x90 (ID_PROTOCOL_SYNC) and 0x92 (ID_PLACEID_VERIFICATION).

Gskartwii commented 5 years ago

I'm assuming this issue is resolved for now. If you have further questions, feel free join the newly create Discord server or reopen this issue.

ghost commented 5 years ago

Ok, im in.