首页
社区
课程
招聘
[原创]元宵节献礼,用类的思想处理PE结构附源码
2015-3-5 22:07 20134

[原创]元宵节献礼,用类的思想处理PE结构附源码

2015-3-5 22:07
20134
最近在论坛里接了个业务,客户看了我的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元/年,续费同价!

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (45)
雪    币: 341
活跃值: (133)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
地狱怪客 2 2015-3-5 22:24
2
0
看看学习一下
雪    币: 194
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
baron 2015-3-5 22:58
3
0
这文章肯定不能射精了。
雪    币: 126
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
蓅行耍褲 2015-3-5 23:29
4
0
。。额,表示不懂
雪    币: 539
活跃值: (58)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
专业路过 1 2015-3-5 23:35
5
0
对于这种模块化的拿来就能用的代码 只能赞一个!
雪    币: 118
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dalerkd 1 2015-3-5 23:45
6
0
mark一下下
雪    币: 138
活跃值: (460)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Nermor 1 2015-3-6 09:37
7
0
原来赏金的《壳的编写》是你做的呀~  
当时让我受益匪浅 万分感谢~!
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-6 13:38
8
0
多谢啦,那个是我几年前写的教程!
雪    币: 47
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lhwqqq 2015-3-6 15:08
9
0
老狼 我也看过你的《壳的编写》教程  也是受益匪浅啊
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-6 20:05
10
0
再次编辑,谢谢关注!
雪    币: 84
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
longbit 2015-3-6 21:08
11
0
学习中。谢谢老大!
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-7 22:24
12
0
谢谢看雪老大鼓励,我会继续努力的!
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
Naylon 2 2015-3-8 09:30
13
0
可以读读PeLib的代码,C++写的,很精致
雪    币: 49
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狼啸 2015-3-8 10:59
14
0
mark mark
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-8 12:30
15
0
谢谢啦,我会努力的。
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
AioliaSky 1 2015-3-8 12:33
16
0
感谢分享,mark一下
雪    币: 341
活跃值: (133)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
地狱怪客 2 2015-3-8 21:38
17
0
终于精了~哈。。
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-8 21:50
18
0
是看雪老大为了鼓励我给的精华。
雪    币: 341
活跃值: (133)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
地狱怪客 2 2015-3-8 21:51
19
0
把你那套android放出来肯定是哈哈哈。。。。得不偿失...
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-8 23:07
20
0
打死也不能开源的,我一年多的心血。
雪    币: 1309
活跃值: (1757)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
远洋方舟 2015-3-9 00:47
21
0
不放的话就你就是唯一作者,你知道的
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
人在塔在 2015-3-9 10:50
22
0
原来赏金的教程是你做的
一定要致谢咯,~~
雪    币: 27
活跃值: (631)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
bklang 1 2015-3-9 11:24
23
0
谢谢,你也看过啊?
雪    币: 1230
活跃值: (202)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xinxinqing 2015-3-9 11:39
24
0
大神,嘿嘿。
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
hrpirip 1 2015-3-9 14:59
25
0
NiCe! Bump up the thread
游客
登录 | 注册 方可回帖
返回