|
网络安全编程:加壳与脱壳[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 添加新节区
- PUSHAD
- MOV EAX, 00401000
- XOR BYTE PTR DS:[EAX],88
- INC EAX
- CMP EAX, 00404FFF
- JNZ 00408006
- POPAD
- MOV EAX, 00401000
- 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()函数的作用是对代码节的内容进行加密,这里选择的加密算法是异或算法。在进行加密以前需要获得代码节在文件中的位置,以及代码节的长度。有了这两个信息就可以进行加密了,代码如下:
- // 加密代码节
- VOID CMyShellDlg::Encode()
- {
- DWORD dwRead = 0;
- PBYTE pByte = NULL;
- pByte = (PBYTE)malloc(m_SecTextInfo.Misc.VirtualSize);
- SetFilePointer(m_hFile, m_SecTextInfo.PointerToRawData, 0, FILE_BEGIN);
- ReadFile(m_hFile, pByte, m_SecTextInfo.Misc.VirtualSize, &dwRead, NULL);
- for ( DWORD i = 0; i < m_SecTextInfo.Misc.VirtualSize; i++ )
- {
- pByte[i] ^= 0x88;
- }
- SetFilePointer(m_hFile, m_SecTextInfo.PointerToRawData, 0, FILE_BEGIN);
- WriteFile(m_hFile, pByte, m_SecTextInfo.Misc.VirtualSize, &dwRead, NULL);
- free(pByte);
- }
复制代码 在虚拟地址和汇编指令的中间部分就是汇编指令对应的机器码,将其取出并定义为C语言的数组,定义如下:
- 00408000 > 60 PUSHAD
- 00408001 B8 00104000 MOV EAX,HelloWor.00401000
- 00408006 8030 88 XOR BYTE PTR DS:[EAX],88
- 00408009 40 INC EAX
- 0040800A 3D 464B4000 CMP EAX,HelloWor.00404B46
- 0040800F ^ 75 F5 JNZ SHORT HelloWor.00408006
- 00408011 61 POPAD
- 00408012 B8 41104000 MOV EAX,HelloWor.00401041
- 00408017 FFE0 JMP EAX
复制代码 这个机器码在解密的过程中要根据实际的PE信息进行修改,修改的位置有3处,分别是代码节的起始虚拟地址、代码节的结束虚拟地址和程序的原始入口点。代码如下:
- VOID CMyShellDlg::WriteDecode()
- {
- DWORD dwWrite = 0;
- // 写入代码节的开始位置
- *(DWORD *)&Decode[2] = m_dwImageBase + m_SecTextInfo.VirtualAddress;
- // 代码节终止位置
- *(DWORD *)&Decode[11] = m_dwImageBase + m_SecTextInfo.VirtualAddress + m_
- SecTextInfo.Misc.VirtualSize;
- // 写入 OEP
- *(DWORD *)&Decode[19] = m_dwImageBase + m_dwEntryPoint;
- SetFilePointer(m_hFile, m_SecNewHdr.PointerToRawData, 0, FILE_BEGIN);
- WriteFile(m_hFile, (LPVOID)Decode, sizeof(Decode), &dwWrite, NULL);
- }
复制代码 这就是解密代码,大家可以找个用VC写的程序来进行测试。这里使用Release版的helloworld测试通过。
这个壳属于袖珍版的壳,严格来说,算不上是一个壳,但是这个壳在免杀领域是有用的,也就是把定位到的特征码进行加密,然后写入解密代码,从而隐藏特征码。一个真正的壳会对导入表、导出表、资源、TLS、附加数据等相关的部分进行处理。加密壳会加入很多反调试的功能,还会让壳和可执行文件融合在一起,达到“骨肉相连”的程度来增加脱壳的难度。
|
|