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…

login

poly view

user main

Multiple chat view with YConnect!
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)