
IMEncryptor: Encrypt your IM (Instant Messenger) conversations.

Ficture_1. The big picture.
Contents
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?
- There are a couple of software packages available, but... you must buy them.
- Try to figure out possible ways to encrypt the conversation lines. This is what I was thinking...
- 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.
- Low level Windows messaging (well... now very low - just using the old WM_* messages).
- .NET cryptography.
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:
- The area in which you are typing the message that is to be sent - WriteArea.
- The area that displays the sent/received messages from your friend - TalkArea.
- 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
- Cut the message from the writing area -
hWndWriteArea
.
- Encrypt it with our application.
- Paste it back, marked for decryption, into the writing area -
hWndWriteArea
.
- Send it by simulating a click on the "Send" button -
hWndSendButton
Decrypting an incoming encrypted message
- Get the messages from the conversation area -
hWndTalkArea
.
- Check the messages for markers.
- Decrypt the marked message.
- Paste these messages back into the conversation area -
hWndTalkArea
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 hWnd
s 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;
IntPtr hWndTalkArea;
IntPtr hWndWriteArea;
IntPtr hWndSendButton;
const String windowTitle = "- Instant Message";
const String writeAreaClassName = "YIMInputWindow";
const String talkAreaContainerName = "YHTMLContainer";
const String talkAreaClassName = "Internet Explorer_Server";
const String sendButtonClassName = "Button";
const String sendButtonText = "&Send";
const String startTag = "!%";
const String stopTag = "%!";
const String decryptedLineMarker = "* ";
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:
- 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.
- Initialize and use a Simetrical cryptographic provider
SIMCrypto
(3DES) by calling sc.Encrypt
to encrypt the clear text message.
- Write the message back to the window behind the
hWndWriteArea
using Win32API.WM_SETTEXT
.
- 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()
{
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);
SIMCrypto sc =
new SIMCrypto(SIMCrypto.ServiceProviderEnum.TripleDES);
String encryptedText = startTag +
sc.Encrypt(writingtext.ToString(), secretPassword) +
stopTag;
Win32API.SendMessage(hWndWriteArea,
Win32API.WM_SETTEXT, 0,
System.Text.Encoding.ASCII.GetBytes("".ToCharArray()));
byte[] encryptedText_byte =
System.Text.Encoding.ASCII.GetBytes(
encryptedText.ToCharArray());
Win32API.SendMessage(hWndWriteArea,
Win32API.WM_SETTEXT, 0, encryptedText_byte);
Win32API.SendMessage(hWndSendButton,
Win32API.BM_CLICK, 0, encryptedText_byte);
Win32API.SendMessage(hWndWriteArea,
Win32API.WM_SETTEXT, 0,
System.Text.Encoding.ASCII.GetBytes("".ToCharArray()));
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:
- 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.
- Next we are parsing its structure (in a trivial way) to get the marked messages.
- Decrypt the marked messages using the same cryptographic provider,
SIMCrypto
(3DES) and by calling sc.Decrypt
method.
- 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()
{
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))
if ((el.innerText != null) &&
(el.innerText.IndexOf("!%") >= 0) &&
(el.innerText.LastIndexOf("%!") > 0))
{
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;
}
el.innerText = decryptedText;
}
}
- 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.
- Further optimization of the code.
- Support for multiple crypto algorithms.
- Automatic key exchange mechanism.
- Management of multiple keys (for multiple users).
- Enable a global hook to capture the Enter key?
- Support for other IMs (MSN Messenger, Google Talk, ...)?
- You name the feature...
- 20.10.2005 - Version 1.0.
- The first release. Includes the main functional features.