恶意代码研究 -- 功能技术类 -- windows PE恶意代码(二)文件遍历

不管用什么计算机语言写代码,文件遍历都是不可或缺的操作,以便对文件进行批量处理。

对恶意代码来说文件读写就是必备功能了,比如说木马病毒窃取机密文件然后开一个隐秘端口将文件内容发送回去。

相关API

函数

这里用到了windows api提供的FindFirstFileFindNextFile函数。
msdn对这两个函数的描述:

FindFirstFile定义如下:
该函数查找指定目录的第一个文件或目录并返回它的句柄

HANDLE FindFirstFile(
  LPCTSTR lpFileName, 
  LPWIN32_FIND_DATA lpFindFileData 
); 

FindNextFile定义如下:

BOOL FindNextFileW(
  HANDLE             hFindFile,
  LPWIN32_FIND_DATAW lpFindFileData
);
#define FindNextFile  FindNextFileW

结构体

这里用到了WIN32_FIND_DATA结构体

typedef struct _WIN32_FIND_DATA {
   DWORD dwFileAttributes; //文件属性
   FILETIME ftCreationTime; // 文件创建时间
   FILETIME ftLastAccessTime; // 文件最后一次访问时间
   FILETIME ftLastWriteTime; // 文件最后一次修改时间
   DWORD nFileSizeHigh; // 文件长度高32位
   DWORD nFileSizeLow; // 文件长度低32位
   DWORD dwReserved0; // 系统保留
   DWORD dwReserved1; // 系统保留
   TCHAR cFileName[ MAX_PATH ]; // 长文件名
   TCHAR cAlternateFileName[ 14 ]; // 8.3格式文件名
  } WIN32_FIND_DATA, *PWIN32_FIND_DATA;

操作流程

  • 调用FindFirstFile函数,该函数接收文件路径,第二个参数指向WIN32_FIND_DATA结构的指针。若函数成功则返回搜索句柄。该结构包含文件的名称,创建日期,属性,大小等信息。
  • 调用FindNextFile搜索下一个文件,根据返回值判断是否搜索到文件,若没有则说明文件遍历结束
  • 搜索完毕后,调用FindClose函数关闭搜索句柄,释放资源缓冲区资源

示例代码

#include<Windows.h>
#include<stdio.h>


void SearchFile(wchar_t *pszDirectory)
{
	// 搜索指定类型文件
	DWORD dwBufferSize = 2048;
	wchar_t *pszFileName = NULL;
	wchar_t *pTempSrc = NULL;
	WIN32_FIND_DATA FileData = { 0 };
	BOOL bRet = FALSE;

	// 申请动态内存
	pszFileName = new wchar_t[dwBufferSize];
	pTempSrc = new wchar_t[dwBufferSize];

	// 构造搜索文件类型字符串, *.*表示搜索所有文件类型
	::wsprintf(pszFileName, L"%s\\*.*", pszDirectory);

	// 搜索第一个文件
	HANDLE hFile = ::FindFirstFile(pszFileName, &FileData);
	if (INVALID_HANDLE_VALUE != hFile)
	{
		do
		{
			// 要过滤掉 当前目录"." 和 上一层目录"..", 否则会不断进入死循环遍历
			if ('.' == FileData.cFileName[0])
			{
				continue;
			}
			// 拼接文件路径   
			::wsprintf(pTempSrc, L"%s\\%s", pszDirectory, FileData.cFileName);
			// 判断是否是目录还是文件
			if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				// 目录, 则继续往下递归遍历文件
				SearchFile(pTempSrc);
			}
			else
			{
				// 文件
				printf("%S\n", pTempSrc);
			}

			// 搜索下一个文件
		} while (::FindNextFile(hFile, &FileData));
	}

	// 关闭文件句柄
	::FindClose(hFile);
	// 释放内存
	delete[]pTempSrc;
	pTempSrc = NULL;
	delete[]pszFileName;
	pszFileName = NULL;
}

int _tmain(int argc, _TCHAR* argv[])
{
	SearchFile(L"D:\\projects\\python");
	return 0;
}

运行结果就不展示了,就是把指定目录下所有文件名列举出来,这里并没有设计文件读写等操作,纯粹的文件夹遍历,这里字符类型我都是用wchar_t,所以字符串值前面也加上L,并且printf格式化输出用大写S

IDA反汇编后的伪代码

main函数的就不放出了,直接方出SearchFile

void __cdecl sub_411410(int a1)
{
  int v1; // [esp+Ch] [ebp-38Ch]
  WCHAR *v2; // [esp+14h] [ebp-384h]
  WCHAR *v3; // [esp+20h] [ebp-378h]
  void *v4; // [esp+2Ch] [ebp-36Ch]
  void *v5; // [esp+38h] [ebp-360h]
  HANDLE hFindFile; // [esp+104h] [ebp-294h]
  int v7; // [esp+110h] [ebp-288h]
  struct _WIN32_FIND_DATAW FindFileData; // [esp+11Ch] [ebp-27Ch]
  LPWSTR v9; // [esp+374h] [ebp-24h]
  LPWSTR v10; // [esp+380h] [ebp-18h]
  int v11; // [esp+38Ch] [ebp-Ch]

  v11 = 2048;
  v10 = 0;
  v9 = 0;
  FindFileData.dwFileAttributes = 0;
  j_memset(&FindFileData.ftCreationTime, 0, 0x24Cu);
  v7 = 0;
  v2 = (WCHAR *)operator new(0x1000u);
  v10 = v2;
  v3 = (WCHAR *)operator new(2 * v11);
  v9 = v3;
  wsprintfW(v10, L"%s\\*.*", a1);
  hFindFile = FindFirstFileW(v10, &FindFileData);
  if ( hFindFile != (HANDLE)-1 )
  {
    do
    {
      if ( FindFileData.cFileName[0] != 46 )
      {
        wsprintfW(v9, L"%s\\%s", a1, FindFileData.cFileName);
        if ( FindFileData.dwFileAttributes & 0x10 )
          sub_4110F5((int)v9);
        else
          printf("%S\n", v9);
      }
    }
    while ( FindNextFileW(hFindFile, &FindFileData) );
  }
  FindClose(hFindFile);
  v4 = v9;
  operator delete(v9);
  if ( v4 )
  {
    v9 = (LPWSTR)33059;
    v1 = 33059;
  }
  else
  {
    v1 = 0;
  }
  v9 = 0;
  v5 = v10;
  operator delete(v10);
}

可以看到这里用的是去除了宏定义的wsprintfWFindFirstFileWFindNextFileW(我用的VS2013,wsprintfWFindFirstFileWFindNextFileW是预先宏定义好的,如下),可以验证宏定义在编译时预处理阶段就被处理了。

#define wsprintf  wsprintfW
#define FindFirstFile  FindFirstFileW
#define FindNextFile  FindNextFileW
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值