windows的net send的信息如何截获? (100分)

  • 主题发起人 主题发起人 qevan
  • 开始时间 开始时间
Q

qevan

Unregistered / Unconfirmed
GUEST, unregistred user!
欧只知道 net send 功能是windows的Messager服务,如何自己写个程序将之替代,
可以和别的机器的messager服务通信?
 
好象系统用的是邮件槽服务还是命名管道,,,
 
关注。
会不会类似qq之类的。
 
procedure SendNetMessage(YourName, ComputerName,
MessageStr: String);
Var
Rc: LongBool;
MsHandle: Longint;
MsgText: String;
BytesWritten: Cardinal;
MailSlotName: String;
begin
MailSlotName := '//' + ComputerName + '/mailslot/messngr';
MsgText := YourName + Chr(0) + ComputerName + Chr(0) + MessageStr + Chr(0);
MsHandle := CreateFile(PChar(MailSlotName), GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, $FFFFFFFF);
if MsHandle = INVALID_HANDLE_VALUE then
RaiseLastWin32Error;

RC := WriteFile(MsHandle, Pointer(MsgText)^, Length(MsgText), BytesWritten, 0);

if not Rc then
RaiseLastWin32Error;

Rc := CloseHandle(MsHandle);
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
SendNetMessage('yang', 'yang', 'Hello');
end;

WinPopup
This here started with me getting fed up with the way WinPopup was working. I
always had this big visible block in my taskbar in Windows 95, and therefore I
often did not use my WinPopup - which the others often thought irritateing.
Also the fact that I was using non English letters in my login name, which made
the Danish versions (not the English versions) of WinPopup ignore sending
messages to me, even I had started WinPopup.

So what do a programmer do? He deside to make his own version of WinPopup! Yes,
but how?

I looked around in the WIN32 API for functions which were meeting the
functionabillity of WinPopup, and found mailslots. Mailslots is a conection
less service, which is made directly accessible in Windows 95 and NT. The
mailslots create a kind of virtual file on your machine (when your are the
owner of a mailslot), where other machines can write into.

The mailslots should be tried out, so I implemented the functionallity in a
program, and it all looked like the functionallity of WinPopup, but I was
still not any further because a mailslot have a name, and what name did
Microsoft choose to there system messages (Printer notification and WinPopup
messages) - I could not guess :(

I created a usable mailslot object, and made it avalible on the Internet so
other could user my work now when I coudn't (wasn't that nice of me?). After
a week - or so - someone wrote to me and asked if I knew how he could send a
message to WinPopup :( - and ofcource I cound not help him. But this guy
started searching himself, and a few days later he mailed me the "secret"
mailslot name "messngr".

Next we were looking for the format of a message - that was not so difficult
to find out of by sending messages. A recieved block of data is threaded as
folow three NULL terminated strings after each other :


Sender

Reciever

Message

So 'MARTIN'#0'DON'#0'Hi'#0 is a message from Martin to Don with the message Hi.
In the next I'll tell how to use mailslots (the Windows - WinPopup one as example),
using examples in a Pascal-like code. The code parts is not fully explaining
(if you want to use mailslots in a program you have a compiler and a helpfile
where you can find the exact syntax) - I'll just tell you about what you need
for making use of this function.
If you are Delphi 2.0 developer then you can go to my VCL page where I have a
fully functional VCL, with all the source code, for free download. For writing
to an existing mailslot (send a message over the network), all you have to do
is to thread the mailslot as a file on the target machine, whith this filename :


"//"+Server_Name+"/mailslot/messngr"
To write to this file, first open it like this :


Handle := CreateFile("//THOR/mailslot/messngr",
GENERIC_WRITE,
FILE_SHARE_READ,
NIL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
-1)
The handle returned can then be used in a call to write to the file like this :


WriteFile(Handle,
Data,
Size(Data),
BytesWritten,
NIL)
It is wise to close the handle after user with a call like this :


CloseHandle(Handle)
That was easy - wasn't it?

To make a mailslot avalible for other to use, you have to create a mailslot
usong the CreateMailslot function like this :


Handle := CreateMailSlot("//./mailslot/messngr",
0,
$FFFFFFFF,
NIL)
The handle returned from the CreateMailSlot function should then be used for accessing the mailslot. Note the value $FFFFFFFF should also be called "MAILSLOT_WAIT_FOREVER", but my Delphi 2.0 does not reconize the name. The value is also said in the WIN32 API helpfile to make a read from the mailslot go into a blocked waitstate until something is arriving into it, but I can not make it do so :(.

For checking up anything is in the mailslot call the GetMailSlotInfo function


GetMailSlotInfo(Handle,NIL, NextSize, @Waiting, NIL)
where NextSize and Waiting is both defined as DWord's.
NextSize will after a call contain the size of the next message
(for allocation of buffer) and Waiting will contain the number of messages waiting.

For reading from a mailslot, all which is needed to be done, is to call the ReadFile function with the handle recieved from the CreatMailSlot function, like this :


ReadFile(Handle,Buffer^,NextSize,ReadSize,NIL)
After end use of the mailslot I'll advise you to close the handle with the CloseHandle function (as far as I have understood, it is not strictly necessary) like this :


CloseHandle(FHandle)
Before continuing to the next problem, I'll like to thank Don Hass for telleing me about the "messngr" mailslot.

 
不知楼上的方法在xp下能用否,我晚上try 以下,
不管能用不用,谢谢先!
 
能用,不过俺也是copy来的,大概是tseug或者dragonpc??最近贴的吧。
一个国外论坛上面的帖子。
 
多谢。
有没有取信息的sample,
另外,文件名一定是messngr?我试了其他的文件名不管用的

还有一定要用对方的计算机名么?用IP不行么?
如果不在同一子网里,用计算机名不就不能net send 了嘛,怎么办?

原贴是在哪个论坛上的?能否告诉我。
 
用ip是可以的。
但是我遇到别的问题,就是把Messenger服务停止后,自己开邮件槽。但是别人发不过来。???
 
不行的阿,我用ip试的不行啊,
 
net send 使用信使服务,用IP可以
但把Messenger服务停止,就不行了
有个软件叫 凶宝宝 可以借鉴一下
可以修改信息源,设置群发,连续发送次数(比如1000000次)
 
to breezee, 不是用net send 阿,
是用4楼的方法,怎么用IP 阿?
 
首先把ip转成域名不就行了
 
unit Unit2;

interface

uses
Classes,winsock,sysutils,windows;

type
convert = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;

implementation
uses unit1;

function GetIP(Name:string) : string;
type
TaPInAddr = array [0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe :PHostEnt;
pptr : PaPInAddr;
I : Integer;
GInitData : TWSADATA;
begin
WSAStartup($101, GInitData);
Result := '';
phe :=GetHostByName(pchar(Name)); //返回一个指向主机信息结构的指针
pptr := PaPInAddr(Phe^.h_addr_list); //强制转换
result:=StrPas(inet_ntoa(pptr^[0]^));//返回一个点分形式的字符串IP地址
WSACleanup;
end;

function GetDomainName(Ip:string):string;
var
pH:PHostent;
data:twsadata;
ii:dword; //即ii 为LongWord类型
begin
WSAStartup($101, Data);
ii:=inet_addr(pchar(ip)); // 返回一个适合Internet的数字化地址
pH:=gethostbyaddr(@ii,sizeof(ii),PF_INET);//返回一个指向主机信息结构的指针
if (ph<>nil) then
result:=pH.h_name //返回该结构的主机名
else
result:='';
WSACleanup();
end;

procedure convert.Execute;
var i:integer;temp:string;comp:boolean;
begin
temp:=form1.Edit1.Text;
comp:=false;
for i:=1 to length(temp) do begin
if ((temp>'9') or (temp<'0')) and (temp<>'.') then begin//是IP则要换成dns
form1.Button1.Caption:='终止';
Form1.Edit1.Text:=GetIp(temp);
comp:=true;
Form1.Button1.Caption:='转化';
end;
if comp then break;//完成DNS->IP的转化
end;
if not comp then begin //是IP,则完成IP->DNS的转化
form1.Button1.Caption:='终止';
Form1.Edit1.Text:=GetDomainName(temp);
Form1.Button1.Caption:='转化';
end;
end;

end.
 
如果在不同的子网里,主机名是无法识别的,
像net send要发给另一个子网的机器就只能用ip不能用主机名的。
 
有意思,我就知道去事件日志里查,帮你顶
 
我也一直在找这个问题的答案,不过没有好的,有一种简单方法是:在2000或XP下时,找到“信使服务 ”这个窗口,得到上面的文字。,在98下用上面的方法就可以了。
 
我找到了:
发信人:zzzzzzzzzzzz(肥龟·Synchronize),信区:Programming
标题:拦截你的NetSend(一)
发信站:逸仙时空Yat-senChannel(SunMay412:51:262003),站内信件

作者:ZSQ

大家应该会经常收到一些骚扰的NetSend消息,有没有想过怎么实现消息过滤呢?

有没有想过为netsend定制一个pp一点的界面呢,或者利用NetSend做一个聊天室
呢?

归结到最后,我们发现问题的关键在于,如何替换掉WindowsNetSend服务

如果大家注意一下nbtstat的输出,就会发现

NetBIOSRemoteMachineNameTable

NameTypeStatus
--------------------------------------------
ZSQ<00>UNIQUERegistered
CHINA<00>GROUPRegistered
ZSQ<20>UNIQUERegistered
ZSQ<03>UNIQUERegistered
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~这个就是NetSend用的Stub
CHINA<1E>GROUPRegistered
ZSQ<01>UNIQUERegistered

类似于Socket中端口,所有的NetSend消息,都是通过这个位置传到你的计算机的

所以我们的第一个任务就是要先把这个端口关闭,然后用我们自己的服务来替换掉它

命令行方式的netstopmsg可以把整个消息服务关闭

只要我们写的程序沿用消息服务的协议,就可以完全地替换掉它的功能了

(待续)

Windows的消息服务沿用的是SMB/CIFSOverNetbiosOverTCP/IP的架构

我们自然就从这方面着手,主要实现两个功能,1是接收,二是发送

以下是实现的源代码,具体的原理也容易理解

//QMessngr.h

#defineWM_QMESSNGR_NOTIFYWM_USER+1

#defineMAX_BUFFER_LENGTH500
#defineREPLY_LENGTH35
#defineSMB_HEADER_LENGTH35
#defineNAME_LENGTH16


classCQMessngr
{
public:
CQMessngr();
virtual~CQMessngr();

public:

//发送函数
BOOLSend(char*sTo,char*sMsg);

//启动/停止消息接收线程
//参数:HWND接收消息的窗口句柄,
//收到消息后会发送WM_MESSENGER_NOTIFY到该窗口
intStart(HWNDhwnd);
intStop();

//线程函数
staticUINTMsgMonitorProc(LPVOIDparam);
staticCQMessngr*pseudoThis;//
staticHWNDhWndNotify;

public:
charm_sLocalName[16];
charm_sMsg[400];
UCHARm_sBuffer[500];
CWinThread*m_pThread;

};

(待续)


//QMessngr.cpp


#pragmacomment(lib,"netapi32.lib")
#pragmacomment(lib,"ws2_32.lib")

CQMessngr*CQMessngr::pseudoThis=NULL;
HWNDCQMessngr::hWndNotify=NULL;

voidToNcbName(char*str1,char*str2)
{
charpattern[20];
sprintf(pattern,"%%%ds",NAME_LENGTH);
sprintf(str2,pattern,"/3");
memcpy(str2,str1,strlen(str1));
}

CQMessngr::CQMessngr()
{
//成员变量初始化
WSADATAwsadata;
charname[NAME_LENGTH];
WSAStartup(MAKEWORD(2,0),&amp;wsadata);
gethostname(name,NAME_LENGTH);
_tcsupr(name);
strcpy(m_sLocalName,name);
strcpy(m_sRemoteName,"*");
strcpy(m_sMsg,"");

//NETBIOS初始化
NCBncb;
memset(&amp;ncb,0,sizeof(ncb));
ncb.ncb_command=NCBRESET;
intb=Netbios(&amp;ncb);

charncbname[NAME_LENGTH];
ToNcbName(m_sLocalName,ncbname);
ncb.ncb_command=NCBADDNAME;
memcpy((char*)ncb.ncb_name,ncbname,NAME_LENGTH);

b=Netbios(&amp;ncb);
if(b==NRC_DUPNAME){
MessageBox(NULL,"Messngr端口发现重名,初始化失败","警告",MB_OK);
return;
}elseif(b!=0){
MessageBox(NULL,"Messngr未知错误,初始化失败","警告",MB_OK);
}
}

CQMessngr::~CQMessngr()
{
NCBncb;
charncbname[NAME_LENGTH];
memset(&amp;ncb,0,sizeof(ncb));
ToNcbName(m_sLocalName,ncbname);
ncb.ncb_command=NCBDELNAME;
memcpy((char*)ncb.ncb_name,ncbname,NAME_LENGTH);
intb=Netbios(&amp;ncb);
}



//发送函数
BOOLCQMessngr::Send(char*sTo,char*sMsg)
{
NCBncb;
charncbname[NAME_LENGTH];
intbRet;

memset(&amp;ncb,0,sizeof(ncb));
ToNcbName(m_sLocalName,ncbname);
memcpy((char*)ncb.ncb_name,ncbname,16);
ToNcbName(sTo,ncbname);
memcpy((char*)ncb.ncb_callname,ncbname,16);
ncb.ncb_command=NCBCALL;
bRet=Netbios(&amp;ncb);

//memset(buffer,0,sizeof(buffer));
memset(m_sBuffer,0,sizeof(m_sBuffer));
sprintf((char*)m_sBuffer,"%c%s%c",0xff,"SMB",0xD0);
unsignedchar*pos=m_sBuffer+0x21;
intLength=7+strlen(m_sLocalName)+strlen(sTo)+strlen(sMsg);
*((WORD*)pos)=Length;
pos+=2;
*(pos++)=4;//TYPE
strcpy((char*)pos,m_sLocalName);//MACHINENAME
pos+=strlen(m_sLocalName)+1;
*(pos++)=4;//TYPE
strcpy((char*)pos,sTo);//MACHINENAME
pos+=strlen(sTo)+1;
*(pos++)=1;
*((WORD*)pos)=strlen(sMsg);
pos+=2;
memcpy(pos,sMsg,strlen(sMsg));
ncb.ncb_buffer=m_sBuffer;
ncb.ncb_length=Length+0x23;
ncb.ncb_command=NCBSEND;
bRet=Netbios(&amp;ncb);

ncb.ncb_command=NCBRECV;
ncb.ncb_buffer=m_sBuffer;
ncb.ncb_length=MAX_BUFFER_LENGTH;
bRet=Netbios(&amp;ncb);

ncb.ncb_command=NCBHANGUP;
bRet=Netbios(&amp;ncb);

returnTRUE;
}

//初始化NETBIOS功能,启动消息接收线程
//参数:HWND接收消息的窗口句柄,
//收到消息后会发送WM_MESSENGER_NOTIFY到该窗口
intCQMessngr::Start(HWNDhwnd)
{
pseudoThis=this;
hWndNotify=hwnd;
m_pThread=AfxBeginThread(MsgMonitorProc,NULL);
returnTRUE;

}

intCQMessngr::Stop()
{
TerminateThread(m_pThread->m_hThread,0);
return0;
}


//线程函数
UINTCQMessngr::MsgMonitorProc(LPVOIDparam)
{
NCBncb;
charncbname[NAME_LENGTH];
intbRet;

while(TRUE)
{
////////////LISTENONNAMESTUB//////////////
memset(&amp;ncb,0,sizeof(ncb));
ToNcbName(pseudoThis->m_sLocalName,ncbname);
memcpy((char*)ncb.ncb_name,ncbname,NAME_LENGTH);
strcpy((char*)ncb.ncb_callname,"*");
ncb.ncb_command=NCBLISTEN;
bRet=Netbios(&amp;ncb);

//RECEIVETHENETBIOSBLOCKWHICHCONTAININGSMBDATA//
ncb.ncb_command=NCBRECV;
ncb.ncb_buffer=pseudoThis->m_sBuffer;
ncb.ncb_length=MAX_BUFFER_LENGTH;
bRet=Netbios(&amp;ncb);

////////////SENDNETBIOSACK/////////////////
pseudoThis->m_sBuffer[33]=0;
ncb.ncb_length=REPLY_LENGTH;
ncb.ncb_command=NCBSEND;
bRet=Netbios(&amp;ncb);

///////////PARSETHESMBPACKET//////////////
//SMBStructure
//TYPE1byte04Name
//REMOTEMACHINENAMEstringterminatewith'/0'
//TYPE1byte04Name
//LOCALMACHINENAMEstringterminatewith'/0'
//TYPE1byte01Message
//LENGTH2byte
//DATAstringwiththeLengthindicateinLENGTH

unsignedchar*pos=pseudoThis->m_sBuffer+SMB_HEADER_LENGTH+1;
strcpy(pseudoThis->m_sRemoteName,(char*)pos);
pos+=strlen((char*)pos)+2;
pos+=strlen((char*)pos)+2;
WORDMsgLength=*((WORD*)pos);
pos+=2;
memset(pseudoThis->m_sMsg,0,sizeof(pseudoThis->m_sMsg));
memcpy(pseudoThis->m_sMsg,(char*)pos,MsgLength);
*(pseudoThis->m_sMsg+MsgLength)=0;

////////////POSTAMESSAGETOTHENOTIFYWINDOW//////////
PostMessage(hWndNotify,WM_QMESSNGR_NOTIFY,NULL,NULL);

}
return0;
}

(待续)

 
后退
顶部