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

本文基于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重定位vaauto preloc = (pimage_base_relocation)(getoptheader(hmodule)->datadirectory[5].virtualaddress+ hmodule);//获取stub.dll的.text区段的rvadword 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 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; //加上新rvavirtualprotect(pfixaddr, 4, dwoldproc, &dwoldproc);}//指向下一个重定位块preloc = (pimage_base_relocation)((dword)preloc + preloc->sizeofblock);}}现在只是暂时搭建一个壳框架所以先不处理随机基址的问题,所以要去掉随机基址,后期再来解决随机基址的问题。

电机启动器工作原理、作用及选型
可穿戴式电脑,未来能否实现?
解耦表征所得出的因子是否真正独立
智能电力运维是做什么的,它的作用有哪些
浅谈GNSS接收机维护保养及维护
C++写壳详细教程(上)
贴片钽电容的优势有哪些?
一文讲明白MEMS硅晶振与石英晶振的区别
科技头条:滴滴调整组织架构、苹果华为下调7nm芯片订单、骁龙855移动平台发布
LiFi踢馆WiFi 哪天真能取代WiFi也未可知
TomskSoft :价格实惠的专业网络开发机构
LED芯片新兴应用快速发展,LED封装市场寻找“新蓝海”
三大运营商严控成本费用,如何为用户创造更多价值
石墨烯在锂电行业有哪些应用
从测试的角度看“连接型”智能设备的需求
沈阳仪表院原院长:中国传感器最大短板!警惕!可能重蹈“IC芯片”之辙!
运算放大器厂商:上海迦美信芯通讯技术有限公司简介
iphone8什么时候上市?iphone8最新消息汇总:iphone8诸多新功能曝光,哪一项功能最值得期待?
电池剩余电量显示 手机是如何做到的?
利用蜂鸣器演奏简单的乐谱