Click here to Skip to main content
15,860,859 members
Articles / Programming Languages / C#
Article

Protect your IM (Instant Messenger) conversations by encrypting them

Rate me:
Please Sign up or sign in to vote.
4.63/5 (26 votes)
19 Oct 20056 min read 150.4K   2.8K   76   39
Learn how to encrypt IM (Instant Messenger) conversations.

Image 1

IMEncryptor: Encrypt your IM (Instant Messenger) conversations.

Image 2

Ficture_1. The big picture.

Contents

Introduction

Nowadays everybody knows how to make use of a packet sniffer and probably (if the channel is not already secured) find some sensitive information. By placing such a tool "under the skin" of your network in a couple of sensitive zones, someone could get for example, the Yahoo Messenger conversations. That's because (and you probably know this fact) these conversations are not encrypted.

Short story

Some time back in 2000, there was a Yahoo Messenger Enterprise Edition version. This version used encryption to protect conversations. Since the big corporations didn't buy it (because it was not free), after three years, Yahoo dissolved its enterprise solutions division.

Getting back to our tool, what can you do to protect yourself?

  1. There are a couple of software packages available, but... you must buy them.
  2. Try to figure out possible ways to encrypt the conversation lines. This is what I was thinking...

Features

  • Encryption (decryption) of the text messages sent to (received from) your friends using Yahoo messenger.
  • This initial (version 1.0) version supports only 3DES encryption algorithm.
  • Encrypted messages are marked with a star (*).
  • Saved messages on your HDD (messages archive) remain encrypted. The messages are decrypted as soon as you start the application.

Image 3

Figure_2. Message archive.

Prerequisites

The pieces of the puzzle or... what are we playing with?

  • Low level Windows messaging (well... now very low - just using the old WM_* messages).
  • .NET cryptography.

The idea - in words

As you can see the Yahoo's messenger window is divided into several zones or areas. These zones are windows and each window has a hWnd (Window handler). Other Windows software packages don't use this kind of technique (for example, the Office suite). Using a window handler for each control consumes the system resources. In our case, these handlers will help us achieve our goals.

The three window areas, we are interested in are:

  1. The area in which you are typing the message that is to be sent - WriteArea.
  2. The area that displays the sent/received messages from your friend - TalkArea.
  3. The button we click to send these messages - SendButton.

Image 4

Figure_3. The window areas.

Next, you will see the necessary steps required to encrypt a message, to send the encrypted message and to decrypt a received encrypted message.

Sending an encrypted line of message

  1. Cut the message from the writing area - hWndWriteArea.
  2. Encrypt it with our application.
  3. Paste it back, marked for decryption, into the writing area - hWndWriteArea.
  4. Send it by simulating a click on the "Send" button - hWndSendButton

Decrypting an incoming encrypted message

  1. Get the messages from the conversation area - hWndTalkArea.
  2. Check the messages for markers.
  3. Decrypt the marked message.
  4. Paste these messages back into the conversation area - hWndTalkArea

The idea - in code

Finding the HWNDs of the three window areas we are interested in

Check if the foreground window is a Yahoo messenger conversation window. If it's true, call MessengerYahoo_HandleWindow method. This method moves the IMEncryptor window next to the conversation window by calling MessengerYahoo_MoveTheWindow and then, using a delegate, it loops through the child windows to find the hWnds we are interested in, MessengerYahoo_HandleEnumChild.

Tip: This function should return true if you want to search again through the child windows and false otherwise.

C#
private bool MessengerYahoo_HandleEnumChild(
                          IntPtr hWnd, IntPtr lParam)
{
    int textLength = Win32API.SendMessage(hWnd, 
                 Win32API.WM_GETTEXTLENGTH, 0, IntPtr.Zero);
    StringBuilder text = new StringBuilder(textLength + 1);
    Win32API.SendMessage(hWnd, Win32API.WM_GETTEXT, 
                                     textLength + 1, text);
    
    StringBuilder className = new StringBuilder();
    Win32API.GetClassName(hWnd, className, 
                                    className.MaxCapacity);

    if (className.ToString().Contains(writeAreaClassName))
        hWndWriteArea = hWnd;

    if (className.ToString().Contains(talkAreaContainerName))
        hWndTalkArea = Win32API.FindWindowEx(hWnd, 
                 IntPtr.Zero, talkAreaClassName, IntPtr.Zero);

    if (className.ToString().Contains(sendButtonClassName))
        if (text.ToString().Contains(sendButtonText))
            hWndSendButton = hWnd;

    if ((hWndWriteArea == IntPtr.Zero) || 
                        (hWndTalkArea == IntPtr.Zero) || 
                        (hWndSendButton == IntPtr.Zero))
        return true;
    else
        return false;
}

