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;ASt ream: TStream);
procedure IdLogStream1Receive(ASende r: 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(Sen der: TObject);
begin
IdTCPClient1.BoundIP:='127 .0.0.1';
IdTCPClient1.BoundPort:=18 63;
IdTCPClient1.Host:='127.0. 0.1';
IdTCPClient1.Port:=1863;
IdTCPClient1.Connect;
If IdTCPClient1.Connected Then
ShowMessage('Connected');
end;
procedure TForm1.IdLogEvent1Send(ASe nder: TIdConnectionIntercept;
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si ze);
AStream.Position:=0;
AStream.Read(sLine[1],AStr eam.Size);
finally
Memo1.Lines.Add('<='+sLine );
end;
end;
procedure TForm1.IdLogEvent1Receive( ASender: TIdConnectionIntercept;
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si ze);
AStream.Position:=0;
AStream.Read(sLine[1],AStr eam.Size);
finally
Memo1.Lines.Add('=>'+sLine );
end;
end;
procedure TForm1.IdLogStream1Receive (ASender: TIdConnectionIntercept;
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si ze);
AStream.Position:=0;
AStream.Read(sLine[1],AStr eam.Size);
finally
Memo1.Lines.Add('Received: '+sLine);
end;
end;
procedure TForm1.IdLogStream1Send(AS ender: TIdConnectionIntercept;
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si ze);
AStream.Position:=0;
AStream.Read(sLine[1],AStr eam.Size);
finally
Memo1.Lines.Add('Sent: '+sLine);
end;
end;
procedure TForm1.btnDisconnectClick( Sender: TObject);
begin
IdTCPClient1.Disconnect;
end;
end.
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
procedure IdLogStream1Receive(ASende
procedure IdLogStream1Send(ASender: TIdConnectionIntercept; AStream: TStream);
procedure btnDisconnectClick(Sender:
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnConnectClick(Sen
begin
IdTCPClient1.BoundIP:='127
IdTCPClient1.BoundPort:=18
IdTCPClient1.Host:='127.0.
IdTCPClient1.Port:=1863;
IdTCPClient1.Connect;
If IdTCPClient1.Connected Then
ShowMessage('Connected');
end;
procedure TForm1.IdLogEvent1Send(ASe
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si
AStream.Position:=0;
AStream.Read(sLine[1],AStr
finally
Memo1.Lines.Add('<='+sLine
end;
end;
procedure TForm1.IdLogEvent1Receive(
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si
AStream.Position:=0;
AStream.Read(sLine[1],AStr
finally
Memo1.Lines.Add('=>'+sLine
end;
end;
procedure TForm1.IdLogStream1Receive
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si
AStream.Position:=0;
AStream.Read(sLine[1],AStr
finally
Memo1.Lines.Add('Received:
end;
end;
procedure TForm1.IdLogStream1Send(AS
AStream: TStream);
Var
sLine:String;
begin
try
SetLength(sLine,AStream.Si
AStream.Position:=0;
AStream.Read(sLine[1],AStr
finally
Memo1.Lines.Add('Sent: '+sLine);
end;
end;
procedure TForm1.btnDisconnectClick(
begin
IdTCPClient1.Disconnect;
end;
end.
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,Acom mand,'');
ChatWindow.DropWindow.Add(
Format('%s Says:',
[TFriend(UserFromAddy(Word At(Acomman d,2))^).ni ck]) //todo get user name from addy
);
ChatWindow.DropWindow.Add( ' '+tmp);
ChatWindow.Alertit;
ChatWindow.Show;
end;
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
if WordAt(tmp,1)='text/plain;
Tmp:=GetWordAfter(#13#10+#
ChatWindow.DropWindow.Add(
Format('%s Says:',
[TFriend(UserFromAddy(Word
);
ChatWindow.DropWindow.Add(
ChatWindow.Alertit;
ChatWindow.Show;
end;
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.
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-messenge r
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
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.
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Pragma: no-cache
Content-Type: application/x-msn-messenge
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
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
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.
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
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 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
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(AThre ad: TIdPeerThread);
var
lLines: TStringList;
lURI: TIdURI;
lsHost, lsResponse: string;
begin
lLines := TStringList.Create;
try
lLines.Text := AThread.Connection.Current ReadBuffer ;
if lLines.Count > 0 then
begin
Memo1.Lines.Add('=== REQUEST ===');
Memo1.Lines.AddStrings(lLi nes);
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.Cl ear;
while lLines[0] <> '' do
begin
HTTP.Request.RawHeaders.Ad d(lLines[0 ]);
HTTP.Request.ProcessHeader s;
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(H TTP.Respon se.Respons eText + #13#10 + HTTP.Response.RawHeaders.T ext + #13#10 + lsResponse);
Memo1.Lines.Add('=== RESPONSE ===');
lLines.Text := HTTP.Response.ResponseText + #13#10 + HTTP.Response.RawHeaders.T ext + #13#10 + lsResponse;
Memo1.Lines.AddStrings(lLi nes);
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.BasicAuthentic ation = False
ProxyParams.ProxyPort = 0
Request.ContentLength = -1
Request.ContentRangeEnd = 0
Request.ContentRangeStart = 0
Request.ContentType = 'text/html'
Request.Accept = 'text/html, */*'
Request.BasicAuthenticatio n = 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.Numeric Code = 0
OnExecute = ServerExecute
ReplyExceptionCode = 0
ReplyTexts = <>
ReplyUnknownCommand.Numeri cCode = 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
*** 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(AThre
var
lLines: TStringList;
lURI: TIdURI;
lsHost, lsResponse: string;
begin
lLines := TStringList.Create;
try
lLines.Text := AThread.Connection.Current
if lLines.Count > 0 then
begin
Memo1.Lines.Add('=== REQUEST ===');
Memo1.Lines.AddStrings(lLi
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.Cl
while lLines[0] <> '' do
begin
HTTP.Request.RawHeaders.Ad
HTTP.Request.ProcessHeader
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(H
Memo1.Lines.Add('=== RESPONSE ===');
lLines.Text := HTTP.Response.ResponseText
Memo1.Lines.AddStrings(lLi
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.BasicAuthentic
ProxyParams.ProxyPort = 0
Request.ContentLength = -1
Request.ContentRangeEnd = 0
Request.ContentRangeStart = 0
Request.ContentType = 'text/html'
Request.Accept = 'text/html, */*'
Request.BasicAuthenticatio
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.Numeric
OnExecute = ServerExecute
ReplyExceptionCode = 0
ReplyTexts = <>
ReplyUnknownCommand.Numeri
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
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
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.
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.
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.
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.
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.
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.
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;
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.
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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