created sniff-packets program

sniffed update_tags and registry_data packets to .bin files
This commit is contained in:
MeexReay 2025-05-04 03:15:22 +03:00
parent eb46fdfc45
commit 7ffccfed26
12 changed files with 457 additions and 2528 deletions

17
.envrc Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env bash
# ^ make editor happy
#
# Use https://direnv.net/ to automatically load the dev shell.
#
if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
fi
watch_file nix/**
watch_file -- **/*.nix
# Adding files to git includes them in a flake
# But it is also a bit much reloading.
# watch_file .git/index .git/HEAD
use flake . --show-trace

2
rust-toolchain.toml Normal file
View File

@ -0,0 +1,2 @@
[toolchain]
channel = "stable"

View File

@ -6,6 +6,7 @@ mkShell {
direnv
rustc
cargo
rustfmt
python3
python3Packages.beautifulsoup4
python3Packages.requests

1
sniff-packets/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

192
sniff-packets/Cargo.lock generated Normal file
View File

@ -0,0 +1,192 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "craftflow-nbt"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a2d5312462b00f8420ace884a696f243be136ada9f50bf5f3d9858ff0c8e8e"
dependencies = [
"cesu8",
"serde",
"thiserror",
]
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "flate2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rust_mc_proto"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "734168f5b9aef1991db4b11c0bcd71c0336b0a5ba98269f0df39b41b8463ac8c"
dependencies = [
"flate2",
"uuid",
]
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sniff-packets"
version = "0.1.0"
dependencies = [
"craftflow-nbt",
"rust_mc_proto",
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "uuid"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"

11
sniff-packets/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "sniff-packets"
version = "0.1.0"
edition = "2024"
[dependencies]
rust_mc_proto = "0.1.19"
serde = "1.0.219"
serde_json = "1.0.140"
craftflow-nbt = "2.1.0"
uuid = "1.16.0"

179
sniff-packets/src/main.rs Normal file
View File

@ -0,0 +1,179 @@
use std::{fs, io::Read};
use craftflow_nbt::DynNBT;
use rust_mc_proto::{prelude::*, write_packet, MCConnTcp, Packet, ProtocolError};
use uuid::Uuid;
pub trait ReadWriteNBT<T>: DataReader + DataWriter {
fn read_nbt(&mut self) -> Result<T, ProtocolError>;
fn write_nbt(&mut self, val: &T) -> Result<(), ProtocolError>;
}
impl ReadWriteNBT<DynNBT> for Packet {
fn read_nbt(&mut self) -> Result<DynNBT, ProtocolError> {
let mut data = Vec::new();
let pos = self.get_ref().position();
self.get_mut()
.read_to_end(&mut data)
.map_err(|_| ProtocolError::StringParseError)?;
let (remaining, value) =
craftflow_nbt::from_slice(&data).map_err(|_| ProtocolError::StringParseError)?;
self.get_mut()
.set_position(pos + (data.len() - remaining.len()) as u64);
Ok(value)
}
fn write_nbt(&mut self, val: &DynNBT) -> Result<(), ProtocolError> {
craftflow_nbt::to_writer(self.get_mut(), val).map_err(|_| ProtocolError::StringParseError)?;
Ok(())
}
}
fn main() -> Result<(), ProtocolError> {
let mut conn = MCConnTcp::connect("localhost:25565").unwrap();
conn.write_packet(&Packet::build(0x00, |packet| {
packet.write_varint(770)?;
packet.write_string("localhost")?;
packet.write_unsigned_short(25565)?;
packet.write_varint(2)
})?)?;
conn.write_packet(&Packet::build(0x00, |packet| {
packet.write_string("TheMixRay")?;
packet.write_uuid(&Uuid::default())
})?)?;
loop {
let mut packet = conn.read_packet()?;
if packet.id() == 0x03 {
let threshold = packet.read_varint()?;
if threshold >= 0 {
conn.set_compression(Some(threshold as usize));
}
} else if packet.id() == 0x02 {
break;
}
}
conn.write_packet(&Packet::empty(0x03))?;
conn.write_packet(&Packet::build(0x02, |packet| {
packet.write_string("minecraft:brand")?;
packet.write_string("vanilla")
})?)?;
conn.write_packet(&Packet::build(0x00, |packet| {
packet.write_string("en_us")?;
packet.write_signed_byte(12)?;
packet.write_varint(0)?;
packet.write_boolean(true)?;
packet.write_byte(127)?;
packet.write_varint(1)?;
packet.write_boolean(true)?;
packet.write_boolean(true)?;
packet.write_varint(0)
})?)?;
let mut packet = conn.read_packet()?; // server brand
let id = packet.read_string()?;
println!("message id: {}", id);
println!("message data: {}", String::from_utf8_lossy(&packet.get_bytes()[id.len()+1..]));
let mut packet = conn.read_packet()?; // feature flags
let flags_len = packet.read_varint()?;
println!("got {} feature flags:", flags_len);
for _ in 0..flags_len {
let flag = packet.read_string()?;
println!("flag: {}", flag);
}
let mut packet = conn.read_packet()?; // wait for known packs packet
if packet.id() != 0x0E {
println!("got unexpected packet while looking for 0x0E: 0x{:02X}", packet.id());
return Ok(());
}
let packs_len = packet.read_varint()?;
println!("got {} known packs:", packs_len);
for _ in 0..packs_len {
println!("{}:{} v{}", packet.read_string()?, packet.read_string()?, packet.read_string()?);
}
packet.set_id(0x07); // make it serverbound
conn.write_packet(&packet)?;
let mut data = Vec::new();
loop {
let mut packet = conn.read_packet()?;
if packet.id() != 0x07 { // update tags
let registries_len = packet.read_varint()?;
println!("got update tags: {}", registries_len);
for _ in 0..registries_len {
let registry = packet.read_string()?;
println!("registry: {}", registry);
let tags_len = packet.read_varint()?;
for _ in 0..tags_len {
let tag_name = packet.read_string()?;
println!("tag: {}", tag_name);
let entries_len = packet.read_varint()?;
for _ in 0..entries_len {
let entry = packet.read_varint()?;
println!("entry: {}", entry);
}
}
}
fs::write("update-tags.bin", packet.get_bytes()).unwrap();
break;
}
println!("got registry: {}", packet.read_string()?);
let entries_len = packet.read_varint()?;
for _ in 0..entries_len {
let entry_id = packet.read_string()?;
let has_data = packet.read_boolean()?;
if has_data {
let entry_data = packet.read_nbt()?;
println!("entry: {}, data: {:?}", entry_id, entry_data);
} else {
println!("entry: {}, no data", entry_id);
}
}
write_packet(&mut data, None, 0, &packet)?;
}
fs::write("registry-data.bin", &data).unwrap();
Ok(())
}

View File

@ -157,6 +157,11 @@ pub fn handle_connection(
particle_status,
});
client.write_packet(&Packet::build(clientbound::configuration::PLUGIN_MESSAGE, |p| {
p.write_string("minecraft:brand")?;
p.write_string("rust_minecraft_server")
})?)?;
handle_configuration_state(client.clone())?;
client.write_packet(&Packet::empty(clientbound::configuration::FINISH))?;

View File

@ -1,64 +1,67 @@
use std::{collections::HashMap, sync::Arc};
use std::{io::Cursor, sync::Arc};
use craftflow_nbt::DynNBT;
use log::debug;
use rust_mc_proto::{DataWriter, Packet};
use serde_json::{json, Value};
use rust_mc_proto::{read_packet, DataWriter, Packet};
use crate::server::{
data::ReadWriteNBT, player::context::ClientContext, ServerError
player::context::ClientContext, ServerError
};
use super::id::{clientbound::{self, configuration::REGISTRY_DATA}, serverbound};
use super::id::*;
pub fn send_update_tags(
client: Arc<ClientContext>,
) -> Result<(), ServerError> {
// rewrite this hardcode bullshit
client.write_packet(&Packet::from_bytes(clientbound::configuration::UPDATE_TAGS, include_bytes!("update-tags.bin")))?;
Ok(())
}
pub fn send_registry_data(
client: Arc<ClientContext>,
) -> Result<(), ServerError> {
let registry_data = include_str!("registry_data.json");
let registry_data: Value = serde_json::from_str(registry_data).unwrap();
let registry_data = registry_data.as_object().unwrap();
for (registry_name, registry_data) in registry_data {
let registry_data = registry_data.as_object().unwrap();
// rewrite this hardcode bullshit
let mut packet = Packet::empty(clientbound::configuration::REGISTRY_DATA);
packet.write_string(registry_name)?;
packet.write_usize_varint(registry_data.len())?;
debug!("sending registry: {registry_name}");
for (key, value) in registry_data {
packet.write_string(key)?;
packet.write_boolean(true)?;
let mut data = Vec::new();
craftflow_nbt::to_writer(&mut data, value).unwrap();
debug!("- {key}");
packet.write_bytes(&data)?;
}
let mut registry_data = Cursor::new(include_bytes!("registry-data.bin"));
while let Ok(mut packet) = read_packet(&mut registry_data, None) {
packet.set_id(clientbound::configuration::REGISTRY_DATA);
client.write_packet(&packet)?;
}
Ok(())
}
pub fn process_known_packs(
client: Arc<ClientContext>
) -> Result<(), ServerError> {
let mut packet = Packet::empty(clientbound::configuration::KNOWN_PACKS);
packet.write_varint(1)?;
packet.write_string("minecraft")?;
packet.write_string("core")?;
packet.write_string("1.21.5")?;
client.write_packet(&packet)?;
client.read_packet(serverbound::configuration::KNOWN_PACKS)?;
Ok(())
}
pub fn handle_configuration_state(
client: Arc<ClientContext>, // Контекст клиента
) -> Result<(), ServerError> {
let mut p = Packet::empty(clientbound::configuration::KNOWN_PACKS);
p.write_varint(1)?;
p.write_string("minecraft")?;
p.write_string("core")?;
p.write_string("1.21.5")?;
client.write_packet(&p)?;
client.read_packet(serverbound::configuration::KNOWN_PACKS)?;
let mut packet = Packet::empty(clientbound::configuration::FEATURE_FLAGS);
packet.write_varint(1)?;
packet.write_string("minecraft:vanilla")?;
client.write_packet(&packet)?;
process_known_packs(client.clone())?;
send_registry_data(client.clone())?;
send_update_tags(client.clone())?;
Ok(())
}
@ -100,7 +103,14 @@ pub fn handle_play_state(
packet.write_boolean(false)?; // Enforces Secure Chat
client.write_packet(&packet)?;
loop {}
loop {}
// TODO: отдельный поток для чтения пакетов
// TODO: переработка функции read_packet так чтобы когда
// делаешь read_any_packet, пакет отправлялся сначала всем другим
// функциям read_packet которые настроены на этот айди пакета,
// а потом если таковых не осталось пакет возвращался
Ok(())
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.