吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 29549|回复: 73
收起左侧

[原创] ELF64手脱UPX壳实战

  [复制链接]
一米丶阳光 发表于 2019-11-4 22:01
本帖最后由 一米丶阳光 于 2019-11-4 22:12 编辑

最近在做CTF逆向习题时,遇到一个带有UPX壳的ELF CrackMe,题目的目标是找到flag。
由于此前只对PE做过UPX脱壳,本来使用UPX的脱壳工具,用命令就能脱壳,但是出于研究的目的,看看ELF文件的UPX如何手动脱壳,话不多说,进入正题~

0x1 工具和环境

  • IDA
  • Ubuntu18.04

0x2 寻找OEP

  • 首先在Ubuntu上运行程序,观察程序的运行情况
    1.png
    2.png
  • Ubuntu上打开终端使用命令查看当前IP
    6.png
  • 将IDA文件夹内的linux_server64拷贝到Ubuntu系统中,给与运行权限并运行
    3.png
    4.png
  • 将ELF文件拖入Win上的IDA内,选择Linux远程调试器,填入Ubuntu的IP地址启动调试,弹框点击确定
    5.png
    7.png
  • 开始单步调试,单步调试遵循两个原则:1.除非F8跑飞,否则不用F7。2.循环直接跳过。
    8.png
    9.png
    10.png
    11.png
    12.png
    13.png
    14.png

0x3 Dump内存文件

  • 顺利找到OEP,准备dump内存
    15.png
  • dump文件执行结束,在对应目录生成dump文件
    16.png
    17.png
  • 将dump文件拖入Ubuntu系统给与权限,并运行查看结果
    18.png

0x4 Dump文件代码

#include <idc.idc>
#define PT_LOAD              1
#define PT_DYNAMIC           2
static main(void)
{
         auto ImageBase,StartImg,EndImg;
         auto e_phoff;
         auto e_phnum,p_offset;
         auto i,dumpfile;
         ImageBase=0x400000;
         StartImg=0x400000;
         EndImg=0x0;
         if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f )
  {
    if(dumpfile=fopen("G:\\dumpfile","wb"))
    {
      e_phoff=ImageBase+Qword(ImageBase+0x20);
      Message("e_phoff = 0x%x\n", e_phoff);
      e_phnum=Word(ImageBase+0x38);
      Message("e_phnum = 0x%x\n", e_phnum);
      for(i=0;i<e_phnum;i++)
      {
         if (Dword(e_phoff)==PT_LOAD || Dword(e_phoff)==PT_DYNAMIC)
                         { 
                                 p_offset=Qword(e_phoff+0x8);
                                 StartImg=Qword(e_phoff+0x10);
                                 EndImg=StartImg+Qword(e_phoff+0x28);
                                 Message("start = 0x%x, end = 0x%x, offset = 0x%x\n", StartImg, EndImg, p_offset);
                                 dump(dumpfile,StartImg,EndImg,p_offset);
                                 Message("dump segment %d ok.\n",i);
                         }    
         e_phoff=e_phoff+0x38;
      }

      fseek(dumpfile,0x3c,0);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);

      fseek(dumpfile,0x28,0);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      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);
        }
}

0x5 总结

  • 样本来源于CTF的逆向题,各位可放心下载练习,如果有兴趣,可以继续找出目标flag,好啦,附件拿走,免费评分留下 ~
  • 链接: https://pan.baidu.com/s/1v_uL26C6FooLhHHSbPUhmQ 提取码: ubmc
  • 解压密码:52pojie.cn

免费评分

