LOB - level11 - (skeleton->golem) 'LD_*' 영역을 활용한 쉘코드 넣기

golem.c 의 소스코드는 다음과 같다.
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));
}

[ret] 을 제외한 버퍼의 모든 문자열 및 프로그램 시작시 주는 매개변수 환경변수등을 모두 0으로 덮는다.

그러므로 우리가 버퍼를 이용하여 조작할 수 있는 값은 [ret]뿐으로 보인다.

그렇다면 buffer, argv, env 와 같은 위치를 제외한 어딘가에 쉘코드가 올라가야 한다.

'LD_PRELOAD' 환경변수는 특정 라이브러리를 프로그램이 시작될 때 pre load 해주는 기능을 한다.

그래서 이 LD_PRELOAD 기능을 이용하여 원본 라이브러리 함수들을 hooking하기도 한다. 하지만 LD_PRELOAD 환경변수를 이용하여 실제 라이브러리가 등록되기 위해서는 실행중인 프로세스의 권한과 라이브러리의 권한이 서로 맞아야 한다. root 권한의 라이브러리라면 어떠한 프로그램에도 적용 될 것 같고, root가 아니라면 uid가 서로 같아야 할 것이다.
[skeleton@localhost test]$ cat program.c
#include <stdio.h>

int main()
{
        printf("hello world!\n");

        return 0;
}
[skeleton@localhost test]$ gcc -o program program.c
[skeleton@localhost test]$ cat hook.c
#include <stdlib.h>

int printf(char *str)
{
        puts("goodbye world!");

        return 0;
}
[skeleton@localhost test]$ gcc -shared -fPIC -o hook.so hook.c
[skeleton@localhost test]$ export LD_PRELOAD=./hook.so
[skeleton@localhost test]$ ./program
goodbye world!
[skeleton@localhost test]$
서론이 길었다.

결론은 LD_PRELOAD 환경변수에 등록된 라이브러리를 미리 로드하는 과정에서(실패를 했든 성공을 했든.) 메모리에 환경변수 값인 파일경로가 올라간다는 것이다. 나중에 level19에서도 알겠지만 이 파일경로가 올라가는 메모리 주소는 main함수가 시작되는 스택주소에서 -3000 정도 떨어진 곳에 size 3000 정도로 존재하는 것 같다.(이 위치 어딘가에 문자열이 존재한다.)

결론은 "LD_*" 관련 환경변수를 (라곤 하지만 LD_LIBRARY_PATH 와 같은 다른 환경변수는 메모리에서 값을 찾지 못했음.) 등록해주면 특정 메모리에 환경변수의 값이 올라간다. 파일경로를 이용한 쉘코드이므로 level8에서 사용했던 0x2f('/') 가 없는 쉘코드를 올려주면 된다.

정확히 확인한 주소로 올라가는 환경변수는 LD_PRELOAD.
LD_LIBRARY_PATH는 올라가지 않는 듯 하다.

댓글