Lately, i’ve been tired of hexing others client. Too much limitation on that (though I LOVE the challenge from that). It’ll be worst damn difficult if the program used EXE Compressor(T_T couldnt have my hand on those resource pointer). Afterall, hexing is just to crack the software, not to fully modified the software.. Then, bye bye UltraEdit..
Thanks to the “limitation”, I’m beginning to code my own chat client. Why do i have to create a new one when there are lot of free yahoo chat client out there?? The answer is simple, satisfaction.
Introducing, the new birth of chat client (not completed yet though…). For me, ability of ID polygamy in yahoo chat client is important. Therefore, this client I’ve developed able to do that in an organized way (not with lot of instances!!!).
Here is what I’ve done so far…




Multiple chat view with YConnect!
So, what’s the fuss!??
Well, after all, i have to say, program the chat client isn’t really an easy task. Before I could comment on others chat client, “lack of this, lack of that!“, “doesn’t feel like using ym“,”client is too bulky! not user friendly!“, “client is just a social tool, not a hacker’s tool!“…for now, I’ll juz keep silence (hehehe)..
Chat client I love???
Actually, I like YSupra than others. First, the user interface is simple and up-to-date (not like those Yahelite, Yazak, I mean those bulky win2000 style, uweek). Second, because i can log on with it (i’m using sialcom broadband, got some problem with other client. Up to now, i have only 2 yahoo chat client(except my own YConnect) able to logged in from this damned connection. It’s Yahoo Messenger Local and Y!Supra.. After developing this client, I realized the cause of that problem.
1) When logging in, client will get token/crumb and exchange packet to login.yahoo.com which might not be resolve by sialcom broadband.
Resolution : Either both client connect directly using ip, and set SSL error policy to always true (since different hostname revoke the certificate.
2) yahoo 1236 error?! : In my case it is caused by the use of HTTP1.1 when sending packet. I’ve used this, and after few hours checking up the code, I’ve change the protocol to HTTP1.0 and voila, I’m able to logged on. actually, this code define somewhat of user account lock or of the sort. I’m not sure actually, but adding the case for this isn’t that painful ^_^
So, I’ve ended up with this (I’m using System.Net.HttpWebRequest here)
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
YNet1 = HttpWebRequest.Create("https://" & HostName & "/config/pwtoken_get?src=ymsgr&ts=&login=" & YahooID & "&passwd=" & Password & "&chal=" & YmChallenge)
YNet1.ProtocolVersion = HttpVersion.Version10 ' <- use Version10
YNet1.AllowAutoRedirect = True
YMSG16??? What’s new? What’s not so new?
YMSG16 is the protocol used in YM9 and most of other client out there using it (for NO5, hmmm, i have no comment on that). It’s damn difficult to log in but the packet defined the structure of the data in which i think is better. The example shown here is in VB.Net(2008) syntax. However, i could rewrite the code in VB6, C# and Java(not confident how to handle certificate though, but I gez I could try, hehe..)
Logging in to YMSG16:
This is the class i used to log in (THIS IS ORIGINAL, NOT RIPPED OFF FROM OTHERS, CAUSE I HATE WHEN PEOPLE ACCUSE ME FOR THAT!)
Option Strict Off
Option Explicit On
Imports System.Text
Imports System.Security.Cryptography
Imports System.Runtime.InteropServices
Imports System.Net
Imports System.IO
Imports System.Security.Permissions
Imports System.Net.Security
Imports System.Security.Cryptography.X509Certificates
Friend Class Login
Public Delegate Function ServerCertificateValidationCallback( _
ByVal sender As Object, _
ByVal certificate As X509Certificate, _
ByVal chain As X509Chain, _
ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
Public Function ValidateServerCertificate(ByVal sender As Object, _
ByVal cert As X509Certificate, _
ByVal chain As X509Chain, _
ByVal ssl As SslPolicyErrors) As Boolean
Return True
End Function
Public oEncoderAnsi As System.Text.Encoding
Public Event InvalidLogin()
Public Event RecvToken(ByVal Y_CookiePart As String, ByVal T_CookiePart As String, ByVal LoginHash As String)
Public Event SckError(ByVal ErrorNum As Integer, ByVal ErrorDesc As String)
Private WithEvents YNet1 As System.Net.HttpWebRequest
Private WithEvents YNet2 As System.Net.HttpWebRequest
Private SecureHost, HttpBuffer, YmsgChallenge As String
Public Function getResponse(ByVal request As HttpWebRequest)
Dim myHttpWebResponse As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
Dim receiveStream As Stream = myHttpWebResponse.GetResponseStream()
Dim encode As Encoding = System.Text.Encoding.GetEncoding(950)
Dim readStream As New StreamReader(receiveStream, encode)
Return readStream.ReadToEnd()
End Function
Public Sub GetToken(ByRef YahooID As String, ByRef Password As String, ByRef YmChallenge As String, Optional ByRef HostName As String = "66.163.169.186")
On Error Resume Next
Main.lbStatMsg.Text = "Sending Challenge"
YmsgChallenge = YmChallenge
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
YNet1 = HttpWebRequest.Create("https://" & HostName & "/config/pwtoken_get?src=ymsgr&ts=&login=" & YahooID & "&passwd=" & Password & "&chal=" & YmChallenge)
YNet1.ProtocolVersion = HttpVersion.Version10
YNet1.AllowAutoRedirect = True
YNet1.Method = "GET"
con1_2(getResponse(YNet1))
End Sub
Private Sub con1_2(ByRef data As String)
Main.lbStatMsg.Text = "Getting crumbs"
On Error Resume Next
Dim SplDat1() As String
Dim SplDat2() As String
If InStr(1, data, "ymsgr=") Then
SplDat1 = Split(data, "ymsgr=")
SplDat2 = Split(SplDat1(1), vbCrLf)
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
YNet2 = HttpWebRequest.Create("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=" & SplDat2(0))
YNet2.ProtocolVersion = HttpVersion.Version11
YNet2.AllowAutoRedirect = True
YNet2.Method = "GET"
con2(getResponse(YNet2))
Else
RaiseEvent InvalidLogin()
End If
End Sub
Public Sub con2(ByRef data As String)
Main.lbStatMsg.Text = "Got crumb"
On Error Resume Next
Dim SplDat1() As String
Dim SplDat2() As String
Dim YCookie, TCookie, YCrumb As String
If InStr(1, data, "crumb=") > -1 Then
SplDat1 = Split(data, "Y=")
SplDat2 = Split(SplDat1(1), ";")
YCookie = SplDat2(0) & "; path=/; domain=.yahoo.com"
SplDat1 = Split(data, "T=")
SplDat2 = Split(SplDat1(1), ";")
TCookie = SplDat2(0) & "; path=/; domain=.yahoo.com"
SplDat1 = Split(data, "crumb=")
SplDat2 = Split(SplDat1(1), vbCrLf)
YCrumb = SplDat2(0)
Dim crypted As String = ProcessAuth16(YCrumb, YmsgChallenge)
Main.lbStatMsg.Text = "Logged In!"
RaiseEvent RecvToken(YCookie, TCookie, crypted)
End If
End Sub
Public Function ProcessAuth16(ByVal Crumb As String, ByVal Challenge As String) As String
Dim Crypt As String = String.Join(String.Empty, New String() {Crumb, Challenge})
Dim Hash As Byte() = HashAlgorithm.Create("MD5").ComputeHash(Encoding.[Default].GetBytes(Crypt))
Dim Auth As String = Convert.ToBase64String(Hash).Replace("+", ".").Replace("/", "_").Replace("=", "-")
Return Auth.ToString
End Function
End Class
This one is pretty simple and not too bloated like other example on the web. But first, I wanna thanks YCoderCookBook for his YTainer sourcecode reference, carbonized.co.uk for his explaination on YMSG16 login packets.
As you can see from the code, I’m using System.Net.WebHttpRequest in which is networking class in .Net framework. Using INet (I bet many of client out there using this) is too oldschool. WinHttp is another alternative, but I want to rely only on .Net and not COM.
So, what’s with YConnect?!!
As you can see, YConnect use a fairly simple user-interface (thanks to dubee of YSupra for the inspiration) without losing most of the option. For id polygamy, it’ll just run in one instance of the program, with tab in which i think is quite great. I always think, it would be great if YSupra has buddylist much like Yahoo Messenger, so, I’ve build one. However, I’m using Treeview with OwnerDraw, I have to think if there’s a way to retrieve the user avatar asyncronously since retrieve avatar for every paint update is CPU-killing. Maybe I’ll setUp a hashMap for user avatar later.
Here’s the code in tvBuddyList_DrawMode()
If (e.State And TreeNodeStates.Focused) <> 0 Then
Dim focusBounds As Rectangle = NodeBounds(e.Node)
focusBounds.Size = New Size(focusBounds.Width, focusBounds.Height)
e.Graphics.FillRectangle(Brushes.LightGray, 0, focusBounds.Y, tvBuddyList.Width, 36)
End If
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim data As String = e.Node.Tag
Dim sep As Char = Convert.ToChar(860)
Dim type As String = data.Split(sep)(0)
Dim text As String
Dim status As Boolean
Dim statusmsg As String
Dim bound As Rectangle = NodeBounds(e.Node)
If type = "group" Then
Dim fx As New System.Drawing.Font("Verdana", 8.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
text = data.Split(sep)(1)
Dim pt() As Point = {New Point(bound.X + 6, bound.Y + 15), New Point(bound.X + 6, bound.Y + 23), New Point(bound.X + 15, bound.Y + 19)}
e.Graphics.FillPolygon(Brushes.Black, pt, Drawing2D.FillMode.Winding)
e.Graphics.DrawString(text, fx, Brushes.DarkViolet, bound.X + 20, bound.Y + 13)
ElseIf type = "buddy" Then
' Debug.Print("drawing..")
text = data.Split(sep)(1)
status = (data.Split(sep)(2) = "online")
statusmsg = data.Split(sep)(3)
Dim fStyle As FontStyle = IIf(status, System.Drawing.FontStyle.Bold, System.Drawing.FontStyle.Italic)
Dim fx As New System.Drawing.Font("Verdana", 8.0!, fStyle, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Dim fx1 As New System.Drawing.Font("Verdana", 7.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Dim o9color As Brush = IIf(status, Brushes.Orange, Brushes.LightGray)
Dim o9color2 As Pen = IIf(status, Pens.DarkOrange, Pens.Gray)
' Dim ava As New PictureBox
' ava.LoadAsync("http://img.msg.yahoo.com/avatar.php?format=jpg&yids=" & e.Node.Text.Split(sep)(0))
' Draw avatar from HashTable of <string, Image>
e.Graphics.DrawImage(avaHashMap(e.Node.Text.Split(sep)(0)), bound.X + 5, bound.Y + 5, 30, 30)
e.Graphics.FillEllipse(o9color, New Rectangle(bound.X + 40, bound.Y + 6, 8, 8))
e.Graphics.DrawEllipse(o9color2, New Rectangle(bound.X + 40, bound.Y + 6, 8, 8))
e.Graphics.DrawString(text, fx, Brushes.DarkSlateGray, bound.X + 54, bound.Y + 3)
e.Graphics.DrawString(statusmsg, fx1, Brushes.Gray, bound.X + 40, bound.Y + 17)
End If
Well I’ve got YM-styled buddy list soo far. I’ll just have to build the treeNode inside the tvBuddyList, with buddy tree tag set to
type["group"|"buddy"] & Char(860) & buddyname & Char(860) & status["online"|"offline"] & Char(860) & statusmessage
everytime the buddy status change, just change the key for the treeNode corresponding to the buddy.
Problem I faced so far
I have problem with captcha image. Actually, I wanna make the captcha image to appear into chat browser. Only captcha Image. Like those on YSupra. But maybe lack of knowledge, I’m not able to do that. Everytime I try to retrieve the captcha image from the ImgUrl parameter given when signing in to room, it got invalidated. Hurghhhh!!
No security feature in this client yet. I dunno if this client is easily booted, haven’t test for that. But given the nature of boot is by the inability of the client to process massive packet, maybe I’ll have workaround on that later.
Duplicate PM msg problem. I dunno if this problem is common or not, but I have found post regarding this issue. Chat server will send 2 packet, technically. But maybe I’ll resolve this issue later (juz few conditional block anyway).
Only using YMSG16 protocol. Well I think I’ll just leave it at it. YMSG14 has been deprecated and for YMSG15, i guess there’s not much difference from YMSG16 except for login process (I’ll added later). For YMSG17, I’ll produce the code when it is widely used later (i gez some folk in YSupra has a workaround on this) ^_^
Conclusion
I’ll happily give out the full sourcecode, ONLY if you wanna help me on problems I’ve faced. I have the same project for VB.Net (but using YMSG14 on this time, later I’ll add support for YMSG16)