/*
The Lord of the BOF : The Fellowship of the BOF
- golem
- stack destroyer
*/
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
main(int argc, char *argv[])
{
char buffer[40];
int i;
if(argc < 2){
printf("argv error\n");
exit(0);
}
if(argv[1][47] != '\xbf')
{
printf("stack is still your friend.\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
// stack destroyer!
memset(buffer, 0, 44);
memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));
}
코드를 보면 stack destroyer 때문에 [그림 1-1] 처럼 스택이 초기화된다. 따라서 인자, 환경변수 등 공격을 할 수 없다.
buffer 변수보다 낮은 주소는 초기화가 안되기 때문에 그 부분을 이용해야한다.
이 문제를 풀기전에 tmp 카테고리에 공유 라이브러리를 읽고오자!
프로그램이 실행되면 메모리에는 많은 정보들이 올라간다.
함수를 실행하기 위해서 함수도 메모리에 올라가야하고 함수의 주소를 참조하여 함수를 실행한다.
golem.c 에는 memset, strcpy도 당연히 메모리 공간에 올라가야한다.
golem 파일은 공유 라이브러리 방법을 사용한다.
공유 라이브러리와 연결된 프로그램을 실행하면 내부적으로 dynamic loader라는 프로그램이 먼저 동작해 shared library를 찾고 메모리에 올린다. (프로그램 올리기 전)
이때 환경변수 중 하나로 LD_PRELOAD 에 파일을 등록하면 해당 파일이 프로그램이 메모리 로드 되기 전에 먼저 메모리에 로드된다.이때 라이브러리에 중복된 이름의 함수가 있을 경우 LD_PRELOAD에 설정된 라이브러리가 먼저 로딩 되므로 LD_PRELOAD의 라이브러리에서 함수를 호출한다. -> 후킹가능
[그림 1-3] 처럼 공유라이브러리 영역은 스택보다 낮은 주소에 위치한다. 따라서 LD_PRELOAD 환경변수에 특정 파일을 등록하면 해당 파일 이름과 코드가 프로그램의 스택 아래쪽에 등록이 되므로 stack destroyer 영향을 미치지 않는다!
따라서 LD_PRELOAD에 a.c라는 파일을 쉘 코드 이름으로 등록하자.
먼저 a.c 빈 파일을 만들자
그리고 a.c 파일을 쉘코드 이름으로 컴파일하자. (파일 이름 이므로 /x2f가 없는 쉘코드 이용!)
gcc 옵션
-fPIC: 파일을 동적라이브러리로 사용하도록 컴파일 하는 옵션
-shared: so 파일을 컴파일하기 위한 옵션, so는 공유라이브러리 파일 확장자를 의미한다.
-o: 실행 파일의 이름을 지정해주는 옵션
그리고 LD_PRELOAD 환경변수에 해당 파일(쉘 코드 이름으로 된 빈 파일)을 등록해주자.
이 때 파일명은 반드시 절대경로로 지정해야 한다.
해당 파일 위치를 찾기위해 gdb 를 키자 0xbffffb80 이다.
payload 작성 후 exploit ㄱㄱ
Segmentation ... core 파일에서 실제 위치를 찾자!
ret 값을 \xbffff4f8로 변경 후 exploit ㄱㄱ
굿 !
디렉토리 이동 후 해보자!
성공!