参与人数 37吾爱币 +32 热心值 +32 收起 理由
beiwjk + 1 + 1 我很赞同!
七个涨停一倍 + 1 鼓励转贴优秀软件安全工具和文档!
gink + 1 + 1 谢谢@Thanks!
薛定谔消失的弦 + 1 + 1 谢谢@Thanks!
wuwutian + 1 + 1 热心回复!
THook + 1 用心讨论,共获提升!
aywl47 + 1 用心讨论,共获提升!
11987GENIUS + 1 我很赞同!
Damon尼 + 1 我很赞同!
cpj1203 + 1 谢谢@Thanks!
zhangchang + 1 用心讨论,共获提升!
jmnzhlx + 1 + 1 用心讨论,共获提升!
Spwpun + 1 + 1 学习了linux调试的方法、ELF脱壳没了解过,最近在看IDA Pro脚本编写的部分.
chencg + 1 我很赞同!
jnez112358 + 1 + 1 谢谢@Thanks!
对影三人 + 1 + 1 热心回复!
macsun + 1 + 1 谢谢@Thanks!
guojinhao + 1 用心讨论,共获提升!
yixi + 1 + 1 谢谢@Thanks!
zhengyg + 1 + 1 谢谢@Thanks!
gaosld + 1 + 1 用心讨论,共获提升!
1390794904 + 1 + 1 请勿灌水,提高回帖质量是每位会员应尽的义务!
LOLQAQ + 1 + 1 我很赞同!
40m41h42t + 1 + 1 谢谢@Thanks!
run_boy + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
aileki + 1 + 1 谢谢@Thanks!
sunnylds7 + 1 + 1 热心回复!
hszt + 1 + 1 谢谢@Thanks!
凉米饭 + 1 谢谢@Thanks!
GenW + 3 + 1 支持技术帖!
yaoyao7 + 1 + 1 我很赞同!
hjm666 + 1 热心回复!
为海尔而战 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
itmaple + 1 我很赞同!
sumile + 1 + 1 用心讨论,共获提升!
陈世界 + 1 + 1 热心回复!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lishua 发表于 2021-2-23 16:59
本帖最后由 lishua 于 2021-3-25 15:47 编辑
一米丶阳光 发表于 2021-1-7 14:59
因为只有LOAD和DYNAMIC段才是运行时真正用到的

网上找了一篇文章(ELF文件的加载过程 https://blog.csdn.net/gatieme/article/details/51628257 其实只是大致看了elf加载的流程)。ELF加载后内存中只有标识为PT_LOAD或PT_DYNAMIC的segment,所以如果想要还原原始的程序信息,是不是也只有PT_LOAD或PT_DYNAMIC的segment可以下手,这样让自己理解感觉又很牵强
今天使用楼主提供的idc脚本成功将一个找到OEP的64 bits程序给dump脱壳了。
我仿照楼主代码写的32位的脱壳脚本不知道为啥脱了一个32位程序,运行后是segment fault,楼主大大看到帖子能否抽空帮忙看一下? 解答一下困惑
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <idc.idc>
#define PT_LOAD              1
 
#define PT_DYNAMIC           2
 
static main(void)
{
  auto ImageBase,StartImg,EndImg;
  auto e_phoff;
  auto e_phnum,p_offset;
  auto i,dumpfile;
  ImageBase=0x08048000;
  StartImg=0x08048000;
  EndImg=0x0;
  if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f )
  {
    if(dumpfile=fopen("d:\\dumpfile","wb"))
    {
      e_phoff=ImageBase+Dword(ImageBase+0x1c);
      Message("e_phoff = 0x%x\n", e_phoff);
      e_phnum=Word(ImageBase+0x2c);
      Message("e_phnum = 0x%x\n", e_phnum);
      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+0x8);//p_vaddr
            EndImg=StartImg+Dword(e_phoff+0x14);//p_memsz
            Message("start = 0x%x, end = 0x%x, offset = 0x%x\n", StartImg, EndImg, p_offset);
            dump(dumpfile,StartImg,EndImg,p_offset);
            Message("dump segment %d ok.\n",i);
         }   
         e_phoff=e_phoff+0x20;
      }
 
      fseek(dumpfile,0x30,0);//e_shnum e_shstrndx
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
      fputc(0x00,dumpfile);
 
      fseek(dumpfile,0x20,0);//e_shoff
      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);
  }
}
 楼主| 一米丶阳光 发表于 2019-11-6 19:38
zhengyg 发表于 2019-11-6 19:34
按照您的教程我也弄出来了,好厉害,谢谢您,那个脚本怎么写的呀,只能看懂一点点,想学的话从哪里入手好呢 ...

嘿嘿 恭喜你,要想写那个脚本,你得先去了解一下ELF64的头部结构,然后结合脚本代码你就明白啦
wl960612 发表于 2019-11-4 22:47
夜步城 发表于 2019-11-4 23:30
支持楼主
头像被屏蔽
xiao135140 发表于 2019-11-5 05:58
谢谢分享啊啊
Hmily 发表于 2019-11-5 08:09
elf程序脱壳资料不多,加精鼓励,期待更多分享。
GJH588 发表于 2019-11-5 08:25
这类教程很少,期待更多的教学,支持一下
 楼主| 一米丶阳光 发表于 2019-11-5 09:08
Hmily 发表于 2019-11-5 08:09
elf程序脱壳资料不多,加精鼓励,期待更多分享。

谢H大,我会继续努力
yaoyao7 发表于 2019-11-5 09:37
elf脱壳的少见啊,多分享一下
A-new 发表于 2019-11-5 10:20
为什么不直接用edb呢
daymissed 发表于 2019-11-5 10:21
视频学习起来更好点。感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-15 14:58

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表