安全矩阵

 找回密码
 立即注册
搜索
查看: 2450|回复: 0

网络安全编程:加壳与脱壳

[复制链接]

221

主题

233

帖子

792

积分

高级会员

Rank: 4

积分
792
发表于 2021-6-21 19:05:08 | 显示全部楼层 |阅读模式
网络安全编程:加壳与脱壳[url=]计算机与网络安全[/url] 今天
一次性付费进群,长期免费索取资料。
回复公众号:微信群 可查看进群流程。
广告
加密与解密(第4版)(博文视点出品)作者:段钢
京东


微信公众号:计算机与网络安全
ID:Computer-network

1. 手动加壳

壳是一种较为特殊的软件。壳分为两类,一类是压缩壳,另一类是加密壳。当然,还有介于两者之间的混合壳。下面先来手动为一个可执行文件加一层外壳,需要准备的工具有C32ASM、LordPE、添加节表工具和OD。

首先用 LordPE 查看可执行文件,并对需要的几个数据做一个简单的记录,如图1所示。

图1  PE格式中需要用到的数据

在LordPE中,查看几个需要的数据,包括PE文件的入口RVA、映像地址和代码节的相关数据。有了这些数据以后就可以通过C32ASM对代码进行加密了。用C32ASM以十六进制的方式打开可执行文件,然后从代码节的文件偏移开始选择,也就是从1000h的位置开始选择,一直选到4fffh的位置。然后单击右键,在弹出的快捷菜单上选择“修改数据”命令,在“修改数据”对话框中选择“异或”算法来对代码节进行加密,如图2所示。

图2  用“异或”算法对代码节进行加密

使用0x88对代码节进行异或加密,单击“确定”按钮后,代码节被修改。保存以后,使用编写的添加节表的软件对可执行文件添加一个新的节,如图3所示。

图3  添加新节区

  1. PUSHAD
  2. MOV EAX, 00401000
  3. XOR BYTE PTR DS:[EAX],88
  4. INC EAX
  5. CMP EAX, 00404FFF
  6. JNZ 00408006
  7. POPAD
  8. MOV EAX, 00401000
  9. JMP EAX
复制代码
​以上代码的作用是将上面修改的代码节内容还原,然后进行保存。用LordPE修改该可执行文件的入口和代码节的属性,如图4、图5和图6所示。

图4  修改入口点


图5  添加代码节属性


图6  修改新节属性

运行修改过的可执行文件,可以正常运行。

下面整理一下思路,以方便写代码。最开始用LordPE查看了将要用到的一些PE信息,然后用C32ASM对代码节进行了简单的异或加密,接下来新添加了一个节,并在新节中写入了还原代码节的解密指令,最后用LordPE修改了文件的入口地址、代码节属性和新添加节的属性。对照一下前后两个文件的不同之处,如图7所示。

图7  加壳前后PE文件的对比

从图中可以看出这两个PE文件的差别。下面开始手动打造一个简单的加壳软件。
2. 编写简单的加壳工具

其实不按照上面的步骤进行也可以,只要步骤合理就可以。这里主要有4个函数需要实现,分别是获取PE信息GetPeInfo()、添加新节AddSection()、加密代码节Encode()和写入解密代码WriteDecode()。介绍一下Encode()和WriteDecode()。

Encode()函数的作用是对代码节的内容进行加密,这里选择的加密算法是异或算法。在进行加密以前需要获得代码节在文件中的位置,以及代码节的长度。有了这两个信息就可以进行加密了,代码如下:
  1. // 加密代码节
  2. VOID CMyShellDlg::Encode()
  3. {
  4.   DWORD dwRead = 0;
  5.   PBYTE pByte = NULL;
  6.   pByte = (PBYTE)malloc(m_SecTextInfo.Misc.VirtualSize);
  7.   SetFilePointer(m_hFile, m_SecTextInfo.PointerToRawData, 0, FILE_BEGIN);
  8.   ReadFile(m_hFile, pByte, m_SecTextInfo.Misc.VirtualSize, &dwRead, NULL);
  9.   for ( DWORD i = 0; i < m_SecTextInfo.Misc.VirtualSize; i++ )
  10.   {
  11.     pByte[i] ^= 0x88;
  12.   }
  13.   SetFilePointer(m_hFile, m_SecTextInfo.PointerToRawData, 0, FILE_BEGIN);
  14.   WriteFile(m_hFile, pByte, m_SecTextInfo.Misc.VirtualSize, &dwRead, NULL);
  15.   free(pByte);
  16. }
复制代码
在虚拟地址和汇编指令的中间部分就是汇编指令对应的机器码,将其取出并定义为C语言的数组,定义如下:
  1. 00408000 > 60 PUSHAD
  2. 00408001 B8 00104000 MOV EAX,HelloWor.00401000
  3. 00408006 8030 88 XOR BYTE PTR DS:[EAX],88
  4. 00408009 40 INC EAX
  5. 0040800A 3D 464B4000 CMP EAX,HelloWor.00404B46
  6. 0040800F ^ 75 F5 JNZ SHORT HelloWor.00408006
  7. 00408011 61 POPAD
  8. 00408012 B8 41104000 MOV EAX,HelloWor.00401041
  9. 00408017 FFE0 JMP EAX
复制代码
这个机器码在解密的过程中要根据实际的PE信息进行修改,修改的位置有3处,分别是代码节的起始虚拟地址、代码节的结束虚拟地址和程序的原始入口点。代码如下:
  1. VOID CMyShellDlg::WriteDecode()
  2. {
  3. DWORD dwWrite = 0;
  4. // 写入代码节的开始位置
  5. *(DWORD *)&Decode[2] = m_dwImageBase + m_SecTextInfo.VirtualAddress;
  6. // 代码节终止位置
  7. *(DWORD *)&Decode[11] = m_dwImageBase + m_SecTextInfo.VirtualAddress + m_
  8. SecTextInfo.Misc.VirtualSize;
  9. // 写入 OEP
  10. *(DWORD *)&Decode[19] = m_dwImageBase + m_dwEntryPoint;
  11. SetFilePointer(m_hFile, m_SecNewHdr.PointerToRawData, 0, FILE_BEGIN);
  12. WriteFile(m_hFile, (LPVOID)Decode, sizeof(Decode), &dwWrite, NULL);
  13. }
复制代码
这就是解密代码,大家可以找个用VC写的程序来进行测试。这里使用Release版的helloworld测试通过。

这个壳属于袖珍版的壳,严格来说,算不上是一个壳,但是这个壳在免杀领域是有用的,也就是把定位到的特征码进行加密,然后写入解密代码,从而隐藏特征码。一个真正的壳会对导入表、导出表、资源、TLS、附加数据等相关的部分进行处理。加密壳会加入很多反调试的功能,还会让壳和可执行文件融合在一起,达到“骨肉相连”的程度来增加脱壳的难度。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 06:37 , Processed in 0.013082 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表