最近在论坛里接了个业务,客户看了我的ID后说,我发的都是求助帖,对我的能力很质疑,我自己一看才发现,真是除了几年前发了个破解的帖子蒙混过关骗得一个邀请码之外,一直在做伸手党
,于是翻出了之前给赏金论坛做过的一套《壳的编写》的教程,因为做的时候答应人家不能再出售,所以就不发教程了,只是把里面的源码拿来用下。
一直以来我都是以开发为主,类的思想在我脑海里根深蒂固,几年前研究PE结构的时候发现,PE结构完全可以用类的思想处理,于是写了几个处理的代码,并用这个思想写了个简单的加壳程序,可以给notepad.exe加壳,仅供参考,现把代码贴上献丑。
---------------------------------第二次编辑---------------------------------------------------------
其实主要想法就是减少重复劳动,做到代码最大限度的重用,把功能模块化,比如得到NT头,这个功能很多数据都是通过这里开始的,这样就不用每次都重复这个代码,直接调用类中的这个代码就可以了,特别是利用C++的集成功能,可以在继承的子类中使用这部分代码,而对于子类这个代码是不可见的,功能可以用类区分开,代码非常容易管理。下面贴出个别核心代码供大家参考。
//基本的PE处理 可以得到dos头 NT头 节 等信息
class LPEFile
{
public:
BOOL LoadPEFile(BYTE* lpBuffer,DWORD dwSize); //载入PE文件
LPVOID RvaToPtr(DWORD dwRVA); //计算偏移
LPVOID GetDirectoryEntryToData(USHORT DirectoryEntry);
PIMAGE_SECTION_HEADER GetSection(int nIndex); //得到节的信息
BOOL IsPEFile();
PIMAGE_SECTION_HEADER GetFirstSectionHeader(); //得到第一个节
int GetSectionCount(); //得到节的个数
PIMAGE_DATA_DIRECTORY GetDataDirectory(int nIndex); //得到数据目录
PIMAGE_DATA_DIRECTORY GetDataDirectory(); //得到数据目录
PIMAGE_OPTIONAL_HEADER GetNtOptionalHeader();
PIMAGE_FILE_HEADER GetNtFileHeader();
PIMAGE_NT_HEADERS GetNtHeader();
PIMAGE_DOS_HEADER GetDosHeader();
DWORD GetImageSize();
BYTE* GetImage();
bool Free();
BOOL LoadPEFile(char* lpFilename);
BOOL SetInfo(MAP_FILE_STRUCT *pMapFileMsg);
MAP_FILE_STRUCT* GetInfo();
void operator=(LPEFile& lPeFile);
LPEFile();
virtual ~LPEFile();
private:
//用于标识文件的打开状态//用于标识文件的打开状态
BYTE bLoadStact;
//用于存储打开的文件句柄,文件数据,文件大小
protected:
MAP_FILE_STRUCT *pstMapFile;
};
//用于将文件载入内存
BOOL LPEFile::LoadPEFile(char *lpFilename)
{
HANDLE hFile;
HANDLE hMapping;
LPVOID ImageBase;
pstMapFile=new MAP_FILE_STRUCT;
bLoadStact=LFILE_FROM_FILE;
hFile=CreateFile(lpFilename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==NULL)
{
return FALSE;
}
pstMapFile->dwFileSize=GetFileSize(hFile,NULL);
hMapping=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,pstMapFile->dwFileSize,NULL);
if (hMapping==NULL)
{
CloseHandle(hFile);
return FALSE;
}
ImageBase=MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,pstMapFile->dwFileSize);
if (ImageBase==NULL)
{
CloseHandle(hFile);
CloseHandle(hMapping);
return FALSE;
}
pstMapFile->hFile=hFile;
pstMapFile->hMapping=hMapping;
pstMapFile->ImageBase=ImageBase;
return TRUE;
}
//得到文件的dos头
PIMAGE_DOS_HEADER LPEFile::GetDosHeader()
{
return (PIMAGE_DOS_HEADER)GetImage();
}
//得到文件的NT头,这里就不需要从得到Dos开始了,直接调用编写好的类函数
PIMAGE_NT_HEADERS LPEFile::GetNtHeader()
{
PIMAGE_DOS_HEADER pDH=GetDosHeader();
if (pDH!=NULL)
{
return (PIMAGE_NT_HEADERS32)((DWORD)GetImage()+pDH->e_lfanew);
}
return NULL;
}
//得到文件头
PIMAGE_FILE_HEADER LPEFile::GetNtFileHeader()
{
PIMAGE_NT_HEADERS pNth=GetNtHeader();
if (pNth!=NULL)
{
return (PIMAGE_FILE_HEADER)&pNth->FileHeader;
}
return NULL;
}
//得到可选头
PIMAGE_OPTIONAL_HEADER LPEFile::GetNtOptionalHeader()
{
PIMAGE_NT_HEADERS pNth=GetNtHeader();
if (pNth!=NULL)
{
return (PIMAGE_OPTIONAL_HEADER32)&pNth->OptionalHeader;
}
return NULL;
}
//得到数据目录
PIMAGE_DATA_DIRECTORY LPEFile::GetDataDirectory()
{
PIMAGE_OPTIONAL_HEADER pOptionalHeader=GetNtOptionalHeader();
if (pOptionalHeader!=NULL)
{
return (PIMAGE_DATA_DIRECTORY) pOptionalHeader->DataDirectory;
}
return NULL;
}
PIMAGE_DATA_DIRECTORY LPEFile::GetDataDirectory(int nIndex)
{
if (nIndex>=0&&nIndex<16)
{
PIMAGE_DATA_DIRECTORY pDataDir=GetDataDirectory();
if (pDataDir!=NULL)
{
return &pDataDir[nIndex];
}
}
return NULL;
}
有了基本的PE处理之后,就可以在类上做继承,扩展新功能,功能上独立,代码简洁。
//继承LPEFile里面基础处理功能并对 对节处理进行扩展
class LPESection : public LPEFile
{
public:
BOOL WriteSectionData(int nIndex,DWORD dwOffset,BYTE* lpBuffer,DWORD *dwSize); //写入节数据
BYTE* GetSectionData(int nIndex,DWORD* rdwSize); //得到节数据
BOOL AddSection(char* pSectionName,DWORD &dwSectionSize,DWORD dwSectionStact); //添加一个节
DWORD OffsetToRva(DWORD dwOffset); //计算偏移
DWORD RvaToOffset(DWORD dwRva); //计算偏移
DWORD GetVRk(int nSeciotnIndex);
int OffsetToSectionIndex(DWORD dwOffset);
int RvaToSectionIndex(DWORD dwRva);
LPESection();
virtual ~LPESection();
void operator =(LPEFile& lPeFile);
};
//得到节的数据,代码非常简洁,因为很多功能来自父类
BYTE* LPESection::GetSectionData(int nIndex, DWORD *rdwSize)
{
BYTE* lpBuffer=NULL;
PIMAGE_SECTION_HEADER pSection=GetSection(nIndex);
if (pSection->SizeOfRawData>0)
{
DWORD dwFileOffset=pSection->PointerToRawData;
*rdwSize=pSection->SizeOfRawData;
lpBuffer=GetImage()+dwFileOffset;
}
return lpBuffer;
}
//写入节数据
BOOL LPESection::WriteSectionData(int nIndex, DWORD dwOffset, BYTE *lpBuffer, DWORD *dwSize)
{
BOOL bIsOK=false;
DWORD dwSectionSize;
BYTE* lpMyBuffer=NULL;
lpMyBuffer=GetSectionData(nIndex,&dwSectionSize);
if (lpMyBuffer!=NULL&&dwSectionSize>=(*dwSize+dwOffset))
{
lpMyBuffer=lpMyBuffer+dwOffset;
memcpy(lpMyBuffer,lpBuffer,*dwSize);
FlushViewOfFile(pstMapFile->hMapping,pstMapFile->dwFileSize);
bIsOK=TRUE;
}
return bIsOK;
}
//继承自LPEFile 对处理重定位表功能进行扩展
class LPEReLocal : public LPEFile
{
public:
BOOL RelocaltionVA(DWORD dwNewAddress, DWORD dwNewImageBase, DWORD &dwOldVA);
BOOL RelocationMySelf(DWORD dwNewSecAddress,DWORD dwImageBase);
DWORD GetReLocaltionRVA(int nRelocalIndex,int nTypeOffsetIndex);
WORD GetReLocationType(int nRelocalIndex,int nTypeOffsetIndex);
WORD GetTypeOffset(int nRelocalIndex,int nOffsetIndex);
int GetTypeOffsetCount(int nIndex);
PIMAGE_BASE_RELOCATION GetReLocal(int nCount,DWORD *rdwOffset);
int GetReLocalCount();
PIMAGE_BASE_RELOCATION GetFirstReLocaltion();
LPEReLocal();
virtual ~LPEReLocal();
void operator=(LPEFile& lPeFile);
};
//得到首个重定位表
PIMAGE_BASE_RELOCATION LPEReLocal::GetFirstReLocaltion()
{
PIMAGE_BASE_RELOCATION pRelocalDesc=NULL;
pRelocalDesc=(PIMAGE_BASE_RELOCATION)GetDirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_BASERELOC);
if (pRelocalDesc==NULL)
{
return NULL;
}
return pRelocalDesc;
}
//得到重定位表的个数
int LPEReLocal::GetReLocalCount()
{
int i=0;
DWORD dwOffset;
PIMAGE_DATA_DIRECTORY pDataDir=GetDataDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC);
dwOffset=pDataDir->VirtualAddress;
PIMAGE_BASE_RELOCATION pTempReLocal=GetFirstReLocaltion();
while(pTempReLocal->VirtualAddress)
{
++i;
dwOffset=dwOffset+(pTempReLocal->SizeOfBlock);
pTempReLocal=(PIMAGE_BASE_RELOCATION)RvaToPtr(dwOffset);
}
return i;
}
//继承自LPEFile 对处理导入表功能进行扩展
class LPEImport : public LPEFile
{
public:
BOOL ReLocalImport(DWORD dwRVA);
DWORD GetImportThunk(PIMAGE_IMPORT_DESCRIPTOR pImportDesc);
void operator=(LPEFile& lPeFile);
PIMAGE_IMPORT_BY_NAME GetImportFucByName(DWORD RavThunk);
PIMAGE_IMPORT_DESCRIPTOR GetImportDesc(int index);
int GetImportDesCount();
PIMAGE_IMPORT_DESCRIPTOR GetFirstImportDesc();
LPEImport();
virtual ~LPEImport();
};
//得到整个首个导入表
PIMAGE_IMPORT_DESCRIPTOR LPEImport::GetFirstImportDesc()
{
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
pImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)GetDirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_IMPORT);
if(!pImportDesc)
return NULL;
return pImportDesc;
}
//得到共有多少个dll
int LPEImport::GetImportDesCount()
{
int i=0;
PIMAGE_IMPORT_DESCRIPTOR pTempImport=GetFirstImportDesc();
while (pTempImport->FirstThunk)
{
++i;
++pTempImport;
}
return i;
}
// 得到某个dll导入表
PIMAGE_IMPORT_DESCRIPTOR LPEImport::GetImportDesc(int index)
{
int i=GetImportDesCount();
if (index>=i)
{
return NULL;
}
PIMAGE_IMPORT_DESCRIPTOR pTempImport=GetFirstImportDesc();
return &pTempImport[index];
}
//得到某个API 函数的名字
PIMAGE_IMPORT_BY_NAME LPEImport::GetImportFucByName(DWORD RavThunk)
{
PIMAGE_NT_HEADERS pNtH=NULL;
PIMAGE_IMPORT_BY_NAME pApiName=NULL;
pApiName=(PIMAGE_IMPORT_BY_NAME)RvaToPtr(RavThunk);
return pApiName;
}
//继承自LPEFile对处理导出表功能进行扩展
class LPEExport : public LPEFile
{
public:
WORD GetNameOrdValue(int nIndex);
DWORD GetNameOrd(int nIndex);
DWORD GetFirstNameOrd();
char* GetNameValue(int nIndex);
DWORD GetName(int nIndex);
DWORD GetFirstName();
DWORD GetFuncValue(int nIndex);
DWORD GetFunc(int nIndex);
DWORD GetFirstFunc();
int GetNameCount();
int GetFuncCount();
PIMAGE_EXPORT_DIRECTORY GetExportTab();
LPEExport();
virtual ~LPEExport();
void operator=(LPEFile& lPeFile);
};
PIMAGE_EXPORT_DIRECTORY LPEExport::GetExportTab()
{
PIMAGE_EXPORT_DIRECTORY pExportDesc;
pExportDesc=(PIMAGE_EXPORT_DIRECTORY)GetDirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_EXPORT);
if (pExportDesc==NULL)
{
return NULL;
}
return pExportDesc;
}
int LPEExport::GetFuncCount()
{
PIMAGE_EXPORT_DIRECTORY pExportDesc=GetExportTab();
if (pExportDesc)
{
return pExportDesc->NumberOfFunctions;
}
return -1;
}
int LPEExport::GetNameCount()
{
PIMAGE_EXPORT_DIRECTORY pExportDesc=GetExportTab();
if (pExportDesc)
{
return pExportDesc->NumberOfNames;
}
return -1;
}
DWORD LPEExport::GetFirstFunc()
{
PIMAGE_EXPORT_DIRECTORY pExportDesc=GetExportTab();
if (pExportDesc)
{
return pExportDesc->AddressOfFunctions;
}
return 0;
}
DWORD LPEExport::GetFunc(int nIndex)
{
if (nIndex<GetFuncCount())
{
DWORD dwFirstFunc=GetFirstFunc();
return dwFirstFunc+nIndex*4;
}
return 0;
}
开源的加壳代码已经很多了,重要的不是介绍怎样加壳,而是给大家提供一种新的PE文件处理思路,本人小菜,不当之处请多包含!
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开
发者可享99元/年,续费同价!