I am trying to make a Minecraft fake client a.k.a Minecraft chatbot in c# using packets.
I already tried lots of different ways to acomplish this but no luck.
Everytime I send a packet it sends no data (Using a packetsniffer).
Although the packetsniffers says that the total size of the packet is: 190 bytes.
and the size is: 17 bytes.
Here is my code:
static TcpClient client = new TcpClient();
static void Main(string[] args)
{
Console.WriteLine("Start GATHERING INFO.....");
Console.Write("Write a ip: ");
IPAddress ip = IPAddress.Parse("192.168.178.11");
try
{
ip = IPAddress.Parse(Console.ReadLine());
}
catch
{
Console.Write("\nUnknown/Wrong ip entered redirecting to : 127.0.0.1 (AKA Localhost)");
ip = IPAddress.Parse("192.168.178.11");
}
Console.Write("\nWrite a port: ");
int port = int.Parse(Console.ReadLine());
Console.WriteLine("Connecting.....");
try
{
client.Connect(ip, port);
client.NoDelay = false;
Console.WriteLine("Connection succesfull!");
}catch
{
Console.WriteLine("--== ERROR WHILE TRYING TO CONNECT PLEASE RESTART PROGRAM ==--");
Console.ReadKey();
client.Close();
Main(args);
}
Stream stream = client.GetStream();
Console.Write("Please enter a username: ");
string usrn = Console.ReadLine();
Console.Write("\n");
byte[] data = new byte[3 + usrn.Length*2];
data[0] = (byte)2;
data[1] = (byte)29;
gb(usrn).CopyTo(data, 2);
stream.Write(data, 0, data.Length);
Console.ReadKey();
}
public static byte[] gb(String str)
{
return System.Text.ASCIIEncoding.ASCII.GetBytes(str);
}
Here is how the packet should look like:
http://www.wiki.vg/Protocol#Handshake_.280x02.29
I'm ignoring server host and server port since the other bots didnt use it. (although they didnt work to :/
Here's what the original client packet holds:
'shows weird goto: https://dl.dropbox.com/u/32828727/packetsocketsminecraft.txt '
timboiscool9 (my username)
192.168.178.1 (server ip)
There's more after that but this is what i need.
I am fairly new to sockets and tcpclients
I cleaned up your code a bit:
static void Main(string[] args)
{
bool keepTrying = true;
while (keepTrying)
{
Console.Write("Enter server IP Address: ");
IPAddress ip;
if(!IPAddress.TryParse(Console.ReadLine(), out ip))
{
Console.WriteLine("Invalid ip entered, defaulting to 192.168.178.11");
ip = IPAddress.Parse("192.168.178.11");
}
Console.Write("Enter server port: ");
Int16 port;
if(!Int16.TryParse(Console.ReadLine(), out port))
{
Console.WriteLine("Invalid port entered, defaulting to 1234");
port = 1234;
}
Console.WriteLine("Connecting.....");
try
{
TcpClient client = new TcpClient();
client.Connect(new IPEndPoint(ip, port));
client.NoDelay = false;
Console.WriteLine("Connection succesfull!");
List<byte> data = new List<byte>() { 2, 29 };
Console.Write("Please enter a username: ");
byte[] userName = ASCIIEncoding.ASCII.GetBytes(Console.ReadLine());
data.AddRange(userName);
using (var stream = client.GetStream())
{
stream.Write(data.ToArray(), 0, data.Count);
Console.Write("Data sent!");
}
keepTrying = false;
}
catch
{
Console.WriteLine("--== ERROR CONNECTING ==--");
Console.WriteLine();
}
}
}
As for your original question, we need more information. You say that the packet sniffer shows no data but then you say the data has a size. So are you seeing data or not? Are you sure the server is up? The code I posted works for me, meaning it connects to a server on my local system and sends the bytes.
This is a bit old, but I'll still see if I can help you out.
The Minecraft protocol is quite complicated, and you will not be able to connect to Minecraft servers without implementing the vast majority of it. The protocol details can be found here.
I suggest you consider going a different route. Because of how complex Minecraft is, I'd avoid implementing it yourself. Luckily, I'm a Minecraft enthusiast, and I've done most of the work for you. I suggest you take a look at the Craft.Net library. It contains a full protocol implementation and making a chat bot from it would be trivial. In fact, here's an example chat program using Craft.Net for you to peruse.
Related
So in my client I am looking for a way to return how many times a background worker was run to a server. Here is the code section for the client:
}
public int searchcount = 1;
public void SL_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(RecieveIP.Text, 8001); // use the ipaddress as in the server program
MessageBox.Show("Connected");
Stream stm = tcpclnt.GetStream();
MessageBox.Show("Listening for information......");
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
string atk = Encoding.UTF8.GetString(bb.AsSpan(0, k));
Console.WriteLine($"S Connected to attack server at IPv4 address {RecieveIP.Text} Attack command Received: {atk}. If command is g, attacking google. Y means attacking yahoo. A means attacking aol. Yo meants attacking youtube, and s is attacking spotify");//test
//if you want your check
//this will not work if your incoming data contains white space or other bytes that were converted.
if (atk == "g" || atk.Contains("g"))
MessageBox.Show("Recieved Command " + atk);
if (atk == "g")
{
MessageBox.Show("Google");
search.RunWorkerAsync();
On thought, I do have a string
public int searchcount = 1;
Which the background worker in question adds one to display to the person running the client how many times it was run.
Console.WriteLine("Since start: " + count++.ToString());
Is there a way to return the count++ string to the server via both TCP and UDP? Thanks.
TCP(socket) is a protocol that you can send packages both ways. Udp on the other hand is stateless, you can only send packages from client to server. You cant maintain UDP connections open and keep sending/receiving packages. That said, you can send packages from client to server using UDP if the server dont need to respond your package.
I'm really doing some resume on what tcp/udp protocols are and i really encourage you to read about them on MS official docs before using anything on production.
Here some TCP , UDP and sockets examples and documentation on MS official docs.
Tcp Client/Server
Udp Client/Server
Sockets
I have two third party programs running on my PC which communicate with each other via UDP. Program A is simply a user-interface application which connects via UDP and allows the user to send specific hex commands to program B which sends back some acknowledgement in hex. I know that program B receives on port 11001 and sends on port 11000. I am trying to recreate program A myself in C# as a console application to start with. I've written the following code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
network udpNetwork = new network();
Console.WriteLine("Hello World!");
udpNetwork.StartListener();
}
}
class network
{
private const int sendPort = 11001; //Port to transmit to
private const int receivePort = 11000; //Port to receive on
public void StartListener()
{
string IP_Address = Dns.GetHostByName(Environment.MachineName).AddressList[1].ToString();
IPAddress broadcast = IPAddress.Parse(IP_Address); //create IP address
IPEndPoint endpointSend = new IPEndPoint(broadcast, sendPort);
IPEndPoint endpointReceive = new IPEndPoint(broadcast, receivePort);
UdpClient udpServer = new UdpClient(AddressFamily.InterNetwork);
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(endpointSend);
var packetData = new byte[] { 0x1F, 0x7F, 0x80, 0x1F, 0xFF };
try
{
udpServer.Connect(endpointSend);
udpServer.Send(packetData, packetData.Length);
udpServer.Close();
UdpClient udpReceive = new UdpClient(AddressFamily.InterNetwork);
udpReceive.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpReceive.Client.Bind(endpointReceive);
Byte[] receiveBytes = udpReceive.Receive(ref endpointReceive);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("This is the message you received " +
returnData.ToString());
} catch(Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
The code runs fine until the line Byte[] receiveBytes = udpReceive.Receive(ref endpointReceive); where it hangs. I read that this function is blocking which means that the program is waiting for data but obviously not receiving any. Program B listening on port 11001 should send back a response after I have sent the packetData but doesn't. I don't have anyway to use program B to confirm that it is getting the data I am sending. How could I confirm that Program B receives my data in the first place, or do I have some other issue with my code?
edit:
I have edited my code to make use of IPV4 rather than IPV6 as per Jdweng's suggestion. (Shown corrected in the code snippet above). Program B is however still not receiving any data which I can confirm by using TCPView. After launchign the program from within Visual Studio 2019 TCPView shows that there were no received packets by Program B.
So I have two Ruby programs, they are a client and server sockets programs and they work together exchanging messages. But a C# client does not work. I give MCVE, first the ruby client.
#socketClient.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"
while sum = $stdin.gets.chomp # Read lines from the socket
socket = TCPSocket.open("localhost", 3000)
#puts "Starting the Client..................."
socket.puts sum
while message = socket.gets # Read lines from the socket
puts message.chomp
end
socket.close # Close the socket
end
#puts "Closing the Client..................."
and the server
#simplestSocketServer.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"
port = 3000
ipAddress = "127.0.0.1"
server = TCPServer.open(ipAddress, port) # Server would listen on port 3000
loop { # Servers run forever
puts "Starting the Server, accepting connections on port " + port.to_s + "..................."
client_connection = server.accept # Establish client connect connection
begin
clientText = client_connection.gets.chomp
puts clientText
resp = "Acknowledged"
client_connection.puts("#{clientText}" + "#{resp}") # Send the answer to the client
client_connection.puts("Closing the connection with #{client_connection}")
rescue Exception => getException
puts "#{getException}"
end
client_connection.close # Disconnect from the client
}
and the C# console program
using System;
using System.Net.Sockets;
using System.Text;
namespace SimplestCSharpRubySocketsClient
{
class Program
{
static void Main(string[] args)
{
try
{
string ipAddress = "127.0.0.1";
Int16 portNumber = 3000;
TcpClient _client; _client = new TcpClient();
_client.Connect(ipAddress, portNumber);
System.Console.WriteLine("we have connected, seemingly ...");
NetworkStream stream;
stream = _client.GetStream();
Byte[] sendBytes = Encoding.UTF8.GetBytes("some text");
System.Console.WriteLine("writing and flushing some bytes ...");
stream.Write(sendBytes, 0, sendBytes.Length);
stream.Flush();
Byte[] recvBytes = new byte[_client.ReceiveBufferSize];
System.Console.WriteLine("_client.ReceiveBufferSize = " + _client.ReceiveBufferSize); // <--- this prints 65536
System.Console.WriteLine("waiting to read bytes ...");
stream.Read(recvBytes, 0, recvBytes.Length); //<--- hangs here
System.Console.WriteLine("comething came back ...");
string result = Encoding.UTF8.GetString(recvBytes);
string result2 = result.Substring(0, result.LastIndexOf("\r\n"));
_client.Close();
_client.Dispose();
_client = null;
}
catch (Exception ex)
{
//TODO figure out a better error handler
throw ex;
}
}
}
}
The C# program connects and writes bytes but when looking to read bytes it just hangs.
And be aware I am running the C# console program in Visual Studio with admin rights. The two ruby programs run in their own separate Windows console windows.
Folding in some feedback, I added another line in the ruby server to output the clientText. And it prints nothing, suggesting the server is not fully receiving the bytes. Is there a termination signal that C# is required to send?
Thanks in advance.
The problem here is that the C# client does not send a newline at the end of the string, like the Ruby version does (socket.puts sends a string with a newline at the end).
If you change your sendBytes array to include a \n in the payload like this:
Byte[] sendBytes = Encoding.UTF8.GetBytes("some text\n");
you will see that it prints comething came back ... on the console.
The newline is required because of the following gets in the Ruby server:
clientText = client_connection.gets.chomp
My client isn't able to connect to the irc server I am trying to connect to. I did some research and it says that I need to listen on port 113 and respond back to the server in a certain format. I am not sure exactly how to do this. When I tried doing it before I got an error message. Here is the code before I tried listening. The irc sends the message to my client "No ident response". Do I need to create an entire different all together that will listen respond on port 113 or can I do it in here?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ConnectIRC
{
class Program
{
static void Main(string[] args)
{
string ip = "asimov.freenode.net";
string nick = " NICK IKESBOT \r\n";
string join = "JOIN #NetChat\r\n";
int port = 6667;
const int recvBufSize = 8162;
byte[] recvbBuf = new byte[recvBufSize];
//stores the nick
byte[] nickBuf = Encoding.ASCII.GetBytes(nick);
//Stores the room join
byte[] joinBuf = Encoding.ASCII.GetBytes(join);
Socket conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
conn.Connect(ip, port);
conn.Send(nickBuf, nickBuf.Length, SocketFlags.None);
conn.Send(joinBuf, joinBuf.Length, SocketFlags.None);
for(;;){
byte[] buffer = new byte[3000];
int rec = conn.Receive(buffer, 0, buffer.Length, 0);
Array.Resize(ref buffer, rec);
Console.WriteLine(Encoding.Default.GetString(buffer));
}
}
}
}
Despite #Saruman's answer above, you don't need to create an ident server to connect to most IRC networks (including freenode). You can completely ignore the error about "No ident response". It's an outdated technology which is no longer secure and only ever worked properly on Unix-based multiuser systems.
Your actual issue appears to be that you never finish registering the connection to the IRC server. The specification states that you need to send both USER and NICK messages:
string ip = "asimov.freenode.net";
string nick = "NICK IKESBOT \r\n";
// format is: USER <username> * * :<realname>
string user = "USER IKESBOT * * :IKESBOT\r\n";
string join = "JOIN #NetChat\r\n";
int port = 6667;
const int recvBufSize = 8162;
byte[] recvbBuf = new byte[recvBufSize];
//stores the nick
byte[] nickBuf = Encoding.ASCII.GetBytes(nick);
byte[] userBuf = Encoding.ASCII.GetBytes(user);
//Stores the room join
byte[] joinBuf = Encoding.ASCII.GetBytes(join);
Socket conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
conn.Connect(ip, port);
conn.Send(nickBuf, nickBuf.Length, SocketFlags.None);
conn.Send(userBuf, userBuf.Length, SocketFlags.None);
conn.Send(joinBuf, joinBuf.Length, SocketFlags.None);
(You've got an extra space before the NICK - this may or may not break things.)
Aside:
You may find it easier to use TcpClient, StreamReader and StreamWriter to access the underlying socket - they wrap it and deal with the buffers for you. You can then read the response line by line directly into a string, and write to the socket by just passing a string. No fiddling around with encoding and buffers.
TcpClient client = new TcpClient("chat.freenode.net", 6667);
StreamReader reader = new StreamReader(client.GetStream());
StreamWriter writer = new StreamWriter(client.GetStream());
string recievedData = reader.ReadLine();
writer.WriteLine("NICK IKESBOT");
writer.Flush();
Yes you will need to create a totally separate port to listen on and respond back to ident requests
More information on ident can be found here
I'm working o a project that monitors the IP and HWID on a specific port by TCPListen sent from a client that kills a specific process.
Monitor works perfect, I receive ip and hwid and manage to save to .txt files but what I want to do is to implement a method in server how to block the ip by reading the hwid from a text file.
If some one can help me please I will appreciate it really.
Here is a part from code of client(send) , server (receive):
Server:
textFromClient = ("From: " + tcpClient.Client.RemoteEndPoint + " HWID:" + encoder.GetString(message, 0, bytesRead));
Client:
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(getUniqueID("C"));
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
I think I understand but maybe that I didn't explain right. Well, my server listen on any ip on port 8000 . Clients connects automaticly to server ip and port: exemple : 127.0.0.1:8000. Well clients works like this: When client is connected to server it runs a application".exe". Client is made to kill the process of some application by name. I made a timer for kill the process all the time client is running. When a process is killed client sends to server the IP from pc where process was killed and HWID code: byte[] outStream = System.Text.Encoding.ASCII.GetBytes(getUniqueID("C"));
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush(); and server recive on a listbox the ip and hwid. Well i'm thinking to do so . Example: On this recive message code where i get the HWID from client encoder.GetString(message, 0, bytesRead) to do something like:
if (encoder.GetString(message, 0, bytesRead) = LoadBlockHWID(new FileInfo(#"c:\testfileHWID.txt")));
{
//Code to block connection from specified IP on hwid.
}
I whant that server should not let the client connect to server by HWID. I think I must edit server to see ip and hwid connected and client to send hwid when connected.
Load your HWID into a List/Dictionary by reading your file before you start accepting connections.
in your code where you get tcpClient.Client.RemoteEndPoint, extract just the IPAddress out of that.
Then compare the IPAddress to the block list and if it matches, then see if the HWID matches if that matches then don't perform the task otherwise just do it.
mBlockCheck = new SO15147104();
Here is an example for you. Just instantiate the class and in your line where you Might want to block a request, just
if (!mBlockCheck.BlockRequest(ip, hwid))
{
//Do the operation
}
This is the class code you should be able to figure out from this.
using System.Collections.Generic;
using System.IO;
using System.Net;
public class SO15147104
{
private List<string> HWIDLookup;
private List<IPAddress> IPAddressLookup;
public SO15147104()
{
HWIDLookup = LoadBlockHWID(new FileInfo(#"c:\testfileHWID.txt"));
IPAddressLookup = LoadBlockIPAddresses(new FileInfo(
#"c:\testfileIPAddresses.txt"));
}
public bool BlockRequest(IPAddress ip, string HWIDtoCheck)
{
if (IPAddressLookup.Contains(ip) &&
HWIDLookup.Contains(HWIDtoCheck.ToUpperInvariant().Trim()))
{
return true;
}
return false;
}
private List<IPAddress> LoadBlockIPAddresses(FileInfo fi)
{
List<IPAddress> result = new List<IPAddress>();
using (StreamReader sr = fi.OpenText())
{
while (!sr.EndOfStream)
{
IPAddress theIP = IPAddress.Any;
string thisLine = sr.ReadLine().Trim();
//This should allow IPv6 and IPv4 to be listed 1IP per Line
if (IPAddress.TryParse(thisLine, out theIP))
{
result.Add(theIP);
}
}
}
return result;
}
private List<string> LoadBlockHWID(FileInfo fi)
{
List<string> result = new List<string>();
using (StreamReader sr = fi.OpenText())
{
while (!sr.EndOfStream)
{
result.Add(sr.ReadLine().Trim().ToUpperInvariant());
}
}
return result;
}