Link to home
Start Free TrialLog in
Avatar of pepoclv
pepoclv

asked on

How to make a MSN Messenger Chat Monitor?

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.
Avatar of Jacco
Jacco
Flag of Netherlands image

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:

https://www.experts-exchange.com/questions/20551029/Monitoring-Ports.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
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;
Avatar of pepoclv
pepoclv

ASKER

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.
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
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
IRIS is a firewall like application. Is "guard" feature is actually a firewall.
he'll need a threaded proxy will indy cope with that?

i personally prefer the tserversocket in blocking mode (TCustomWinsocket)

best regards,
mark
Indy is a lot easier.

Its threaded.

TIdMappedPortTCP inherits directly from TIdTCPServer and uses a TIdMappedPortThread for each connection.
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
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
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
humm it should do by defalt if you have told it to use a proxy it should always use it strange..
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
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
Avatar of pepoclv

ASKER

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.
Avatar of pepoclv

ASKER

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.
Avatar of pepoclv

ASKER

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.

Avatar of pepoclv

ASKER

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:
https://www.experts-exchange.com/questions/21149551/How-to-discover-which-network-adapter-is-connected-to-internet.html
that ask how to determine which adapter is connected on internet, like a Modem or LAN.

Regards,

Rafael;
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial