Click here to Skip to main content
Click here to Skip to main content

Protect your IM (Instant Messenger) conversations by encrypting them

, 19 Oct 2005
Rate this:
Please Sign up or sign in to vote.
Learn how to encrypt IM (Instant Messenger) conversations.

IMEncryptor: Encrypt your IM (Instant Messenger) conversations.

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.

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.

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.

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.

#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.

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.

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

Share

About the Author

Silviu Gologan
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 PinmemberM.yuliandana3-May-13 5:38 
Generalbad word filter to protect my kids. with [***********] 's PinmemberZUPERKOOL7-Feb-10 10:19 
GeneralYahoo Messenger 9 Pinmembermetalmouth24-Sep-08 2:02 
GeneralThe Other Way Pinmembersabrown10017-Oct-07 14:37 
NewsTwo other related encryption articles in CodeProject ... PinmemberTony Selke27-Sep-07 8:02 
Generalthe fallowing thing does not work PinmemberDani G7-Aug-07 10:55 
GeneralHelp PinmemberTariqaziz15-Jul-07 22:28 
Generalcan't get it to work [modified] PinmemberjavaJones6-Jul-07 13:41 
Questionwindow handlers? PinmemberDorian Darius8-Dec-06 3:19 
AnswerRe: window handlers? PinmemberSilviu Gologan28-Apr-07 5:19 
QuestionDoes it work with YM 7.5? PinmemberFlorin Ochiana27-Jun-06 22:13 
Generalgood question Pinmemberm41418-Jun-06 0:44 
AnswerRe: good question PinmemberSilviu Gologan28-Apr-07 5:20 
GeneralSupport for Rich text Pinmember_Sanjay_13-Mar-06 4:11 
GeneralIt donnot view the decrypted message. PinmembercnLiYue9-Jan-06 1:49 
GeneralRe: It donnot view the decrypted message. PinmembercnLiYue16-Jan-06 17:34 
GeneralVOIP recorder Pinmembertriplebit4-Jan-06 8:59 
GeneralRe: VOIP recorder PinmemberSilviu Gologan9-Jan-06 3:03 
GeneralCompile Problem PinmembercnLiYue3-Jan-06 20:21 
AnswerRe: Compile Problem PinmemberSilviu Gologan5-Jan-06 6:05 
Hi!
 
The information you need already exists in my article. Smile | :)
 
Tip: To be able to work with IHTMLDocument2 you need to add a reference to a .NET component named Microsoft.mshtml.
 
The steps to do that (in case that you haven't solved the problem) are:
1. Open the Solution Explorer window.
2. Right-click on References.
3. Select Add reference... from the menu.
4. On the .NET tab page, double-click on the Microsoft.mshtml component.
5. Click OK.
 
Well, that's it. If you need more help let me know.
Regards,
Silviu Gologan.

GeneralThe method used sucks ... Pinsussy00daa24-Oct-05 21:59 
GeneralRe: The method used sucks ... Pinmemberwindrago25-Oct-05 9:28 
GeneralRe: The method used sucks ... PinsussHannibal MDo26-Oct-05 15:54 
AnswerRe: The method used sucks ... PinmemberSilviu Gologan26-Oct-05 22:52 
GeneralRe: The method used sucks ... Pinmemberezekial29-Jan-07 22:14 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411023.1 | Last Updated 20 Oct 2005
Article Copyright 2005 by Silviu Gologan
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid