当前位置:主页 > 教程 > 编程教程 >

C++写壳详解之基础篇
栏目分类:编程教程   发布日期:2019-11-30   浏览次数:

④ 区段以文件对齐粒度对齐后的大小SizeOfRawData(文件对齐大小是0x200的整数倍) 而使用壳代码的时候要注意,因为加完壳后,在壳代码中无法使用导入表,因此,需要自己动态获取需要使用的API函数的地址。 在加壳过程中,有一个加壳器程序和stub.dll两个文

   ④ 区段以文件对齐粒度对齐后的大小SizeOfRawData(文件对齐大小是0x200的整数倍) 而使用壳代码的时候要注意,因为加完壳后,在壳代码中无法使用导入表,因此,需要自己动态获取需要使用的API函数的地址。 在加壳过程中,有一个加壳器程序和stub.dll两个文件,加壳器程序会把原文件(要加壳的文件)以文件方式读取到堆内存,它还是以文件对齐粒度(200h)对齐的,而stub.dll是以不处理的方式读取到了内存中,它是以内存粒度(1000h)对齐的。 再自定义一个共享头文件share.h,这个文件保存一些加壳程序和stub.dll中都会用到的一些数据,封装的函数,及共用的结构体! 区段头内容虽然设置好了,但真正重要的区段里的数据还需要插入到文件中,以扩充文件的大小,因为区段头只是一个相当于目录的存在,如果只有目录而没有内容,就会造成这个文件成为一个无效的PE文件。 使用010Editor打开测试程序,按alt+4出现一个模板菜单找到NumberOfSection把该数字加1,这里改为了9。 根据之前说的已经知道壳区段就是新添加的区段了,里面将保存移植过来的stub的.text段里的所有内容,称之为壳代码。 当然事实上并没有那么简单,stub.dll里的.text段里面的数据需要先进行重定位修复,修复完成后再移植过去,这样壳区段才能正常运行起来。 这个字段的值记录的是一个PE文件在内存中的大小,可以将之设置为: 最后一个区段在内存中的位置 + 最后一个区段在内存中的大小,即: 先找到扩展头的DLL属性字段,去掉随机基址,把40 81改为 00 81后保存。 这就是一个完整的壳流程了,虽然这个壳的内容只有一条跳转到原入口点的代码,但万丈高楼平地起。基础的东西弄懂了后面才能少遇见一些坑! 之后会把存根文件stub.dll的.data,.rdata这2个区段合并到.text段并设置为可读可写可执行属性,需要前置代码 然后再使用OD打开,进入到入口点就是41F000,因为默认加载基址是0x400000, 发现全是00 00 00的字节,没用内容。把第一行代码改为跳转到原来的入口点jmp 0x411055,然后打一个补丁,程序就能正常运行了。 现在PE文件已经被扩充了大小,扩展头中的映像大小必须更新,否则当PE文件加载到内存后,新区段的数据将无法得到正常加载。 在加壳器中把原文件的中除了.tls和.rsrc段的其他段的数据一个一个的按顺序取出来,然后拼接在一起,然后对这份拼接后数据进行一个整体的压缩,之后需要再添加一个区段专门用于存放压缩后的数据,这个过程中,需要把压缩后的区段的文件偏移和文件大小都清零,如下图所示,把.tsl段和.rsrc段移动到头部的后面。 然后是获取GetProcAddress函数的汇编代码,可以使用C语言方式获取,但我觉得用汇编写,它就这样赤裸裸呈现,能更加清晰的了解找到一个函数地址的过程。 我们在逆向破解的时候通常第一方法是找到关键字符串,关键代码等,他们都是存在于代码段的,那么只要把代码段进行加密,这种方式就不可行了。 移植数据到新区段,把整个stub.dll的代码段.text移植到目标文件新添加的区段中,这样就完成了最简单加壳操作。 在这里为了方便,就使用LordPE来操作剩下的步骤了,先记录原始的OEP入口点为11055,把他改为新区段的RVA 1F000然后点击保存。 使用LoadLibraryExA加载DLL并且第三个参数使用DONT_RESOLVE_DLL_REFERENCES的时候,他就不会对这个文件进行重定位等操作,是以原始形态加载到内存。 现在只是暂时搭建一个壳框架所以先不处理随机基址的问题,所以要去掉随机基址,后期再来解决随机基址的问题。 使用DLL动态库文件保存壳代码,我们称它为存根部分(stub),直接把这个文件里的内容移植到我们新添加的区段里面,pk微信?百度“直达号”到底!因为PE文件涉及到重定位,而DLL也是一个PE文件,移植后里面的数据就变得很容易修复了。 这说一下压缩大概思路,首先不能压缩头部,考虑到后面要处理TLS,还有一个程序的图标在资源段,所以不压缩这两个段。 首先根据stub.dll的重定位表获取出stub.dll中.text段需要重定位的数据,然后把该数据 ③ 区段的VirtualAddress(区段数据在内存中的RVA),此值必须是: 上一个区段的VirtualAddress+ 上一个区段经内存对齐粒度对齐后的大小(内存对齐大小是0x1000的整数倍) C++里auto的功能是自动获取后面数据类型,这也体现了C++的强大之处。 添加保存之后, 重新运行010Editor的模板(或者重启010),区段就增加了一个。 保存之后,运行该程序,就能正常运行(中间某些环节操作错了就会导致该文件无法正常运行)到此添加区段成功了。那么加壳也就成功了90%,这个新区段之后称为壳代码段。 值得注意的是没有处理TLS时要把TLS表的RVA和大小清零,TLS在数据目录表的第九项。 一个壳的基本框架就搭建完成了,而加壳主要是为了防止被别人破解,所以接下来就可以执行加密操作了,下一次再说说IAT加密,Hash加密,动态解密,反调试等技术吧。 找到工程所在文件夹,新建一个bin目录,把这两个工程属性中的输出目录改为bin,这样操作起来方便一些,不改也行,但是加载stub时路径就要填写正确才行。 到此一个简单的加密压缩壳就完成了,在这个过程中实际出现了很多bug,因为涉及到DLL文件无法用VS调试, 所以使用OD或者x64dbg进行调试,推荐使用x64dbg(x32dbg),这个软件一直在更新,而且字符串提示更友好,更方便快捷。OD主要用于脱壳破解,逆向还是x64dbg更方便。 要想弄明白怎么对PE文件加壳,首先需要对PE文件比较熟悉,而最快的熟悉PE文件的方法就是自己写一个PE解析工具和写壳了。 本文基于Windows平台对PE文件加壳的项目,经过一个月的缓冲,决定复习总结及分享下的我的心得。 压缩是一个比较复杂的过程,对于一个主要功能的加密的壳来说,压缩也有一定的加密效果,如果使用了一些加密库加密,即使你压缩了,会发现加壳后的文件比没加壳之前还要大! 用C++写代码,首先封装了很多常用的函数,如获取DOS头和NT头,区段头等。这样会节省后面大量敲代码的时间。 很多常见的壳都用汇编写的,确实,汇编确实可以写出很多短小精悍、骚操作的代码,这是C++所没有的,但是C++支持内联汇编,在一定程度上弥补了它的不足。 可以先使用010Editor、LordPE、OD等工具查看节区个数,我实验程序的原始区段(节区)个数是8个。

相关热词: c++基础

相关内容
Copyright © 2002-2020 www.atsierra.com 2019六开彩公开资料 版权所有    粤ICP备88888888号   关于我们 | 广告合作 | 版权声明 | 意见反馈 | 联系方式 | 原创投稿 | 网站地图 |
特效 教程 资源 资讯