上回我给出了加壳程序的核心的代码,这回我给出 相关的汇编代码。 使用汇编我很无奈,我还不能能用纯C/C++来实现这些嵌入的代码。 代码注释得很清楚,是加壳这个壳的原始代码。 其中的加压缩的部分其实就是脱壳的部分。 其中注释中注明需重定位的,则需要在组装EXE文件的时候修改的。 也就是地址的重定位。。。
具体的看上回发的代码~~ 结合上下文就能看明白了
- cpu P3
- bits 32
- global _start
- section .text
- ;---------------------------------------------------------------
- ;初始化
- _start:
- push ebp
- mov ebp,esp
- sub esp,0x20
- pushad
- mov esi,0xFFFFFFFF ;需重定位 解压源地址
- mov [ebp-0x04*0x00],esi
- mov edi,0xFFFFFFFF ;需重定位 解压目的地址
- mov [ebp-0x04*0x01],edi
- mov ecx,0xFFFFFFFF ;需重定位 压缩数据长度
- mov [ebp-0x04*0x02],ecx
- mov eax,0xFFFFFFFF ;需重定位 源代码入口
- mov [ebp-0x04*0x03],eax
- mov eax,0xFFFFFFFF ;需重定位 IAT源地址
- mov [ebp-0x04*0x04],eax
- mov eax,0xFFFFFFFF ;需重定位 IAT目的地址
- mov [ebp-0x04*0x05],eax
- mov eax,0xFFFFFFFF ;需重定位 IAT长度
- mov [ebp-0x04*0x06],eax
- ;---------------------------------------------------------------
- ;解码,恢复原映像数据
- ; @decode_next_byte:
- ; mov al,[esi]
- ; not al
- ; mov [edi],al
- ; inc esi
- ; inc edi
- ; loop @decode_next_byte
- ;pcx 的RLE解码
- @rle_decode_next_byte:
- mov al,[esi]
- cmp al,0xc0
- je @rle_decode_exit ;0xC0结束符
- jc @output_1
- jnc @output_x
- @output_1:
- mov al,[esi]
- mov [edi],al
- inc edi
- inc esi
- jmp @rle_decode_next_byte
- @output_x:
- mov al,[esi]
- sub al,0xC0
- xor ecx,ecx
- mov cl,al
- inc esi
- mov al,[esi]
- @next_repeat_byte:
- mov al,[esi]
- mov [edi],al
- inc edi
- loop @next_repeat_byte
- inc esi
- jmp @rle_decode_next_byte
- @rle_decode_exit:
- ;---------------------------------------------------------------
- ;拷贝IAT
- mov ecx,[ebp-0x04*0x06]
- mov esi,[ebp-0x04*0x04]
- mov edi,[ebp-0x04*0x05]
- dec ecx
- @copy_iat_next_byte:
- mov al,[esi]
- mov [edi],al
- inc esi
- inc edi
- loop @copy_iat_next_byte
- ;---------------------------------------------------------------
- ;准备进入原镜像代码
- popad
- mov eax,[ebp-0x04*0x03]
- mov esp,ebp
- pop ebp
- jmp eax
- ;---------------------------------------------------------------
以上就是了那个啥,汇编代码了。。。 使用nasm编译通过
我是使用命令 nasm -f bin loader.asm -l loader.lst -o loader.dat。 对了,上述的汇编代码保存成 loader.asm文件哦
关于如何重定位,相关的C++代码是这样的
- //重定位壳代码的地址
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[0])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfImage;
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[1])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfHeaders;
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[2])) = nPackerCodeEntryOffset;
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[3])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.AddressOfEntryPoint;
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[4])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfImage+nPackerIATOffset;
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[5])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
- *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[6])) = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
另外我提一下,就是我采用的压缩解压算法是类似于 PCX 的游程码压缩,压缩比不是很高。。。 我就顺便提一下,嘿嘿。
由于时间问题,我没时间研究PE的资源等结构。。。所以现在这个加壳器不支持带资源的EXE文件,目前测试过的就是使用VC++编译的控制台程序运行正常~
找个机会我把我的工程代码发到 csdn 资源