Solved

How to make a MSN Messenger Chat Monitor?

Posted on 2004-09-17
22
1,475 Views
Last Modified: 2008-01-09
I want to make a little spy service to monitor MSN Messenger Chat.
I know that I have to listen to 1863 TCP-IP port. Take a look what I did till now.

I dropped IdTCPClient1, IdLogStream1, memo1, btnConnect and btnDisconnect to a form.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdIntercept, IdLogBase, IdLogEvent, IdLogStream;

type
  TForm1 = class(TForm)
    IdTCPClient1: TIdTCPClient;
    btnConnect: TButton;
    Memo1: TMemo;
    IdLogStream1: TIdLogStream;
    btnDisconnect: TButton;
    procedure btnConnectClick(Sender: TObject);
    procedure IdLogEvent1Send(ASender: TIdConnectionIntercept; AStream: TStream);
    procedure IdLogEvent1Receive(ASender: TIdConnectionIntercept;AStream: TStream);
    procedure IdLogStream1Receive(ASender: TIdConnectionIntercept; AStream: TStream);
    procedure IdLogStream1Send(ASender: TIdConnectionIntercept; AStream: TStream);
    procedure btnDisconnectClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnConnectClick(Sender: TObject);
begin
  IdTCPClient1.BoundIP:='127.0.0.1';
  IdTCPClient1.BoundPort:=1863;
  IdTCPClient1.Host:='127.0.0.1';
  IdTCPClient1.Port:=1863;
  IdTCPClient1.Connect;
  If IdTCPClient1.Connected Then
    ShowMessage('Connected');
end;

procedure TForm1.IdLogEvent1Send(ASender: TIdConnectionIntercept;
  AStream: TStream);
Var
  sLine:String;
begin
  try
    SetLength(sLine,AStream.Size);
    AStream.Position:=0;
    AStream.Read(sLine[1],AStream.Size);
  finally
    Memo1.Lines.Add('<='+sLine);
  end;
end;

procedure TForm1.IdLogEvent1Receive(ASender: TIdConnectionIntercept;
  AStream: TStream);
Var
  sLine:String;
begin
  try
    SetLength(sLine,AStream.Size);
    AStream.Position:=0;
    AStream.Read(sLine[1],AStream.Size);
  finally
    Memo1.Lines.Add('=>'+sLine);
  end;
end;

procedure TForm1.IdLogStream1Receive(ASender: TIdConnectionIntercept;
  AStream: TStream);
Var
  sLine:String;
begin
  try
    SetLength(sLine,AStream.Size);
    AStream.Position:=0;
    AStream.Read(sLine[1],AStream.Size);
  finally
    Memo1.Lines.Add('Received: '+sLine);
  end;
end;

procedure TForm1.IdLogStream1Send(ASender: TIdConnectionIntercept;
  AStream: TStream);
Var
  sLine:String;
begin
  try
    SetLength(sLine,AStream.Size);
    AStream.Position:=0;
    AStream.Read(sLine[1],AStream.Size);
  finally
    Memo1.Lines.Add('Sent: '+sLine);
  end;
end;

procedure TForm1.btnDisconnectClick(Sender: TObject);
begin
  IdTCPClient1.Disconnect;
end;

end.
0
Comment
Question by:pepoclv
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 6
  • +1
22 Comments
 
LVL 10

Expert Comment

by:Jacco
ID: 12090741
I think you make one mistake. When I understand correctly you want to make an app that "spies" on the current chat session on your local machine. You would like to grab what is being said by the local or even the remote chatters.

I'll explain why you method will not work. The chat session is a client session from the local machine that connects to a remote machines server session ip/port for example 192.168.0.10:1863. (there is no local port involved in the communication). The communication can not be spied on by connecting a client session to a local server session on your local machine 127.0.0.1:1863. There probably is no server on the local machine listening for new connections.

Now what you probably want is to write an app that does someting like a firewall does: Intercepting communication. This is done in a very different way. I found a question where someone explains how difficult this actually is:

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20551029.html

This is one way around this. You could configure MSN Messenger to use proxy for its communication. A proxy is an application can run on the local machine and accepts client connections on 1863 (so this is a server on the local machine on port 1863). So you can configure MSN Messenger to connect to 127.0.0.1:1863 and the proxy is configured to connect to the remote MSN server on 1863. The proxy will relay all incoming and outgoing communication.

No a proxy is easier to write than a firewall and a appart from its proxy task it could also pass the communication to other applications.

Hope I made thing clear :)

Regards Jacco
0
 
LVL 1

Expert Comment

by:mgazza
ID: 12091725
you cant do it like that

if you want to watch everything msn is doing make a proxy server.
easily done

the msn protocal consists of a notigication server and a switch board server

each chat session has a connection to a sb the msn does not directly connect to other users

iv wrote my own implementation of the msn protocol, and theres lots to handle over 6,000 lines for msnp10

i sujest you make a threaded poroxy server and log MSG


