항상 보안을 공부하다보면 쉘 권한을 얻어서 컴퓨터를 정복한다라는 이야기를 한번 쯤은 들어 보았을 것이다. 그렇다면 쉘이 무엇이길래 쉘 권한이라는 것을 취득하면 컴퓨터를 제어할 수 있는거지라는 의문을 갖는 것이 당연할 수 있을 것 같다.
그래서 오늘은 Shell이 무엇인지와 shellcode가 무엇인지에 대해서 이야기 해보려고 한다.
우선 Shell이란 무엇인지 알아보려 한다.
shell은 사용자와 운영 체제의 내부 커널 사이의 인터페이스를 감싸는 층이라고 이야기 한다. 즉 운영 체제 다양한 기능들을 구현한 인터페이스로 볼 수가 있다.
우선 운영 체제에 대해서 이해가 필요하다. 간단히 설명하자면 하드웨어와 응용 프로그램 사이에서 중개자 역활을 하는 것이 운영 체제이다. 응용 프로그램에서 어떤 것이 필요하면 하드웨어에서 메모리를 할당해주고 언제 이 프로그램을 실행시켜주고 등등 하는 역할을 운영 체제라고 하는데 더 자세한 내용은 따로 글을 작성하려고 하니 이 정도로만 요약하려고 한다.
그 다음은 커널이 무엇인지 알아야 할 필요가 있다.

보이는 사진과 같이 커널은 운영 체제의 핵심 프로그램이며 사스템의 모든 것을 완전히 제어할 수 있는 프로그램을 말한다. 즉 한마디로 이 커널을 상대방이 사용할 수 있다면 내 컴퓨터의 모든 자원을 마음대로 사용할 수 있다는 의미이기도 하다. 더 자세한 이야기 또한 운영 체제 글을 통해 같이 풀어 내보도록 하겠다.
그리고 인터페이스라는 용어는 많이 들었지만 정확히 어떤 의미인지 모르고 넘어가는 경우가 많아 간단하게 이야기 하고 쉘로 넘어가려고 한다.
인터페이스는 서로 다른 시스템 또는 프로그램끼리 정보를 주고 받을 때 그 교환을 가능하게 하는 접점을 인터페이스라고 한다. 쉽게 이야기를 하자면 음류수를 먹으려고 자판기에 돈이라는 정보를 넣으면 자판기는 어떤 음료를 선택하고 정보와 가격을 확인하고 맞는지 확인 후 음류수라는 결과를 교환한다. 여기서 그럼 자판기가 인터페이스가 되는 것이다.
그렇다면 shell은 사용자의 명령을 해석하여 커널에 전달하고 커널의 결과를 사용자에게 표시해주는 역할이라고 이해 할 수 있을 것 같다.
그렇니까 shell interface를 아무나 사용 못하게 권한을 가진 사람만 이용할 수 있는것이다. 그래서 보안을 할 때 shell 권한을 얻으면 마음대로 shell interface를 이용하여 커널한테 이상한 요청을 하여 수행 시킬 수 있기 때문이다.
이제는 shell이 무엇인지 어떤 일들을 하는 것인지 이해를 한 것으로 보인다. 그렇다면 shellcode가 무엇인지 한번 알아보는 시간을 가져보려고 한다.
shellcode는 소프트웨어의 취약점을 이용할 때 사용되는 작은 코드 조각이다. 이를 shellcode라고 부르는 이유는 대부분의 경우 이 코드가 실행될 때 명령 쉘(command shell)을 시작하기 때문이다. 즉 한마디로 shellcode는 기계어로 된 명령어로 보면 이해하기 쉬우며 이 shellcode를 이용하여 쉘 권한을 얻어 명령을 하게하는 해킹 기법이 있다.
그렇다면 어떤 방법을 이용해서 shellcode를 작성하는지 알아보도록 하겠다.
; rdi: 파일 경로 (문자열)
; rsi: 접근 모드 (예: O_RDONLY)
syscall open
; rdi: open에서 반환된 파일 디스크립터
; rsi: 데이터를 저장할 버퍼의 주소
; rdx: 읽어올 바이트 수
syscall read
; rdi: 대상 디스크립터 (예: 1은 표준 출력을 의미)
; rsi: 읽어온 데이터의 버퍼 주소
; rdx: 출력할 바이트 수
syscall write
드림핵 내용
파일 서술자(File Descriptor, fd)는 유닉스 계열의 운영체제에서 파일에 접근하는 소프트웨어에 제공하는 가상의 접근 제어자입니다. 프로세스마다 고유의 서술자 테이블을 갖고 있으며, 그 안에 여러 파일 서술자를 저장합니다. 서술자 각각은 번호로 구별되는데, 일반적으로 0번은 일반 입력(Standard Input, STDIN), 1번은 일반 출력(Standard Output, STDOUT), 2번은 일반 오류(Standard Error, STDERR)에 할당되어 있으며, 이들은 프로세스를 터미널과 연결해줍니다. 그래서 우리는 키보드 입력을 통해 프로세스에 입력을 전달하고, 출력을 터미널로 받아볼 수 있습니다.
프로세스가 생성된 이후, 위의 open같은 함수를 통해 어떤 파일과 프로세스를 연결하려고 하면, 기본으로 할당된 2번 이후의 번호를 새로운 fd에 차례로 할당해줍니다. 그러면 프로세스는 그 fd를 이용하여 파일에 접근할 수 있습니다.
이렇게 원하는 데이터를 open해서 fd를 구하고 이를 활용해서 read으로 버퍼에 저장 후 write으로 출력하게 하는 방식을 알아 보았다.
이렇게 오늘은 shell이 무엇인지 shellcode를 왜 사용하고 어떤 방식을 이용해 왔는지 알아보는 시간을 가졌다.