Resmini verdiğim form ekranını çiziyoruz.Form elemanlarına bakacak olursak;
3 adet label , 2 adet textbox ve bir adet butondan meydana geliyor.Üst kısımdaki resmi kendim ekledim.Eğer sizde isterseniz.ToolBox dan PictureBox elemanını form üzerine sürekleyip aşağıdaki adımları takip ederek SansürlüSansürlüSansürlüSansürlüSansürlüSansürlütan kendinizde insiyatifinize göre image ekleyebilirsiniz..
Şimdi öncelikle backgroundWorker ekliyoruz..
Formumuzun Form1.cs dosyamızın içeriği şu şekilde;




Kod:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace msnconnect
{
public partial class Form1 : Form
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Client = new MsnIstemci (textBox1.Text, textBox2.Text);
textBox1.ReadOnly = true;
textBox2.ReadOnly = true;
label3.Show();
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Client.Connect();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Bağlantı talebinden bulunalım şimdi..
Bunun için öncelikle msnConnectRequest.cs ismiyle bir cs sayfası açıyoruz..
Kod:
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Xml;
using System.Net;
using System.Web;
using System.Web.Services.Protocols;
namespace msnconnect
{
class msnconnectRequest
{
public msnconnectRequest (string XmlCode, string Host)
{
ServerRequest = (HttpWebRequest) WebRequest.Create(Host);
ServerRequest.Method = "POST";
Strem stream = ServerRequest.GetRequestStream();
stream.Write(Encoding.UTF8.GetBytes(XmlCode), 0, Encoding.UTF8.GetBytes(XmlCode) .Lenght);
stream.Close();
}
//Sunucudan yanıt alınması
public XmlDocument GetResponse()
//Sunucudan yanıt alınması
HtppWebResponse ServerResponse = (HttpWebResponse) ServerRequest.GetResponse();
// Gelen veri akışını alalım..
Stream stream = ServerResponse.GetResponseStream();
//Sunucudan gelen yanıtları kaydetmek için bir Xml belgesi oluşturmamız ve bu xml belgesinin
//içerisine yazmamız gerekiyor..
XmlDocument xml = new XmlDocument();
xml.Load(stream);
//Gelen veri akışını durduralım..Yanıtları kaydettik..
//Bunun için stream özelliğini close ile kapatıcaz..
stream.Close();
//Server dan gelen alımıda kapatalım..
ServerResponse.Close();
return xml;
}
private HttpWebRequest ServerRequest;
}
}
Bağlantı talebinde bulunduk gelen akışı kaydettik..Şimdi ise istemci kısmımıza geliyoruz..
Bunun için MSNIstemci.cs ismi ile bir cs sayfası oluşturuyoruz..
Öncelikle yine isim alanlarımızı ekleyerek başlıyoruz..
Kod:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Windows.Forms;
namespace msnconnect
{
class MSNIstemci
{
public MSNIstemci(string account, string password)
{
// İşlem
TrID = 0;
Account = account;
Password = password;
}
public void Connect()
{
// bildiriyi yapmak için dispatch server özelliğini kullanıyoruz..
string host = GetNSHostFromDispatchServer();
// NS girişi
LogIntoNS(host.Split(':')[0], Convert.ToInt32(host.Split(':')[1]));
}
// dispatch server'dan NS host almamız gerekiyor..
private string GetNSHostFromDispatchServer()
{
//İşlemler için Dispatch server'dan bir tcp bağlantısı almamız gerkeiyor
Connection = new TcpConnection("messenger.hotmail.com", 1863);
// Protokol ile ilgili bilgi alıyoruz..
string recvbuf = SendReceiveMSNCommand("VER", "MSNP15", "CVR0");
// OS hakkında bilgi gönderiyoruz..
recvbuf = SendReceiveMSNCommand("CVR", "0x0407", "win 6.0", "i386", "MSNMSGR", "8.5", "MSMSGS", Account);
// Kullanıcı istekleri parametrelerini gönderiyoruz..
(single sign-on) has been introduced
recvbuf = SendReceiveMSNCommand("USR", "SSO", "I", Account);
string host = recvbuf.Split(' ')[3];
//Bağlantıyı kapatıyoruz..
Connection.Close();
return host;
}
// bildirim için sunucuya giriş
private void LogIntoNS(string ip, int port)
{
// Yeni bir bağlantı oluşturuyoruz..
Connection = new TcpConnection(ip, port);
// DS prosedürü..
SendReceiveMSNCommand("VER", "MSNP15", "CVR0");
SendReceiveMSNCommand("CVR", "0x0407", "win 6.0", "i386", "MSNMSGR", "8.5", "MSMSGS", Account);
SendMSNCommand("USR","SSO","I",Account);
// GCF yanıtı almamız gerekiyor..
Connection.ReadLine();
string recvbuf = Connection.ReadLine();
// Cevap için kullanıcı komutunun yerini bildiriyoruz..
int indexOfUSR = recvbuf.IndexOf("USR");
recvbuf = recvbuf.Remove(0, indexOfUSR);
// policy kaydedelim :)
string policy = recvbuf.Split(' ')[4];
// Şimdilik kaydedelim..
string nonce = recvbuf.Split(' ')[5];
string ticket = GetTicket(policy, nonce);
// Ve son olarak giriş için kullanıcı yani USR ismi ile yarattığımız komut dizisini //gönderiyoruz..
SendMSNCommand("USR","SSO","S",ticket);
recvbuf = Connection.ReadLine();
// Sunucunun bize verecepği yanıtı kontrol edelim..İstersek burada mesaj kutus ile bildirim yaptırabiliriz..
if (recvbuf.Split(' ')[2].Equals("OK"))
{
MessageBox.Show("Yep! Msn hesabınla bağlandın..İleri düzeye taşımak senin elinde :-)");
}
}
private string GetTicket(string policy, string nonce)
{
// SOAP istekleri için xml dosyası oluşturalım..
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xml += "<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\"><Header>";
xml += "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">";
xml += "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>";
xml += "<ps:BinaryVersion>4</ps:BinaryVersion>";
xml += "<ps:UIVersion>1</ps:UIVersion>";
xml += "<ps:Cookies></ps:Cookies>";
xml += "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>";
xml += "</ps:AuthInfo>";
xml += "<wsse:Security><wsse:UsernameToken Id=\"user\">";
xml += "<wsse:Username>" + Account + "</wsse:Username>";
xml += "<wsse:Password>" + Password + "</wsse:Password>";
xml += "</wsse:UsernameToken></wsse:Security></Header><Body>";
xml += "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">";
xml += "<wst:RequestSecurityToken Id=\"RST0\">";
xml += "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>";
xml += "<wsp:AppliesTo><wsa:EndpointReference><wsa:Address>http://Passport.NET/tb";
xml += "</wsa:Address></wsa:EndpointReference></wsp:AppliesTo></wst:RequestSecurityToken>";
xml += "<wst:RequestSecurityToken Id=\"RST1\">";
xml += "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType><wsp:AppliesTo><wsa:EndpointReference>";
xml += "<wsa:Address>messengerclear.live.com</wsa:Address></wsa:EndpointReference></wsp:AppliesTo>";
xml += "<wsse:PolicyReference URI=\"" + policy + "\"></wsse:PolicyReference></wst:RequestSecurityToken>";
xml += "<wst:RequestSecurityToken Id=\"RST2\">";
xml += "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>";
xml += "<wsp:AppliesTo>";
xml += "<wsa:EndpointReference>";
xml += "<wsa:Address>contacts.msn.com</wsa:Address>";
xml += "</wsa:EndpointReference>";
xml += "</wsp:AppliesTo>";
xml += "<wsse:PolicyReference URI=\"MBI\">";
xml += "</wsse:PolicyReference>";
xml += "</wst:RequestSecurityToken>";
xml += "</ps:RequestMultipleSecurityTokens></Body></Envelope>";
// Xml ile yeni bir SOAP isteği oluşturuyoruz..
msnconnectRequest SOAPRequest = new msnconnectRequest(xml, "https://login.live.com/RST.srf");
// Xml ile temsili olan sunucudan yanıt alıyoruz..
XmlDocument XmlDoc = SOAPRequest.GetResponse();
string secret = XmlDoc.InnerXml.Remove(0, XmlDoc.InnerXml.IndexOf("<wst:BinarySecret>") + "<wst:BinarySecret>".Length);
secret = secret.Remove(0, secret.IndexOf("<wst:BinarySecret>") + "<wst:BinarySecret>".Length);
secret = secret.Remove(secret.IndexOf("</wst:BinarySecret>"));
string ticket = XmlDoc.InnerXml.Remove(0, XmlDoc.InnerXml.IndexOf("<wsse:BinarySecurityToken Id=\"Compact1\">") + "<wsse:BinarySecurityToken Id=\"PPToken1\">".Length);
ticket = ticket.Remove(ticket.IndexOf("</wsse:BinarySecurityToken>"));
ticket = ticket.Replace("&", "&");
ticket SSOTicket = new ticket(secret, nonce);
//Final ticket olayı :)
return ticket + " " + SSOTicket.value;
}
// NS 'e komut yollama işlemi..
public void SendMSNCommand(string CommandType, params string[] Parameters)
{
string Command = CommandType + " " + Convert.ToString(TrID) + " ";
for (int i = 0; i < Parameters.Length; ++i)
{
Command += Parameters[i];
if (i != Parameters.Length - 1)
{
Command += " ";
}
}
Connection.WriteLine(Command);
TrID++;
}
//Tcp bağlantısı üzerinden msn komutları vermek..Sanırım bitiyor:.
public string SendReceiveMSNCommand(string CommandType, params string[] Parameters)
{
SendMSNCommand(CommandType, Parameters);
return Connection.ReadLine();
}
public TcpConnection Connection;
public int TrID;
private string Account;
private string Password;
}
}
Evet aslında en zahmetli kısımı geride bıraktık..Bundan sonrası işimiz daha kolay olacaktır..
Program.cs ismi ile yeni bir cs dosyası oluşturuyoruz..
Kod:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace msnconnect
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetComparatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
İsterseniz şimdi Tcp bağlantısını nasıl yapacağımıza bakalım..Nitekim soketlerin olduğu yerdeyiz diyebiliriz..
TCPBaglanti.cs ismi ile yeni bir cs dosyası oluşturuyoruz..
İsim uzaylarımızı ekleyerek başlayalım..
Kod:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
namespace msnconnect
{
class TcpConnection
{
public TcpConnection()
{
}
public TcpConnection(strin host, int port)
{
//Yeni bir tcp soketi yaratalım..
Socket = new TcpClient(host, port);
//Stream olayına tekrar dönüyoruz..Soketin ağ akışını stream ile get ediyoruz..
Stream = Socket.GetStream();
Reader = new StreamReader(Stream,Encoding.ASCII);
Writer = new StreamWriter(Stream,Encoding.ASCII);
Writer.AutoFlush = true;
open = true;
}
public vodi WriteLine(message);
}
public void Write(string message)
{
Writer.Write(message);
}
public string ReadLine()
{
return Reader.ReadLine();
}
public string Read(int bufsize)
{
strin o;
chat [] buf = new char[bufsize];
Reader.Read(buf, 0, bufsize);
o = new strinng (buf);
return o;
}
// Bağlantıyı kapatma..
public void Close()
{
open = false;
//Herhangi bir stream'ı okumuyoruz..
Stream.ReadTimeout = 1;
if ( Socket != null)
{
Socket.Close();
Socket = null;
}
if(Stream != null)
{
Stream.Close();
Socket = null;
}
if(Reader != null)
{
Reader.Close();
Reader = null;
}
if(Writer != null)
{
Writer.Close();
Writer = null;
}
private TcpClient Socket;
private NetworkStream Stream;
private StreamReader Reader;
public StreamWriter Writer;
// Bağlantı açık
public bool open;
}
}
Evet son kısımda gerek istemci gerek tcp bağlantısı sırasında veya request olayında kullandığımız ticket sınıfımıza bakalım..
Kod:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace SSOWithMSNP15
{
class ticket
{
public ticket(string key, string nonce)
{
// İlk olarak 4 byte değerinde bir yapı oluşturmamız gerekiyor..
Beginning = new byte[28];
//StructHeaderSize = 28
Beginning[0] = 0x1c;
Beginning[1] = 0x00;
Beginning[2] = 0x00;
Beginning[3] = 0x00;
//CryptMode = 1
Beginning[4] = 0x01;
Beginning[5] = 0x00;
Beginning[6] = 0x00;
Beginning[7] = 0x00;
//CipherType = 0x6603
Beginning[8] = 0x03;
Beginning[9] = 0x66;
Beginning[10] = 0x00;
Beginning[11] = 0x00;
//HashType = 0x8004
Beginning[12] = 0x04;
Beginning[13] = (byte)0x80;
Beginning[14] = 0x00;
Beginning[15] = 0x00;
//IV length = 8
Beginning[16] = 0x08;
Beginning[17] = 0x00;
Beginning[18] = 0x00;
Beginning[19] = 0x00;
//hash length = 20
Beginning[20] = 0x14;
Beginning[21] = 0x00;
Beginning[22] = 0x00;
Beginning[23] = 0x00;
//cipher length = 72
Beginning[24] = 0x48;
Beginning[25] = 0x00;
Beginning[26] = 0x00;
Beginning[27] = 0x00;
// base64 ile çözümlenmiş bir ilk giriş anahtarı yaratıyoruz
byte[] key1 = Convert.FromBase64String(key);
// Özel bir algoritma ile ikinci bir anahtar elde edelim..
(see function DeriveKey())
string key2 = DeriveKey(key1, "WS-SecureConversationSESSION KEY HASH");
// ...ve üçüncü aynı algoritma ile key
string key3 = DeriveKey(key1, "WS-SecureConversationSESSION KEY ENCRYPTION");
// Toparlarsak sha1 kullanacağımızı kestirmiş oluyoruz..yani 3 farklı algoritmayı sha1 de topladık.
HMACSHA1 sha = new HMACSHA1();
sha.Key = Encoding.Default.GetBytes(key2);
byte[] hash = sha.ComputeHash(Encoding.Default.GetBytes(nonce));
;-))
byte[] iv = { 0, 1, 2, 3, 4, 5, 6, 7 };
TripleDESCryptoServiceProvider DES3 = new TripleDESCryptoServiceProvider();
DES3.Key = Encoding.Default.GetBytes(key3);
DES3.Mode = CipherMode.CBC;
DES3.IV = iv;
ICryptoTransform Encryptor = DES3.CreateEncryptor();
byte[] RestOfNonce = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 };
byte[] output = new byte[72];
Encryptor.TransformBlock(Combine(Encoding.Default.GetBytes(nonce), RestOfNonce), 0, Combine(Encoding.Default.GetBytes(nonce), RestOfNonce).Length, output, 0);
string struc = Encoding.Default.GetString(Beginning) + Encoding.Default.GetString(iv) + Encoding.Default.GetString(hash) + Encoding.Default.GetString(output);
value = Convert.ToBase64String(Encoding.Default.GetBytes(struc));
}
private byte[] Combine(byte[] a, byte[] b)
{
byte[] c = new byte[a.Length + b.Length];
System.Buffer.BlockCopy(a, 0, c, 0, a.Length);
System.Buffer.BlockCopy(b, 0, c, a.Length, b.Length);
return c;
}
private string DeriveKey(byte[] key, string magic)
{
HMACSHA1 sha = new HMACSHA1();
sha.Key = key;
byte[] Magic = Encoding.Default.GetBytes(magic);
byte[] hash1 = sha.ComputeHash(Magic);
byte[] hash2 = sha.ComputeHash(Combine(hash1, Magic));
byte[] hash3 = sha.ComputeHash(hash1);
byte[] hash4 = sha.ComputeHash(Combine(hash3, Magic));
byte[] o = { hash4[0], hash4[1], hash4[2], hash4[3] };
return Encoding.Default.GetString(Combine(hash2, o));
}
public string value;
private byte[] Beginning;
}
}
ticket olayına fazla değinemedim.Çünkü değinirsek biraz kafa karıştırıcı olabilir.Bunu bir bütün olarak ele alalım..
Bir sunucuya bağlandık istekler gönderip cevaplar aldık..Bütün bunları yaparken ticket olayı üzerinden yaptık.
Dikkat ederseniz biraz eğer farklı algoritmalarla oluşturulmuş bir şifreleme tekniği var aslında..Biz bağlantılarda
ticket ı çekerek verileri şifreleme algoritmaları üzerinden güvenli bir şekilde gerçekleştirdik.Bunu bilmeniz yeterlidir.
Yine genel olarak yaptıklarımıza bakarsak eğer;
-Form tasarladık..
-Form elemanlarının özelliklerine değerler atayarak kodlar yazdık..
-Kendimize bir istemci oluşturduk.Şayet mevcut bir hosta bağlanmak için istemci oluşturmamız gerekirdi..
-İstemciyi tcp sistematiği üzerinden soketler kullanarak bağlanmasını sağladık..
-Gelen cevapları xml kullanarak kayıt altına aldık..gereken yerlerde xml dosyasından çektik..
-Bağlantı ve cevap bildirileri sırasında ticket ismi ile oluşturduğumuz şifreleme dosyasını dahil ettik..
Bu sayede şifreli bağlantı veri akışını sağladık..
Geliştirilebilir bir uygulama olduğu kanaatindeyim.Genel tcp ağları ve soketler üzerinden client yapısı olarak
değerlendirebiliriz..Kolay gelsin arkadaşlar..
Oguzz | megaturks.net
ufak not: diab kardeşime hediyem..genele hitap ancak onun için oturup yazdım.sıkma canını..
Bookmarks