UPX

upx大家应该都不陌生,在做题时算是比较容易遇到的一种壳,代码开源。

UPX(the Ultimate Packer for eXecutables)是一个免费且开源的可执行程序文件加壳器,支持许多不同操作系统下的可执行文件格式

upx使用

加壳:

upx file -o upx_file

注:如果因为程序过小而压缩失败可以通过添加如下代码进行解决:

int const dummy_to_make_this_compressible[10000] = {1,2,3};

脱壳:

upx -d upx_file

UPX魔改

  • 对upx_file二进制文件进行魔术头修改,将UPX!改为其他数据;
  • 对UPX源码进行魔改,隐藏upx加壳标志,防止一键脱壳。
  • 更改overlay_offset(文件最后4个字节);这里overlay_offset值为p_info字段的文件偏移,通常为0xf4,视情况而定

upx手脱

运行程序后查看进程的内存信息

ps -ef |grep upx_file
pmap -d pid_of_file

脱壳的基本原理是程序在运行时会将代码释放到内存中,我们只需在运行时将内存中的可执行代码段dump出来即可。

如下命令:

sudo dd if=/proc/$(pidof mac-main-upx)/mem of=main_dump skip=0x400000  bs=1c count=786432

当然使用gdb附加,使用(gdb) dump memory /root/memory.dump 0x400000 0x40c000也是一样的效果。

这时便可以动静结合来进行调试了。
当然如果你有能力修复的,那么把dump的程序修复下也是可以的。

脚本

idc dump镜像脚本:

#include <idc.idc>
#define PT_LOAD              1
#define PT_DYNAMIC           2
static main(void)
{
  auto ImageBase,StartImg,EndImg;//基址 08048000
  auto e_phoff;
  auto e_phnum,p_offset;//paddr 0xc 地址,pmemsz ox14大小,p_offset 0x4
  auto i,dumpfile;
  ImageBase=0x08048000;
  StartImg=0x08048000;
  EndImg=0x0; 
  Message("%8x\n",Dword(ImageBase));
  if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f )
  {
    if(dumpfile=fopen("./dumpfile","w+"))
    {
      e_phoff=ImageBase+Word(ImageBase+0x1c);
      e_phnum=Word(ImageBase+0x2c);
      for(i=0;i<e_phnum;i++)
      {
         if (Dword(e_phoff)==PT_LOAD || Dword(e_phoff)==PT_DYNAMIC)
         
          {  p_offset=Dword(e_phoff+0x4);       
            StartImg=Dword(e_phoff+0xc);
            EndImg=Dword(e_phoff+0xc)+Dword(e_phoff+0x14);
             
                dump(dumpfile,StartImg,EndImg,p_offset);
                Message("dump LOAD%d ok.\n",i);
          }   
         
        e_phoff=e_phoff+0x20;
      }
      fseek(dumpfile,0x30,0);
      fputc(0x00,dumpfile);   
      fputc(0x00,dumpfile);   
      fputc(0x00,dumpfile);   
      fputc(0x00,dumpfile);
      fclose(dumpfile);
    }else Message("dump err.");
  }
}
static dump(dumpfile,startimg,endimg,offset)
{
  auto i;
  auto size;
  size=endimg-startimg;
  fseek(dumpfile,offset,0);
    for ( i=0; i < size; i=i+1 )
    {
      fputc(Byte(startimg+i),dumpfile);
    }
}