给PE文件增加可执行代码
来源:互联网 发布:机器人 毛笔字 算法 编辑:程序博客网 时间:2024/05/18 00:14
最近想写一个软件壳,需要给PE文件增加一个区段(Section),来执行一些初始化的工作。只要先学习一下PE文件的格式和结构,有个大概了解后,我想就能很容易写出相关代码。网上有很多PE格式的介绍,这里就不多介绍,直入主题。
增加的执行代码有两个地方可以放,一个是现有PE文件区段在数据对齐时有一些空隙,这样的空隙一般只能存放比较小块的代码,优点是对原有的PE文件数据改动比较小,大小也不会改变;另一个就是增加一个新的区段,这样可以放任意你想放置的代码,发挥的空间也大一些。本文的方法是先判断是否有足够的空隙来存放代码,如果没有,就增加一个Section来存放。
下面这张图,详细说明这个过程
核心代码:
#include "stdafx.h"#include "PEUtil.h"#include <assert.h>CPEUtil::CPEUtil(){}CPEUtil::~CPEUtil(){}DWORD CPEUtil::AlignUp(DWORD x, DWORD v){ if (x%v == 0) return x; return x + v - x%v;}bool CPEUtil::Load(LPCTSTR szFile){ tfstream f(szFile, ios::in | ios::binary); if (!f.is_open()) return false; f.seekg(0, ios::end); m_vBuf.assign(f.tellg(), 0); f.seekg(0, ios::beg); f.read(m_vBuf.data(), m_vBuf.size()); f.close(); return true;}bool CPEUtil::Save(LPCTSTR szFile){ if (m_vBuf.empty()) return false; tfstream f(szFile, ios::out | ios::binary); if (!f.is_open()) return false; f.write(m_vBuf.data(), m_vBuf.size()); f.close(); return true;}bool CPEUtil::AddCode(byte * pCode, DWORD dwSize){ CHeader h(m_vBuf.data()); DWORD dwBase = 0; auto pSec = IMAGE_FIRST_SECTION(h.pNTHeader); if (h.pNTHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return false; // 找空隙 for (size_t i = 0; i < h.pNTHeader->FileHeader.NumberOfSections; i++, pSec++) { if (pSec->SizeOfRawData > 0 && pSec->SizeOfRawData > (pSec->Misc.VirtualSize + dwSize)) { dwBase = pSec->VirtualAddress + pSec->Misc.VirtualSize; break; } } if (!dwBase) { // 空隙不够大,添加一个新的区段 pSec = IMAGE_FIRST_SECTION(h.pNTHeader) +h.pNTHeader->FileHeader.NumberOfSections; memset(pSec, 0, sizeof(pSec)); pSec->Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; strcpy_s((char*)pSec->Name, sizeof(pSec->Name), ".add"); auto pSecPrev = pSec - 1; pSec->SizeOfRawData = AlignUp(dwSize, h.pOp->FileAlignment); pSec->PointerToRawData = AlignUp(pSecPrev->PointerToRawData + pSecPrev->SizeOfRawData, h.pOp->FileAlignment); pSec->VirtualAddress = AlignUp(pSecPrev->VirtualAddress + max(pSecPrev->SizeOfRawData, pSecPrev->Misc.VirtualSize), h.pOp->SectionAlignment); dwBase = pSec->VirtualAddress; // m_vBuf.insert(m_vBuf.end(), pSec->SizeOfRawData, 0); h.Reset(m_vBuf.data()); pSec = IMAGE_FIRST_SECTION(h.pNTHeader) + h.pNTHeader->FileHeader.NumberOfSections; h.pNTHeader->FileHeader.NumberOfSections += 1; // 增加一个区段 h.pOp->SizeOfImage += AlignUp(pSec->SizeOfRawData, h.pOp->SectionAlignment); // 修改映象文件大小 } byte* pWrite = (byte*)(m_vBuf.data() + Rva2Fva(dwBase)); DWORD dwJmp = h.pNTHeader->OptionalHeader.AddressOfEntryPoint - dwBase - dwSize; memcpy(pWrite, pCode, dwSize-sizeof(DWORD)); // pCode 最后5个字节为 jmp 00000000 (0xe9,0x00,0x00,0x00,0x00),作跳转用 memcpy(pWrite + dwSize - sizeof(DWORD), &dwJmp, sizeof(DWORD)); pSec->Misc.VirtualSize += dwSize; pSec->Characteristics |= IMAGE_SCN_MEM_EXECUTE; h.pNTHeader->OptionalHeader.AddressOfEntryPoint = dwBase; return true;}DWORD CPEUtil::Rva2Fva(DWORD dwRva){ CHeader h(&m_vBuf[0]); auto pSec = IMAGE_FIRST_SECTION(h.pNTHeader); pSec += h.pNTHeader->FileHeader.NumberOfSections-1; assert(dwRva <= (pSec->VirtualAddress + pSec->SizeOfRawData)); for (size_t i = 0; i < h.pNTHeader->FileHeader.NumberOfSections ; i++, pSec--) { if (dwRva >= pSec->VirtualAddress) return pSec->PointerToRawData + dwRva - pSec->VirtualAddress; } return 0;}
0 0
- 给PE文件增加可执行代码
- 给PE文件增加节
- 给PE文件添加数字签名的VC6代码
- vc2008中给PE程序的代码段增加可写属性的方法
- 利用PE结构给Windows可执行程序加密码
- PE文件相关代码
- PE文件解析代码
- Linux下给文件添加可执行权限
- 给linux文件添加可执行权限
- 关于PE可执行文件的修改(3) 给PE文件打补丁
- 关于PE可执行文件的修改(3) 给PE文件打补丁
- 放下代码 PE文件变形之初步 移动PE头
- PE文件的修改以及增加节区
- PE文件导入表的代码注入
- 在PE文件上添加执行代码
- PE文件导入表的代码注入
- 手动修改PE文件:添加自定义代码
- PE文件结构分析(代码)
- 动态规划--3.最长公共子序列LCS和最长公共子字符串
- 设计模式:模板方法
- 【Android 进阶】Android 按键事件简单理解
- 题目1010:A + B
- SpringMVC学习(十)之转发与重定向
- 给PE文件增加可执行代码
- maven阿里云中央仓库
- Git设置忽略排除和重新添加已经被忽略过文件(夹)的方法
- Java day3
- P
- 编写高质量的JavaScript
- 题目1015:还是A+B
- reverse the string
- 用优先队列优化后的dijkstra算法模板