关于 win32 下磁盘的遍历方法
最近要写个在线专杀的东东,虽然是专杀(本来只要清除几个特定的文件和杀几个特定的进程,然后把用户的注册表恢复正常,很多病毒木马最喜欢干的一件事情就是写 映像劫持 然后机器一重启,安全相关的软件全部玩完了,不过这也没什么技术含量,利用了操作系统的“漏洞”而已),但是因为是 磁碟机,这个病毒(木马)很恶心,是感染型的,你磁盘上的exe文件可以全部给你感染成一个个的“小磁碟机”,很恐怖,呵呵,所以没办法,要清除它,必须在杀掉磁碟机的进程之后,对全盘进行扫描,对每一个被感染的exe文件(好像com文件不能感染)进行修复,怎么进行磁盘遍历呢?请看下面的代码:(其实杀毒引擎工作的过程就是一个遍历磁盘上文件的过程,然后再对每个文件进行处理)
- // -------------------------------------------------------------------------
- // 函数 : ScanDirectory
- // 功能 : 遍历一个目录,然后做一些事情(想做什么做什么呗)
- // 返回值 : DWORD
- // 参数 : const WCHAR *pwszPath
- // 附注 : 可以为磁盘根目录
- // -------------------------------------------------------------------------
- DWORD ScanDirectory(const WCHAR *pwszPath)
- {
- USES_CONVERSION;
- static int nCountFile = 0;
- DWORD dwRet = 1;
- WCHAR *s = NULL;
- HANDLE hFind = NULL;
- WIN32_FIND_DATAW fd = {0};
- WCHAR wszFileName[MAX_PATH] = L"";
- lstrcpyW(wszFileName, pwszPath);
- s = wszFileName + wcslen(wszFileName);
- if (*(s-1) != L'//')
- *s++ = L'//';
- // wcscpy_s(s, 4, L"*.*");
- ::lstrcpyW(s, L"*.*");
- hFind = FindFirstFileW(wszFileName, &fd);
- if (hFind==INVALID_HANDLE_VALUE)
- goto Exit0;
- do
- {
- // 过滤
- if (_wcsicmp(L".", fd.cFileName) == 0 || _wcsicmp(L"..", fd.cFileName) == 0)
- continue;
- ::lstrcpyW(s, fd.cFileName);
- *(s + lstrlenW(fd.cFileName)) = L'/0';
- // 如果是文件夹则递归
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- // 删除.svn目录,我做一个小工作,删文件,o(∩_∩)o...
- WCHAR wszSvnCmd[MAX_PATH] = {0};
- ::lstrcpyW(wszSvnCmd, L"rmdir /s/q ");
- ::lstrcatW(wszSvnCmd, wszFileName);
- ::lstrcatW(wszSvnCmd, L"//.svn");
- system(W2A(wszSvnCmd));
- ScanDirectory(wszFileName);
- }
- else
- {
- // 对文件进行扫描
- // 这里你可以放入你对文件的处理代码
- }
- }while(::FindNextFileW(hFind, &fd));
- dwRet = 0;
- Exit0:
- if( hFind != INVALID_HANDLE_VALUE )
- {
- ::FindClose( hFind );
- hFind = NULL;
- }
- return dwRet;
- }
当然上面的代码还只能遍历一个磁盘,除非你知道自己的机器上有几个磁盘,然后调用几次就可以了,但是你不知道用户的机器上有几个什么磁盘咯,所以还须有下面的代码和上面配合:
- // -------------------------------------------------------------------------
- // 函数 : ParseDiskName
- // 功能 : 解析机器上能扫描的磁盘的名
- // 返回值 : DWORD 返回能扫描的磁盘数量
- // 参数 : TCHAR *pszDiskName 缓冲区 放入可扫描的磁盘的英文盘符名
- // 附注 :
- // -------------------------------------------------------------------------
- DWORD ParseDiskName(TCHAR *pszDiskName)
- {
- static TCHAR *pszWordTable = {"abcdefghijklmnopqrstuvwxyz"};
- DWORD dwDisk;
- DWORD dwBase = 0x1;
- DWORD dwCount = 0; // 记录磁盘数量
- DWORD dwScanCount = 0; // 要扫描的有效磁盘数量,用于返回
- DWORD dwStyle;
- TCHAR szDiskPath[4] = {0}; // 缓存一个磁盘根目录名
- TCHAR szDiskArray[26] = {0}; // 记录要扫描的所有磁盘名
- dwDisk = GetLogicalDrives();
- while (dwDisk && dwCount <= ::lstrlen(pszWordTable))
- {
- memset(szDiskPath, 0, sizeof(szDiskPath));
- if (dwDisk & dwBase)
- {
- ::lstrcpyn(szDiskPath, pszWordTable + dwCount, 2);
- ::lstrcat(szDiskPath, TEXT("://"));
- dwStyle = GetDriveType(szDiskPath);
- // 是否可扫描的
- if (DRIVE_REMOVABLE == dwStyle || DRIVE_FIXED == dwStyle)
- {
- szDiskArray[dwScanCount] = pszWordTable[dwCount];
- dwScanCount++;
- }
- }
- dwDisk = dwDisk & ~dwBase;
- dwBase = dwBase * 2;
- dwCount++;
- }
- ::lstrcpy(pszDiskName, szDiskArray);
- return dwScanCount;
- }
呵呵,差不多了,不过上面的遍历文件用递归实现的,有可能出现堆栈溢出的情况,用迭代实现遍历磁盘也是可以的,不过我一直没有去写一个,还是觉得太麻烦了,递归多方便啊。再show点代码,对计算机进行重启的,不过这个重启是类似于掉电重启的,大家别随便试啊,一调你的机器得不到任何通知就重启了,为什么要这么用呢?是因为有些病毒再收到系统重启通知的时候会干些坏事情,用这种方法才能彻底清除它。
- // -------------------------------------------------------------------------
- // 函数 : ForceShutDown
- // 功能 : 强制重启
- // 返回值 : HRESULT
- // 附注 :
- // -------------------------------------------------------------------------
- HRESULT ForceShutDown()
- {
- // 强制重启参数 函数指针声明
- typedef enum _SHUTDOWN_ACTION
- {
- ShutdownNoReboot,
- ShutdownReboot,
- ShutdownPowerOff
- } SHUTDOWN_ACTION;
- typedef DWORD (WINAPI* lpNtShutdownSystem)(SHUTDOWN_ACTION Action);
- LONG nRet = FALSE;
- HANDLE hToken;
- TOKEN_PRIVILEGES tkp;
- HANDLE hProcess = NULL;
- HMODULE hNTDLL = NULL;
- hProcess = ::GetCurrentProcess();
- if(hProcess == NULL)
- goto Exit0;
- if(!::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
- goto Exit0;
- if(!::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
- goto Exit0;
- tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
- hNTDLL = LoadLibrary(_T("NTDLL.DLL"));
- if (hNTDLL)
- {
- lpNtShutdownSystem NtShutdownSystem = (lpNtShutdownSystem)GetProcAddress(hNTDLL, "NtShutdownSystem");
- if (NtShutdownSystem)
- {
- NtShutdownSystem(ShutdownReboot);
- }
- ::FreeLibrary(hNTDLL);
- nRet = TRUE;
- }
- Exit0:
- if(hToken)
- {
- ::CloseHandle(hToken);
- hToken = NULL;
- }
- if(hProcess)
- {
- ::CloseHandle(hProcess);
- hProcess = NULL;
- }
- return nRet;
- }
以后再说说那个堆栈溢出的情况吧。
http://blog.csdn.net/magictong/article/details/2784420
关于 win32 下磁盘的遍历方法的更多相关文章
- 不同WINDOWS平台下磁盘逻辑扇区的直接读写
不同WINDOWS平台下磁盘逻辑扇区的直接读写 关键字:VWIN32.中断.DeviceIoControl 一.概述 在DOS操作系统下,通过BIOS的INT13.DOS的INT25(绝对读).INT ...
- Java中Map的三种遍历方法
Map的三种遍历方法: 1. 使用keySet遍历,while循环: 2. 使用entrySet遍历,while循环: 3. 使用for循环遍历. 告诉您们一个小秘密: (下↓面是测试代码,最爱看 ...
- Jquery中each的三种遍历方法
Jquery中each的三种遍历方法 $.post("urladdr", { "data" : "data" }, function(dat ...
- JavaScript、jQuery、fish的遍历方法(each、forEach)总结
起因 在工作中,需要在遍历的dom中找到第一个并做下操作然后退出遍历,我首先想到了用each方法,但由于无论是公用的jQuery组件还是公司的fish组件.我都忘记了怎么去退出遍历,所以就有了这篇帖子 ...
- python数据结构与算法——二叉树结构与遍历方法
先序遍历,中序遍历,后序遍历 ,区别在于三条核心语句的位置 层序遍历 采用队列的遍历操作第一次访问根,在访问根的左孩子,接着访问根的有孩子,然后下一层 自左向右一一访问同层的结点 # 先序遍历 # ...
- Oracle 11g RAC环境下Private IP修改方法及异常处理
Oracle 11g RAC环境下Private IP修改方法及异常处理 Oracle 11g RAC环境下Private IP修改方法及异常处理 一. 修改方法 1. 确认所有节点CRS服务以启动 ...
- 两种QMultiMap的遍历方法(最好使用只读遍历器)
留个爪,备查 QMultiMap<QString, QString>& remote_map = my_obj->m_MapVersion; // ccc 这里体现了引用的好 ...
- java 完全二叉树的构建与四种遍历方法
本来就是基础知识,不能丢的太干净,今天竟然花了那么长的时间才写出来,记一下. 有如下的一颗完全二叉树: 先序遍历结果应该为:1 2 4 5 3 6 7 中序遍历结果应该为:4 2 5 ...
- linux下磁盘占用达到100%了,找不到哪些大文件耗尽了磁盘
Linux下的根分区使用率100%,但是查看/分区下的目录都不大,没有占用满,这该怎么处理? 重启是肯定有效的,目前处理情况:重新restart应用后,空间释放出来 1.lsof | grep del ...
随机推荐
- TstringBuilder Delphi2007版
2010中的StringBuilder对象用的比较爽快!于是稍作了一些修改(增加了几个函数和属性)然后移植到D2007中来使用了!效果不错,共享一下! unit DxStringBuilder; in ...
- Struts2——(7)拦截器组件
AOP:面向切面编程(通过配置文件来指定作用到目标对象) OOP:面向对象编程 AOP具有很好的可插拔特性,很灵活. 可用于封装共通的业务处理,之后可以通过配置作用到Action组件上. 共通的业务处 ...
- CUDA二维纹理内存+OpenCV图像滤波
CUDA和OpenCV混合编程,使用CUDA的纹理内存,实现图像的二值化以及滤波功能. #include <cuda_runtime.h> #include <highgui/hig ...
- CUDA+OpenCV 绘制朱利亚(Julia)集合图形
Julia集中的元素都是经过简单的迭代计算得到的,很适合用CUDA进行加速.对一个600*600的图像,需要进行360000次迭代计算,所以在CUDA中创建了600*600个线程块(block),每个 ...
- C++中placement new操作符
placement new是重载operator new的一个标准.全局的版本,它不能被自定义的版本代替(不像普通的operator new和operator delete能够被替换成用户自定义的版本 ...
- PHP关联数组教程
PHP 数组 关联数组 什么是数组?在使用 PHP 进行开发的过程中,或早或晚,您会需要创建许多相似的变量.无需很多相似的变量,你可以把数据作为元素存储在数组中.数组中的元素都有自己的 ID,因此可以 ...
- Feature extraction - sklearn文本特征提取
http://blog.csdn.net/pipisorry/article/details/41957763 文本特征提取 词袋(Bag of Words)表征 文本分析是机器学习算法的主要应用领域 ...
- 高性能mysql笔记 第一章 mysql架构
1.1 mysql逻辑结构 第一层: 负责连接处理,授权认证,安全等事情 第二层:负责mysql的大部分核心功能 ,查询解析,分析,优化,缓存和所有的内置函数,所有跨存储引擎的功能都在这一层实现,, ...
- MVVM讲解
一,MVVM理论知识 从上一篇文章中,我们已经知道,WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通 ...
- C#开发奇技淫巧一:调试windows系统服务
原文:C#开发奇技淫巧一:调试windows系统服务 windows系统服务不能直接运行,只能在安装完服务之后启动.暂停.继续.停止服务,导致服务的调试不能使用一般的断点调试. 要调试系统服务,可以采 ...