#include "StdAfx.h"
#include <malloc.h>
#include ".\joperatpe.h"
JoperatPe::JoperatPe(TCHAR *path):m_IsPe(0),m_IsNt(0)
{
tpath = NULL;
tpath = (char*)malloc(strlen(path)+1);
memset(tpath,0,strlen(path)+1);
strcpy(tpath,path);
m_lpf = NULL;
m_lpf = fopen(tpath,"rb+");
if(m_lpf == NULL)
{
OutputDebugString("无文件操作权限!\n");
}
}
JoperatPe::~JoperatPe(void)
{
if(tpath != NULL )
free(tpath);
if(m_lpf != NULL)
fclose(m_lpf);
}
/*------------------------------------------------------------------------------------
检查目标文件是否为正确的PE格式文件
返回该PE文件格式类型
-------------------------------------------------------------------------------------*/
HRESULT JoperatPe::check()
{
if(m_lpf == NULL) //文件读取错误
return E_FAIL;
WORD IsMZ = 0;
fread(&IsMZ,sizeof(WORD),1,m_lpf);
if(IsMZ == 0x5a4d)
{
//合法文件
if(fseek(m_lpf,0x3c,SEEK_SET) == 0)
{
//获取偏移地址
fread(&m_IsNt,sizeof(DWORD),1,m_lpf);
//
fseek(m_lpf,m_IsNt,SEEK_SET);
fread(&m_IsPe,sizeof(DWORD),1,m_lpf);
if(m_IsPe != 0x00004550)
{
return JE_NOTWIN;
}
else
{
return JE_WINPE;
}
}
return E_FAIL; //偏移地址错误
}
else
{
return JE_FAIL;
}
}
//
//得到DOS头对于Win32程序来所只有2个数据项有用一个是头表示一个文件的正确性
//另一个是尾表示该PE文件的(文件内)偏移
//
HRESULT JoperatPe::SetImageDosHeaderLong(IMAGE_DOS_HEADER *pDosHeader,DWORD dIndx)
{
if(m_lpf == NULL || dIndx == 0 || pDosHeader == NULL)
{
OutputDebugString("操作不明确,或文件没有被打开!\n");
return E_FAIL;
}
fseek(m_lpf,0x00,SEEK_SET);
try
{
switch(dIndx)
{
case SCL_GET:
fread(pDosHeader,sizeof(IMAGE_DOS_HEADER),1,m_lpf);
m_IsNt = pDosHeader->e_lfanew;
break;
case SCL_SET:
fwrite(pDosHeader,sizeof(IMAGE_DOS_HEADER),1,m_lpf);
}
}
catch(...)
{
OutputDebugString("文件操作错误!\n");
return S_FALSE;
}
return S_OK;
}
/*--------------------------------------------------------------------------------
读取或设置PE文件头
---------------------------------------------------------------------------------*/
HRESULT JoperatPe::SetFileHeaderLong(IMAGE_NT_HEADERS *pFileHeader,DWORD dIndx)
{
if(m_lpf == NULL || dIndx == 0)
{
OutputDebugString("操作不明确,或文件没有打开!\n");
return E_FAIL;
}
try
{
//跳过DOS程式
//现在都是win32程式,DOS程式不处理
//m_IsNt纪录了该PE文件的偏移地址
//每个PE文件的该偏移地址都不太一样
//所以某些文档说该地址是固定的这个结论是错误的
if(m_IsNt == 0)
{
OutputDebugString("偏移地址错误!\n");
return E_FAIL;
}
if(fseek(m_lpf,m_IsNt,SEEK_SET) == 0)
{
switch(dIndx)
{
case SCL_GET:
fread(pFileHeader,sizeof(IMAGE_NT_HEADERS),1,m_lpf);
break;
case SCL_SET:
fwrite(pFileHeader,sizeof(IMAGE_FILE_HEADER),1,m_lpf);
break;
default:
break;
}
m_dwFileAlignment = pFileHeader->OptionalHeader.FileAlignment;
return S_OK;
}
}
catch(...)
{
OutputDebugString("文件操作错误!\n");
return S_FALSE;
}
return E_FAIL;
}
//
//直接的到节数
//
WORD JoperatPe::GetSection(WORD *num)
{
if(m_lpf == NULL || num == NULL) //文件读取错误
return 0;
if(fseek(m_lpf,m_IsNt+0x06,SEEK_SET) == 0)
{
fread(num,sizeof(WORD),1,m_lpf);
m_dSctnCnt = *num;
}
return *num;
}
//
//获得可选头尺寸
//
WORD JoperatPe::SizeofOpetionHeader(WORD *num)
{
if(m_lpf == NULL || num==NULL )
return E_FAIL;
if(fseek(m_lpf,m_IsNt+0x14,SEEK_SET) == 0)
{
fread(num,sizeof(WORD),1,m_lpf);
}
return *num;
}
/*-----------------------------------------------------------
说明:该函数用来设置获取字符标志位
参数:dIndex = SCL_SET,设置该字符标志位为num
dIndex = SCL_GET,获取该标志为标志num为输出
-------------------------------------------------------------*/
HRESULT JoperatPe::SetCharactLong(WORD *num,DWORD dIndex)
{
if(m_lpf==NULL || num == NULL)
return E_FAIL;
int icout = 0;
if(fseek(m_lpf,m_IsNt+0x16,SEEK_SET) == 0)
{
switch(dIndex)
{
case SCL_SET:
icout = fwrite(num,sizeof(WORD),1,m_lpf);
return S_OK;
case SCL_GET:
fread(num,sizeof(WORD),1,m_lpf);
return S_OK;
default:
return E_FAIL;
}
return S_OK;
}
return E_FAIL;
}
/*----------------------------------------------------------------------------
可选头的读取/设置
-----------------------------------------------------------------------------*/
HRESULT JoperatPe::SetOpHdStrcLong(IMAGE_OPTIONAL_HEADER32 *iph,DWORD dIndex)
{
if( m_lpf == NULL|| iph == NULL)
return E_FAIL;
if(fseek(m_lpf,m_IsNt+0x18,SEEK_SET) == 0)
{
switch(dIndex)
{
case SCL_SET:
fwrite(iph,sizeof(IMAGE_OPTIONAL_HEADER32),1,m_lpf);
break;
case SCL_GET:
fread(iph,sizeof(IMAGE_OPTIONAL_HEADER32),1,m_lpf);
if(iph->Magic != 0x010b)
return JE_FAIL;
break;
default:
return E_FAIL;
}
return S_OK;
}
return E_FAIL;
}
/*----------------------------------------------------------------------------------
块表信息
注意: pSctnHdr必须为使用malloc分配的内存且该内存长度必须
为/块表长度 == 0
-----------------------------------------------------------------------------------*/
HRESULT JoperatPe::SetSectionHeaderLong(IMAGE_SECTION_HEADER *pSctnHdr,DWORD dIndx)
{
if(m_lpf == NULL || pSctnHdr == NULL || dIndx == 0 )
{
OutputDebugString("操作不明确!\n");
return E_FAIL;
}
int nlen = 0;
IMAGE_NT_HEADERS MgNtHdr = { 0 };
try
{
//只能使用malloc分配内存
nlen = _msize((void*)pSctnHdr);
if( nlen < sizeof(IMAGE_SECTION_HEADER)*m_dSctnCnt)
{
OutputDebugString("请分配节数的内存空间!");
return E_FAIL;
}
if(FAILED(SetFileHeaderLong(&MgNtHdr,SCL_GET)))
{
return E_FAIL;
}
nlen = MgNtHdr.FileHeader.SizeOfOptionalHeader+FIELD_OFFSET(IMAGE_NT_HEADERS32,OptionalHeader);
//这里通过计算得到首块的位置
if(fseek(m_lpf,m_IsNt+nlen,SEEK_SET) == 0)
{
nlen = 0 ;
switch(dIndx)
{
case SCL_GET:
nlen = fread(pSctnHdr,sizeof(IMAGE_SECTION_HEADER),m_dSctnCnt,m_lpf);
if(nlen < m_dSctnCnt)
return E_FAIL;
break;
case SCL_SET:
nlen = fwrite(pSctnHdr,sizeof(IMAGE_SECTION_HEADER),m_dSctnCnt,m_lpf);
if(nlen < m_dSctnCnt)
return E_FAIL;
break;
default:
return E_FAIL;
}
return S_OK;
}
}
catch(...)
{
OutputDebugString("文件操作失败\n");
return S_FALSE;
}
return E_FAIL;
}
/*-------------------------------------------------------------------------------
Out Parament:引入函数表指的是该PE文件编译的时候所使用的相关
PE文件信息
--------------------------------------------------------------------------------*/
HRESULT JoperatPe::SetImportTable(IMAGE_IMPORT_DESCRIPTOR *pImprtDscrptr,DWORD dIndex)
{
if(pImprtDscrptr == NULL || dIndex == 0)
{
return E_FAIL;
}
IMAGE_OPTIONAL_HEADER32 MgPtnlHd = { 0 };
IMAGE_IMPORT_DESCRIPTOR MgMprtDscrp = { 0 };
if(FAILED(SetOpHdStrcLong(&MgPtnlHd,SCL_GET)))
{
return E_FAIL;
}
try
{
fseek(m_lpf,MgPtnlHd.DataDirectory[1].VirtualAddress,SEEK_SET);
fread(&MgMprtDscrp,sizeof(IMAGE_IMPORT_DESCRIPTOR),1,m_lpf);
char p[MAX_PATH] = { 0 };
sprintf(p,"%",(char)MgMprtDscrp.Name);
}
catch(...)
{
}
return E_FAIL;
}
请问PE块中的输入库在PE文件的什么位置或则说只能通过RAV动态得到
[培训]科锐逆向工程师培训第53期2025年7月8日开班!