diff --git a/classes/CustomPacketHandler.class.php b/classes/CustomPacketHandler.class.php new file mode 100644 index 0000000000..985b07b6c6 --- /dev/null +++ b/classes/CustomPacketHandler.class.php @@ -0,0 +1,99 @@ +raw, $this->offset); + if($check === true){ + $this->offset = strlen($this->raw); + } + return $data; + } + $data = substr($this->raw, $this->offset, $len); + if($check === true){ + $this->offset += $len; + } + return $data; + } + + public function __construct($pid, $raw = "", $data = array(), $create = false){ + $this->raw = $raw; + $this->data = $data; + $this->offset = 0; + $this->c = (bool) $create; + switch($pid){ + case 0x400090: + case "clientHandshake": + $this->name = "clientHandshake"; + if($this->c === false){ + $this->data["counter"] = Utils::readTriad($this->get(3)); + $this->data["id"] = ord($this->get(1)); + $this->data["clientID"] = $this->get(8); + $this->data["unknown1"] = $this->get(1); + $this->data["unknown2"] = $this->get(4); + $this->data["session"] = $this->get(4); + }else{ + $this->raw .= Utils::writeTriad(0); //counter + $this->raw .= chr(9); + $this->raw .= $this->data["clientID"]; + $this->raw .= "\x00"; + $this->raw .= "\x00\x00\x00\x00"; + $this->raw .= $this->data["session"]; + } + break; + case 0x600300: + case "serverHandshake": + $this->name = "serverHandshake"; + if($this->c === false){ + $this->data["counter"] = Utils::readTriad($this->get(3)); + $this->data["id"] = ord($this->get(1)); + $this->data["unknown1"] = $this->get(4); + $this->data["cookie"] = $this->get(4); // 043f57ff + $this->data["unknown2"] = ord($this->get(1)); + $this->data["port"] = Utils::readShort($this->get(2)); + $this->data["dataArray"] = Utils::readDataArray($this->get(true, false), 10); + $this->data["unknown3"] = $this->get(1); + $this->data["unknown4"] = $this->get(4); + $this->data["session"] = $this->get(4); + $this->data["unknown5"] = $this->get(8); + }else{ + $this->raw .= Utils::writeTriad(0); //counter + $this->raw .= chr(0); + $this->raw .= "\x00\x00\x00\x10"; + $this->raw .= "\x04\x3f\x57\xff"; + $this->raw .= "\x00"; + $this->raw .= "\x7f"; + $this->raw .= Utils::writeShort($this->data["port"]); + } + break; + } + } + +} \ No newline at end of file diff --git a/classes/MinecraftInterface.class.php b/classes/MinecraftInterface.class.php index ec46dbe6be..66ac4702c2 100644 --- a/classes/MinecraftInterface.class.php +++ b/classes/MinecraftInterface.class.php @@ -55,7 +55,7 @@ class MinecraftInterface{ $p .= Utils::hexdump($raw); if(is_array($data)){ foreach($data as $i => $d){ - $p .= $i ." => ".(!is_array($d) ? $this->pstruct[$pid][$i]."(".(($this->pstruct[$pid][$i] === "magic" or substr($this->pstruct[$pid][$i], 0, 7) === "special" or is_int($this->pstruct[$pid][$i])) ? Utils::strToHex($d):$d).")":$this->pstruct[$pid][$i]."(***)").PHP_EOL; + $p .= $i ." => ".(!is_array($d) ? $this->pstruct[$pid][$i]."(".(($this->pstruct[$pid][$i] === "magic" or substr($this->pstruct[$pid][$i], 0, 7) === "special" or is_int($this->pstruct[$pid][$i])) ? Utils::strToHex($d):$d).")":$this->pstruct[$pid][$i]."(\"".serialize($d)."\")").PHP_EOL; } } $p .= PHP_EOL; diff --git a/classes/Packet.class.php b/classes/Packet.class.php index f0bdeb5511..85282f3cdd 100644 --- a/classes/Packet.class.php +++ b/classes/Packet.class.php @@ -59,19 +59,30 @@ class Packet{ switch($type){ case "special1": switch($this->pid){ + case 0xc0: + case 0xa0: + if($this->data[1] === false){ + $this->addRaw($this->data[$field]); + } + break; case 0x05: - case 0x84: - case 0x8c: $this->addRaw($this->data[$field]); break; } break; + case "customData": + $reply = new CustomPacketHandler($this->data[1], "", $this->data[$field], true); + $this->addRaw($reply->raw); + break; case "magic": $this->addRaw(MAGIC); break; case "float": $this->addRaw(Utils::writeFloat($this->data[$field])); break; + case "triad": + $this->addRaw(Utils::writeTriad($this->data[$field])); + break; case "int": $this->addRaw(Utils::writeInt($this->data[$field])); break; @@ -139,21 +150,30 @@ class Packet{ switch($type){ case "special1": switch($this->pid){ + case 0xc0: + case 0xa0: + if($this->data[1] === false){ + $this->data[] = $this->get(3); + } + break; case 0x05: - case 0x84: - case 0x8c: $this->data[] = $this->get(true); - break; + break; } break; + case "customData": + $d = new CustomPacketHandler($this->data[1], $this->get(true)); + $d->data["packetName"] = $d->name; + $this->data[] = $d->data; + break; case "magic": $this->data[] = $this->get(16); break; + case "triad": + $this->data[] = Utils::readTriad($this->get(3)); + break; case "int": $this->data[] = Utils::readInt($this->get(4)); - if($field === 5 and $this->pid === "17" and $this->data[$field] === 0){ - $continue = false; - } break; case "string": $this->data[] = $this->get(Utils::readShort($this->get(2))); diff --git a/classes/PocketMinecraftClient.class.php b/classes/PocketMinecraftClient.class.php index b5bea7be81..bf62a4cc94 100644 --- a/classes/PocketMinecraftClient.class.php +++ b/classes/PocketMinecraftClient.class.php @@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or class PocketMinecraftClient{ protected $interface, $protocol, $entities, $player, $cnt, $events, $username, $version, $clientID, $connected, $serverID, $start; - var $serverList = array(); + var $serverList = array(), $counter; function __construct($username, $protocol = CURRENT_PROTOCOL, $version = CURRENT_VERSION){ //$this->player = new Player($username); $this->start = microtime(true); @@ -44,6 +44,7 @@ class PocketMinecraftClient{ console("[INFO] Version: ".$this->version); $this->event("onReceivedPacket", "packetHandler", true); $this->stop = false; + $this->counter = array(0,0); declare(ticks=15); register_tick_function(array($this, "tickerFunction")); } @@ -112,18 +113,23 @@ class PocketMinecraftClient{ case 0x08: $serverID = $data[1]; $this->send(0x84, array( - 0, - "\x00\x00\x40\x00\x90\x00\x00\x00\x09".$this->serverID.Utils::writeDouble((microtime(true) - $this->start) * 1000).chr(0x00), - /*"\x00\x00\x00\x40\x00\x90\x00\x00\x00\x09", - $this->serverID, - (microtime(true) * 1000), - 0,*/ + $this->counter[0], + 0x400090, + array( + "clientID" => $this->clientID, + "session" => "\x00\x0c\x98\x00", + ), )); + ++$this->counter[0]; break; - case 0xc0: - $this->send(0xc0, array( - $data[0], - )); + case 0x84: + $this->counter[1] = $data[0]; + $this->send(0xc0, array(1, true, $data[0])); + switch($custom->name){ + case "serverHandshake": + + break; + } break; } } diff --git a/classes/Session.class.php b/classes/Session.class.php index 6fe4677ffd..ab9bfe554e 100644 --- a/classes/Session.class.php +++ b/classes/Session.class.php @@ -28,7 +28,7 @@ the Free Software Foundation, either version 3 of the License, or class Session{ protected $server, $serverID, $timeout, $eventID, $connected; - var $clientID, $ip, $port; + var $clientID, $ip, $port, $counter; function __construct($server, $clientID, $ip, $port){ $this->server = $server; $this->clientID = $clientID; @@ -38,6 +38,7 @@ class Session{ $this->eventID = $this->server->event("onTick", array($this, "checkTimeout")); console("[DEBUG] New Session started with ".$ip.":".$port, true, true, 2); $this->connected = true; + $this->counter = array(0, 0); } public function checkTimeout($time){ @@ -66,10 +67,20 @@ class Session{ )); break; case 0x84: - $counter = $data[0]; - /*$this->send(0xc0, array( - "\x00\x01\x01\x00\x00\x00", - ));*/ + $this->counter[1] = $data[0]; + $this->send(0xc0, array(1, true, $data[0])); + switch($data[2]["packetName"]){ + case "clientHandshake": + $this->send(0x84, array( + $this->counter[0], + 0x600300, + array( + "port" => $this->port, + ), + )); + ++$this->counter[0]; + break; + } break; case 0x8c: $counter = $data[0]; diff --git a/classes/Utils.class.php b/classes/Utils.class.php index 3c944fad52..93e00c9040 100644 --- a/classes/Utils.class.php +++ b/classes/Utils.class.php @@ -271,6 +271,27 @@ class Utils{ return pack("n", $value); } + public static function readTriad($str){ + list(,$unpacked) = unpack("N", "\x00".$str); + return (int) $unpacked; + } + + public static function writeTriad($value){ + return substr(pack("N", $value), 1); + } + + public static function readDataArray($str, $len = 10){ + $data = array(); + $offset = 0; + for($i = 1; $i <= $len; ++$i){ + $l = Utils::readTriad(substr($str, $offset, 3)); + $offset += 3; + $data[] = substr($str, $offset, $l); + $offset += $l; + } + return $data; + } + public static function readInt($str){ list(,$unpacked) = unpack("N", $str); return (int) $unpacked; diff --git a/common/dependencies.php b/common/dependencies.php index 03708db540..390a2a0691 100644 --- a/common/dependencies.php +++ b/common/dependencies.php @@ -72,6 +72,7 @@ if($errors > 0){ require_once("classes/Utils.class.php"); require_once("classes/Socket.class.php"); require_once("classes/Packet.class.php"); +require_once("classes/CustomPacketHandler.class.php"); require_once("classes/MinecraftInterface.class.php"); ?> \ No newline at end of file diff --git a/pstruct/RakNet.php b/pstruct/RakNet.php index 03eb83d589..ec88731576 100644 --- a/pstruct/RakNet.php +++ b/pstruct/RakNet.php @@ -79,25 +79,43 @@ $pstruct = array( "magic", "string", //Data ), + + 0x80 => array( + "triad", + "triad", + "customData", + ), 0x84 => array( - "ubyte", - "ubyte", - "special1", + "triad", + "triad", + "customData", + ), + + 0x88 => array( + "triad", + "triad", + "customData", ), 0x8c => array( - "ubyte", - "ubyte", - "special1", + "triad", + "triad", + "customData", ), 0xa0 => array( - 6, + "short", + "bool", + "triad", + "special1", ), 0xc0 => array( - 6, + "short", + "bool", + "triad", + "special1", ), ); \ No newline at end of file diff --git a/pstruct/packetName.php b/pstruct/packetName.php index 98bdb60d98..061f00e55a 100644 --- a/pstruct/packetName.php +++ b/pstruct/packetName.php @@ -34,8 +34,10 @@ $packetName = array( 0x1a => "ID_INCOMPATIBLE_PROTOCOL_VERSION", //RakNet 0x1c => "ID_UNCONNECTED_PONG", //RakNet 0x1d => "ID_ADVERTISE_SYSTEM", //RakNet - 0x84 => "ID_RESERVED_7", //Minecraft Implementation + 0x80 => "Unknown", //Minecraft Implementation + 0x84 => "Data Packet", //Minecraft Implementation + 0x88 => "Unknown", //Minecraft Implementation 0x8c => "Unknown", //Minecraft Implementation 0xa0 => "Unknown", //Minecraft Implementation - 0xc0 => "Unknown", //Minecraft Implementation + 0xc0 => "ACK", //Minecraft Implementation ); \ No newline at end of file