this is what i do when i get the command MSG

 if tmp='MSG' then begin

     tmp:=GetWordAfter('Content-Type: ',Acommand,#13#10);
       if WordAt(tmp,1)='text/plain;' then begin //its a text message
         Tmp:=GetWordAfter(#13#10+#13#10,Acommand,'');

         ChatWindow.DropWindow.Add(
            Format('%s Says:',
            [TFriend(UserFromAddy(WordAt(Acommand,2))^).nick])         //todo get user name from addy
            );
         ChatWindow.DropWindow.Add(' '+tmp);
         ChatWindow.Alertit;
         ChatWindow.Show;
       end;
0
 

Author Comment

by:pepoclv
ID: 12092327
So why monitoring port software like IRIS can intercept msn messages and chat? Does IRIS software connect to 1863 port? Or IRIS is an proxy?
I'm confused now.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Expert Comment

by:mgazza
ID: 12092369
it will be a proxy
                                                                                              the request sets this
msn  ->http connection request  -> [poxy server]  ->process  -> open internet port
                                                  <- accept?
connected

msn writes header+ its packet      ->[proxy] -> writes packet  ->internet
internet  ->   [poxy gets packet]  ->   msn

and example of msn requesting a proxy connection

POST http://gateway.messenger.hotmail.com/gateway/gateway.dll?Action=open&Server=NS&IP=207.46.104.20 HTTP/1.1
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN Messenger 6.2.0137)
Host: gateway.messenger.hotmail.com
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Pragma: no-cache
Content-Type: application/x-msn-messenger
Content-Length: 27

VER 122 MSNP10 MSNP9 CVR0



this will make the server open a connection to the above and send VER 122 MSNP10 MSNP9 CVR0\n\r
0
 
LVL 10

Expert Comment

by:Jacco
ID: 12092484
With Indy components it is very easy to build a proxy. Just drop a TIdMappedPortTCP component on a form, configure it, an you are ready to go.

Indy is delivered with Delphi and there website is

http://www.nevrona.com/indy

Demo projects with a proxy server can be found there as well.

Good luck,

Regards Jacco
0
 
LVL 10

Expert Comment

by:Jacco
ID: 12092501
IRIS is a firewall like application. Is "guard" feature is actually a firewall.
0
 
LVL 1

Expert Comment

by:mgazza
ID: 12092503
he'll need a threaded proxy will indy cope with that?

i personally prefer the tserversocket in blocking mode (TCustomWinsocket)

best regards,
mark
0
 
LVL 10

Expert Comment

by:Jacco
ID: 12093029
Indy is a lot easier.

Its threaded.

TIdMappedPortTCP inherits directly from TIdTCPServer and uses a TIdMappedPortThread for each connection.
0
 
LVL 1

Expert Comment

by:mgazza
ID: 12093046
well thats wat i sujest you do then :D

create a thread on each connection to your server read the headers open a connection to the requested address return the data  keep the connection alive unless told other wise in the conection header from the connection opened
0
 
LVL 1

Expert Comment

by:mgazza
ID: 12123418
500 pointer didnt realise..,., id write out code for you but i dont realy have time A.S maths and physics n stuff...

i can give you help tho i sugest you decrease the points! unless you get some code :D
0
 
LVL 10

Expert Comment

by:Jacco
ID: 12125857
I tried cooking up some code using Indy but it turned out a bit harder like you said :~( TIdMappedPortThread doesn't do the job. And MSN messenger refuses to uses a prooxy when I set it. It tests it correctly with my code when disconnected. But when restarting it doesn't use my homemade HTTP proxy...

Regards Jacco
0
 
LVL 1

Expert Comment

by:mgazza
ID: 12125896
humm it should do by defalt if you have told it to use a proxy it should always use it strange..
0
 
LVL 10

Expert Comment

by:Jacco
ID: 12126000
Here is the code I cooked. When clicking the button "Test Connection" in the "Options" dialog it returned the connection is OK.

*** start of pascal ***
unit Main;

interface

uses
  Windows, Messages, Graphics, Controls, Forms, Dialogs, StdCtrls,
  SysUtils, Classes, IdBaseComponent, IdComponent, IdTCPServer, IdMappedPortTCP,
  IdSocks, IdTCPConnection, IdTCPClient, IdHTTP;


type
  TForm1 = class(TForm)
    Memo1: TMemo;
    HTTP: TIdHTTP;
    Server: TIdTCPServer;
    procedure ServerExecute(AThread: TIdPeerThread);
  private
  public
  end;

var
  Form1: TForm1;

implementation

uses
  IdURI, IdHTTPHeaderInfo;

{$R *.DFM}

procedure TForm1.ServerExecute(AThread: TIdPeerThread);
var
  lLines: TStringList;
  lURI: TIdURI;
  lsHost, lsResponse: string;
begin
  lLines := TStringList.Create;
  try
    lLines.Text := AThread.Connection.CurrentReadBuffer;
    if lLines.Count > 0 then
    begin
      Memo1.Lines.Add('=== REQUEST ===');
      Memo1.Lines.AddStrings(lLines);
      lsHost := lLines[0];
      Delete(lsHost, 1, 5);
      lURI := TIdURI.Create(lsHost);
      try
        HTTP.Host := lURI.Host;
        HTTP.Port := 80;
        lLines.Delete(0);
        // header
        HTTP.Request.RawHeaders.Clear;
        while lLines[0] <> '' do
        begin
          HTTP.Request.RawHeaders.Add(lLines[0]);
          HTTP.Request.ProcessHeaders;
          lLines.Delete(0);
        end;
        lLines.Delete(0);
        lsResponse := HTTP.Post(lURI.Path + lURI.Document + Copy(lURI.Params, 1, Length(lURI.Params)-9), lLines);
        AThread.Connection.Write(HTTP.Response.ResponseText + #13#10 + HTTP.Response.RawHeaders.Text + #13#10 + lsResponse);
        Memo1.Lines.Add('=== RESPONSE ===');
        lLines.Text := HTTP.Response.ResponseText + #13#10 + HTTP.Response.RawHeaders.Text + #13#10 + lsResponse;
        Memo1.Lines.AddStrings(lLines);
      finally
        lURI.Free;
      end;
    end;
  finally
    lLines.Free;
  end;
end;

end.
*** end of pascal ***

*** start of dfm ***
object Form1: TForm1
  Left = 311
  Top = 193
  Width = 354
  Height = 264
  Caption = 'Proxy Demo'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 0
    Top = 0
    Width = 346
    Height = 230
    Align = alClient
    TabOrder = 0
  end
  object HTTP: TIdHTTP
    MaxLineAction = maException
    ReadTimeout = 0
    AllowCookies = True
    ProxyParams.BasicAuthentication = False
    ProxyParams.ProxyPort = 0
    Request.ContentLength = -1
    Request.ContentRangeEnd = 0
    Request.ContentRangeStart = 0
    Request.ContentType = 'text/html'
    Request.Accept = 'text/html, */*'
    Request.BasicAuthentication = False
    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
    Request.ProxyConnection = 'Keep-Alive'
    HTTPOptions = [hoKeepOrigProtocol]
    Left = 80
    Top = 96
  end
  object Server: TIdTCPServer
    Active = True
    Bindings = <>
    CommandHandlers = <>
    DefaultPort = 81
    Greeting.NumericCode = 0
    MaxConnectionReply.NumericCode = 0
    OnExecute = ServerExecute
    ReplyExceptionCode = 0
    ReplyTexts = <>
    ReplyUnknownCommand.NumericCode = 0
    Left = 192
    Top = 96
  end
end
*** end of dfm ***

Because I couldn't get MSN to use the proxy permanently I didn't clean up the code.

Regards Jacco
0
 
LVL 1

Expert Comment

by:mgazza
ID: 12126061
you will need to code your proxy first before using any msn client with it
msn tests a proxy and if its not compleate it wont use it

i sujest you test your proxy by making a raw port app

Tclientsocket or email me i have one.  write setting the address as your.proxy.com
and sending

GET Http://get.my.web.page.com HTTP/1.1
connection: keep-alive
Host: get.my.web.page.com
#13#10
#13#10

email rcmgazza2@hotmail.com oka :D
0
 

Author Comment

by:pepoclv
ID: 12126895
Cool. Very nice guys. Thanks a lot.
I got Erwan L. (erwan.l@free.fr) sniffer project for example. And I'm working on it to listen to msn port.
But I will try proxy example too.

Thanks again.
0
 

Author Comment

by:pepoclv
ID: 12160167
So, I modified the Erwan L. sniffer to listen msn port. It works well on windows 2k, xp or high,
but don't run on Windows 98.

I think I went back to zero stage...

You can find my project at: http://200.201.133.13/mundo6br/listentomsn.zip

Any kind of help are welcome.

Thanks.
0
 

Author Comment

by:pepoclv
ID: 12192375
no comments, why?

I restarted my project from zero point  and now I'm using WinPCap functions and Snoop component.
It works well on all windows.

Thanks a lot for all help.

You can find my project at:  http://200.201.133.13/mundo6br/listentomsn.zip

Regards,

Rafael.

0
 

Author Comment

by:pepoclv
ID: 12192464
If it don't connect try others values for i on this procedure:


procedure TfrmMSNListen.StartCapture;
Var
  i:Integer;
  strIP:String;
begin
  Snoop1.Filter:='';
      Snoop1.ReadTimeOut:=100;
      Snoop1.SnapLen:=1600;
      Snoop1.ThreadSafe:=True;
      If SnoopMemory=Nil Then SnoopMemory:=TSnoopMemory.Create;
  i:=0; // <= HERE
  TryToConnect(i);
  While NOT(Snoop1.Active) Do
  Begin
    i:=i+1;
    TryToConnect(i);
    If i>5 then Break;
  End;
  If i>5 then
    Application.Terminate;
end;

-----------------

i variable is between 0 and 5 that represents index of network adapter, and I have another question at:
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21149551.html
that ask how to determine which adapter is connected on internet, like a Modem or LAN.

Regards,

Rafael;
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 13432813
PAQed with points refunded (500)

modulo
Community Support Moderator
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

729 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question