writeAreaClassName, talkAreaContainerName, talkAreaClassName, sendButtonClassName and sendButtonText are defined in the Variables and Constants region, at the beginning of the FrmMain class.

C#
#region Variables and Constants 

IntPtr hWndForegroundWindow;  // Foreground window handler
IntPtr hWndTalkArea;          // Talk area window handler
IntPtr hWndWriteArea;         // Write area window handler
IntPtr hWndSendButton;        // Send button window handler

// Yahoo Messenger's window title contains this string
const String windowTitle = "- Instant Message"; 
// The class name of the writeArea zone                
const String writeAreaClassName = "YIMInputWindow";             
// The container name of the "talkArea"
const String talkAreaContainerName = "YHTMLContainer";            
// The class name of the "talkArea"
const String talkAreaClassName = "Internet Explorer_Server";    
// The class name of the "sendButton"
const String sendButtonClassName = "Button";                    
// The text of the "sendButton"
const String sendButtonText = "&Send";                        

// Marks the START of an encrypted line of message
const String startTag = "!%";                                   
// Marks the END of an encrypted line of message
const String stopTag = "%!";                                    

// This is a decrypted line
const String decryptedLineMarker = "* ";                        

// The secret password entered by the user
static String secretPassword;                                    

#endregion

Sending an encrypted line of message

MessengerYahoo_HandleSend method of the FrmMain class deals with this issue. As you can see in the code below:

  1. We send Win32Api.WM_GETTEXTLENGTH to get the length of the text from the window behind the hWndWriteArea and Win32Api.WM_GETTEXT message to get the clear text message.
  2. Initialize and use a Simetrical cryptographic provider SIMCrypto (3DES) by calling sc.Encrypt to encrypt the clear text message.
  3. Write the message back to the window behind the hWndWriteArea using Win32API.WM_SETTEXT.
  4. Send the encrypted message, by simulating a click on the Send button (we send a Win32API.BN_CLICK message to the button).

Tip: Setting the foreground window back, by calling Win32API.SetForegroundWindow, will enable the user to start typing another message.

C#
private void MessengerYahoo_HandleSend()
{
    // 1. GET the message from the writeArea
    int textLength = Win32API.SendMessage(hWndWriteArea, 
                   Win32API.WM_GETTEXTLENGTH, 0, IntPtr.Zero);
    StringBuilder writingtext = 
                            new StringBuilder(textLength + 1);
    Win32API.SendMessage(hWndWriteArea, 
            Win32API.WM_GETTEXT, textLength + 1, writingtext);

    // 2. ENCRYPT the message
    SIMCrypto sc = 
       new SIMCrypto(SIMCrypto.ServiceProviderEnum.TripleDES);
    String encryptedText = startTag + 
          sc.Encrypt(writingtext.ToString(), secretPassword) + 
          stopTag;

    // Delete the message from the writeArea
    Win32API.SendMessage(hWndWriteArea, 
          Win32API.WM_SETTEXT, 0, 
          System.Text.Encoding.ASCII.GetBytes("".ToCharArray()));

    // 3. PASTE the new encrypted message
    byte[] encryptedText_byte = 
          System.Text.Encoding.ASCII.GetBytes(
                                    encryptedText.ToCharArray());
    Win32API.SendMessage(hWndWriteArea, 
                     Win32API.WM_SETTEXT, 0, encryptedText_byte);

    // 4. SEND the new encrypted message 
    // (by simulating a click on the Send button)
    Win32API.SendMessage(hWndSendButton, 
                 Win32API.BM_CLICK, 0, encryptedText_byte);

    // Delete the message from the writeArea
    Win32API.SendMessage(hWndWriteArea, 
          Win32API.WM_SETTEXT, 0, 
          System.Text.Encoding.ASCII.GetBytes("".ToCharArray()));

    // Set the foreground window = the messeger window
    Win32API.SetForegroundWindow(hWndForegroundWindow);
}

