본문 바로가기

시스템 보안

쉘 코드 작성

쉘이란 사용자로부터 입력받은 명령어를 기계어나 어셈으로 바꿔 컴퓨터에게 전달해주는 역할을 하는 프로그램이다. 예를 들어서 윈도우 cmd창에 dir을 치면 현재 디렉토리의 목록을 볼 수 있는데 여기서 cmd가 쉘인 것이다.


https://ko.wikipedia.org/wiki/%EC%85%B8


쉘코드는 이러한 쉘을 어셈으로 짠 것으로 BOF같은 공격을 통해서 쉘코드를 스택에 넣고 RET값을 쉘코드가 저장되어 있는 주소로 바꿔 쉘을 얻을때 쓴다.


쉘코드를 만들때에는 우선 자신이 사용할 함수에 대해 자세히 알아야 한다. 쉘코드를 만들때 execve를 쓸 것이데 그러면 이 execve의 용도 및 인자값에 대한 정보(어떤 값이 들어가는지, 인자 값의 데이텨형은 어떠한지)를 조사한다.


http://forum.falinux.com/zbxe/?mid=C_LIB&page=3&document_srl=408569


리눅스에서 /bin/sh 쉘을 execve함수를 통해서 띄울 것인데 소스코드는 다음과 같다.


void main()

{

char *shell[2];


shell[0]="/bin/sh";

shell[1]=NULL;


execve(shell[0], shell, NULL);

}


이 소스코드를 gcc를 통해서 컴파일 해주고 난 뒤 실행을 시키면 아래와 같이 쉘을 얻게 됩니다.



이제 함수에 대한 파악을 하였으니 어셈으로 짜면 됩니다.


우선 execve의 콜백터를  /usr/include/asm/unistd.h에서 확인합니다.





그리고 어셈으로 짜면 됩니다~





asm은 어셈으로 짠다는 소리이고 volatile은 최적화를 하지 말라-라는 뜻입니다(최적화란 불필요한 요소들을 컴파일과정을 통해서 생략하는 것 입니다.).


더 자세한 내용 http://ezbeat.tistory.com/150


첫번째줄부터 xor %eax, %eax를 해주는데 그 이유는 이 코드를 objdump를 해서 봤을때 쉘코드 중 0x00이 있으면 문자열에 끝으로 인식하고 0x00이전까지만 읽게 됩니다. 그러면 쉘코드가 실행이 되겠지요. 이것을 막기위해 직접적으로 0x00을 %eax에 넣는 것이 아니라 자기 자신을 xor했을때 0이 된다라는 특징을 이용합니다.


두번째줄은 /bin/sh의 문자열의 끝을 알려주기 위해 xor로 만든 0을 넣어줍니다.


세번째~네번째줄은 /bin/sh의 아스키코드 값입니다. 그리고 여기서는 리틀엔디안 형식으로 넣었습니다.

다섯번째줄은 mov %esp, %ebx인데 이것은 esp를 ebx에다가 넣어준다-라는 말입니다.(아!!! 그리고 이 코드의 어셈은 인텔형식이 아닌 AT&T형식입니다.)

이렇게 해준 이유는 execve에 첫번째 인자가 /bin/sh의 주소이기 때문입니다.


https://wiki.kldp.org/KoreanDoc/html/Assembly_Example-KLDP/Assembly_Example-KLDP.html


여섯번째줄~일곱번째줄은 push %eax하고 push %ebx를 해주는 데 push %eax는 왜 해주는 지 잘 모르겠습니다;;;;;; 죄송해요 ㅠㅠ
push %ebx를 해주는 이유는 두번째 인자는 shell(위의 소스코드를 보면)인데 이것은 포인터 배열의 이름, 즉 주소이죠. *shell == shell[0]이고 **shell==/bin/sh입니다. 즉 더블 포인터라는 말이겠네요. 그래서 push %ebx(%ebx는 %esp의 주소, 즉 아까 /bin/sh의 주소)를 해주고 그 다음 줄인 mov %esp, %ecx를 해주면 현재 %esp는 push되어 있는 %ebx를 가리키고 있고 이 %ebx는 /bin/sh의 주소를 가지고 있으므로 execve의 두번째 인자와 데이터 형이 같습니다.


아홉번째줄 mov %eax, %edx인데 이것은 execve의 마지막인자인 NULL을 의미합니다.


열번째줄인 mov $0xb, %al는 execve의 콜 벡터의 값입니다. 그리고 그 다음 줄 int $0x80은 함수를 호출하겠다-라는 의미입니다.

(아!!! 그런데 왜 mov $0xb, %al을 해주는 이유는 만약 %eax로 하면 이것은 32비트인데 al은 하위 8비트를 이용하겠다-라는 뜻입니다. 그래서 만약 %eax로 썼을 경우 objdump를 떴을때 0x00이 나오기 때문에 %al을 해주는 것입니다. 자세한 내용은 직접해보시고 눈으로 보시는 게 더 이해가 잘 될것 같습니다.


이 방법이외에 다른 방식으로 쉘코드를 짠 것이 있는데 이것은 아직 공부를 안해서 나중에 추후에 공부하고 추가하겠습니다(setreuid를 추가한 부분과 쉘코드 종류 및 리버스 쉘에 대한 것도).


http://cosyp.tistory.com/205


 

 

'시스템 보안' 카테고리의 다른 글

스택(Stack)  (0) 2017.04.23
BOF  (0) 2017.04.23