设置密码隐密文件工具 v1.4

 设置密码隐密文件工具 v1.4

设计原理:在磁盘上创建一个文件夹,并通过修改此文件夹的访问控制列表(ACL)和文件夹属性从而“加密”此文件夹;之后在被“加密”的文件夹系统内部存储需要被隐藏的文件。访问文件夹系统内部需要密码,密码由程序用户设定。存储访问密码的文件同样被置于此文件夹系统内部,且被设定为系统及隐藏文件属性。

隐藏原理:设定访问控制列表(ACL)和文件属性。

设计缺陷:可在Windows资源管理器(explorer.exe)中通过手动键入路径,从而直接访问到被隐藏的文件。此外,深谙Windows文件系统以及Windows命令行的你可在5分钟内破解“加密”。

设计实现:基于Windows API(文件系统API及控制台系统API)。

/*设置密码隐密文件工具 v1.4
**By obertys 2020/08/13
**使用说明:
**	定义keyMAXLen宏为设置密码最大允许的长度
**	定义caclsPATH宏为最外层的文件夹绝对路径
**	定义targetPATH宏为内层文件夹的绝对路径(是caclsPATH的子路径)
**	定义dataFilePATH常量作为存贮密码的数据文件绝对路径(位于targetPATH内部,含文件名)
**	定义pragramTitle常量作为控制台显示标题
**注意事项:
**	除非出于研究程序工作原理的目的,否则勿更改文件夹系统的属性
**	此程序仅供个人学习使用;勿将此程序作为专业的文件加密工具
**  如磁盘根目录下有与caclsPATH同名的文件夹存在,则只需修改caclsPATH即可;如无必要,勿改动targetPATH或dataFilePATH的路径深度
**	如忘记密码或有其它问题,请联系程序作者或自己动手
**编译支持:
**	Windows平台下的C编译器
**运行支持:
**	Windows操作系统
*/

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

#define keyMAXLen 16	//密码最大长度
#define caclsPATH "C:\\data"	//隐密文件夹一级路径
#define targetPATH caclsPATH"\\crtys"	//存放隐密文件的目录(必须是caclsPATH的子目录)
const char* dataFilePATH=targetPATH"\\data.at";	//存贮密码的文件路径(必须是targetPATH的子路径)
const char* pragramTitle="设置密码隐密文件工具 v1.4";

#if (keyMAXLen<=0)
#error 密码最大长度无效
#endif // keyMAXLen

DWORD WINAPI Th(LPVOID pParam)	//线程函数
{
	getch();	//等待任意键输入
	*(BOOL*)pParam=TRUE;	//接受到输入后将函数传参置为TRUE
	return 0;
}

DWORD fileExist(const char* filePath)	//检验文件filePath是否存在;若不存在返回0,若存在返回文件属性DWORD值
{
	WIN32_FIND_DATA fd;
	HANDLE hFind=FindFirstFile(filePath,&fd);
	if(hFind==INVALID_HANDLE_VALUE)	//查找文件失败
		return 0;
	else
	{
		FindClose(hFind);
		return fd.dwFileAttributes;
	}
}

size_t readInputKey(char* key)	//从标准输入流读取密码,key为指向一个char[keyMAXLen+1]数组的char指针,返回读取到的密码实际长度
{
	*key='\0';
	size_t inputKeyLen=0;	//密码实际长度
	char c;
	while((c=getch())!='\r')	//敲下回车键输入终止
		if(c=='\b')	//敲下退格键
		{
			if(inputKeyLen>0)
			{
				key[--inputKeyLen]='\0';	//密码删除最后一位
				printf("\b \b");	//清除一个字符'*'
			}
		}
		else if(inputKeyLen<keyMAXLen)
		{
			key[inputKeyLen++]=c;	//密码后缀当前输入字符
			key[inputKeyLen]='\0';	//确保空结尾
			putchar('*');	//打印一个字符'*'
		}
	putchar('\n');
	return inputKeyLen;
}

int newKey(void)	//设置新密码
{
	/*输入密码*/
	char inputKey_A[keyMAXLen+1],inputKey_B[keyMAXLen+1];
	size_t len;	//新密码长度
	for(BOOL loop=TRUE; loop; )
	{
		printf("请设置新密码:");
		readInputKey(inputKey_A);
		printf("请再键入一次:");
		len=readInputKey(inputKey_B);
		if(strcmp(inputKey_A,inputKey_B)!=0)
			puts("密码不一致!");
		else if(len==0)
			puts("密码不能为空!");
		else
			loop=FALSE;	//当新密码合法时结束循环
	}
	/*打开数据文件*/
	DWORD dataFileAttrib=fileExist(dataFilePATH);
	if(dataFileAttrib!=0)	//数据文件存在
	{
		if((dataFileAttrib&FILE_ATTRIBUTE_SYSTEM)==FILE_ATTRIBUTE_SYSTEM)	//数据文件是系统属性
			dataFileAttrib^=FILE_ATTRIBUTE_SYSTEM;	//解除系统属性
		if((dataFileAttrib&FILE_ATTRIBUTE_HIDDEN)==FILE_ATTRIBUTE_HIDDEN)	//数据文件是隐藏属性
			dataFileAttrib^=FILE_ATTRIBUTE_HIDDEN;	//解除隐藏属性
		SetFileAttributes(dataFilePATH,dataFileAttrib);
	}
	FILE* dataFile=fopen(dataFilePATH,"wb");
	if(dataFile==NULL)
	{
		puts("无法打开数据文件\n未能设置新密码");
		getch();
		return 2;
	}
	/*写入数据文件*/
	fwrite(inputKey_A,sizeof(char),len,dataFile);	//向文件写入密码(仅含有效字符,不含'\0'或'\n')
	fclose(dataFile);
	if(dataFileAttrib==0)	//数据文件是新创建的
		dataFileAttrib=GetFileAttributes(dataFilePATH);	//获取最新属性
	dataFileAttrib|=FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM;	//设置隐藏属性及系统属性
	SetFileAttributes(dataFilePATH,dataFileAttrib);
	puts("新密码已设置\n");
	getch();
	return 0;
}

