0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++写壳详细教程(上)

jf_78858299 来源:看雪论坛九阳道人 作者:看雪论坛九阳道人 2023-03-17 14:49 次阅读

本文基于Windows平台对PE文件加壳的项目,经过一个月的缓冲,决定复习总结及分享下的我的心得。

主要工具: 010Editor、VS2017、x64dbg、LordPE、OD

实验平台:win10 64位

实现功能:加壳,压缩,对代码段加密。

一、加壳原理

要想弄明白怎么对PE文件加壳,首先需要对PE文件比较熟悉,而最快的熟悉PE文件的方法就是自己写一个PE解析工具和写壳了。

先只用工具010Editor完成一个手工加壳,那么就明白加壳的原理了。

首先进行手工加壳

先用VS随便生成一个exe文件,我们使用它进行实验。

可以先使用010Editor、LordPE、OD等工具查看节区个数,我实验程序的原始区段(节区)个数是8个。

1. 给PE文件添加一个新区段

修改文件头的NumberOfSection

使用010Editor打开测试程序,按alt+4出现一个模板菜单找到NumberOfSection把该数字加1,这里改为了9。

图片

2. 设置新的区段头

添加保存之后, 重新运行010Editor的模板(或者重启010),区段就增加了一个。

图片

设置整个新增加的区段的数据,主要需要设置的字段如下:

图片

① 区段名(可选)

② 区段数据的实际字节数Misc.VirtualSize

③ 区段的VirtualAddress(区段数据在内存中的RVA),此值必须是: 上一个区段的VirtualAddress + 上一个区段经内存对齐粒度对齐后的大小(内存对齐大小是0x1000的整数倍)

④ 区段以文件对齐粒度对齐后的大小SizeOfRawData(文件对齐大小是0x200的整数倍)

⑤ 区段的PointerToRawData(区段数据在文件中的偏移),此值必须是:上一个区段的PointerToRawData + 上一个区段的SizeOfRawData

⑥ 区段属性主要设置区段为可读可写可执行如下图

图片

对比上一个区段修改新添加的区段里的字段。

图片

3. 添加区段数据

区段头内容虽然设置好了,但真正重要的区段里的数据还需要插入到文件中,以扩充文件的大小,因为区段头只是一个相当于目录的存在,如果只有目录而没有内容,就会造成这个文件成为一个无效的PE文件。

把010Editor里的数据页滚动到最下面按Ctrl+shift+i添加200h个(16进制)字节

图片

图片

4. 修改PE文件的扩展头的SizeofImage

现在PE文件已经被扩充了大小,扩展头中的映像大小必须更新,否则当PE文件加载到内存后,新区段的数据将无法得到正常加载。

这个字段的值记录的是一个PE文件在内存中的大小,可以将之设置为: 最后一个区段在内存中的位置 + 最后一个区段在内存中的大小,即:

OptionalHeader.SizeofImage = 最后一个区段.VirtualAddress + 最后一个区段.SizeOfRawData按内存对齐粒度对齐的大小

图片

保存之后,运行该程序,就能正常运行(中间某些环节操作错了就会导致该文件无法正常运行)到此添加区段成功了。那么加壳也就成功了90%,这个新区段之后称为壳代码段。

5. 添加壳代码

先找到扩展头的DLL属性字段,去掉随机基址,把40 81改为 00 81后保存。

图片

在这里为了方便,就使用LordPE来操作剩下的步骤了,先记录原始的OEP入口点为11055,把他改为新区段的RVA 1F000然后点击保存。

图片

然后再使用OD打开,进入到入口点就是41F000,因为默认加载基址是0x400000, 发现全是00 00 00的字节,没用内容。把第一行代码改为跳转到原来的入口点jmp 0x411055,然后打一个补丁,程序就能正常运行了。

图片

这就是一个完整的壳流程了,虽然这个壳的内容只有一条跳转到原入口点的代码,但万丈高楼平地起。基础的东西弄懂了后面才能少遇见一些坑!

二、为什么用C++写壳?

我的答案是简单、便捷、方便新手入门。

很多常见的壳都用汇编写的,确实,汇编确实可以写出很多短小精悍、骚操作的代码,这是C++所没有的,但是C++支持内联汇编,在一定程度上弥补了它的不足。

使用DLL动态库文件保存壳代码,我们称它为存根部分(stub),直接把这个文件里的内容移植到我们新添加的区段里面,因为PE文件涉及到重定位,而DLL也是一个PE文件,移植后里面的数据就变得很容易修复了。

三、C++加壳流程

1. 处理加壳程序

在加壳过程中,有一个加壳器程序和stub.dll两个文件,加壳器程序会把原文件(要加壳的文件)以文件方式读取到堆内存,它还是以文件对齐粒度(200h)对齐的,而stub.dll是以不处理的方式读取到了内存中,它是以内存粒度(1000h)对齐的。

使用LoadLibraryExA加载DLL并且第三个参数使用DONT_RESOLVE_DLL_REFERENCES的时候,他就不会对这个文件进行重定位等操作,是以原始形态加载到内存。

//将DLL以不会执行代码的标志加载到进程中.
HMODULE hStubDll = LoadLibraryExA("Stub.dll", 0,
DONT_RESOLVE_DLL_REFERENCES);

再自定义一个共享头文件share.h,这个文件保存一些加壳程序和stub.dll中都会用到的一些数据,封装的函数,及共用的结构体!

流程如下:

① 使用加壳器给被加壳程序添加新区段。

② 加密/压缩被加壳程序。

③ 将stub的代码段移植到新区段。

④ 将被加壳程序的OEP记录到share.h中。

⑤ 将被加壳程序的EP设置到新区段。

⑥ 去掉随机基址。

⑦ 保存为新文件。

移植数据到新区段,把整个stub.dll的代码段.text移植到目标文件新添加的区段中,这样就完成了最简单加壳操作。

图片

当然事实上并没有那么简单,stub.dll里的.text段里面的数据需要先进行重定位修复,修复完成后再移植过去,这样壳区段才能正常运行起来。

首先根据stub.dll的重定位表获取出stub.dll中.text段需要重定位的数据,然后把该数据

① 减去原始基址

② 减去原始代码段Rva

③ 加上新基址(exe目标文件)

④ 加上新Rva (exe中新添加的区段RVA)

用C++写代码,首先封装了很多常用的函数,如获取DOS头和NT头,区段头等。这样会节省后面大量敲代码的时间。

//获取DOS头
PIMAGE_DOS_HEADER GetDosHeader(char* pBase)
{
return (PIMAGE_DOS_HEADER)pBase;
}

//获取NT头
PIMAGE_NT_HEADERS GetNtHeader(char* pBase)
{
return (PIMAGE_NT_HEADERS)
(GetDosHeader(pBase)->e_lfanew + (DWORD)pBase);
}

例如获取NT头:

auto pNt = (PIMAGE_NT_HEADERS)GetNtHeader(pBase);

C++里auto的功能是自动获取后面数据类型,这也体现了C++的强大之处。

完整重定位代码:

//修复stub的重定位
void FixStubReloc(char* pTarBuff, char*& hModule,DWORD dwNewBase,DWORD dwNewSecRva)
{
//获取sutb.dll重定位va
auto pReloc = (PIMAGE_BASE_RELOCATION)
(GetOptHeader(hModule)->DataDirectory[5].VirtualAddress
+ hModule);
//获取stub.dll的.text区段的Rva
DWORD dwTextRva = (DWORD)GetSecHeader(hModule, ".text")->VirtualAddress;

//修复重定位
while (pReloc->SizeOfBlock)
{
struct TypeOffset
{
WORD offset : 12;
WORD type : 4;
};
TypeOffset* pTyOf = (TypeOffset*)(pReloc + 1);
DWORD dwCount = (pReloc->SizeOfBlock - 8) / 2;
for (size_t i = 0; i < dwCount; i++)
{
if(pTyOf[i].type != 3)
continue;
//要修复的Rva
DWORD dwFixRva = pTyOf[i].offset + pReloc->VirtualAddress;
//要修复的地址
DWORD* pFixAddr = (DWORD*)(dwFixRva + (DWORD)hModule);
DWORD dwOldProc;
VirtualProtect(pFixAddr, 4, PAGE_READWRITE, &dwOldProc);
*pFixAddr -= (DWORD)hModule; //减去原始基址
*pFixAddr -= dwTextRva; //减去原始代码段Rva
*pFixAddr += dwNewBase; //加上新基址
*pFixAddr += dwNewSecRva; //加上新Rva
VirtualProtect(pFixAddr, 4, dwOldProc, &dwOldProc);
}
//指向下一个重定位块
pReloc = (PIMAGE_BASE_RELOCATION)
((DWORD)pReloc + pReloc->SizeOfBlock);
}
}

现在只是暂时搭建一个壳框架所以先不处理随机基址的问题,所以要去掉随机基址,后期再来解决随机基址的问题。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • WINDOWS
    +关注

    关注

    4

    文章

    3584

    浏览量

    89483
  • C++
    C++
    +关注

    关注

    22

    文章

    2114

    浏览量

    73934
  • PE文件
    +关注

    关注

    0

    文章

    4

    浏览量

    5469
