登陸認證階段

認證階段抓包如上圖,和初始化握手一樣,前四個位元組屬于訊息頭,后面的部分屬于訊息體 ,報文的結構圖如下:

這里主要設定 用戶名 密碼 和資料庫名這三個引數,其他的使用抓包的默認值即可,用戶名和資料庫名直接將字符轉為十六進制就可以,唯一需要注意的是密碼加密部分
官網提供的加密規則如下
SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )
實作代碼如下:
<?php
function encryptionPass($pass, $seed)
{
$pass1 = getBytes(sha1($pass, true));
$pass2 = sha1(getString($pass1), true);
$pass3 = getBytes(sha1(hexToStr($seed) . $pass2, true));
$result = "";
for ($i = 0, $count = count($pass3); $i < $count; ++$i) {
$result .= str_pad(dechex(($pass3[$i] ^ $pass1[$i])),2,0,STR_PAD_LEFT);
}
return $result;
}
function getBytes($data)
{
$bytes = [];
$count = strlen($data);
for ($i = 0; $i < $count; ++$i) {
$byte = ord($data[$i]);
$bytes[] = $byte;
}
return $bytes;
}
function getString(array $bytes)
{
return implode(array_map('chr', $bytes));
}
function hexToStr($hex_str){
$send_msg = "";
foreach (str_split($hex_str,2) as $key => $value) {
$send_msg .= chr(hexdec($value));
}
return $send_msg;
}
我們從抓包記錄中驗證一下代碼的正確性,在初始化握手包中獲取兩個salt的值 “1c171e1765783a57” 和 “50185b5a250f323d63394279”


執行代碼獲取加密結果
<?php
$salt1 = "1c171e1765783a57";
$salt2 = "50185b5a250f323d63394279";
echo encryptionPass("123456",$salt1.$salt2);
//生成結果:"a1b247e81adf52e0700e31698960ad96271b34f5"
生成的結果與抓包獲取的結果一致

客戶端向服務端發起認證請求后,服務端回應的情況分以下幾種:
當客戶端發起認證請求或命令請求后,服務器會回傳相應的執行結果給客戶端,客戶端在收到回應報文后,需要首先檢查第1個位元組的值,來區分回應報文的型別,
| 回應報文型別 | 第1個位元組取值范圍 |
|---|---|
| OK 回應報文 | 0x00 |
| Error 回應報文 | 0xFF |
| Result Set 報文 | 0x01 - 0xFA |
| Field 報文 | 0x01 - 0xFA |
| Row Data 報文 | 0x01 - 0xFA |
| EOF 報文 | 0xFE |
注:回應報文的第1個位元組在不同型別中含義不同,比如在OK報文中,該位元組并沒有實際意義,值恒為0x00;而在Result Set報文中,該位元組又是長度編碼的二進制資料結構(Length Coded Binary)中的第1位元組,
代碼分享地址
https://github.com/gphper/PHPMysql
參考檔案:
https://dev.mysql.com/doc/internals/en/client-server-protocol.html
https://www.cnblogs.com/davygeek/p/5647175.html
https://github.com/louislivi/SMProxy
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/29093.html
標籤:PHP
