Target Eye 揭秘:第六部分 - 文件隐藏






4.89/5 (26投票s)
Target Eye 使用一种过时的文件隐藏方法,然而它最近变得很实用。
引言
本文是关于 Target Eye 监控系统 系列文章的第六篇,也是最后一篇。该系统开发于 2000 年,一直到 2010 年才被停止使用。
- 第一篇文章是关于 Target Eye 的自动更新机制,以及它如何能够检查更新、下载并安装它们,然后运行新版本,而无需最终用户干预。
- 第二篇文章是关于 Target Eye 的屏幕捕获机制,以及如何创建紧凑的 JPG 文件,在保证合理图像质量的同时保持小巧的体积。
- 第三篇文章是关于 购物清单机制。
- 第四篇文章是关于 键盘捕获。
- 第五篇文章 则涉及用于让我们的秘密特工潜入的包装。换句话说,Target Eye 如何用于用我们称之为“掩护故事”的内容来包装它。
关于本文
接下来的文章将解释文件是如何以及何时被隐藏的,同时揭示如何显示这些隐藏的文件。Target Eye 使用一种简单的机制来隐藏文件,但这种技巧对大多数 Windows 用户来说是有效的,因为显示这些隐藏文件的选项并不是文件资源管理器默认用户界面的一部分,所以即使勾选了“显示隐藏的项目”,Target Eye 隐藏的文件也不会被显示出来。
Target Eye 的 TEHideFile() 函数
TEHideFile()
函数用于隐藏和显示文件,以及更改给定文件的大小为随机大小,从而更难对其进行采样和检测。
用法
通过查看 Target Eye 2005 的源代码,该函数定义如下:
BOOL TEHideFile(CString FileName,BOOL Hide,BOOL RandomSize)
FileName
= 文件的完整路径和名称Hide
= 告诉函数是隐藏还是显示文件RandomSize
= 告诉函数是否向文件添加“垃圾”数据(而不影响其功能),同时将其大小更改为更大。
Target Eye 文件是如何被隐藏的
Target Eye 使用了一种看似老式的方法。它没有使用内核(SSDT 操纵)或用户级别的全局挂钩,而是创建了一个类似的 **系统文件**。这种方法在 Windows XP 的早期很有用。然而,在 Windows 7 和 8 上进行测试时,您可能会意识到隐藏的文件确实被隐藏了,即使勾选了“隐藏的项目”。
以下截图说明了“隐藏的项目”复选框
正如您所见,在 Windows 7 和 8 的用户界面中,即使勾选了“查看隐藏的项目”,也很难注意到存在额外的隐藏系统文件。常识认为,勾选此复选框后,所有文件都将可见。
然而,Target Eye 隐藏的文件并非如此。即使勾选此选项,这些文件也不会显示。
这提供了一个机会,可以在不使用各种挂钩和内核级操作的情况下,相对地将文件隐藏起来,不被大多数用户发现。
这些系统文件到底如何才能显示出来?
好吧,方法就在这里。
- 您需要打开“文件夹选项”对话框,可以通过搜索找到它。当您使用 Windows 8 搜索时,需要搜索“所有”,而不仅仅是“文件”,输入“显示隐藏文件夹”并按 Enter 键。
- 将显示“文件夹选项”对话框。
您需要取消勾选“隐藏受保护的操作系统文件”,然后当出现下方的警告时,按“是”。
只有这样,您才能看到 Target Eye 隐藏的文件……
TEHideFile() 源代码
//
// TEHideFile
BOOL TEHideFile(CString FileName,BOOL Hide,BOOL RandomSize)
{
HANDLE g_hCapFile; // Handle to file
DWORD dwBytes; // number of bytes read from file
ULONG FileLen; // length of the file
FileLen=GetFileLen(FileName); // Getting the file length
if(FileLen==0) return(FALSE); // If file is empty, quitting
// Reading file
g_hCapFile=CreateFile((char *)FileName.GetBuffer(0),GENERIC_READ,NULL,NULL,
OPEN_ALWAYS,/*FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM*/NULL,NULL);
if(g_hCapFile==INVALID_HANDLE_VALUE)
{
// Error: file doesn't exist
return(FALSE);
}
// Allocating a buffer to hold the file
char *buffer=(char *)malloc(FileLen);
memset(buffer,'\0',FileLen);
// Read the file into the buffer
ReadFile(g_hCapFile,buffer,FileLen,&dwBytes,NULL);
// Closing the file
CloseHandle(g_hCapFile);
// Deleting the file
DeleteFile(FileName);
// If "Hide" is true, creating a new file using
// FILE_ATTRIBUTE_SYSTEM and FILE_ATTRIBUTE_HIDDEN attributes
if(Hide)
g_hCapFile=CreateFile((char *)FileName.GetBuffer(0),GENERIC_WRITE,
FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,NULL);
// if "Hide" is false, creating a "normal" file
else
g_hCapFile=CreateFile((char *)FileName.GetBuffer(0),GENERIC_WRITE,0,
NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(g_hCapFile==INVALID_HANDLE_VALUE)
{
// Error: can't create the new file
return(FALSE);
}
// Purging the contents of the buffer into the new file
if(!(WriteFile(g_hCapFile,buffer,FileLen,&dwBytes,NULL)))
{
// Error: can't write to the new file
free(buffer);
CloseHandle(g_hCapFile);
return(FALSE);
}
// If RandomSize is true, creating random number of "garbage" bytes to the new file
if(RandomSize)
{
int x;
char *temp;
x=(int)((double)rand()/(double )RAND_MAX*8630.0)+3201; // Creating a random
// size which is at least 3201 bytes
temp=(char *)malloc(x); // allocating memory
if(temp)
{
int i;
// Filling the buffer with random ("garbage") date
for(i=0;i<x;i++) *(temp+i)=(int)((double)rand()/
(double )RAND_MAX*((int)'z'-(int)'a'+1))+(int)'a';
// Appending the buffer to the end of the file
if(!(WriteFile(g_hCapFile,temp,FileLen,&dwBytes,NULL)))
{
free(temp);
free(buffer);
CloseHandle(g_hCapFile);
return(FALSE);
}
free(temp);
}
}
free(buffer);
CloseHandle(g_hCapFile);
return(TRUE);
}
我编写了 GetFileLen()
,以便更容易测量给定文件的大小。
ULONG GetFileLen(CString FileName)
{
DWORD dwBytes;
HANDLE g_hCapFile;
if(FileName=="") return(0);
g_hCapFile=CreateFile((char *)FileName.GetBuffer(0),GENERIC_READ,NULL,
NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,NULL);
if(g_hCapFile==INVALID_HANDLE_VALUE)
return(0);
dwBytes=SetFilePointer(g_hCapFile,0,NULL,FILE_END);
CloseHandle(g_hCapFile);
return(dwBytes);
}
全局 API 挂钩呢?
要了解全局 API 挂钩,我推荐阅读 ApriorIT 撰写的优秀文章:“轻松设置全局 API 挂钩”。如果您对内核级隐藏感兴趣,可以使用驱动程序来实现。有几种技术,包括 SSDT/IDT 表操纵。例如,请参阅本文,或者阅读关于 SSDT 的这篇。
历史
- 2014 年 6 月 15 日:初始版本
Michael Haephrati,CodeProject MVP 2013
©2000-2010 Target Eye LTD (UK)