Add very basic MITM protocol injector.

This commit is contained in:
UnknownShadow200 2015-02-22 06:43:25 +11:00
parent 8c54b0056e
commit d5b6950f33
12 changed files with 1448 additions and 1 deletions

View file

@ -4,6 +4,8 @@ Microsoft Visual Studio Solution File, Format Version 11.00
# SharpDevelop 4.4
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassicalSharp", "ClassicalSharp.csproj", "{BEB1C785-5CAD-48FF-A886-876BF0A318D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Injector", "Injector\Injector.csproj", "{7591660C-A783-414C-93D9-37B5A60E7A06}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -18,6 +20,10 @@ Global
{BEB1C785-5CAD-48FF-A886-876BF0A318D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEB1C785-5CAD-48FF-A886-876BF0A318D4}.Release|Any CPU.Build.0 = Release|Any CPU
{BEB1C785-5CAD-48FF-A886-876BF0A318D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7591660C-A783-414C-93D9-37B5A60E7A06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7591660C-A783-414C-93D9-37B5A60E7A06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7591660C-A783-414C-93D9-37B5A60E7A06}.Release|Any CPU.Build.0 = Release|Any CPU
{7591660C-A783-414C-93D9-37B5A60E7A06}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Injector {
public class EntityMetadata {
public Dictionary<int, object> Metadata = new Dictionary<int, object>();
public static EntityMetadata ReadFrom( StreamInjector reader ) {
EntityMetadata dict = new EntityMetadata();
for( byte item = reader.ReadUInt8(); item != 0x7F; item = reader.ReadUInt8() ) {
int index = item & 0x1F;
int type = item >> 5;
if( type == 0 ) {
dict.Metadata[index] = reader.ReadInt8();
} else if( type == 1 ) {
dict.Metadata[index] = reader.ReadInt16();
} else if( type == 2 ) {
dict.Metadata[index] = reader.ReadInt32();
} else if( type == 3 ) {
dict.Metadata[index] = reader.ReadFloat32();
} else if( type == 4 ) {
dict.Metadata[index] = reader.ReadString();
} else if( type == 5 ) {
dict.Metadata[index] = reader.ReadSlot();
} else if( type == 6 ) {
int x = reader.ReadInt32();
int y = reader.ReadInt32();
int z = reader.ReadInt32();
dict.Metadata[index] = new Vector3I( x, y, z );
}
}
return dict;
}
public override string ToString() {
StringBuilder builder = new StringBuilder();
foreach( var pair in Metadata ) {
builder.AppendLine( " " + pair.Key + ": " + pair.Value );
}
return builder.ToString();
}
}
public struct Vector3I {
public int X, Y, Z;
public Vector3I( int x, int y, int z ) {
X = x;
Y = y;
Z = z;
}
public override string ToString() {
return X + "," + Y + "," + Z;
}
}
}

64
Injector/Injector.csproj Normal file
View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{7591660C-A783-414C-93D9-37B5A60E7A06}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Exe</OutputType>
<RootNamespace>Injector</RootNamespace>
<AssemblyName>Injector</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<AppDesignerFolder>Properties</AppDesignerFolder>
<NoWin32Manifest>False</NoWin32Manifest>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<BaseAddress>4194304</BaseAddress>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<StartAction>Project</StartAction>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="EntityMetadata.cs" />
<Compile Include="InjectorThread.cs" />
<Compile Include="InjectorThread.Logging.cs" />
<Compile Include="StreamInjector.cs" />
<Compile Include="Packets\InboundPackets.cs" />
<Compile Include="Packets\OutboundPackets.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Packets" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
namespace Injector {
public partial class InjectorThread {
StreamWriter c2sWriter, s2cWriter;
void SetupLogging() {
DateTime now = DateTime.Now;
s2cWriter = new StreamWriter( "log " + now.ToString( "dd-MM-yyyy HH-mm-ss" ) + "_s2c.txt" );
s2cWriter.AutoFlush = true;
c2sWriter = new StreamWriter( "log " + now.ToString( "dd-MM-yyyy HH-mm-ss" ) + "_c2s.txt" );
c2sWriter.AutoFlush = true;
foreach( var constructor in inboundConstructors ) {
if( constructor == null ) continue;
PacketS2C packet = constructor();
Type type = packet.GetType();
FieldInfo[] fields = type.GetFields( BindingFlags.NonPublic | BindingFlags.Instance );
s2cPrinters[type] = MakePrinter<PacketS2C>( fields );
}
foreach( var constructor in outboundConstructors ) {
if( constructor == null ) continue;
PacketC2S packet = constructor();
Type type = packet.GetType();
FieldInfo[] fields = type.GetFields( BindingFlags.NonPublic | BindingFlags.Instance );
c2sPrinters[type] = MakePrinter<PacketC2S>( fields );
}
}
Action<T, StringBuilder> MakePrinter<T>( FieldInfo[] fields ) {
return (T p, StringBuilder printer) => {
FieldInfo[] fields2 = fields;
for( int i = 0; i < fields2.Length; i++ ) {
FieldInfo field = fields2[i];
object value = field.GetValue( p );
if( value is byte[] ) {
byte[] arrayValue = ( value as byte[] );
printer.AppendLine( field.Name + ": ("+ arrayValue.Length + " bytes) " +
Utils.ToSpacedHexString( arrayValue ) );
} else if( value is Slot[] ) {
Slot[] slotsValue = ( value as Slot[] );
printer.AppendLine( field.Name + ": ("+ slotsValue.Length + " items)" );
for( int j = 0; j < slotsValue.Length; j++ ) {
printer.AppendLine( " " + j + ": " + slotsValue[j].ToString() );
}
} else {
printer.AppendLine( field.Name + ": " + value.ToString() );
}
}
};
}
const string format = "[{0} (0x{1},{2})]";
void LogC2S( byte opcode, PacketC2S packet ) {
Type type = packet.GetType();
if( IgnoreC2S( type ) ) return;
c2sWriter.WriteLine(
String.Format( format,
DateTime.Now.ToString( "HH:mm:ss" ),
opcode.ToString( "X2" ),
type.Name )
);
StringBuilder builder = new StringBuilder();
c2sPrinters[type]( packet, builder );
builder.AppendLine();
c2sWriter.WriteLine( builder.ToString() );
}
void LogS2C( byte opcode, PacketS2C packet ) {
Type type = packet.GetType();
if( IgnoreS2C( type ) ) return;
s2cWriter.WriteLine(
String.Format( format,
DateTime.Now.ToString( "HH:mm:ss" ),
opcode.ToString( "X2" ),
type.Name )
);
StringBuilder builder = new StringBuilder();
s2cPrinters[type]( packet, builder );
s2cWriter.WriteLine( builder.ToString() );
}
bool IgnoreS2C( Type type ) {
return type == typeof( MapChunkInbound ) || type == typeof( PrepareChunkInbound ) ||
type == typeof( MapsInbound );
}
bool IgnoreC2S( Type type ) {
return type == typeof( PlayerPosAndLookOutbound ) || type == typeof( PlayerOutbound ) ||
type == typeof( PlayerPosOutbound ) || type == typeof( PlayerLookOutbound );
}
Dictionary<Type, Action<PacketC2S, StringBuilder>> c2sPrinters = new Dictionary<Type, Action<PacketC2S, StringBuilder>>();
Dictionary<Type, Action<PacketS2C, StringBuilder>> s2cPrinters = new Dictionary<Type, Action<PacketS2C, StringBuilder>>();
}
}

143
Injector/InjectorThread.cs Normal file
View file

@ -0,0 +1,143 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Injector {
public partial class InjectorThread {
TcpClient c2sClient, s2cClient;
NetworkStream s2cStream, c2sStream;
StreamInjector s2cReader, c2sReader;
public InjectorThread( TcpClient client, IPEndPoint serverIp ) {
c2sClient = client;
s2cClient = new TcpClient();
s2cClient.Connect( serverIp );
}
public void Run() {
s2cStream = new NetworkStream( s2cClient.Client );
c2sStream = new NetworkStream( c2sClient.Client );
s2cReader = new StreamInjector( s2cStream, c2sStream );
c2sReader = new StreamInjector( c2sStream, s2cStream );
SetupHandlers();
SetupLogging();
try {
while( true ) {
while( s2cStream.DataAvailable ) {
ReadS2C();
}
while( c2sStream.DataAvailable ) {
ReadC2S();
}
Thread.Sleep( 1 );
}
} catch( Exception ex ) {
Console.WriteLine( ex );
} finally {
c2sClient.Close();
s2cClient.Close();
}
}
void ReadS2C() {
byte id = s2cReader.ReadUInt8();
PacketS2C packet = inboundConstructors[id]();
packet.ReadData( s2cReader );
LogS2C( id, packet );
}
void ReadC2S() {
byte id = c2sReader.ReadUInt8();
PacketC2S packet = outboundConstructors[id]();
packet.ReadData( c2sReader );
LogC2S( id, packet );
}
void SetupHandlers() {
RegisterInbound( 0x00, () => new KeepAliveInbound() );
RegisterInbound( 0x01, () => new LoginRequestInbound() );
RegisterInbound( 0x02, () => new HandshakeInbound() );
RegisterInbound( 0x03, () => new ChatInbound() );
RegisterInbound( 0x04, () => new TimeUpdateInbound() );
RegisterInbound( 0x05, () => new EntityEquipmentInbound() );
RegisterInbound( 0x06, () => new SpawnPositionInbound() );
RegisterInbound( 0x08, () => new UpdateHealthInbound() );
RegisterInbound( 0x09, () => new RespawnInbound() );
RegisterInbound( 0x0D, () => new PlayerPosAndLookInbound() );
RegisterInbound( 0x11, () => new UseBedInbound() );
RegisterInbound( 0x12, () => new AnimationInbound() );
RegisterInbound( 0x14, () => new SpawnPlayerInbound() );
RegisterInbound( 0x15, () => new SpawnPickupInbound() );
RegisterInbound( 0x16, () => new CollectItemInbound() );
RegisterInbound( 0x17, () => new SpawnObjectInbound() );
RegisterInbound( 0x18, () => new SpawnMobInbound() );
RegisterInbound( 0x19, () => new SpawnPaintingInbound() );
RegisterInbound( 0x1C, () => new EntityVelocityInbound() );
RegisterInbound( 0x1D, () => new DestroyEntityInbound() );
RegisterInbound( 0x1E, () => new EntityInbound() );
RegisterInbound( 0x1F, () => new EntityRelativeMoveInbound() );
RegisterInbound( 0x20, () => new EntityLookInbound() );
RegisterInbound( 0x21, () => new EntityLookAndRelativeMoveInbound() );
RegisterInbound( 0x22, () => new EntityTeleportInbound() );
RegisterInbound( 0x26, () => new EntityStatusInbound() );
RegisterInbound( 0x27, () => new AttachEntityInbound() );
RegisterInbound( 0x28, () => new EntityMetadataInbound() );
RegisterInbound( 0x32, () => new PrepareChunkInbound() );
RegisterInbound( 0x33, () => new MapChunkInbound() );
RegisterInbound( 0x34, () => new MultiBlockChangeInbound() );
RegisterInbound( 0x35, () => new BlockChangeInbound() );
RegisterInbound( 0x36, () => new BlockActionInbound() );
RegisterInbound( 0x3C, () => new ExplosionInbound() );
RegisterInbound( 0x3D, () => new SoundEffectInbound() );
RegisterInbound( 0x46, () => new ChangeGameStateInbound() );
RegisterInbound( 0x47, () => new ThunderboltInbound() );
RegisterInbound( 0x64, () => new OpenWindowInbound() );
RegisterInbound( 0x65, () => new CloseWindowInbound() );
RegisterInbound( 0x67, () => new SetSlotInbound() );
RegisterInbound( 0x68, () => new WindowItemsInbound() );
RegisterInbound( 0x69, () => new WindowPropertyInbound() );
RegisterInbound( 0x6A, () => new ConfirmTransactionInbound() );
RegisterInbound( 0x82, () => new UpdateSignInbound() );
RegisterInbound( 0x83, () => new MapsInbound() );
RegisterInbound( 0xC8, () => new StatisticsInbound() );
RegisterInbound( 0xFF, () => new DisconnectInbound() );
RegisterOutbound( 0x00, () => new KeepAliveOutbound() );
RegisterOutbound( 0x01, () => new LoginRequestOutbound() );
RegisterOutbound( 0x02, () => new HandshakeOutbound() );
RegisterOutbound( 0x03, () => new ChatOutbound() );
RegisterOutbound( 0x07, () => new UseEntityOutbound() );
RegisterOutbound( 0x09, () => new RespawnOutbound() );
RegisterOutbound( 0x0A, () => new PlayerOutbound() );
RegisterOutbound( 0x0B, () => new PlayerPosOutbound() );
RegisterOutbound( 0x0C, () => new PlayerLookOutbound() );
RegisterOutbound( 0x0D, () => new PlayerPosAndLookOutbound() );
RegisterOutbound( 0x0E, () => new PlayerDiggingOutbound() );
RegisterOutbound( 0x0F, () => new PlayerPlaceBlockOutbound() );
RegisterOutbound( 0x10, () => new HeldItemChangeOutbound() );
RegisterOutbound( 0x12, () => new AnimationOutbound() );
RegisterOutbound( 0x13, () => new EntityActionOutbound() );
RegisterOutbound( 0x27, () => new AttachEntityOutbound() );
RegisterOutbound( 0x65, () => new CloseWindowOutbound() );
RegisterOutbound( 0x66, () => new ClickWindowOutbound() );
RegisterOutbound( 0x6A, () => new ConfirmTransactionOutbound() );
RegisterOutbound( 0x82, () => new UpdateSignOutbound() );
RegisterOutbound( 0xFF, () => new DisconnectOutbound() );
}
void RegisterOutbound( byte opcode, Func<PacketC2S> cons ) {
outboundConstructors[opcode] = cons;
}
void RegisterInbound( byte opcode, Func<PacketS2C> cons ) {
inboundConstructors[opcode] = cons;
}
Func<PacketC2S>[] outboundConstructors = new Func<PacketC2S>[256];
Func<PacketS2C>[] inboundConstructors = new Func<PacketS2C>[256];
}
}

View file

@ -0,0 +1,602 @@
using System;
namespace Injector {
public abstract class PacketS2C {
public abstract void ReadData( StreamInjector reader );
}
public sealed class KeepAliveInbound : PacketS2C {
public override void ReadData( StreamInjector reader ) {
}
}
public sealed class LoginRequestInbound : PacketS2C {
int entityId;
string unknown;
long mapSeed;
byte dimension;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
unknown = reader.ReadString();
mapSeed = reader.ReadInt64();
dimension = reader.ReadUInt8();
}
}
public sealed class HandshakeInbound : PacketS2C {
string hash;
public override void ReadData( StreamInjector reader ) {
hash = reader.ReadString();
}
}
public sealed class ChatInbound : PacketS2C {
string text;
public override void ReadData( StreamInjector reader ) {
text = reader.ReadString();
}
}
public sealed class TimeUpdateInbound : PacketS2C {
long worldAge;
public override void ReadData( StreamInjector reader ) {
worldAge = reader.ReadInt64();
}
}
public sealed class EntityEquipmentInbound : PacketS2C {
int entityId;
short slotId;
Slot slot;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
slotId = reader.ReadInt16();
short id = reader.ReadInt16();
short damage = reader.ReadInt16();
slot = new Slot() { Id = id, Count = 1, Damage = damage };
}
}
public sealed class SpawnPositionInbound : PacketS2C {
int spawnX, spawnY, spawnZ;
public override void ReadData( StreamInjector reader ) {
spawnX = reader.ReadInt32();
spawnY = reader.ReadInt32();
spawnZ = reader.ReadInt32();
}
}
public sealed class UpdateHealthInbound : PacketS2C {
short health;
public override void ReadData( StreamInjector reader ) {
health = reader.ReadInt16();
}
}
public sealed class RespawnInbound : PacketS2C {
byte dimension;
public override void ReadData( StreamInjector reader ) {
dimension = reader.ReadUInt8();
}
}
public sealed class PlayerPosAndLookInbound : PacketS2C {
float x, y, z, stanceY;
float yaw, pitch;
public override void ReadData( StreamInjector reader ) {
x = (float)reader.ReadFloat64();
stanceY = (float)reader.ReadFloat64();
y = (float)reader.ReadFloat64();
z = (float)reader.ReadFloat64();
yaw = reader.ReadFloat32();
pitch = reader.ReadFloat32();
}
}
public sealed class UseBedInbound : PacketS2C {
int entityId;
byte unknown;
int x, y, z;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
unknown = reader.ReadUInt8();
x = reader.ReadInt32();
y = reader.ReadUInt8();
z = reader.ReadInt32();
}
}
public sealed class AnimationInbound : PacketS2C {
int entityId;
byte anim;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
anim = reader.ReadUInt8();
}
}
public sealed class SpawnPlayerInbound : PacketS2C {
int entityId;
string playerName;
float x, y, z;
float yaw, pitch;
short currentItem;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
playerName = reader.ReadString();
x = reader.ReadInt32() / 32f;
y = reader.ReadInt32() / 32f;
z = reader.ReadInt32() / 32f;
yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
currentItem = reader.ReadInt16();
}
}
public sealed class SpawnPickupInbound : PacketS2C {
int entityId;
short itemId;
byte itemsCount;
short itemDamage;
float x, y, z;
float yaw, pitch, roll;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
itemId = reader.ReadInt16();
itemsCount = reader.ReadUInt8();
itemDamage = reader.ReadInt16();
x = reader.ReadInt32() / 32f;
y = reader.ReadInt32() / 32f;
z = reader.ReadInt32() / 32f;
yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
roll = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
}
}
public sealed class CollectItemInbound : PacketS2C {
int collectedId;
int collectorId;
public override void ReadData( StreamInjector reader ) {
collectedId = reader.ReadInt32();
collectorId = reader.ReadInt32();
}
}
public sealed class SpawnObjectInbound : PacketS2C {
int entityId;
byte type;
float x, y, z;
int objData;
float velX, velY, velZ;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
type = reader.ReadUInt8();
x = reader.ReadInt32() / 32f;
y = reader.ReadInt32() / 32f;
z = reader.ReadInt32() / 32f;
objData = reader.ReadInt32();
if( objData > 0 ) {
velX = reader.ReadInt16() / 8000f;
velY = reader.ReadInt16() / 8000f;
velZ = reader.ReadInt16() / 8000f;
}
}
}
public sealed class SpawnMobInbound : PacketS2C {
int entityId;
byte type;
float x, y, z;
float yaw, pitch;
EntityMetadata meta;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
type = reader.ReadUInt8();
x = reader.ReadInt32() / 32f;
y = reader.ReadInt32() / 32f;
z = reader.ReadInt32() / 32f;
yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
meta = EntityMetadata.ReadFrom( reader );
}
}
public sealed class SpawnPaintingInbound : PacketS2C {
int entityId;
string title;
int x, y, z;
int direction;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
title = reader.ReadString();
x = reader.ReadInt32();
y = reader.ReadInt32();
z = reader.ReadInt32();
direction = reader.ReadInt32();
}
}
public sealed class EntityVelocityInbound : PacketS2C {
int entityId;
float velX, velY, velZ;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
velX = reader.ReadInt16() / 8000f;
velY = reader.ReadInt16() / 8000f;
velZ = reader.ReadInt16() / 8000f;
}
}
public sealed class DestroyEntityInbound : PacketS2C {
int entityId;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
}
}
public sealed class EntityInbound : PacketS2C {
int entityId;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
}
}
public sealed class EntityRelativeMoveInbound : PacketS2C {
int entityId;
float dx, dy, dz;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
dx = reader.ReadInt8() / 32f;
dy = reader.ReadInt8() / 32f;
dz = reader.ReadInt8() / 32f;
}
}
public sealed class EntityLookInbound : PacketS2C {
int entityId;
float yaw, pitch;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
}
}
public sealed class EntityLookAndRelativeMoveInbound : PacketS2C {
int entityId;
float dx, dy, dz;
float yaw, pitch;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
dx = reader.ReadInt8() / 32f;
dy = reader.ReadInt8() / 32f;
dz = reader.ReadInt8() / 32f;
yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
}
}
public sealed class EntityTeleportInbound : PacketS2C {
int entityId;
float x, y, z;
float yaw, pitch;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
x = reader.ReadInt32() / 32f;
y = reader.ReadInt32() / 32f;
z = reader.ReadInt32() / 32f;
yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
}
}
public sealed class EntityStatusInbound : PacketS2C {
int entityId;
byte status;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
status = reader.ReadUInt8();
}
}
public sealed class AttachEntityInbound : PacketS2C {
int collectedId;
int collectorId;
public override void ReadData( StreamInjector reader ) {
collectedId = reader.ReadInt32();
collectorId = reader.ReadInt32();
}
}
public sealed class EntityMetadataInbound : PacketS2C {
int entityId;
EntityMetadata meta;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
meta = EntityMetadata.ReadFrom( reader );
}
}
public sealed class PrepareChunkInbound : PacketS2C {
int chunkX, chunkZ;
bool load;
public override void ReadData( StreamInjector reader ) {
chunkX = reader.ReadInt32();
chunkZ = reader.ReadInt32();
load = reader.ReadBool();
}
}
public sealed class MapChunkInbound : PacketS2C {
int x, y, z;
int sizeX, sizeY, sizeZ;
byte[] compressedData;
public override void ReadData( StreamInjector reader ) {
x = reader.ReadInt32();
y = reader.ReadInt16();
z = reader.ReadInt32();
sizeX = reader.ReadUInt8() + 1;
sizeY = reader.ReadUInt8() + 1;
sizeZ = reader.ReadUInt8() + 1;
int compressedSize = reader.ReadInt32();
compressedData = reader.ReadRawBytes( compressedSize );
}
}
public sealed class MultiBlockChangeInbound : PacketS2C {
int chunkX, chunkZ;
ushort[] posMasks;
byte[] blockTypes;
byte[] blockMetas;
public override void ReadData( StreamInjector reader ) {
chunkX = reader.ReadInt32();
chunkZ = reader.ReadInt32();
int count = reader.ReadInt16();
posMasks = new ushort[count];
for( int i = 0; i < count; i++ ) {
posMasks[i] = reader.ReadUInt16();
}
blockTypes = reader.ReadRawBytes( count );
blockMetas = reader.ReadRawBytes( count );
}
}
public sealed class BlockChangeInbound : PacketS2C {
int x, y, z;
byte blockType, blockMeta;
public override void ReadData( StreamInjector reader ) {
x = reader.ReadInt32();
y = reader.ReadUInt8();
z = reader.ReadInt32();
blockType = reader.ReadUInt8();
blockMeta = reader.ReadUInt8();
}
}
public sealed class BlockActionInbound : PacketS2C {
int x, y, z;
byte data1, data2;
public override void ReadData( StreamInjector reader ) {
x = reader.ReadInt32();
y = reader.ReadInt16();
z = reader.ReadInt32();
data1 = reader.ReadUInt8();
data2 = reader.ReadUInt8();
}
}
public sealed class ExplosionInbound : PacketS2C {
float x, y, z;
float radius;
Record[] records;
struct Record {
public sbyte X, Y, Z;
public Record( sbyte x, sbyte y, sbyte z ) {
X = x;
Y = y;
Z = z;
}
}
public override void ReadData( StreamInjector reader ) {
x = (float)reader.ReadFloat64();
y = (float)reader.ReadFloat64();
z = (float)reader.ReadFloat64();
radius = reader.ReadFloat32();
records = new Record[reader.ReadInt32()];
for( int i = 0; i < records.Length; i++ ) {
records[i] = new Record( reader.ReadInt8(), reader.ReadInt8(), reader.ReadInt8() );
}
}
}
public sealed class SoundEffectInbound : PacketS2C {
int effectId;
int x, y, z;
int data;
public override void ReadData( StreamInjector reader ) {
effectId = reader.ReadInt32();
x = reader.ReadInt32();
y = reader.ReadInt8();
z = reader.ReadInt32();
data = reader.ReadInt32();
}
}
public sealed class ChangeGameStateInbound : PacketS2C {
byte state;
public override void ReadData( StreamInjector reader ) {
state = reader.ReadUInt8();
}
}
public sealed class ThunderboltInbound : PacketS2C {
int entityId;
byte unknown;
float x, y, z;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
unknown = reader.ReadUInt8();
x = reader.ReadInt32() / 32f;
y = reader.ReadInt32() / 32f;
z = reader.ReadInt32() / 32f;
}
}
public sealed class OpenWindowInbound : PacketS2C {
byte windowId;
string inventoryType;
string windowTitle;
byte numSlots;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
inventoryType = reader.ReadString();
windowTitle = reader.ReadString();
numSlots = reader.ReadUInt8();
}
}
public sealed class CloseWindowInbound : PacketS2C {
byte windowId;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
}
}
public sealed class SetSlotInbound : PacketS2C {
byte windowId;
short slotIndex;
Slot slot;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
slotIndex = reader.ReadInt16();
slot = reader.ReadSlot();
}
}
public sealed class WindowItemsInbound : PacketS2C {
byte windowId;
Slot[] slots;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
slots = new Slot[reader.ReadInt16()];
for( int i = 0; i < slots.Length; i++ ) {
slots[i] = reader.ReadSlot();
}
}
}
public sealed class WindowPropertyInbound : PacketS2C {
byte windowId;
short property;
short value;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
property = reader.ReadInt16();
value = reader.ReadInt16();
}
}
public sealed class ConfirmTransactionInbound : PacketS2C {
byte windowId;
short actionNum;
bool accepted;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
actionNum = reader.ReadInt16();
accepted = reader.ReadBool();
}
}
public sealed class UpdateSignInbound : PacketS2C {
int x, y, z;
string line1, line2, line3, line4;
public override void ReadData( StreamInjector reader ) {
x = reader.ReadInt32();
y = reader.ReadInt16();
z = reader.ReadInt32();
line1 = reader.ReadString();
line2 = reader.ReadString();
line3 = reader.ReadString();
line4 = reader.ReadString();
}
}
public sealed class MapsInbound : PacketS2C {
short itemType;
short itemDamage;
byte[] data;
public override void ReadData( StreamInjector reader ) {
itemType = reader.ReadInt16();
itemDamage = reader.ReadInt16();
data = reader.ReadRawBytes( reader.ReadUInt8() );
}
}
public sealed class StatisticsInbound : PacketS2C {
int statId;
byte amount;
public override void ReadData( StreamInjector reader ) {
statId = reader.ReadInt32();
amount = reader.ReadUInt8();
}
}
public sealed class DisconnectInbound : PacketS2C {
string reason;
public override void ReadData( StreamInjector reader ) {
reason = reader.ReadString();
}
}
}

