论坛首页 安全编程开发区 阅读主题

[原创][开源]用C++实现的壳(基础版)

499 浏览 24 回复
#1 楼主 2026-06-01 21:09:02
上图简单的示意了加壳前后的PE文件变化,首先是多出了一个区段,用于存放Shell部分的代码,再就是入口点变为了Shell部分的入口点,这样保证能够先运行我们壳部分的代码,执行我们想要的操作,最后就是跳回到原始程序的OEP,开始执行原始程序。

        流程看着简单,但如果能够让一般的PE文件正常运行,需要注意的细节还是很多的,下面我就来详细道来。


        框架:在一个普通的MFC新建工程基础上,自己添加了两个类,一个为Pack类,另一个为PE类。 MFC自带工程仅仅负责界面,加壳的主要流程是在Pack类里,在加壳过程中需要对PE文件操作是,就调用PE类中的函数来实现。

        加壳部分的流程(此流程在Pack类中的Pack()函数中实现):

        1.读取文件PE文件信息并保存 

        2.加密代码段操作

        3.将必要的信息保存到Shell (Pack部分和Shell部分的数据交换)

        4.将Shell部分附加到PE文件

        5.保存文件,完成加壳

        6.释放资源


 具体实现:

 1.读取文件PE文件信息并保存 

        要为一个PE文件加壳,首先就是要了解这个PE文件。那么就需要把这个文件读到内存中,加载到内存中的方式有两种,一种是以文件对齐的方式读到内存,也就是直接读取文件的二进制数据,另一种方式是以内存对齐的方式读到内存,或者其实就在模拟程序运行时的内存分部,我选择的是第二种,以内存对齐的方式读到内存,这样的好处就是在对PE文件进行操作的时候,不需要将相对虚拟地址(RVA)转换为文件偏移(ROffset),操作起来也更直观,直接就是内存中的偏移地址。读取文件的代码详见源码PE类中的InitPE(CString strFilePath)函数,或者参考《加密与解密 第三版》第443页内容。

        将文件读取到内存以后,下一步就是获取我们关注的信息并保存了,信息保存在PE类中的成员变量中,这样在Pack类中只需要定义一个PE类的对象,即可调用这些信息。

        我保存的关键信息有:保存PE文件的缓冲区的指针,PE文件的NT头指针、镜像大小、镜像基址、OEP地址、区段数量以及重定位表、导入表指针信息。这里保存的信息其实越详细越好,方便以后拓展功能的时候能够用到。


        加壳以后,运行程序弹出MessageBox:


        加壳测试在 Win7 x64 系统下,对大多数程序加壳后都可以正常运行,不支持dll加壳。

        有兴趣的朋友可以下载源码看一下,由于本人才疏学浅、能力有限,有错的第地方还请大牛指出!

        注:此壳不以加密为目的,被脱秒秒种的事...  


   源码下载: CyxvcProtect@15PB.rar//PE.h
public:
  HANDLE          m_hFile;      //PE文件句柄
  LPBYTE          m_pFileBuf;      //PE文件缓冲区
  DWORD          m_dwFileSize;    //文件大小
  DWORD          m_dwImageSize;    //镜像大小
  PIMAGE_DOS_HEADER    m_pDosHeader;    //Dos头
  PIMAGE_NT_HEADERS    m_pNtHeader;    //NT头
  PIMAGE_SECTION_HEADER  m_pSecHeader;    //第一个SECTION结构体指针
  DWORD          m_dwImageBase;    //镜像基址
  DWORD          m_dwCodeBase;    //代码基址
  DWORD          m_dwCodeSize;    //代码大小
  DWORD          m_dwPEOEP;      //OEP地址
  DWORD          m_dwShellOEP;    //新OEP地址
  DWORD          m_dwSizeOfHeader;  //文件头大小
  DWORD          m_dwSectionNum;    //区段数量
  DWORD          m_dwFileAlign;    //文件对齐
  DWORD          m_dwMemAlign;    //内存对齐
  DWORD          m_IATSectionBase;  //IAT所在段基址
  DWORD          m_IATSectionSize;  //IAT所在段大小
  IMAGE_DATA_DIRECTORY  m_PERelocDir;    //重定位表信息
  IMAGE_DATA_DIRECTORY  m_PEImportDir;    //导入表信息void CPE::GetPEInfo()
  m_pDosHeader  = (PIMAGE_DOS_HEADER)m_pFileBuf;
  m_pNtHeader    = (PIMAGE_NT_HEADERS)(m_pFileBuf + m_pDosHeader->e_lfanew);
  m_dwFileAlign  = m_pNtHeader->OptionalHeader.FileAlignment;
  m_dwMemAlign  = m_pNtHeader->OptionalHeader.SectionAlignment;
  m_dwImageBase  = m_pNtHeader->OptionalHeader.ImageBase;
  m_dwPEOEP    = m_pNtHeader->OptionalHeader.AddressOfEntryPoint;
  m_dwCodeBase  = m_pNtHeader->OptionalHeader.BaseOfCode;
  m_dwCodeSize  = m_pNtHeader->OptionalHeader.SizeOfCode;
  m_dwSizeOfHeader= m_pNtHeader->OptionalHeader.SizeOfHeaders;
  m_dwSectionNum  = m_pNtHeader->FileHeader.NumberOfSections;
  m_pSecHeader  = IMAGE_FIRST_SECTION(m_pNtHeader);
  m_pNtHeader->OptionalHeader.SizeOfImage = m_dwImageSize;
  //保存重定位目录信息
  m_PERelocDir =

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-206804.htm
#17 2026-06-01 21:09:02
感谢楼主分享.........................
#18 2026-06-01 21:09:02
请教一下,什么是bambam 啊
#19 2026-06-01 21:09:02
可以结合bambam,就不用loadlibrary了
#20 2026-06-01 21:09:02
感谢分享!
#21 2026-06-01 21:09:02
唉  我只能说 15PB  广告打的真多  一开始真有期待 最后你发现 都是基础 的基础   发些内部视频出来啊
#22 2026-06-01 21:09:02
感谢分享
#23 2026-06-01 21:09:02
还真没去那里看过,多谢提醒,以后常去逛逛
#24 2026-06-01 21:09:02
扔到github上
#25 2026-06-01 21:09:02
赞 111111
‹ 上一页 1 2 下一页 ›

请登录后参与讨论

立即登录 注册账号