文章标题:使用VC自己动手编写加壳程序(3)——打造自己的壳
主要内容:检测文件格式(是否为PE格式的EXE文件)
基本要求:了解VC++6.0基本使用方法;了解PE格式,不熟悉的地方能够通过查阅资料弄懂;
阅读对象:想写壳的新手。高手掠过,本文仅限于写壳入门。
文章类型:原创
文章作者:天漏客 QQ:285252760
完成日期:2009年03月29日
作者主页:www.lilu.name
文章地址:www.lilu.name/Html/heikexuetang/2009-3/11103348.html
文章说明:允许转载,但最好注明转载出处。
本次的主要内容为检测文件是否为PE格式,且是否为EXE文件。DLL等文件也是PE格式,但其加壳的一些数据处理方式不一样,最明显的一个差别就是DLL文件需要重定位。本系统现在暂时只处理EXE可执行文件。
本次的源代码为:
[点击浏览该文件:PEPacker(3).rar]
截图效果:(在RichEdit中多了个文件格式提示)
首先添加一个成员函数:IsPe,用来判断文件格式。如果满足就返回TRUE,否则返回FALSE。
在classview视图中,找到CPEPackerDlg类,在其上面点击右键,选择“Add member Function...” ,函数类型为BOOL,函数描述为IsPE(HANDLE hFile),Access为public,然后确定,编辑此函数。
//检测文件是否是PE可执行文件格式
BOOL CPEPackerDlg::IsPE(HANDLE hFile)
{
WORD wTemp; //暂存读取的字节
DWORD dwBufferRead; //实际读取的字节数
DWORD dwOffset; //PE头偏移位置
DWORD dwOEP; //程序OEP
//读取MZ标志
SetFilePointer(hFile,0,NULL,FILE_BEGIN);
ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL);
//因为二进制目标文件反着顺序存储,所以要反过来判断。
if (wTemp!='ZM')
{
return FALSE;
}
//读取PE头位置
SetFilePointer(hFile,0x3C,NULL,FILE_BEGIN);
ReadFile(hFile,&dwOffset,4,&dwBufferRead,NULL);
//读取PE头信息
SetFilePointer(hFile,dwOffset,NULL,FILE_BEGIN);
ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL);
//判断是否为PE,同样要反着判断。
if (wTemp!='EP')
{
return FALSE;
}
//获取文件OEP
SetFilePointer(hFile,dwOffset+0x28,NULL,FILE_BEGIN);
ReadFile(hFile,&dwOEP,4,&dwBufferRead,NULL);
//如果OEP为0。
if (!dwOEP)
{
return FALSE;
}
//获取文件特征,判断是exe还是dll文件。
SetFilePointer(hFile,dwOffset+0x16,NULL,FILE_BEGIN);
ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL);
if (wTemp & 0x2000 !=0)
{
return FALSE;
}
return TRUE;
}
最后在OnButtonPacking函数中,运用此函数。将此函数添加在打开文件CreateFile和创建映射之间。
如果文件格式正确,就创建映射;否则,就返回。添加后的代码为:
…………………………
//如果文件打开失败,就弹出对话框,并返回。
if (hFile==INVALID_HANDLE_VALUE)
{
MessageBox("打开文件失败!","错误提示",MB_OK);
return;
}
/////////////////第三次加的内容/////////////////////////////////////////////
//判断文件格式
if (!IsPE(hFile))
{
m_RichEditProcInfo.ReplaceSel("错误提示:文件不是PE格式!\r\n");
MessageBox("文件不是PE可执行文件","错误提示!",MB_OK);
return;
}
//////////////////////////////////////////////////////////////////////////
//获取文件大小
dwFileSize=GetFileSize(hFile,NULL);
//设定加壳后的文件名,我采取了一个偷懒的简单方法。
//如果要严格做,需要获取文件路径,扩展名等等。
m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName.GetLength()-4)+"_packed.exe";……………………………………