Writing MySQL Proxy in GO for self-learning: Part 2 — decoding handshake packet

Packet: 01 00 00 00 01+------------+-----------------+-------------+
| Length = 1 | Sequence ID = 0 | Payload = 1 |
+------------+-----------------+-------------+
| 01 00 00 | 00 | 01 |
+------------+-----------------+-------------+
Initial Handshake starts with server sending the Initial Handshake Packet. After this, optionally, client can request an SSL connection to be established with SSL Connection Request Packet, and then client sends the Handshake Response Packet.
sudo ngrep -x -q -d lo0 '' 'port 3306'
MySQL Protocol Communication Steps
1              [0a] protocol version
string[NUL] server version
4 connection id
string[8] auth-plugin-data-part-1
1 [00] filler
2 capability flags (lower 2 bytes)
if more data in the packet:
1 character set
2 status flags
2 capability flags (upper 2 bytes)
if capabilities & CLIENT_PLUGIN_AUTH {
1 length of auth-plugin-data
} else {
1 [00]
}
string[10] reserved (all [00])
if capabilities & CLIENT_SECURE_CONNECTION {
string[$len] auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8))
if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL] auth-plugin name
}
Handshake Packet
uint16(b[0]) | uint16(b[1])<<8
b[0]                = 00001111 (8 bit integer)
uint16(b[0]) = 0000000000001111 (we created 16 bit integer)
They are both still represent the same value (15 in decimal)b[1] = 10000001 (8 bit integer)
uint16(b[1]) = 0000000010000001 (we created 16 bit integer)
But the value of second byte alone doesn't make sense to us. So we move it to be in the "right place" by shifting it by 8 bits.uint16(b[1])<<8 = 1000000100000000 (shifting left 8 times)and finally we use bitwise sumuint16(b[0]) | uint16(b[1])<<8 = 1000000100001111 (33039 in decimal)We successfully reconstructed the original value.Just remind you how the binary sum works:0000000000001111
10000001
00000000
----------------
1000000100001111
b[0]                = 00001111 (8 bit integer)
uint16(b[0]) = 0000000000001111 (we created 16 bit integer)
uint16(b[0])<<8 = 0000111100000000
We shifted the byte at index 0 by 8 bits, cause Big Endian says this byte is the most significant byte, so we move it to the right position.b[1] = 10000001 (8 bit integer)
uint16(b[1]) = 0000000010000001 (we created 16 bit integer)
And finally apply bitwise sum operatoruint16(b[0]) | uint16(b[1])<<8 = 0000111110000001This number is 3969 in decimal, but the original number was 33039
string<lenenc>Protocol::LengthEncodedString
string<fix>Protocol::FixedLengthString
string<var>Protocol::VariableLengthString:
string<EOF>Protocol::RestOfPacketString
string<NUL>Protocol::NulTerminatedString
binary.LittleEndian.Uint16()
index := bytes.IndexByte(payload, byte(0x00))

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store