利用MoveFileEx实现程序的隐藏、自启动与自删除

来源:互联网 发布:磨石软件 编辑:程序博客网 时间:2024/05/30 04:22

摘要:程序的自启动与自删除几乎是所有后门或者木马所必须具备的功能。程序实现自启动的方法有很多种,最常见的方法莫过于写注册表,添加服务,或者将自身复制到启动目录。自删除通常的办法是写批处理。但是这些方法都已经众所周知,均被各杀毒软件、防护软件,主动防御软件以及经验丰富的管理员视为可疑行为。本文利用API函数MoveFileEx的dwFlags参数实现了上述功能,并且具有一定的隐蔽性。

一、了解MoveFileEx
MoveFileEx是MoveFile函数的扩展函数,也是用来移动文件,不过多加了一些功能。MoveFileEx函数的原型如下:
BOOL MoveFileEx (
LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName,   DWORD dwFlags );
第一个参数是要移动的文件名,第二个是移动后的文件名,最后一个参数决定了移动的方式。
仔细看最后一个参数可取的值,其中一项为MOVEFILE_DELAY_UNTIL_REBOOT ,MSDN中对此标记描述如下:
The function does not move the file until the operating system is restarted. The system moves the file immediately after AUTOCHK is executed, but before creating any paging files. Consequently, this parameter enables the function to delete paging files from previous startups.
This flag can only be used if the process is in the context of a user who belongs to the administrator group or the LocalSystem account.
This flag cannot be used with the MOVEFILE_COPY_ALLOWED flag.
当dwFlags被设为MOVEFILE_DELAY_UNTIL_REBOOT时,函数直到系统重启后才移动文件。注意文件的移动是发生在AUTOCHK执行之后,在页面文件创建之前。而此时用户还没有完全的进入操作系统,所以可以应用这点删除那些正常情况下很难删除的文件甚至是页面文件。
lpNewFileName为NULL时,MovefileEx实现的就是删除的功能。很多杀毒软件和一些恶意程序删除工具就是利用了MoveFileEx函数的这个特性来实现的重启后删除病毒。
MOVEFILE_DELAY_UNTIL_REBOOT标记使用时需要具有管理员或者LocalSystem用户的进程上下文。
MOVEFILE_DELAY_UNTIL_REBOOT标记不能和MOVEFILE_COPY_ALLOWED标记一同使用。因为在不同的卷下实现不了真正的移动,MOVEFILE_COPY_ALLOWED标记使用的时候,函数通过模拟CopyFile 和 DeleteFile 两个函数实现移动。正在运行的程序不能移动到不同的卷(分区)下,这时只实现了Copyfile,下一步DeleteFile没有成功,正在运行的程序是不能删除的。
当dwFlags参数被设置为MOVEFILE_DELAY_UNTIL_REBOOT时,MoveFileEx把重启后移动的文件和要移到的文件的位置存在下面的多字符注册表值(REG_MULTI_SZ)里:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session\Manager\PendingFileRenameOperations。如图1。

图 1
二、进一步探究
我们都知道Windows下正在运行的程序是不能直接删除的(Linux下正在运行的程序则可以删除的)。
下面的演示的是一个比较简单后门程序(door.exe),绑定端口1985,实现了一些基本的后门功能。运行此后门。如果删除的话会弹出如下对话框:
图 2
正在运行的程序虽然不能删除,但是一般可以改名或者移动,移动后程序依然可以运行。如图3、4

图 3

图 4
可以看到正在运行的程序被移动到了另一个目录。
图 5
而且比较有意思的是一般的进程查看工具查看的此时door.exe进程的文件映像还是在没移动的目录里。
下面是Process Explorer查看的结果:
图 6
还有下面这个syscheck2:

图 7
试了很多可以查看进程的工具,发现只有IceSword可以检测出移动后的进程所在目录:

图 8
这样对方发现这个程序,到相应的目录确找不到它,某种程度实现了隐藏文件的目的.如果用在线程插入的dll文件上,其隐蔽性就很好了.

三、MoveFileEx的利用与实现
利用刚才上面所提到的,我们就可以实现文件的隐藏、自删除以及自启动。
我们可以将一个程序运行后,就将它移动到一个不易发现的目录下(在我的下面的程序里是移动到回收站目录里),然后利用MoveFileEx,设置dwFlags为MOVEFILE_DELAY_UNTIL_REBOOT,使文件重启后移动到一个可以启动的目录下(对于中文的Windows XP操作系统,启动目录为
“C:\Documents and Settings\All Users\「开始」菜单\程序\启动”)。这样文件运行后便立即不在它运行时的目录了,实现了“自删除”功能。下次重启后,系统还没有被登陆,便已经将文件移动到了启动目录里。当用户登陆时,程序启动,随即被移到其他目录中,此时在启动文件夹里也已经没有了它的踪迹,所以通过正常的检查是看不出来文件到底在那里被启动的。整个过程只是调用了一个系统API,没有直接的写注册表。现在的主动防御和杀毒软件不会将这视为可疑操作。
下面是我编的一个示例代码,其中StartShell为后门函数,大家可以自己实现其功能.代码很简单大家一看就懂.
//得到启动目录
char szPath[100]={0};
::GetSystemDirectory(szPath,MAX_PATH);
char szDst[100]={0};
for (int i=0; i<3;i++)
szDst[i]=szPath[i];
strcat(szDst,"Documents and Settings\\All Users\\「开始」菜单\\程序\\启动\\test.EXE");
//得到当前程序名
TCHAR szCurPath[MAX_PATH];  
memset(szCurPath,   0,   MAX_PATH);  
GetModuleFileName(NULL,   szCurPath,   sizeof(szCurPath)/sizeof(TCHAR));
if !(MoveFileEx(szCurPath,"c:\\RECYCLER\\FK.BAK",MOVEFILE_REPLACE_EXISTING)))//若是要在不同的volume下移动文件,需要设置为MOVEFILE_COPY_ALLOWED
::MessageBox(NULL,"第一次移动文件失败","test",MB_OK);   if(!::MoveFileEx("c:\\RECYCLER\\FK.BAK",szDst,MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING)){
::MessageBox(NULL,"移动文件失败","test",MB_OK); }  
else printf("任务完成\n");
//创建并等待线程
// StartShell 为后门线程函数.
HANDLE hthread=::CreateThread(NULL,NULL,StartShell,NULL,NULL,NULL);
CloseHandle(hthread);
::WaitForSingleObject(hthread,INFINITE);
return 0;

四、补充与后记
一直以来都想写点技术上的东西,但却总是为各种各样的事情烦恼和忙碌着。我的四年的大学生活要结束了,我的爱情消逝了,我一直深爱着的人离开了,我也终于把这篇文章写完了。欲哭无泪,长歌当哭……(希望编辑不要删除我的话)
程序的缺点也是显而易见的:如果不登陆,程序在启动文件夹就不会运行,在服务器上应用价值就有问题了,因为服务器很多时间是不登陆状态的;程序必须放到与系统分区下,因为不同分区下正在运行的程序移动不了。
除了MoveFileEx函数MoveFileWithProgress函数也可实现一样的功能,所不同的是它提供了对文件移动过程信息的追踪,具体可以查下MSDN。

转自:http://user.qzone.qq.com/1174632606/infocenter#!app=2&via=QZ.HashRefresh&pos=1316710557