Pwnstar

zer0ptsCTF oneshot 본문

CTF

zer0ptsCTF oneshot

포너블처돌이 2021. 3. 8. 13:33

좀 아쉬움이 많이 남는 CTF였다. 건드리면서 거의 다 풀었다고 생각한 문제들이 많았는데 결국 푼거는 이 한문제밖에 없다. 그래도 비교적 빨리 풀어서 기분은 좋았다.

가젯찾기 좀 힘든 문제였음.

checksec

got overwrite는 가능하고, NX bit만 걸려있다.

main

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

  v4 = 0uLL;
  printf("n = ", argv, envp, 0LL, 0LL);
  __isoc99_scanf("%d", &v4);
  if ( (signed int)v4 > 255 )
    exit(1);
  *((_QWORD *)&v4 + 1) = calloc((signed int)v4, 4uLL);
  printf("i = ", 4LL);
  __isoc99_scanf("%d", (char *)&v4 + 4);
  printf("arr[%d] = ", DWORD1(v4));
  __isoc99_scanf("%d", 4LL * SDWORD1(v4) + *((_QWORD *)&v4 + 1));
  puts("Done!");
  return 0;
}

main함수는 이렇게 되어있는데, calloc함수에 -1을 집어넣으면 return값이 0이 되어서 원하는 주소에 원하는 값을 써 넣을 수 있다. 먼저 main함수가 계속 반복되게 만들기 위해서 puts함수의 got에 main함수의 주소를 넣어주어야한다.

문제에서 libc도 주기 때문에 oneshot gadget을 활용하기 위해서 libc leak을 해야하는데 이걸 하는데에 어려움이 많았다 rdi에 got 주소가 들어가야하는데, main함수의 어느 부분으로 뛰어도 프로그램이 터져버려서 ida를 보면서 생각을 해보다가

 

이런 가젯을 발견했다. __bss_start에는 stdout의 주소가 들어있는데, rax의 값은 calloc함수의 return값이 들어있기 때문에, printf함수의 주소를 입력하면 이 가젯을 이용해서 leak을 진행할 수 있다.

마지막으로 exit got를 원샷 가젯으로 덮어주고 다시 n의 값을 입력하는 부분에서 256보다 큰 값을 입력하면 쉘을 획득할 수 있다.

 

zer0pts{th1s_1s_why_y0u_sh0uld_ch3ck_r3turn_v4lu3_0f_malloc}

아마 더 쉽게 푸는 방법이 있지 않을까 싶다

'CTF' 카테고리의 다른 글

nahamconCTF Rock Paper Scissors  (0) 2021.03.15
nahamcon CTF Sort It!  (0) 2021.03.15
diceCTF flippidy  (0) 2021.02.08
CSAW CTF bard's fail  (0) 2020.09.18
SSTF2020 eat_the_pie  (0) 2020.08.18
Comments