Decrypting an incoming encrypted message

MessengerYahoo_HandleDecryption method of the FrmMain class deals with this issue. As you can see in the code below:

  1. We get a handler to the IHTMLDocument2 by sending a WM_HTML_GETOBJECT message to the hWndTalkArea. IHTMLDocument2 is enclosed by the "Internet Explorer_Server" control, defined above as the talkAreaClassName. A small, but interesting article on this issue can be found here.
  2. Next we are parsing its structure (in a trivial way) to get the marked messages.
  3. Decrypt the marked messages using the same cryptographic provider, SIMCrypto (3DES) and by calling sc.Decrypt method.
  4. Paste the decrypted message back to where it belongs.

Tip: To be able to work with IHTMLDocument2 you need to add a reference to a .NET component named Microsoft.mshtml.

C#
private void MessengerYahoo_HandleDecryption()
{
    // 1. GET the messages from the conversation area
    uint msg = 
      Win32API.RegisterWindowMessage("WM_HTML_GETOBJECT");
    IntPtr lRes = IntPtr.Zero;
    Win32API.SendMessageTimeout(hWndTalkArea, msg, 
        IntPtr.Zero, IntPtr.Zero, 
        Win32API.SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 
        1000, out lRes);

    IHTMLDocument2 myHTMLDoc = 
      (mshtml.IHTMLDocument2)Win32API.ObjectFromLresult(lRes, 
               typeof(mshtml.IHTMLDocument).GUID, IntPtr.Zero);
    foreach (IHTMLElement el in (IHTMLElementCollection)myHTMLDoc.body.all)
        if ((el.GetType().ToString().
           CompareTo("mshtml.HTMLSpanElementClass") == 0) && 
                                                    (el.className != null))
        
            // 2. CHECK for the markers
            if ((el.innerText != null) && 
                 (el.innerText.IndexOf("!%") >= 0) && 
                 (el.innerText.LastIndexOf("%!") > 0))
            {
                // 3. DECRYPT the marked message
                String ts = el.innerText.ToString();
                String ts2 = ts.Substring(el.innerText.IndexOf(startTag) + 2, 
                                       el.innerText.LastIndexOf(stopTag) - 2);
                
                String decryptedText = null;
                try
                {
                    SIMCrypto sc = 
                       new SIMCrypto(SIMCrypto.ServiceProviderEnum.TripleDES);
                    decryptedText = 
                       decryptedLineMarker + sc.Decrypt(ts2, secretPassword);
                }
                catch (Exception ex)
                {
                    decryptedText = 
                            "\n" + "Received a malformed encrypted string:" + 
                            ts2 + "\n" + "Exception generated: " + ex.Message;
                }
                
                // 4. PASTE the decrypted message 
                el.innerText = decryptedText;
            }
}

