brunch

You can make anything
by writing

C.S.Lewis

by Younggi Seo May 04. 2018

Section5: malicious RCE attack

버퍼 오버플로 공격의 원리 정리

컴퓨터 구조에서 CPU와 주변 장치 간의 연결을 도식화한 것(그림 1.)으로 프로그램이 수행될 때 CPU는 CU(Control Unit)이라는 구성 요소에 의해 내부 기억장치에서 명령어를 인출 및 해석하고 '제어 신호'를 내보내서 '각 장치의 동작'을 제어한다. 그리고 인출한 명령어(현재 계산 중인 값)를 CPU 내부에서 저장하는 곳이 레지스터(Register)이다. 대부분의 CPU는 메인 메모리에서 레지스터로 데이터를 옮겨와서 처리한 후 다시 메모리에 저장한다.


그림1. 시스템 구조 (조성문 정영훈, 2014)



즉 메모리는 프로세스 실행을 위한 '작업장'과 같은 역할을 하므로 해커라면 논리적 메모리 구조뿐만 아니라 물리적 구조도 알아야 한다. 공격 루트로 이용되는 취약성은 벤더에 의해 패치가 되기 때문에 '우회 경로 확보'를 위해 필수적으로 선행되어야 할 지식이다. 아래 그림 2. 는 버퍼 오버플로 공격의 원리를 논리적 구조로 도식화하였다. 그림 1. 에서 붉은선을 확장하면 아래와 같은 원리로 공격의 흐름이 이루어진다는 것을 알 수 있다. 레지스터(CPU 내부)의 구성 요소 중 EIP(Extended Instruction Pointer: 다음 실행해야 할 명령어가 존재하는 주소의 값이 저장되는 레지스터) 값을 조작(윈도나 리눅스의 보안패치로 최신 버전은 동작하지 않지만)해서 해킹 코드(Malware Shell Code)를 실행한다.   


그림2. Buffer Overflow Attack Diagram by Daniel (조성문 정영훈, 2014)



결국 오버플로우 공격은 C 언어의 명령어  임시 메모리의 경계선을 구분하지 않는 취약점에서 비롯하였지만 시스템의 동작 흐름을 살펴보면 메모리 관리가 CPU에게 지시하는 운영체제나 메모리 관리자만이 할 수 있는 영역이 아니라 레지스터와 메인 메모리의 스택 영역에서 연산 데이터의 개체들이 개입하여 시스템 오류를 일으킬 수 있다는 데 있다. 만약 디스크에 컴파일되어 저장된 프로그램을 메모리에 적재(loading) 하지 않고 실행이 가능하다면 운영체제(시스템)에 의해 제어를 받는 상태(Process)가 일어나지 않으므로 메모리 할당이나 CPU를 통한 프로세스 동작도 일어나지 않을 것이다. 하지만 애초에 컴퓨터의 전신은 폰 노이만의 내장 프로그램 개념(stored program concept)으로 이루어졌다.



"요점은 현재의 컴퓨터 메모리는 두 가지 목적을 위해 사용된다. (1) 데이터를 저장하고 (2) 데이터를 처리하는 명령어를 저장한다. 저장 프로그램 개념은 또한 컴퓨터(CPU)가 명령어를 실행시키기 위해서 메모리로부터 프로세서로 명령어를 전송하는 회로(Bus)를 요구한다. 일반적으로 프로세서(processor, 인텔 아키텍처)는 명령어를 실행시킬 뿐만 아니라 또한 메모리로부터 가져오는 것을 제어한다." (David; Kenny, 2017) 이러한 프로세스(Process) 흐름 간에 메모리 관리가 CPU를 통해 이루어 지는데 이때 주소, 변수, 개체, 반환값(RETurn Value) 등이 저장될 때 해킹에 의해 해당 데이터 값을 변경하면서 시스템 단의 공격이 가능하다. 그래서 프로그램이 실행 가능한 상태로 메모리를 조작하려면 메모리가 어떻게 구성되고 어떻게 동작하는지 꿰차고 있어야 한다. 그다음이 반복된 행태를 자동화시킨 스크립트인 악성코드* 주입(Exploiting)이다.



리눅스 우분투 커널 중 오래된 버전인 경우, C 코드를 컴파일할 때 아래와 같은 에러 메시지가 뜰 수도 있는데(stdio는 standard io의 준말로 C에서 처음 include로 불러들이는 표준 입출력 라이브러리 중의 하나이다),

"overflowedtest.c:1:19: 오류: stdio.h: No such file or directory
 overflowedtest.c: In function ‘main’:
 overflowedtest.c:6: warning: incompatible implicit declaration of built-in function ‘printf’"


이때는 아래 명령어를 통해 우분투를 업데이트시킨 후 다시 공격의 원리를 끝까지 파헤쳐 보자.

$ sudo apt-get update && sudo apt-get install build-essential


Section 6에서 Section 4에서 말한 gdb 디버깅을 통한 중단점(브레이크 포인트) 설정과 네이티브 코드를 역어셈블한 어셈블리어를 보고 공격이 가능한 메모리 스택을 추출하는 과정 및 공격 코드를 그 스택에 덮어쓴 결과를 확인할 수 있다.





* 해커가 직접 작성하지 않더라도 수많은 악성코드는 인터넷에서 거래되고 있다. 특히 중국이나 러시아를 포함한 근방의 국가들이 유포하는 'Exploit kit'을 거래하는 시장이 해커들의 지하시장이고 여기에 조직폭력배 집단들이 개입하는 말 그대로 '블랙 해커'들의 영역이 따로 존재하는 걸로 들었다(from '나는 프로그래머다' iPod cast)




참조

1) Riley, D. D. (2015). 문봉교, 김웅섭 공역(2017). 컴퓨팅 사고: 소프트웨어를 통한 문제 해결. Computational thinking for the modern problem solver. Boca Raton, FL: CRC Press.

2) 조성문, 정영훈 (2014). 파이썬 해킹 입문: 공격의 언어 파이썬을 이용한 해킹 연습 그림 1. 그림 2. 원문, 서울: 프리렉.

매거진의 이전글 Section3: malicious RCE attack
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari