Skip to content

Instantly share code, notes, and snippets.

@AlexeySachkov
Created December 26, 2015 16:33
Show Gist options
  • Save AlexeySachkov/041cfa2252689b803833 to your computer and use it in GitHub Desktop.
Save AlexeySachkov/041cfa2252689b803833 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
using System.Net.Sockets;
using Renci.SshNet.Common;
using System.Globalization;
using Renci.SshNet.Security;
namespace test_application
{
class Program
{
internal const int SSH_MSG_KEXINIT = 20;
internal const int SSH_MSG_KEXDH_INIT = 30;
internal const int SSH_MSG_KEXDH_REPLY = 31;
internal const int SSH_MSG_NEWKEYS = 21;
private const string SecondOkleyGroup = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
public static void Main(string[] args)
{
Main2(args);
}
public static void Main1(string[] args)
{
// Setup Credentials and Server Information
ConnectionInfo ConnNfo = new ConnectionInfo("github.com", 22, "AlexeySachkov",
new AuthenticationMethod[]{
// Pasword based Authentication
new PasswordAuthenticationMethod("AlexeySachkov",""),
}
);
using (var sshclient = new SshClient(ConnNfo))
{
sshclient.Connect();
using (var cmd = sshclient.CreateCommand("ls -l"))
{
cmd.Execute();
Console.WriteLine("Command>" + cmd.CommandText);
Console.WriteLine("Return Value = {0}", cmd.ExitStatus);
}
sshclient.Disconnect();
}
}
public static void Main2(string[] args)
{
Console.OutputEncoding = Encoding.Unicode;
Encoding ascii = Encoding.ASCII;
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Connect(System.Net.IPAddress.Parse("192.30.252.131"), System.Convert.ToInt16(22)); // 77.222.40.18
if (!socket.Connected)
{
throw new Exception("Unable to connect to host!");
}
Console.WriteLine("socket connected;");
string clientVersionString = "SSH-2.0-AlexeySachkov.SshClient.0.0.1\r\n";
byte[] serverVersion = new byte[256];
byte[] clientVersion = ascii.GetBytes(clientVersionString);
socket.Send(clientVersion);
Console.WriteLine("sent: ");
for (int i = 0; i < clientVersion.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, clientVersion[i], (char)clientVersion[i]));
}
Console.WriteLine("\n");
Console.WriteLine("client version string sent;");
socket.Receive(serverVersion);
Console.WriteLine("server version string received;");
for (int i = 0; i < serverVersion.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, serverVersion[i], (char)serverVersion[i]));
}
Console.WriteLine("\n");
byte[] serverKex = new byte[1024];
socket.Receive(serverKex);
Console.WriteLine("server kex received;");
for (int i = 0; i < serverKex.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, serverKex[i], (char)serverKex[i]));
}
Console.WriteLine("\n");
Reader serverKexReader = new Reader(serverKex);
UInt32 serverKexPacketLength = serverKexReader.readUInt32();
Byte serverKexPaddingLength = serverKexReader.readByte();
byte[] serverKexPayload = serverKexReader.readBytes((int)serverKexPacketLength);
string[] my_kex_algorithms = { "diffie-hellman-group14-sha1", "diffie-hellman-group1-sha1" };
string[] my_server_host_key_algorithms = { "ssh-dss", "ssh-rsa" };
string[] my_encryption_algorithms_client_to_server = { "aes128-cbc", "3des-cbc", "none" };
string[] my_encryption_algorithms_server_to_client = { "aes128-cbc", "3des-cbc", "none" };
string[] my_mac_algorithms_client_to_server = { "hmac-sha1", "none" };
string[] my_mac_algorithms_server_to_client = { "hmac-sha1", "none" };
string[] my_compression_algorithms_client_to_server = { "none" };
string[] my_compression_algorithms_server_to_client = { "none" };
string[] my_languages_client_to_server = { "" };
string[] my_languages_server_to_client = { "" };
Random random = new Random();
Writer writer = new Writer();
writer.writeByte(SSH_MSG_KEXINIT);
for (int i = 0; i < 16; ++i)
{
writer.writeByte((Byte)random.Next(32, 128));
}
writer.writeNameList(my_kex_algorithms);
writer.writeNameList(my_server_host_key_algorithms);
writer.writeNameList(my_encryption_algorithms_client_to_server);
writer.writeNameList(my_encryption_algorithms_server_to_client);
writer.writeNameList(my_mac_algorithms_client_to_server);
writer.writeNameList(my_mac_algorithms_server_to_client);
writer.writeNameList(my_compression_algorithms_client_to_server);
writer.writeNameList(my_compression_algorithms_server_to_client);
writer.writeNameList(my_languages_client_to_server);
writer.writeNameList(my_languages_server_to_client);
writer.writeBoolean(false);
writer.writeUint32(0);
Byte[] msg = writer.getData();
int pl = writer.getLength() + 5;
byte pm = 8;
int pal = (byte)((-pl) & (pm - 1));
if (pal < pm)
{
pal += pm;
}
Writer binaryProtocolMessage = new Writer();
binaryProtocolMessage.writeUint32((UInt32)msg.Length + 1u + (uint)pal);
binaryProtocolMessage.writeByte((byte)pal);
binaryProtocolMessage.writeBytes(msg);
for (int i = 0; i < pal; ++i)
{
binaryProtocolMessage.writeByte((Byte)random.Next(32, 128));
}
var bdata = binaryProtocolMessage.getData();
socket.Send(bdata);
Console.WriteLine("sent: ");
for (int i = 0; i < bdata.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, bdata[i], (char)bdata[i]));
}
Console.WriteLine("\n");
serverKexReader.reset();
serverKexReader.readUInt32();
serverKexReader.readByte();
int message_code = serverKexReader.readByte(); // expect SSH_MSG_KEXINIT
serverKexReader.readBytes(16); // skip cookie
if (message_code != SSH_MSG_KEXINIT)
{
throw new Exception("Unexpected message code!");
}
Console.WriteLine("server kexinit message received;");
int kex_algorithm_index = _select(my_kex_algorithms, serverKexReader.readNameList());
int server_host_key_algorithm_index = _select(my_server_host_key_algorithms, serverKexReader.readNameList());
int encryption_algorithm_client_to_server_index = _select(my_encryption_algorithms_client_to_server, serverKexReader.readNameList());
int encryption_algorithm_server_to_client_index = _select(my_encryption_algorithms_server_to_client, serverKexReader.readNameList());
int mac_algorithm_server_to_client__index = _select(my_mac_algorithms_server_to_client, serverKexReader.readNameList());
int mac_algorithm_client_to_server_index = _select(my_mac_algorithms_client_to_server, serverKexReader.readNameList());
int compression_algorithm_server_to_client_index = _select(my_compression_algorithms_server_to_client, serverKexReader.readNameList());
int compression_algorithm_client_to_server_index = _select(my_compression_algorithms_client_to_server, serverKexReader.readNameList());
int language_client_to_server_index = _select(my_languages_client_to_server, serverKexReader.readNameList());
int language_server_to_client_index = _select(my_languages_server_to_client, serverKexReader.readNameList());
if (kex_algorithm_index < 0 ||
server_host_key_algorithm_index < 0 ||
encryption_algorithm_client_to_server_index < 0 ||
encryption_algorithm_server_to_client_index < 0 ||
mac_algorithm_client_to_server_index < 0 ||
mac_algorithm_server_to_client__index < 0)
{
throw new Exception("Algorithms negotiation failed!");
}
Console.WriteLine(my_kex_algorithms[kex_algorithm_index]);
Console.WriteLine(my_server_host_key_algorithms[server_host_key_algorithm_index]);
Console.WriteLine(my_encryption_algorithms_client_to_server[encryption_algorithm_client_to_server_index]);
Console.WriteLine(my_encryption_algorithms_server_to_client[encryption_algorithm_server_to_client_index]);
Console.WriteLine(my_mac_algorithms_client_to_server[compression_algorithm_client_to_server_index]);
Console.WriteLine(my_mac_algorithms_server_to_client[compression_algorithm_server_to_client_index]);
Console.WriteLine("start key exchange;");
if (kex_algorithm_index != 1)
{
throw new Exception("Not implemented yet!");
}
BigInteger p;
BigInteger.TryParse(SecondOkleyGroup, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out p);
BigInteger g = new BigInteger(new byte[] { 2 });
BigInteger x;
BigInteger e;
Console.WriteLine(p.BitLength);
Console.WriteLine(g);
Console.WriteLine(p);
do
{
x = BigInteger.Random(p.BitLength);
Console.WriteLine(x);
e = BigInteger.ModPow(g, x, p);
Console.WriteLine(e);
} while (e < 1 || e > (p - 1));
Console.WriteLine(e.ToString());
Writer key_exchange_dhinit_message = new Writer();
key_exchange_dhinit_message.writeByte(SSH_MSG_KEXDH_INIT);
key_exchange_dhinit_message.writeBigInteger(e);
pl = key_exchange_dhinit_message.getLength() + 5;
pm = 8;
pal = (byte)((-pl) & (pm - 1));
if (pal < pm)
{
pal += pm;
}
binaryProtocolMessage = new Writer();
binaryProtocolMessage.writeUint32((uint)key_exchange_dhinit_message.getLength() + 1u + (uint)pal);
binaryProtocolMessage.writeByte((byte)pal);
binaryProtocolMessage.writeBytes(key_exchange_dhinit_message.getData());
for (int i = 0; i < pal; ++i)
{
binaryProtocolMessage.writeByte((Byte)random.Next(32, 128));
}
socket.Send(binaryProtocolMessage.getData());
byte[] tttt = binaryProtocolMessage.getData();
Console.WriteLine("Key exchange dhinit message: ");
for (int i = 0; i < tttt.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, tttt[i], (char)tttt[i]));
}
Console.WriteLine("\n");
Console.WriteLine("key_exchange_dhinit_message sent;");
byte[] serverKexDhReply = new byte[1024];
socket.Receive(serverKexDhReply);
Console.WriteLine("serverKexDhReply: ");
for (int i = 0; i < serverKexDhReply.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, serverKexDhReply[i], (char)serverKexDhReply[i]));
}
Console.WriteLine("\n");
Reader key_exchange_dhreply_message = new Reader(serverKexDhReply, 5);
message_code = key_exchange_dhreply_message.readByte();
Console.WriteLine(message_code);
if (message_code != SSH_MSG_KEXDH_REPLY)
{
throw new Exception("Key exchange failed!");
}
Console.WriteLine("key_exchange_dhreply_message received;");
string K_S = key_exchange_dhreply_message.readString();
BigInteger f = key_exchange_dhreply_message.readBigInteger();
string S = key_exchange_dhreply_message.readString();
BigInteger K = BigInteger.ModPow(f, x, p);
string H = "";
Writer new_keys_message = new Writer();
new_keys_message.writeByte(SSH_MSG_NEWKEYS);
pl = new_keys_message.getLength() + 5;
pm = 8;
pal = (byte)((-pl) & (pm - 1));
if (pal < pm)
{
pal += pm;
}
binaryProtocolMessage = new Writer();
binaryProtocolMessage.writeUint32((uint)new_keys_message.getLength() + 1u + (uint)pal);
binaryProtocolMessage.writeByte((byte)pal);
binaryProtocolMessage.writeBytes(new_keys_message.getData());
for (int i = 0; i < pal; ++i)
{
binaryProtocolMessage.writeByte((Byte)random.Next(32, 128));
}
socket.Send(new_keys_message.getData());
Console.WriteLine("SSH_MSG_NEWKEYS sent;");
byte[] r = new byte[1024];
socket.Receive(r);
Console.WriteLine("r: ");
for (int i = 0; i < r.Length; ++i)
{
Console.WriteLine(String.Format("data[{0}] = {1} ({2})", i, r[i], (char)r[i]));
}
Console.WriteLine("\n");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
private static int _select(string[] a, string[] b)
{
int id = -1;
if (b != null && a != null)
{
for (int i = 0; i < a.Length; ++i)
{
for (int j = 0; j < b.Length; ++j)
{
if (a[i] == b[j])
{
id = i;
break;
}
}
}
}
return id;
}
}
class Writer
{
private Byte[] data;
public Byte[] getData()
{
Byte[] tmpArray = new Byte[this.length];
Array.Copy(this.data, tmpArray, this.length);
return tmpArray;
}
private Int32 length;
public Int32 getLength()
{
return this.length;
}
private Int32 capacity;
public Writer()
{
this.data = new Byte[100];
this.capacity = 100;
this.length = 0;
}
private void checkExpand(int additionalLength)
{
if (this.length + additionalLength >= this.capacity)
{
this.expand(additionalLength);
}
}
private void expand(int min)
{
int newCapacity;
if ((this.capacity - this.length + min) < 2 * this.capacity - this.length)
{
newCapacity = 2 * this.capacity;
}
else
{
newCapacity = this.capacity + 2 * min;
}
Byte[] tmpArray = new Byte[newCapacity];
Array.Copy(this.data, tmpArray, this.length);
this.capacity = newCapacity;
this.data = tmpArray;
}
public void writeByte(Byte value)
{
this.checkExpand(1);
this.data[this.length++] = value;
}
public void writeUint32(UInt32 value)
{
this.checkExpand(4);
this.data[this.length++] = (Byte)(value >> 24);
this.data[this.length++] = (Byte)(value >> 16);
this.data[this.length++] = (Byte)(value >> 8);
this.data[this.length++] = (Byte)(value);
}
public void writeInt32(Int32 value)
{
this.checkExpand(4);
this.data[this.length++] = (Byte)(value >> 24);
this.data[this.length++] = (Byte)(value >> 16);
this.data[this.length++] = (Byte)(value >> 8);
this.data[this.length++] = (Byte)(value);
}
public void writeBytes(Byte[] values)
{
this.checkExpand(values.Length);
Array.Copy(values, 0, this.data, this.length, values.Length);
this.length += values.Length;
}
public void writeString(string value)
{
this.writeUint32((UInt32)value.Length);
this.writeBytes(Encoding.ASCII.GetBytes(value));
}
public void writeNameList(string[] values)
{
if (values != null)
{
string tmpString = string.Join(",", values);
this.writeUint32((UInt32)tmpString.Length);
this.writeBytes(Encoding.ASCII.GetBytes(tmpString));
}
else
{
this.writeUint32(0);
}
}
public void writeBoolean(Boolean value)
{
if (value)
{
this.writeByte(1);
}
else
{
this.writeByte(0);
}
}
public void writeBigInteger(BigInteger value)
{
var bytes = value.ToByteArray().Reverse();
this.writeUint32((UInt32) bytes.ToList().Count);
this.writeBytes(bytes.ToArray());
}
public void writeMPInt(Byte[] mpint)
{
int i = mpint.Length;
if ((mpint[0] & 0x80) != 0)
{
++i;
this.writeInt32(i);
this.writeByte(0);
}
else
{
this.writeInt32(i);
}
this.writeBytes(mpint);
}
}
class Reader
{
private Byte[] data;
private Int32 pos;
public Reader(Byte[] _data)
{
if (_data == null)
{
throw new System.Exception("Input array cannot be null reference!");
}
this.data = _data;
this.pos = 0;
}
public Reader(Byte[] _data, int offset)
: this(_data)
{
if (offset < this.data.Length)
{
this.pos = offset;
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public void reset()
{
this.pos = 0;
}
public Boolean eof()
{
return (this.pos == this.data.Length);
}
public Byte readByte()
{
if (!this.eof())
{
return this.data[this.pos++];
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public Byte[] readBytes(int length)
{
if (length <= 0)
{
throw new System.Exception("Zero length array not allowed!");
}
else if (!this.eof() && this.pos + length <= this.data.Length)
{
Byte[] res = new Byte[length];
Array.Copy(this.data, this.pos, res, 0, length);
this.pos += length;
return res;
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public UInt32 readUInt32()
{
if (!this.eof() && this.pos + 4 < this.data.Length)
{
UInt32 res = (UInt32)(this.data[this.pos] << 24 | this.data[this.pos + 1] << 16 | this.data[this.pos + 2] << 8 | this.data[this.pos + 3]);
this.pos += 4;
return res;
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public Int32 readInt32()
{
if (!this.eof() && this.pos + 4 < this.data.Length)
{
Int32 res = (Int32)(this.data[this.pos] << 24 | this.data[this.pos + 1] << 16 | this.data[this.pos + 2] << 8 | this.data[this.pos + 3]);
this.pos += 4;
return res;
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public string readString()
{
if (!this.eof())
{
UInt32 length = this.readUInt32();
if (length != 0)
{
Byte[] tmpArray = new Byte[length];
Array.Copy(this.data, this.pos, tmpArray, 0, length);
string res = Encoding.ASCII.GetString(tmpArray);
this.pos += (Int32)length;
return res;
}
else
{
return "";
}
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public string[] readNameList()
{
if (!this.eof())
{
UInt32 length = this.readUInt32();
if (length != 0)
{
Byte[] tmpArray = new Byte[length];
Array.Copy(this.data, this.pos, tmpArray, 0, length);
string tmpString = Encoding.ASCII.GetString(tmpArray);
this.pos += (Int32)length;
return tmpString.Split(',');
}
else
{
return null;
}
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public Boolean readBoolean()
{
if (!this.eof())
{
Byte res = this.readByte();
return (res != 0);
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
public BigInteger readBigInteger()
{
var length = this.readUInt32();
var data = this.readBytes((int)length);
return new BigInteger(data.Reverse().ToArray());
}
public Byte[] readMPInt() // TODO: refactor
{
Int32 i = this.readInt32();
byte[] res = new byte[i];
Array.Copy(this.data, this.pos, res, 0, i);
this.pos += i;
return res;
}
public void skipBytes(int n)
{
if (!this.eof() && this.pos + n < this.data.Length)
{
this.pos += n;
}
else
{
throw new System.Exception("End of buffer reached!");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment