获取PE文件入口点

大家好,最近在网上看了一下PE文件结构的解释的文章,里面有一个修改PE文件的示例,是向PE文件插入一个消息框,以让目标PE文件执行时首先显示插入的消息框,其中有一段代码如下:

//计算新的程序入口地址
DWORD dwNewEntryAddress = dwEntryWrite + dwCodeOffset;

这段代码我看不明白,为什么要在最后加上代码偏移值呢?被写入的代码是写在dwEntryWrite地址处,把入口点改在这个地方不就可以了么,为什么要加上代码段的基地址(BaseOfCode)与本节的代码偏移值呢?
请各位高手帮忙解释一下!


------------------以下是摘自某位朋友的博客,即是我所说的那篇文章:
最近学习pe格式和写壳,最终目标是写出自己的壳,并有一定的anti能力.

调试了下修改pe文件的oep,然后在新的入口点什么都没做,只是jmp回到原始入口点,程序继续执行.测试通过. 准备明天在自己入口点的地方添加一个MessageBox代码.

很多是网上朋友的代码,借用下不好意思,如有版权等问题请联系偶,偶会尽快处理,谢谢.

void CPeSecDlg::Go()
{
HANDLE hFile, hMapping;
void * basepointer = NULL;
if(INVALID_HANDLE_VALUE == (hFile = CreateFile("C://CenterServer.exe",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
0)))
{
AfxMessageBox("打开失败!!");
return;
}

if(!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
{
AfxMessageBox("CreateFileMapping打开失败!!");
CloseHandle(hFile);
return;
}

if(!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))
{
AfxMessageBox("MapViewOfFile");
CloseHandle(hMapping);
CloseHandle(hFile);
return;
}

IMAGE_DOS_HEADER * dos_head = (IMAGE_DOS_HEADER*)basepointer;
IMAGE_NT_HEADERS * header = (IMAGE_NT_HEADERS*)((char*)dos_head + dos_head->e_lfanew);
DWORD oldOEP = header->OptionalHeader.AddressOfEntryPoint;
IMAGE_SECTION_HEADER * sectionHeader = (IMAGE_SECTION_HEADER*)(((char*)header + sizeof(IMAGE_NT_HEADERS)));

//此段真实长度
DWORD dwVirtSize = sectionHeader->Misc.VirtualSize;
//此段物理偏移
DWORD dwPhysAddress = sectionHeader->PointerToRawData;
//此段物理长度
DWORD dwPhysSize = sectionHeader->SizeOfRawData;
//取得此段的可用空间
DWORD dwSpace = dwPhysSize - dwVirtSize;
//取得程序的装载地址
DWORD dwProgRAV = header->OptionalHeader.ImageBase;

//代码偏移一般为0
DWORD dwCodeOffset = header->OptionalHeader.BaseOfCode - dwPhysAddress;

//代码写入的物理偏移
DWORD dwEntryWrite = dwPhysAddress + dwVirtSize;
if(0 != (dwEntryWrite%16))
{
dwEntryWrite += (16 - (dwEntryWrite%16));
}

//计算新的程序入口地址
DWORD dwNewEntryAddress = dwEntryWrite + dwCodeOffset;

//将jmp oldOEP的代码写入新的入口地址
SetFilePointer(hFile, dwNewEntryAddress, NULL, FILE_BEGIN);
//jmp oldOEP的16进值码为0xE90002D820
DWORD iWrited = 0;
char cmd[4] = {0};
ChangeDwordToString(/*0x0002D820*/0xFFFE069B, cmd);
/* cmd[0] = (char)0x00;
cmd[1] = (char)0x02;
cmd[2] = (char)0xD8;
cmd[3] = (char)0x20;
WriteFile(hFile, cmd, 4, &iWrited, NULL);
*/ char d[1] = {0};
d[0] = (char)0xE9;
WriteFile(hFile, d, 1, &iWrited, NULL);
WriteFile(hFile, cmd, 4, &iWrited, NULL);

//设置新的入口地址
int nEntryPos = dos_head->e_lfanew + 40;
SetFilePointer(hFile, nEntryPos, NULL, FILE_BEGIN);
char pBuffer[4] = {0};
ChangeDwordToString(/*0x0002D820*/dwNewEntryAddress, pBuffer);
WriteFile(hFile, pBuffer, 4, &iWrited, NULL);

//OK
}

//转换DWORD为字符串,并转换成低低高高顺序
void CPeSecDlg::ChangeDwordToString(DWORD d, char *cBuffer)
{
unsigned char waddress[4] = {0};

cBuffer[3] = (char)(d>>24)&0xFF;
cBuffer[2] = (char)(d>>16)&0xFF;
cBuffer[1] = (char)(d>>8)&0xFF;
cBuffer[0] = (char)(d)&0xFF;
}
----------------------完

 

 

 

 

 


DWORD signature;
IMAGE_FILE_HEADER _head;
IMAGE_OPTIONAL_HEADER opt_head;
IMAGE_SECTION_HEADER section_header;

HANDLE hFile;
HANDLE hMapping;
void *basepointer;

// 打开文件.
if ((hFile = CreateFile(szFileName, GENERIC_READ,
FILE_SHARE_READ,0,OPEN_EXISTING,  
FILE_FLAG_SEQUENTIAL_SCAN,0)) == INVALID_HANDLE_VALUE)
{
MessageBox("can't open file");
return FALSE;
}

// 创建内存映射文件.
if (!(hMapping = CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0)))
{
MessageBox("mapping failed");
CloseHandle(hFile);
return FALSE;
}

// 把文件头映象存入baseointer.
if (!(basepointer = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0)))
{
MessageBox("view failed");
CloseHandle(hMapping);
CloseHandle(hFile);
return FALSE;
}
IMAGE_DOS_HEADER * dos_head =(IMAGE_DOS_HEADER *)basepointer;

// 得到PE文件头.
_head = (IMAGE_FILE_HEADER *)((char *)dos_head + dos_head->e_lfanew);

// 得到OEP地址.
DWORD dwOEP=header->opt_head.AddressOfEntryPoint;

  // 清除内存映射和关闭文件.
UnmapViewOfFile(basepointer);
CloseHandle(hMapping);
CloseHandle(hFile);

 

 

 

 

 


 

 

C++获取PE文件入口点 http://www.rrgod.com/program/38.html

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值