View file

@ -0,0 +1,246 @@
using System;
namespace Injector {
public abstract class PacketC2S {
public abstract void ReadData( StreamInjector reader );
}
public sealed class KeepAliveOutbound : PacketC2S {
public override void ReadData( StreamInjector reader ) {
}
}
public sealed class LoginRequestOutbound : PacketC2S {
int protocolVersion;
string username;
ulong unused;
byte unused2;
public override void ReadData( StreamInjector reader ) {
protocolVersion = reader.ReadInt32();
username = reader.ReadString();
unused = reader.ReadUInt64();
unused2 = reader.ReadUInt8();
}
}
public sealed class HandshakeOutbound : PacketC2S {
string username;
public override void ReadData( StreamInjector reader ) {
username = reader.ReadString();
}
}
public sealed class ChatOutbound : PacketC2S {
string value;
public override void ReadData( StreamInjector reader ) {
value = reader.ReadString();
}
}
public sealed class UseEntityOutbound : PacketC2S {
int entityId; // ignored?
int targetId;
bool leftClick;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
targetId = reader.ReadInt32();
leftClick = reader.ReadBool();
}
}
public sealed class RespawnOutbound : PacketC2S {
byte dimension;
public override void ReadData( StreamInjector reader ) {
dimension = reader.ReadUInt8();
}
}
public sealed class PlayerOutbound : PacketC2S {
bool onGround;
public override void ReadData( StreamInjector reader ) {
onGround = reader.ReadBool();
}
}
public sealed class PlayerPosOutbound : PacketC2S {
bool onGround;
double x, y, z, stanceY;
public override void ReadData( StreamInjector reader ) {
x = reader.ReadFloat64();
y = reader.ReadFloat64();
stanceY = reader.ReadFloat64();
z = reader.ReadFloat64();
onGround = reader.ReadBool();
}
}
public sealed class PlayerLookOutbound : PacketC2S {
bool onGround;
float yaw, pitch;
public override void ReadData( StreamInjector reader ) {
yaw = reader.ReadFloat32();
pitch = reader.ReadFloat32();
onGround = reader.ReadBool();
}
}
public sealed class PlayerPosAndLookOutbound : PacketC2S {
bool onGround;
double x, y, z, stanceY;
float yaw, pitch;
public override void ReadData( StreamInjector reader ) {
x = reader.ReadFloat64();
y = reader.ReadFloat64();
stanceY = reader.ReadFloat64();
z = reader.ReadFloat64();
yaw = reader.ReadFloat32();
pitch = reader.ReadFloat32();
onGround = reader.ReadBool();
}
}
public sealed class PlayerDiggingOutbound : PacketC2S {
DigStatus status;
int locX, locY, locZ;
byte face;
public override void ReadData( StreamInjector reader ) {
status = (DigStatus)reader.ReadUInt8();
locX = reader.ReadInt32();
locY = reader.ReadUInt8();
locZ = reader.ReadInt32();
face = reader.ReadUInt8();
}
}
public enum DigStatus {
Start = 0,
Finish = 2,
DropItem = 4,
}
public sealed class PlayerPlaceBlockOutbound : PacketC2S {
int locX, locY, locZ;
byte direction;
Slot heldItem;
public override void ReadData( StreamInjector reader ) {
locX = reader.ReadInt32();
locY = reader.ReadUInt8();
locZ = reader.ReadInt32();
direction = reader.ReadUInt8();
heldItem = reader.ReadSlot();
}
}
public sealed class HeldItemChangeOutbound : PacketC2S {
short index;
public override void ReadData( StreamInjector reader ) {
index = reader.ReadInt16();
}
}
public sealed class AnimationOutbound : PacketC2S {
int entityId;
byte anim;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
anim = reader.ReadUInt8();
}
}
public sealed class EntityActionOutbound : PacketC2S {
int entityId;
byte action;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
action = reader.ReadUInt8();
}
}
public sealed class AttachEntityOutbound : PacketC2S {
int entityId;
int targetId;
public override void ReadData( StreamInjector reader ) {
entityId = reader.ReadInt32();
targetId = reader.ReadInt32();
}
}
public sealed class CloseWindowOutbound : PacketC2S {
byte windowId;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
}
}
public sealed class ClickWindowOutbound : PacketC2S {
byte windowId;
short slotId;
bool rightClick;
short actionNumber;
bool shift;
Slot clickedItem;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
slotId = reader.ReadInt16();
rightClick = reader.ReadBool();
actionNumber = reader.ReadInt16();
shift = reader.ReadBool();
clickedItem = reader.ReadSlot();
}
}
public sealed class ConfirmTransactionOutbound : PacketC2S {
byte windowId;
short actionNumber;
bool accepted;
public override void ReadData( StreamInjector reader ) {
windowId = reader.ReadUInt8();
actionNumber = reader.ReadInt16();
accepted = reader.ReadBool();
}
}
public sealed class UpdateSignOutbound : PacketC2S {
int locX, locY, locZ;
string line1, line2, line3, line4;
public override void ReadData( StreamInjector reader ) {
locX = reader.ReadInt32();
locY = reader.ReadInt16();
locZ = reader.ReadInt32();
line1 = reader.ReadString();
line2 = reader.ReadString();
line3 = reader.ReadString();
line4 = reader.ReadString();
}
}
public sealed class DisconnectOutbound : PacketC2S {
string text;
public override void ReadData( StreamInjector reader ) {
text = reader.ReadString();
}
}
}

