Created
December 26, 2015 16:33
-
-
Save AlexeySachkov/041cfa2252689b803833 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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