int main(void)
{
	/*初始化界面*/
	system("cmd /c mode con cols=33 lines=8&color 0A");	//设置窗口大小及颜色
	SetConsoleTitle(pragramTitle);	//设置窗口标题
	printf("欢迎使用%s\n",pragramTitle);
	/*初始化文件目录*/
	if(CreateDirectory(caclsPATH,NULL))	//尝试创造目录
	{
		if(!CreateDirectory(targetPATH,NULL))	//在新创建的caclsPATH下创建targetPATH
		{
			printf("路径错误:\"%s\"\n",targetPATH);
			return 4;
		}
		DWORD attrib=GetFileAttributes(caclsPATH);
		attrib|=FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM;	//设置caclsPATH为隐藏属性及系统属性
		SetFileAttributes(caclsPATH,attrib);
		system("cmd /c echo Y|cacls "caclsPATH" /d everyone>nul");	//使用cacls对目录caclsPATH执行权限保护
		HANDLE fileHAND=CreateFile(targetPATH"\\将需要被隐藏的文件或文件夹置于此目录下.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL);
		if(fileHAND!=INVALID_HANDLE_VALUE)
			CloseHandle(fileHAND);
		puts("已设置加密文件存放路径");
	}
	else
	{
		DWORD errorDWORD=GetLastError();
		if(errorDWORD!=ERROR_ALREADY_EXISTS)	//无法创造目录且目录并非已存在
		{
			printf("路径错误:\"%s\"\n",caclsPATH);
			return 3;
		}
		if(CreateDirectory(targetPATH,NULL))	//尝试在已存在的caclsPATH下创建targetPATH
		{
			HANDLE fileHAND=CreateFile(targetPATH"\\将需要被隐藏的文件或文件夹置于此目录下.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL);
			if(fileHAND!=INVALID_HANDLE_VALUE)
				CloseHandle(fileHAND);
			puts("已恢复不存在的加密文件存放路径");
		}
	}
	/*初始化文件*/
	FILE* dataFile=fopen(dataFilePATH,"rb");
	if(dataFile==NULL)	//可能不存在数据文件
	{
		int res=newKey();	//尝试设置新密码
		if(res!=0)	//新密码设置失败
			return res;
		dataFile=fopen(dataFilePATH,"rb");
	}
	char fileKey[keyMAXLen+1];	//从文件读取的密码
	memset(fileKey,0,sizeof(fileKey));
	fread(fileKey,sizeof(char),keyMAXLen+1,dataFile);
	fclose(dataFile);
	/*输入密码*/
	char inputKey[keyMAXLen+1];	//输入的密码
	printf("密码:");
	readInputKey(inputKey);
	if(strcmp(fileKey,inputKey)==0)	//密码正确
	{
		/*打开路径并等待输入*/
		system("explorer "targetPATH);	//打开目标路径
		HANDLE outH=GetStdHandle(STD_OUTPUT_HANDLE);
		CONSOLE_SCREEN_BUFFER_INFO coordToGet;
		GetConsoleScreenBufferInfo(outH,&coordToGet);	//为了得到当前光标所在行数
		COORD cursorPosition= {.X=0,.Y=coordToGet.dwCursorPosition.Y};
		BOOL edit=FALSE;	//判断是否需要修改密码
		DWORD id;
		HANDLE threadH=CreateThread(NULL,0,Th,&edit,0,&id);	//开线程接受任意键输入
		printf(" 秒钟后程序退出,按任意键修改密码");
		for(char i='3'; i>='0'&&!edit; --i)	//3秒钟倒计时
		{
			FillConsoleOutputCharacter(outH,i,1,cursorPosition,NULL);	//刷新秒数显示
			WaitForSingleObject(threadH,1000);	//等待线程结束并同时等待1秒钟(不阻塞标准输入流,调用Sleep()会阻塞标准输入流)
		}
		if(edit)	//线程已接受到任意键输入
		{
			COORD nextLine= {.X=0,.Y=cursorPosition.Y+1};
			SetConsoleCursorPosition(outH,nextLine);	//相当于putchar('\n');
			CloseHandle(threadH);
			return newKey();
		}
		else	//线程仍处于接受输入状态
		{
			TerminateThread(threadH,id);	//强制退出线程
			CloseHandle(threadH);
			return 0;
		}
	}
	else
	{
		puts("密码错误!");
		getch();
		return 1;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值