22
Injector/Program.cs Normal file
View file

@ -0,0 +1,22 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Injector {
class Program {
public static void Main( string[] args ) {
TcpListener listener = new TcpListener( IPAddress.Loopback, 25564 );
listener.Start();
while( true ) {
TcpClient client = listener.AcceptTcpClient();
InjectorThread injector = new InjectorThread( client, new IPEndPoint( IPAddress.Loopback, 25565 ) );
Thread thread = new Thread( injector.Run );
thread.Name = "Client XY";
thread.Start();
}
}
}
}

View file

@ -0,0 +1,31 @@
#region Using directives
using System;
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Injector")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Injector")]
[assembly: AssemblyCopyright("Copyright 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]

117
Injector/StreamInjector.cs Normal file
View file

@ -0,0 +1,117 @@
using System;
using System.IO;
using System.Text;
namespace Injector {
public sealed class StreamInjector : IDisposable {
public Stream inStream, outStream;
private byte[] buff;
public StreamInjector( Stream input, Stream output ) {
inStream = input;
outStream = output;
buff = new byte[8];
}
public void Close() {
Dispose();
}
public void Dispose() {
if( inStream != null ) {
inStream.Close();
}
inStream = null;
buff = null;
}
public bool ReadBool() {
return ReadUInt8() != 0;
}
public byte ReadUInt8() {
int value = inStream.ReadByte();
if( value == -1 ) throw new EndOfStreamException();
outStream.WriteByte( (byte)value );
return (byte)value;
}
public sbyte ReadInt8() {
return (sbyte)ReadUInt8();
}
public short ReadInt16() {
return (short)ReadUInt16();
}
public ushort ReadUInt16() {
FillBuffer( buff, 2 );
return (ushort)( buff[1] | buff[0] << 8 );
}
public int ReadInt32() {
return (int)ReadUInt32();
}
public uint ReadUInt32() {
FillBuffer( buff, 4 );
return (uint)( buff[3] | buff[2] << 8 | buff[1] << 16 | buff[0] << 24 );
}
public long ReadInt64() {
return (long)ReadUInt64();
}
public ulong ReadUInt64() {
FillBuffer( buff, 8 );
uint low = (uint)( buff[7] | buff[6] << 8 | buff[5] << 16 | buff[4] << 24 );
uint high = (uint)( buff[3] | buff[2] << 8 | buff[1] << 16 | buff[0] << 24 );
return (ulong)high << 32 | (ulong)low;
}
public unsafe float ReadFloat32() {
uint value = ReadUInt32();
return *(float*)&value;
}
public unsafe double ReadFloat64() {
ulong value = ReadUInt64();
return *(double*)&value;
}
public string ReadString() {
int length = ReadInt16() * 2;
byte[] text = ReadRawBytes( length );
return Encoding.BigEndianUnicode.GetString( text );
}
public byte[] ReadRawBytes( int count ) {
byte[] buffer = new byte[count];
FillBuffer( buffer, count );
return buffer;
}
void FillBuffer( byte[] buffer, int numBytes ) {
if( numBytes == 0 ) return;
int totalRead = 0;
do {
int read = inStream.Read( buffer, totalRead, numBytes - totalRead );
if( read == 0 ) throw new EndOfStreamException();
totalRead += read;
} while( totalRead < numBytes );
outStream.Write( buffer, 0, numBytes );
}
public Slot ReadSlot() {
Slot slot = new Slot();
slot.Id = ReadInt16();
if( slot.Id >= 0 ) {
slot.Count = ReadUInt8();
slot.Damage = ReadInt16();
}
return slot;
}
}
}

55
Injector/Utils.cs Normal file
View file

@ -0,0 +1,55 @@
using System;
namespace Injector {
// NOTE: These delegates should be removed when using versions later than NET 2.0.
// ################################################################
public delegate void Action<T1, T2>( T1 arg1, T2 arg2 );
public delegate TResult Func<TResult>();
// ################################################################
public static class Utils {
public static double PackedToDegrees( byte packed ) {
return packed * 360.0 / 256.0;
}
public static string ToSpacedHexString( byte[] array ) {
int len = array.Length;
char[] chars = new char[len * 3];
for( int i = 0; i < array.Length; i++ ) {
int value = array[i];
int index = i * 3;
int upperNibble = value >> 4;
int lowerNibble = value & 0x0F;
chars[index] = upperNibble < 10 ? (char)( upperNibble + 48 ) : (char)( upperNibble + 55 ); // 48 = index of 0, 55 = index of (A - 10).
chars[index + 1] = lowerNibble < 10 ? (char)( lowerNibble + 48 ) : (char)( lowerNibble + 55 );
chars[index + 2] = ' ';
}
return new String( chars );
}
}
public class Slot {
public short Id;
public byte Count;
public short Damage;
public bool IsEmpty {
get { return Id < 0; }
}
public static Slot CreateEmpty() {
return new Slot() { Id = -1 };
}
const string format = "({0} of [{1},{2}])";
public override string ToString() {
if( IsEmpty ) return "(empty slot)";
return String.Format( format, Count, Id, Damage );
}
}
}

View file

@ -171,7 +171,7 @@ namespace ClassicalSharp.Network.Packets {
entityId = reader.ReadInt32();
unknown = reader.ReadUInt8();
x = reader.ReadInt32();
y = reader.ReadInt32();
y = reader.ReadUInt8();
z = reader.ReadInt32();
}