魔改upx加密辅助so文件脱壳教学

[复制链接]
查看1741 | 回复0 | 2024-10-16 20:39:23 | 显示全部楼层 |阅读模式

立即注册,突破游客限制,与技术大牛交流切磋,畅享海量资源,让你的技术之路不再孤单!

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在分析辅助so文件的时候,发现了利用魔改upx压缩的样本,因为gdb没有类似于x32dbg那种方便的iat修复功能和内存dump功能,所以esp定律能用也受限。这里使用ida搭配idc脚本的方式进行脱壳,并采用 ida 的finger插件进行函数名称修复。

关键脚本:
压缩壳的脱壳思路基本一致,在解压程序将内容完全解压,然后跳转到真正的入口点,把程序dump下来,然后修复一下iat就差不多了。
但是因为这里是一个辅助样本,基本都是系统调用出来的,所以iat修不修无所谓了。
下面这个idc脚本就是用来dump程序,并且修改iat的作用。

  1. #include <idc.idc>
  2. #define PT_LOAD              1
  3. #define PT_DYNAMIC           2
  4. static main(void)
  5. {
  6.     auto ImageBase,StartImg,EndImg;
  7.     auto e_phoff;
  8.     auto e_phnum,p_offset;
  9.     auto i,dumpfile;
  10.     // 基地址和起始地址,这里根据实际修改,一般不用改
  11.     ImageBase=0x400000;
  12.     StartImg=0x400000;
  13.     EndImg=0x0;
  14.     // 检查是不是elf文件
  15.     if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f )
  16.     {
  17.         if(dumpfile=fopen("D:\\dumpfile","wb"))//更改路径
  18.         {
  19.             // 计算程序头表的偏移和条目数量
  20.             e_phoff=ImageBase+Qword(ImageBase+0x20);
  21.             Message("e_phoff = 0x%x\n", e_phoff);
  22.             e_phnum=Word(ImageBase+0x38);
  23.             Message("e_phnum = 0x%x\n", e_phnum);
  24.             // 遍历程序头表中的每个条目
  25.             for(i=0;i<e_phnum;i++)
  26.             {
  27.                 // 检查程序头条目的类型是否为加载段或动态加载信息段
  28.                 if (Dword(e_phoff)==PT_LOAD || Dword(e_phoff)==PT_DYNAMIC)
  29.                 {
  30.                     // 段在文件中的偏移
  31.                     p_offset=Qword(e_phoff+0x8);
  32.                     // 段的起始地址
  33.                     StartImg=Qword(e_phoff+0x10);
  34.                     // 段的结束地址
  35.                     EndImg=StartImg+Qword(e_phoff+0x28);
  36.                     Message("start = 0x%x, end = 0x%x, offset = 0x%x\n", StartImg, EndImg, p_offset);
  37.                     // 将段的内容保存到文件
  38.                     dump(dumpfile,StartImg,EndImg,p_offset);
  39.                     Message("dump segment %d ok.\n",i);
  40.                 }
  41.                 // 更新程序头表的偏移
  42.                 e_phoff=e_phoff+0x38;
  43.             }
  44.            // 指向程序头表的偏移位置
  45.            fseek(dumpfile,0x3c,0);
  46.            fputc(0x00,dumpfile);
  47.            fputc(0x00,dumpfile);
  48.            fputc(0x00,dumpfile);
  49.            fputc(0x00,dumpfile);
  50.            // 存储着程序头表中每个条目的大小
  51.            fseek(dumpfile,0x28,0);
  52.            fputc(0x00,dumpfile);
  53.            fputc(0x00,dumpfile);
  54.            fputc(0x00,dumpfile);
  55.            fputc(0x00,dumpfile);
  56.            fputc(0x00,dumpfile);
  57.            fputc(0x00,dumpfile);
  58.            fputc(0x00,dumpfile);
  59.            fputc(0x00,dumpfile);
  60.            fclose(dumpfile);
  61.         } else Message("dump err.");
  62.    }
  63. }
  64. static dump(dumpfile,startimg,endimg,offset)
  65. {
  66.     auto i;
  67.     auto size;
  68.     size=endimg-startimg;
  69.     fseek(dumpfile,offset,0);
  70.     for ( i=0; i < size; i=i+1 )
  71.         fputc(Byte(startimg+i),dumpfile);
  72. }
复制代码

操作过程:
使用ida进行远程调试,在调试到真正的入口点之后运行上述idc脚本就可以了。
start函数下个断点,然后就可以开始运行了,按照思路,单步调试还是寻找大跳转,同时也可以ctrl+s看一下有没有新增节区。

截图202410162154374168.png
加壳的程序区段:
截图202410162154481878.png
这里他10b718这里的函数应该就是upx的解密函数了,直接跟进就可以。
往下跟进,根据ida的特性,在解密出新的代码的时候,他不会实时识别成代码段,所以可以将进入红色地址段作为一个新的阶段,比如这里。
截图202410162155022111.png
这个函数直接跟进去,特点就是第一个红色的call代码。
中间遇见循环直接f4往外跳就行了。因为这个样本是一个魔改的upx壳,只魔改了upx的头部,实际的解压代码改变并不大,所以当遇到upx的经典个小三循环之后,就基本上快到oep了。
截图202410162155203258.png
走完之后遇到一个跳转,下面的call跟进去,基本就是程序的oep了
截图202410162155344364.png
程序此时已经出来了新的区块了
截图202410162155486358.png
然后继续f8跟进,同时观察区块,当发现出现新的区块的时候,基本可以断定是脱壳结束了。
截图202410162155597741.png
截图202410162156125763.png
这时候运行脚本,注意修改一下开始地址。就可以得到dump文件了。

技巧
start函数里的call全下好断点,没脱壳的时候ida显示的几个函数在retn也下好断点,经历上面的三个小循环之后直接f8往下跑,会再回到start函数,大概第二次跳回start函数,可以看到真正的区段了。但是区段是空的。
截图202410162157025748.png
再两次就会发现新的elf出现在这个区段了
截图202410162157249319.png
大概再有一次就到了入口点了:
截图202410162157323231.png
多余的区段也被去除了这时。
ida在出现新的区段的时候会自己停住,也可以直接f9往下跑,当ida弹窗显示
截图202410162157418437.png
ok之后会显示新的弹窗:
截图202410162157476516.png
点yes之后就来到了新的区段,就是oep,这里具体还是要看压缩壳的特性来说。
成果
基本上脱壳成功了就算
截图202410162158006991.png
main函数啥的都算是清楚
截图202410162158096099.png
也可以正常运行
截图202410162158185166.png
但是区段发生了明显的变化,并不是一个完整的elf,但是能运行,好神奇
截图202410162158252933.png


这个人还没有签名
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则