基础加壳程序

摘要:     给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盘,就会出现:

如果你喜欢这个程序,请留言,或者联系我。

原文地址:https://www.cnblogs.com/lzjsky/p/1881992.html