Buffer Overflow로 인한 해킹이슈(Worm, Viruses)

msung99·2022년 10월 10일
0
post-thumbnail

리눅스 메모리 구조

  • 스택

    • 각 process 마다 8MB 제한이 있다.
    • malloc() 으로 동적 할당한 메모리를 저장하는 공간
  • Text / Shared Libraries

    • 프로그램을 실행하면 돌아갈 명령어들이 들어있다
    • read only : 프로세스를 실행시키면 read only 상태이다.

메모리 할당 예제

int local = 0; => 지역변수는 스택에 할당

p1, p2 이 가리키고 있는 malloc() 으로 할당한 공간과 같이 크기가 큰 애들은 힙에 저장하면 공간이 모자를 수 있다.

이렇게 크기가 큰 놈들은 힙의 위에서 부터 아래로 방향으로 내려오면서 저장된다.

전역변수(배열)인 big_array 와 huge_array 는 초기값이 자동으로 0으로 설정된다. 이렇게 초기값이 있는 애들은 data 영역에 할당된다.


위 예제 실행결과 메모리 구조


Buffer Overflow

  • fun(0) 을 호출시 배열 a의 a[0] 에 1073741824 가 할당되고,
  • fun(1) 호출시에도 a[1] 에 1073741824 가 할당된다.

그런데 구조체를 보면 배열 a의 크기는 2라서, fun(2) 를 호출하면
a[2] 에 이상한 값이 들어간다.

이때 완전 이상한 값이 들어가는게 아닌, 그래도 할당하려던 원본 값과 조금만 다른 이상한 값이 들어간다.

=> 이렇게 값이 조금만 바껴서 이상한 값이 들어가는 이유는, floating point number 때문이다. float 형은 정수처럼 딱 정확한 값을 저장하는게 아닌 근사값을 저장하는 특성이 있다.

  • fun(4) 를 호출시 정확한 값 3.14 가 할당된다.

  • fun(6) 호출시 어딘지 모르겠는 누군가를 건들게 된다. 이러면 운이 안좋게 segmentation fault 가 발생할 수 있다.


Buffer Overflow

  • 보안 문제발생 이슈o
  • 스택 안에 있는 데이터를 침범했을 떄, 즉 다른 영역을 침범했을 떄를 buffer overflow 가 발생했다고 한다.

String Library Code

  • strcpy, strcat, scanf, .. 등이 모두 개수 상관없이 input 을 모두 다 받는다.

예제

buffer overflow 가 발생할 수 있는 코드

위 함수 2개를 disassemble 한 코드

크기가 4인 char형 배열을 만들어놓고 gets(), puts() 로 사용자로부터 입력을 받아온다.

그런데 위 어셈블리 코드롤 보면 알 수 있듯이, 스택 포인터는 18이라 뺴면서 까지 공간을 확보하는 것을 보아, 사용자로부터 char형 데이터 타입의 입력을 18개나 받은 것이다! => 오버플로우그 발생한 것.

mov %rsp, %rdi : 그냥 단순히 스택 포인터 rsp 를 rdi 에 넣은것.

상세 구조1 - overflow 가 발생했지만, return address 영역을 침범x

해당 stack frame 보면 알 수 있듯이, 입력받은 char 데이터들을 char 배열 buf 에 최대 4개 저장한다. 그런데 이들이 꽉차면 20 bytes unused 공간에다 최대 20byte 만큼의 데이터를 저장할 수 있다.

=> 현상황은 사용자로부터 24개 이하의 char 데이터 입력받은 경우로, char 배열 공간이 꽉차면 unused 공간을 사용해서 return address 영역에 다행히도 침범받지 않은 상황이다.

(오버플로우가 발생했음에도 불구하고, 나름대로 인풋의 양이 적어서(?) 프로그램이 정상적으로 동작한다!)

상세 구조2 - overflow 가 발생했고, return address 영역을 침범o

그런데 사용자로부터 입력을 엄청 많이받아서 (24개 이상의 char 데이터),
unused 공간을 사용했음에도 불구하고 return address 를 위처럼 침범할 수 있다.

=> return address 공간에도 입력받은 데이터를 저장해서, 함수 call 이 종료되고 리턴시에 이상한 주소로 되돌아간다.


예제

  • 위처럼 스택 포인터를 내리고 buf 배열에 데이터를 return address를 침범할 떄 까지 무진장 많이넣고, 이 stack frame의 사이즈를 정확하게만 계산할 수 있다면(안다면) 원하는 곳으로 오버라이드가 가능하다. (이게 해킹에 활용된다.)

=> 원래 return address 가 들어가있던 부분에 buffer overflow 를 이용해서 해킹관련 코드의 시작주소를 넣는다. (해커들이 원하는 곳으로 함수가 리턴되도록 하기위해)

그러면 함수 종료시 해커들이 설정해 놓은 이상한 address 로 return 하게 되어서, 그떄부터 해커들의 바이러스를 주입 가능하게 된다.

(이상한 주소로 리턴되고, 원래 있던던 시스템의 코드가 아닌 해커가 심은 이상한 return address 에 존재하는 악성 코드를 실행하게 된다)


Worm vs Viruses

Worm

  • 혼자 실행될 수 있다
  • 스스로 본인 코드를가지고 있어서, 다른 컴퓨터로 올겨다닐 수 있고 코드를 전파가 가능하다.

(다른 소스의 도움없이 자기 혼자서 stack frame 의 사이즈를 정확하게 계산해서 본인의 시작주소를 스스로 넣을 수 있는 놈. 또한 본인의 코드를 다른 코드에 전달시키는 역할을 할수있다. )

Virus

  • worm 과 달리 혼자 독립적으로 실행되지 못한다. => 다른 프로그램의 소스 코드를 활용해야 돌아간다.

(특정 조건에 맞춰줬을 떄나, 특정 소프트웨어가 실행될때만 그 코드를 활용해서 돌아간다)

결론 : buffer overflow 를 활용해서 return address 를 바꿔치기하면 쉽게 다른 코드를 수행시킬 수 있다.

profile
블로그 이전 : https://haon.blog

0개의 댓글