病毒的自我复制

对静态开源文件进行复制

  设置两个指针,一个指向源文件为srcpf,一个指向目的文件为destpf。为实现用户可控的操作方式,允许输入复制次数,但同时为防止无限次复制导致磁盘损坏,因此设置循环次数上限为1000次。同时,由于各用户磁盘分卷存在差异,因此允许用户对目标地址进行设置;同时在该地址后加上文件名对地址进行测试,以验证并保证地址的可行性。随后,利用fread()函数和fwrite()函数进行文件的读写。需要注意的是,为防止文件名重复,需要对每次循环的文件名进行部分修改,故更改字符“0”使其每次增加1。最后,若复制成功,则输出提示成功字样。
  具体代码如下:

#include<stdio.h>
#include<string.h>
#include<windows.h>

int main(){
	
	int N;
	do{
		printf("请输入复制次数:");
		scanf("%d", &N);
		if(N > 1000)  printf("------复制次数过大建议更改!------\n");
	}while(N > 1000);
	
	FILE *destpf = NULL, *srcpf = NULL;
	char dest[1000], filename[16]={'c', 'o', 'p', 'y','0', '.', 'c', 'p', 'p', '\0'};
	do{
		printf("请输入目标地址:");
		scanf("%s", &dest);
		strcat(dest, filename);
		destpf = fopen(dest, "w+");
		if(destpf == NULL)  printf("------目标地址无效,请重新输入!------\n");
	}while(destpf == NULL);
	
	srcpf = fopen("copy.cpp", "r+");
	if(!srcpf){
		printf("------打开源文件失败!------\n");
		system("pause");
		return 0;
	}  
	
	int size; char temp; 
	rewind(srcpf);
	while(size = (fread(&temp, sizeof(char), 1, srcpf)))
		fwrite(&temp, sizeof(char), 1, destpf);
	fclose(destpf);
	
	int len = strlen(dest);
	for(int i = 1; i < N; i++){
		dest[len - 5] += 1;
		destpf = fopen(dest, "w+");
		rewind(srcpf);
		while(size = (fread(&temp, sizeof(char), 1, srcpf)))
			fwrite(&temp, sizeof(char), 1, destpf);
		fclose(destpf);	
	} 
	
	fclose(srcpf);
	destpf = srcpf = NULL;
	printf("------文件已成功复制!------\n");
	system("pause");	 

	return 0;
}

  对该程序进行测试,当输入超过1000的复制次数时,提示“次数过多”,如下:

  当输入的地址不合法时,提示重新输入直至地址合法,如下:

  当输入正确地址时,按要求在指定地址复制文件并提示“成功复制!”,如下:

  在指定位置查看文件是否成功复制如下:

  观察到,文件已成功复制到指定路径,数量一致且命名数字递增。打开复制文件对内容进行测试,观察到内容也成功被复制,如下:

对静态二进制文件流进行复制

  由于Windows的exe文件采用了PE文件的组织格式,用fopen()等函数无法操作,需要采用文件流的方式进行复制工作,恰好C++的iostream的子类提供了以文件流方式读取的接口。
  引用头文件“fstream”即File Stream中的ifstream类和oftream类。其中ifstream表示从主存中以文件流方式载入一个文件到内存中,由于实验要求完成二进制文件的复制,因此使用参数“ios::binary”以二进制形式载入文件。与之对应的,ofstream表示将内存中的文件以文件流方式转存至主存中,其同样提供了参数“ios::binary”来完成二进制形式的写入方式。注意到,其参数继承于“ios”,因此同样需要包含头文件“ios”。
  为提高交互能力和个性化设置,用户可自行设定复制的目的地址。与静态开源文件的路径检测方式不同,此处笔者使用了新的检测方式,来提供另一种路径检测的思路。使用头文件“io.h”中定义的access()函数,其参数包括“filepath”和“mode”,其中filepath可以为文件或文件夹;mode为检测形式,我们使用参数0表示仅检测该路径是否存在。
  由于不确定要复制的二进制文件长度,因此每次复制一个字符,直到遇到文件尾,同时使用gcount()函数来确定成功复制的字符长度,当其大于0是进行复制写入操作,以保证每次操作的正确性。
  根据上述描述,编写程序代码如下:

#include<iostream>
#include<io.h>
#include<string>
#include<fstream>
#include<ios>
#include<windows.h>
using namespace std;
 
const int BUFFER_SIZE=4;
 
void update(ifstream &in, char *filename){
	std::streamsize length;
	char buffer[2];
	ofstream destfile(filename, ios::binary);
	while(!in.eof()){
		in.read(buffer, 1);
		length = in.gcount();
		if (length > 0)
			destfile.write(buffer, length);
	}
	in.close();
	destfile.close();
}
 
 
int main(){
	
	int N;
	do{
		printf("请输入复制次数:");
		scanf("%d", &N);
		if(N > 1000)  printf("------复制次数过大建议更改!------\n");
	}while(N > 1000);
	
	char dest[1000];
	int flag;
	do{
		printf("请输入目标地址:");
		scanf("%s", &dest);
		flag = access(dest, 0);
		if(flag != 0)  printf("------目标地址无效,请重新输入!------\n");
	}while(flag != 0);
	
	ifstream srcfile("F:\\copyexe.exe");
	if(!srcfile){
		printf("------打开源文件失败!------\n");
		system("pause");
		return 0;
	}
	srcfile.close();
	
	char filetail[16]={'c', 'o', 'p', 'y','0', '.', 'e', 'x', 'e', '\0'};
	strcat(dest, filetail);
	int len = strlen(dest);
	for(int i = 0; i < N; i++){
		dest[len - 5] = '0' + i;
		ifstream srcfile("F:\\copyexe.exe", ios::binary);
		update(srcfile, dest);
	}
	
	printf("------文件已成功复制!------\n");
	system("pause");	
	return 0;
}

  该复制程序对文件复制数量进行了限制,最大复制数量为1000,当超过阈值时提示“复制次数过多”,如下:

  检测access()函数使用的正确性,观察,非法路径是否会被成功拦截,如下:

  当输入有效地址后完成复制并给用户提示,如下:

  在指定地址下查看复制是否成功,观察到出现指定次数个文件,如下:

  打开运行,其功能保持和源程序的一致性,如下:

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

D-A-X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值