收藏 人收藏

    评论

    相关推荐

    C++一个http服务器

    本篇文章不会涉及到很多复杂的概念,也没有很难读懂的模板函数,代码简单可读,本篇文章送给每一个想自己用C++一个http服务器的小伙伴!高手们、大佬们当然可以不用看的啦!
    发表于 09-30 10:47 2291次阅读

    详细讲解C++串口的相关知识

    大家可以先参考一下这篇blog,C++串口通信里面详细讲解了C++串口的相关知识,以及一些函数的讲解。下面我也会根据他的blog再讲解。二、实现过程1、打开串口:使用函数:HANDLE CreateFile();HANDLE C
    发表于 08-24 06:56

    详述不用c++网页的理由

    C++在web开发中地位如何,进来一探究竟吧。
    的头像 发表于 12-22 10:07 6016次阅读

    C++课程资料详细资料合集包括了:面向对象程序设计与C++,算法,函数等

    本文档的主要内容详细介绍的是C++课程资料资料合集包括了:面向对象程序设计与C++,算法,函数,概述, C++语言基础,构造数据类型,数据类型,C+
    发表于 07-09 08:00 18次下载
    <b class='flag-5'>C++</b>课程资料<b class='flag-5'>详细</b>资料合集包括了:面向对象程序设计与<b class='flag-5'>C++</b>,算法,函数等

    基于fpgrowth的c++实现详细资料免费下载

    本文档的主要内容详细介绍的是基于fpgrowth的c++实现详细资料免费下载
    发表于 08-02 08:00 1次下载

    如何提高cc++的安全编程能力?《CC++安全编码》带你详细学习

    ,既详细阐述了C/C++语言及其相关库固有的安全问题和陷阱,系统总结了导致软件漏洞的各种常见编码错误,并给出了应对错误的解决方案;又对C/C++
    发表于 08-28 08:00 0次下载

    如何进行高质量的CC++编程?高质量C++C编程指南详细资料免费下载

    本文档的作用内容详细介绍的是如何进行高质量的CC++编程?高质量C++C编程指南详细资料免费
    发表于 09-10 08:00 30次下载

    VISUAL C++教程之VISUAL C++的安装和使用方法

    本文档的主要内容详细介绍的是VISUAL C++教程之VISUAL C++的安装和使用方法资料免费下载。
    发表于 12-27 16:32 19次下载
    VISUAL <b class='flag-5'>C++</b>教程之VISUAL <b class='flag-5'>C++</b>的安装和使用方法

    C++的cast最完整最详细的解释资料说明

    本文档的主要内容详细介绍的是C++的cast最完整最详细的解释资料说明。
    发表于 01-29 15:26 0次下载
    <b class='flag-5'>C++</b>的cast最完整最<b class='flag-5'>详细</b>的解释资料说明

    C++程序设计教程之C++的初步知识的详细资料说明

    C++程序设计教程之C++的初步知识的详细资料说明包括了:1. 从CC++,2 . 最简单的C++
    发表于 03-14 14:48 31次下载
    <b class='flag-5'>C++</b>程序设计教程之<b class='flag-5'>C++</b>的初步知识的<b class='flag-5'>详细</b>资料说明

    C++程序设计教程之C++工具的详细资料说明

    本文档的详细介绍的是C++程序设计教程之C++工具的详细资料说明主要内容包括了:1. 异常处理,2. 命名空间,3. 使用早期的函数库
    发表于 03-14 16:39 4次下载
    <b class='flag-5'>C++</b>程序设计教程之<b class='flag-5'>C++</b>工具的<b class='flag-5'>详细</b>资料说明

    C++语言编码规范详细说明

    本文档的主要内容详细介绍的是C++语言编码规范详细说明。
    发表于 01-07 16:19 14次下载
    <b class='flag-5'>C++</b>语言编码规范<b class='flag-5'>详细</b>说明

    C语言和C++的特点与用法详细说明

    本文档的主要内容详细介绍的是C语言和C++的特点与用法详细说明。
    的头像 发表于 12-26 10:58 4496次阅读

    qt用C++的2048小游戏源代码

    qt用C++的2048小游戏源代码
    发表于 09-27 11:48 3次下载

    C++详细教程(下)

    本文基于Windows平台对PE文件加的项目,经过一个月的缓冲,决定复习总结及分享下的我的心得。
    的头像 发表于 03-17 14:49 636次阅读
    <b class='flag-5'>C++</b><b class='flag-5'>写</b><b class='flag-5'>壳</b><b class='flag-5'>详细</b>教程(下)