摘要: 给32位的PE文件加壳,包括exe, dll, ocx, 服务程序,com组件等,差不多所有的PE文件都可以用这个给加上了。我写的这个程序需要插上一个U盘,随便有一个U盘就可以,然后才能给程序加壳,加壳的程序也依靠这个U盘才能运行,有点意思吧。先把程序最主要的函数写到下面。 |
//------------------------------------------------------------------- // 功能: 加壳 // 参数: oldpe - 加壳前的PE文件 // shell - 外壳 // newpe - 加壳后的PE文件 // devstr - device string 设备字符串 // 返回: 是否加壳成功 // 说明: 这样合并之后, oldpe, shell也被改变了, 不能用了 // she就是外壳使用的那个段 // 一般roloc就是在最后, 如果万一碰到不是在最后的, 这里就不能加上壳了 // 1-在oldpe中, 2-在shell中, 3-在newpe中 // R表示在文件中偏移raw, V表示在内存中偏移virtual, T表示有效长度true // bool CombinShell(CPeManager* oldpe, CPeManager* shell, CPeManager* newpe, char* devstr) { //保存到壳里面 TShellHead SH = {0}; strcpy(SH.Feature, devstr); SH.ImageBase = oldpe->GetImageBase(); SH.OldEntry = oldpe->GetEntryPoint(); SH.OldImport = oldpe->GetImportVpos(); SH.OldLastSection = *(oldpe->GetLastSection()); SH.OldBoundImportDataDir = *(oldpe->GetBoundImportDataDir()); SH.OldImportDataDir = *(oldpe->GetImportDataDir()); SH.OldIatDataDir = *(oldpe->GetIatDataDir());
//--给新PE申请一个空间--------------
newpe->m_BufSize = oldpe->m_FileSize + shell->m_FileSize + 0x8000; newpe->m_Buf = new BYTE[newpe->m_BufSize]; ::ZeroMemory(newpe->m_Buf, newpe->m_BufSize);
//--把旧PE复制到新PE中去------------
DWORD last1_Rpos = oldpe->GetLastRpos(); DWORD last1_Vpos = oldpe->GetLastVpos(); DWORD last1_Rsize = oldpe->GetLastRsize(); DWORD last1_Tsize = oldpe->GetLastTsize();
memcpy(newpe->m_Buf, oldpe->m_Buf, (last1_Rpos + last1_Rsize));
//--把壳复制到新PE中去-------------------
DWORD she2_Rpos = shell->GetSheRpos(); DWORD she2_Vpos = shell->GetSheVpos(); DWORD she2_Tsize = shell->GetSheTsize(); DWORD she2_Rsize = shell->GetSheRsize();
DWORD she3_Vpos = last1_Vpos + oldpe->AlignV(last1_Rsize); DWORD she3_Rpos = last1_Rpos + oldpe->AlignV(last1_Rsize);
int base_move = oldpe->GetImageBase() - shell->GetImageBase(); int Vpos_move = she3_Vpos - she2_Vpos;
shell->ModifyReloc(base_move, Vpos_move); shell->ModifyImport(Vpos_move);
memcpy(newpe->m_Buf + she3_Rpos, shell->m_Buf + she2_Rpos, she2_Rsize);
//--修正新PE的段头表--------------------------------
DWORD last3_Tsize = she3_Vpos + she2_Rsize - last1_Vpos; DWORD last3_Rsize = oldpe->AlignR(last3_Tsize);
newpe->GetLastSection()->Misc.VirtualSize = last3_Rsize; newpe->GetLastSection()->SizeOfRawData = last3_Rsize;
DWORD file3_size = last1_Rpos + last3_Rsize; DWORD image3_size = last1_Vpos + last3_Rsize;
//--合并重定位表--------------------
if(oldpe->GetRelocSection() != 0) { //保存到壳里面 SH.OldRelocDataDir = *(oldpe->GetRelocDataDir()); SH.OldRelocSection = *(oldpe->GetRelocSection());
DWORD reloc1_Rpos = oldpe->GetRelocRpos(); DWORD reloc1_Tsize = oldpe->GetRelocTsize(); DWORD reloc2_Rpos = shell->GetRelocRpos(); DWORD reloc2_Tsize = shell->GetRelocTsize(); DWORD reloc3_Rpos = last1_Rpos + last3_Rsize; DWORD reloc3_Vpos = last1_Vpos + oldpe->AlignV(last3_Rsize); DWORD reloc3_Tsize = reloc1_Tsize + reloc2_Tsize; DWORD reloc3_Rsize = oldpe->AlignR(reloc3_Tsize + 8);
//把旧PE的重定位表复制到新PE中 memcpy(newpe->m_Buf + reloc3_Rpos, oldpe->m_Buf + reloc1_Rpos, reloc1_Tsize); //把壳的重定位表复制到新的PE中去 memcpy(newpe->m_Buf + reloc3_Rpos + reloc1_Tsize, shell->m_Buf + reloc2_Rpos, reloc2_Tsize);
//--修正新PE的重定位地址---------
newpe->GetRelocSection()->Misc.VirtualSize = reloc3_Rsize; newpe->GetRelocSection()->SizeOfRawData = reloc3_Rsize; newpe->GetRelocSection()->PointerToRawData = reloc3_Rpos; newpe->GetRelocSection()->VirtualAddress = reloc3_Vpos; newpe->GetRelocDataDir()->Size = reloc3_Tsize; newpe->GetRelocDataDir()->VirtualAddress = reloc3_Vpos;
file3_size = reloc3_Rpos + reloc3_Rsize; image3_size = reloc3_Vpos + reloc3_Rsize; }
//--拷贝附加数据--------------------
if(oldpe->GetFixTsize() != 0) { DWORD fix1_Rpos = oldpe->GetFixRpos(); DWORD fix1_Tsize = oldpe->GetFixTsize(); memcpy(newpe->m_Buf + file3_size, oldpe->m_Buf + fix1_Rpos, fix1_Tsize); file3_size += fix1_Tsize; }
//--修改新PE文件的头部----------------------------
//入口地址 if(oldpe->IsDLL()) newpe->GetOptionalHeader()->AddressOfEntryPoint = shell->GetExportFuncVpos("_DllEntry@12") + Vpos_move; else newpe->GetOptionalHeader()->AddressOfEntryPoint = shell->GetExportFuncVpos("_ExeEntry@0") + Vpos_move;
//导入表地址 newpe->GetImportDataDir()->VirtualAddress = shell->GetImportDataDir()->VirtualAddress + Vpos_move; newpe->GetImportDataDir()->Size = shell->GetImportDataDir()->Size; newpe->GetIatDataDir()->VirtualAddress = 0; newpe->GetIatDataDir()->Size = 0; newpe->GetBoundImportDataDir()->VirtualAddress = 0; newpe->GetBoundImportDataDir()->Size = 0;
//映像大小 newpe->GetOptionalHeader()->SizeOfImage = image3_size; newpe->GetOptionalHeader()->CheckSum = 0; newpe->m_FileSize = file3_size;
//每个段都置为可写 int sec_num = newpe->GetSectionNum(); IMAGE_SECTION_HEADER* sec_hs = newpe->GetSectionHeaders(); for(int i = 0; i < sec_num; i++) { sec_hs[i].Characteristics |= 0x80000000; }
//--保存TShellHead结构-----------------------
TShellHead* pHead = newpe->GetShellHead(she3_Rpos, she2_Tsize); if(pHead == 0) return false; *pHead = SH;
return true; } 因为是个教学程序,界面很简单,下面就是打开了一个扫雷程序。
加壳后的扫雷程序运行时:
如果没有U盘,就会出现:
如果你喜欢这个程序,请留言,或者联系我。 |