How to use IMEncryptor

  • Download and install the .NET Framework 2.0 Beta 2 (if it's not already installed).
  • Download and launch the IMEncryptor.exe file (you will find it as IMEncryptor_Demo.zip).
  • Start IMEncryptor, enter your secret password in the text box and check the "Enable encryption" checkbox.
  • Start a Yahoo Messenger conversation window. You will see that the IMEncryptor window stays next to the current conversation window.
  • Type a message in the WriteArea and do not press enter after typing the message. Click on the "Send encrypted" button.
  • Drop me a message (or email) if you like it or not, if you discover bugs or if you want other features to be implemented.

TODO list

  1. Further optimization of the code.
  2. Support for multiple crypto algorithms.
  3. Automatic key exchange mechanism.
  4. Management of multiple keys (for multiple users).
  5. Enable a global hook to capture the Enter key?
  6. Support for other IMs (MSN Messenger, Google Talk, ...)?
  7. You name the feature...

Version history

  • 20.10.2005 - Version 1.0.
    • The first release. Includes the main functional features.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Romania Romania
Y°u may dr°p me a line at -> silviu[d°t]gologan[_at_]gmail[d°t]c°m.

Comments and Discussions

 
Questionquestion for IM Pin
M.yuliandana3-May-13 4:38
M.yuliandana3-May-13 4:38 
Generalbad word filter to protect my kids. with [***********] 's Pin
ZUPERKOOL7-Feb-10 9:19
ZUPERKOOL7-Feb-10 9:19 
GeneralYahoo Messenger 9 Pin
metalmouth24-Sep-08 1:02
metalmouth24-Sep-08 1:02 
Good day Sir,

I found your article quite useful. I really learned a lot.

Just wondering can you help me make it compatible to YM 9? coz i'm having problem with the send button it doesn't seems to be visible to spy++, so i can't get the class name. can you please atleast give me an idea how can i solve the problem? thanks in advance!

By by the way i'm a VB6 programmer i converted your version to VB6 and it's working the same way as yours. i just can't make it work to YM9.
GeneralThe Other Way Pin
sabrown10017-Oct-07 13:37
sabrown10017-Oct-07 13:37 
NewsTwo other related encryption articles in CodeProject ... Pin
Tony Selke27-Sep-07 7:02
Tony Selke27-Sep-07 7:02 
Generalthe fallowing thing does not work Pin
Dani G7-Aug-07 9:55
Dani G7-Aug-07 9:55 
GeneralHelp Pin
Tariqaziz15-Jul-07 21:28
Tariqaziz15-Jul-07 21:28 
Generalcan't get it to work [modified] Pin
javaJones6-Jul-07 12:41
javaJones6-Jul-07 12:41 
Questionwindow handlers? Pin
Dorian Darius8-Dec-06 2:19
Dorian Darius8-Dec-06 2:19 
AnswerRe: window handlers? Pin
Silviu Gologan28-Apr-07 4:19
Silviu Gologan28-Apr-07 4:19 
QuestionDoes it work with YM 7.5? Pin
Florin Ochiana27-Jun-06 21:13
Florin Ochiana27-Jun-06 21:13 
Generalgood question Pin
m41417-Jun-06 23:44
m41417-Jun-06 23:44 
AnswerRe: good question Pin
Silviu Gologan28-Apr-07 4:20
Silviu Gologan28-Apr-07 4:20 
GeneralSupport for Rich text Pin
_Sanjay_13-Mar-06 3:11
_Sanjay_13-Mar-06 3:11 
GeneralIt donnot view the decrypted message. Pin
cnLiYue9-Jan-06 0:49
cnLiYue9-Jan-06 0:49 
GeneralRe: It donnot view the decrypted message. Pin
cnLiYue16-Jan-06 16:34
cnLiYue16-Jan-06 16:34 
GeneralVOIP recorder Pin
triplebit4-Jan-06 7:59
triplebit4-Jan-06 7:59 
GeneralRe: VOIP recorder Pin
Silviu Gologan9-Jan-06 2:03
Silviu Gologan9-Jan-06 2:03 
GeneralCompile Problem Pin
cnLiYue3-Jan-06 19:21
cnLiYue3-Jan-06 19:21 
AnswerRe: Compile Problem Pin
Silviu Gologan5-Jan-06 5:05
Silviu Gologan5-Jan-06 5:05 
GeneralThe method used sucks ... Pin
y00daa24-Oct-05 20:59
sussy00daa24-Oct-05 20:59 
GeneralRe: The method used sucks ... Pin
windrago25-Oct-05 8:28
windrago25-Oct-05 8:28 
GeneralRe: The method used sucks ... Pin
Hannibal MDo26-Oct-05 14:54
sussHannibal MDo26-Oct-05 14:54 
AnswerRe: The method used sucks ... Pin
Silviu Gologan26-Oct-05 21:52
Silviu Gologan26-Oct-05 21:52 
GeneralRe: The method used sucks ... Pin
ezekial29-Jan-07 21:14
ezekial29-Jan-07 21:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.