admin管理员组文章数量:1547074
加壳的实现
我是个初学者,所知有限,难免会有错误,如果有人发现了错误,还请指正。
先大致说一下加壳的原理,即在原PE文件(后面称之为宿主文件)上加一个新的区段(也就是壳),然后从这个新的区段上开始运行;也就算是成功的加上了壳;下面我们就说一下具体的实现。
这个工程有两个项目,一个用来生成壳的Win32项目(dll类型),另一个是实现加壳的MFC项目;
加壳的项目界面是用MFC实现的,除了原有的类外,添加了两个新类,一个用于PE操作,
一个用于加壳。
下面说下加壳过程的实现:
先将原PE文件读取到内存;获取头文件信息,获得.text区段信息,然后对代码段进行加密(简单的异或加密);随后再用LoadLibrary将生成的壳(是一个dll)加载到内存;我们需要在壳的程序里对宿主PE进行解密,并且还要修复重定位,所以要把一些必要的数据存储到加载的壳里面;
申请空间将dll(壳)拷贝一份(此处大家可能会疑惑为什么要拷贝一份,因为我在以LoadLibrary加载进来的壳里直接修改需要重定位的地址信息时,程序运行会出错);
然后申请内存,大小是原宿主PE文件和壳的大小的和;先将宿主程序拷贝进去;
然后修复重定位信息,这个地方应该重点说明一下,我是直接把展开的整个dll拷贝到新PE文件里,并且打算壳的部分利用系统的重定位(每次加载PE文件的时候,如果重定位没有关掉,系统会进行一次重定位),所以在拷贝之前,要把需要重定位的地址修改成在新PE中的虚拟地址,并且我们的壳是通过LoadLibrary的方式加载的,已经被重定位过,我又是直接拷贝过来的,所以修改地址的时候要注意,后面会说到如何修改。
然后,合并PE文件和壳;设置新的OEP,既然加壳,当然要从壳的我们规定的开始位置开始执行,需要将其改成相对新PE开始位置的偏移,原理和修复重定位差不多,不过一个是相对虚拟地址,一个是虚拟地址。
如图:
相对虚拟地址=1+2;
如果修复重定位的话就某一地址的相对虚拟地址再加个默认基址;
下面是代码实现部分:
bool CPack::Pack(WCHAR * szPath)
{
CPe objPe;
//读取要被加壳的PE文件
DWORD dwReadFilSize = 0;
HANDLE hFile = CreateFile(szPath,GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileSize = GetFileSize(hFile, NULL);
char * pFileBuf = new char[dwFileSize];
memset(pFileBuf, 0, dwFileSize);
ReadFile(hFile, pFileBuf, dwFileSize, &dwReadFilSize, NULL);
//获取PE头文件信息
PEHEADERINFO pPeHead = { 0 };
objPe.GetPeHeaderinfo(pFileBuf, &pPeHead);
//加密
IMAGE_SECTION_HEADER pTxtSection;
objPe.GetSectionInfo(pFileBuf, &pTxtSection, ".text");
objPe.XorCode((LPBYTE)(pTxtSection.PointerToRawData + pFileBuf), pTxtSection.SizeOfRawData);
//用loadLibrary加载壳文件
HMODULE pLoadStubBuf = LoadLibrary(L"..\\Release\\Stub.dll");
//存储必要的信息
PPACKINFO PackInfoAdd = (PPACKINFO)GetProcAddress((HMODULE)pLoadStubBuf, "g_PackInfo");
PackInfoAdd->dwOriStartPoint = pPeHead.pOptionHeader->AddressOfEntryPoint; //需要跳转的OEP
PackInfoAdd->dwImageBase = pPeHead.pOptionHeader->ImageBase; //默认加载基址
PackInfoAdd->dwXorCode = pTxtSection.VirtualAddress; //加密代码段地址
PackInfoAdd->dwXorKey = 0xE; //加密密钥
PackInfoAdd->dwXorSize = pTxtSection.SizeOfRawData; //加密大小
PackInfoAdd->stcPeRelocDir = pPeHead.pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; //重定位表信息
PackInfoAdd->dwSizeOfImage = pPeHead.pOptionHeader->SizeOfImage; //原PE的大小
//拷贝一份
MODULEINFO stcModInfo = { 0 };
GetModuleInformation(GetCurrentProcess(), pLoadStubBuf, &stcModInfo, sizeof(MODULEINFO));
版权声明:本文标题:软件加壳的原理及实现 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1727188388a1101191.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论