Solved

How to make a MSN Messenger Chat Monitor?

Posted on 2004-09-17
22
1,430 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
  • 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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
 

Author Comment

by:pepoclv
ID: 12192577
0
 

Accepted Solution

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

modulo
Community Support Moderator
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

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…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

706 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now