////////////////////////////////////////////////////////////////////////// //**程序名称:Exe.cpp
//**程序作用:在现有的exe文件中添加自己的代码
//把工程目录下的文件复制一份命名为
//把函数ExeCode的代码添加在
//并让可以正常运行
//**编译环境:Microsoft Visual C++ 6.0
//**编译参数:win32控制台程序,Debug编译方式,去掉编译参数/GZ
////////////////////////////////////////////////////////////////////////// #include <iostream.h>
#include <windows.h>
#include <stdio.h>
////////////////////////////////////////////////////////////////////////// //*******************************************************************
//*******以下为程序代码*******
//*******************************************************************
////////////////////////////////////////////////////////////////////////// void ExeCode()
{
_asm
{
mov eax , 5
}
return;
}
////////////////////////////////////////////////////////////////////////// //*******************************************************************
//*******主函数*******
//*******************************************************************
////////////////////////////////////////////////////////////////////////// void main()
{
//******************************************************************* //*******首先得到程序代码起始地址,结束地址,代码长度*******
//******************************************************************* /////////////////////////////////////////////////////////////////
//*******变量说明*******
//**dwFunBegAddr:程序函数的开始地址
//**dwFunEndAddr:程序函数的结束地址
//**dwFunCodeLen:程序代码长度
//**dwJmpOff:程序函数jmp区到真正入口的偏移
//**pMove:临时的指针变量
/////////////////////////////////////////////////////////////////
DWORD dwFunBegAddr , dwJmpOff , dwFunEndAddr , dwFunCodeLen;
PBYTE pMove = NULL;
//*******首先指向程序函数的jmp指令*******
pMove = (PBYTE)ExeCode;
cout << "函数的jmp地址为:" << (PVOID)pMove << endl;
//*******定位到jmp后面的偏移处*******
pMove ++;
//*******把偏移赋值给变量*******
dwJmpOff = *((PDWORD)pMove);
/
/*******jmp下一条指令的地址(code + 5)+偏移得到函数真正的入口地址*******
dwFunBegAddr = (DWORD)ExeCode + 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("" , 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("" , "" , FALSE);
if (!bCopy)
{
cout << "CopyFile Error!" << endl;
}
HANDLE hNewFile;
/
/*******打开刚刚复制的文件*******
hNewFile = CreateFile("" , 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 , ".Exe");
//*****更新入口地址*****
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 Exe Code Error!" << endl;
goto CloseNewFileHandle;
}
/
/*****定位到文件尾部*****
dwSetFileP = SetFilePointer(hNewFile , pNewSec->PointerToRawData +
pNewSec->SizeOfRawData , NULL , FILE_BEGIN);printf怎么加endl
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;
}