'U&L Developer˚ε♡з。'에 해당되는 글 233건
- 2011.06.15 [LEVEL18] succubus -> nightmare (plt)
- 2011.06.12 [LEVEL17] zombie_assassin -> succubus (function calls)
- 2011.06.11 [LEVEL16] assassin -> zombie_assassin (fake ebp)
- 2011.06.10 [LEVEL15] giant -> assassin (no stack, no RTL)
- 2011.06.09 [LEVEL14] bugbear -> giant (RTL2, only execve)
- 2011.06.08 [LEVEL13] darkknight -> bugbear (RTL1)
- 2011.06.08 [LEVEL12] golem -> darkknight (sfp) 1
- 2011.06.08 [LEVEL11] skeleton -> golem (stack destroyer)
[view source] |
/* The Lord of the BOF : The Fellowship of the BOF - nightmare - PLT */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dumpcode.h>
main(int argc, char *argv[]) { char buffer[40]; char *addr;
if(argc < 2){ printf("argv error\n"); exit(0); }
// check address addr = (char *)&strcpy; if(memcmp(argv[1]+44, &addr, 4) != 0){ printf("You must fall in love with strcpy()\n"); exit(0); }
// overflow! strcpy(buffer, argv[1]); printf("%s\n", buffer);
// dangerous waterfall memset(buffer+40+8, 'A', 4); } |
♧ RET부분이 strcpy주소로 시작을 하는지 check하고 있다. |
♧ GOT와 PLT [ 참조 ] |
GOT는 Global Offset Table(전역 오프셋 테이블)약자며 실행 후, libc.so내 실제 함수 주소가 담기는 저장소이다. 이 내용 참조를 통해 _dl_runtime_resolve가 수행되고, 실제 시스템 라이브러리 호출이 이루어지게 된다. (매 번이 아닌, 한 번만 수행되고 나면, 그 다음부터는 GOT에 기록된 내용만 참조하여 수행) 이를 실제 시스템 라이브러리 주소를 호출하기 위해 필요한 정보 테이블이라 보면 될 것 같다. |
[ summary ] |
♧ strcpy()를 이용해 argv[2]에 있는 system()를 리턴 주소(strcpy호출 다음)에 복사하여 실행 흐름을 변경한다.
|
[ Attack ] | |||
① 필요한 주소 구하기.
② ∑xploit
|
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함
succubus : "here to stay"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL20] xavis -> death_knight (remote BOF) (0) | 2011.06.18 |
---|---|
[LEVEL19] nightmare -> xavis (fgets + destroyers) (0) | 2011.06.15 |
[LEVEL17] zombie_assassin -> succubus (function calls) (0) | 2011.06.12 |
[LEVEL16] assassin -> zombie_assassin (fake ebp) (0) | 2011.06.11 |
[LEVEL15] giant -> assassin (no stack, no RTL) (0) | 2011.06.10 |
[view source] |
/* The Lord of the BOF : The Fellowship of the BOF - succubus - calling functions continuously */
#include <stdio.h> #include <stdlib.h> #include <dumpcode.h>
// the inspector int check = 0;
void MO(char *cmd) { if(check != 4) exit(0);
printf("welcome to the MO!\n");
// olleh! system(cmd); }
void YUT(void) { if(check != 3) exit(0);
printf("welcome to the YUT!\n"); check = 4; }
void GUL(void) { if(check != 2) exit(0);
printf("welcome to the GUL!\n"); check = 3; }
void GYE(void) { if(check != 1) exit(0);
printf("welcome to the GYE!\n"); check = 2; }
void DO(void) { printf("welcome to the DO!\n"); check = 1; }
main(int argc, char *argv[]) { char buffer[40]; char *addr;
if(argc < 2){ printf("argv error\n"); exit(0); }
// you cannot use library if(strchr(argv[1], '\x40')){ printf("You cannot use library\n"); exit(0); }
// check address addr = (char *)&DO; if(memcmp(argv[1]+44, &addr, 4) != 0){ printf("You must fall in love with DO\n"); exit(0); }
// overflow! strcpy(buffer, argv[1]); printf("%s\n", buffer);
// stack destroyer // 100 : extra space for copied argv[1] memset(buffer, 0, 44); memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100));
// LD_* eraser // 40 : extra space for memset function memset(buffer-3000, 0, 3000-40); } |
1) argv[1]에서 "\x40"이 유무 체크. (library 함수를 사용하지 못함)
|
[ summary ] | |||||||||||||
♧ 스택에서 함수 호출은 다음과 같은 모양이다.
♧ 그리고 맨 마지막 <MO> 함수는 system(인자)를 호출하게 되는데
|
[ Attack ] | |||
① 필요한 주소 구하기.
② ∑xploit
|
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함
zombie_assassin : "no place to hide"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL19] nightmare -> xavis (fgets + destroyers) (0) | 2011.06.15 |
---|---|
[LEVEL18] succubus -> nightmare (plt) (0) | 2011.06.15 |
[LEVEL16] assassin -> zombie_assassin (fake ebp) (0) | 2011.06.11 |
[LEVEL15] giant -> assassin (no stack, no RTL) (0) | 2011.06.10 |
[LEVEL14] bugbear -> giant (RTL2, only execve) (0) | 2011.06.09 |
⊙ 문제의 소스를 보자) |
/* The Lord of the BOF : The Fellowship of the BOF - zombie_assassin - FEBP */
#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 retbayed you!\n"); exit(0); }
if(argv[1][47] == '\x40') { printf("library retbayed you, too!!\n"); exit(0); }
// strncpy instead of strcpy! strncpy(buffer, argv[1], 48); printf("%s\n", buffer); } |
♧ strncpy()함수로 인하여 buffer에 복사할 크기를 48로 정의 함으로써 바로 RTL을 사용하지 못한다. |
1) FAKE EBP? | |
♧ 일반 RTL에서는 하나의 함수밖에 호출하지 못하지만 FAKE EBP를 사용 함으로서 여러 함수를 실행하는 공격이 가능 하다.
♧ RET에 leave;ret 주소를 덮음으로써 조작한 ebp로 실행흐름을 바꿀 수 있게 된다.
|
2) 구성 |
① 공격 당한 함수의 에필로그 leave가 실행되면 [mov ebp esp]로 인해 esp가 ebp의 시작 지점으로 이동하며 (이때 pop ebp로 인해 esp+4가 되며 leave의 주소가 들어있다)
② 다음 인스트럭션 명령인 ret이 실행되고 리턴 주소인(leave)가 pop eip가 되면서 다시 leave로 점프하게 된다. ③ 다시 또 한번 leave가 실행되고 ebp에는 FAKE EBP인 버퍼의 시작 주소를 가리키고 있으므로 [ mov ebp esp]로 인해 esp는 buffer의 시작 지점으로 이동하게 되며 [pop ebp]로 인해 esp+4가 된다. ④ 역시 또 한번 ret이 실행 됨으로 system()를 호출하게 된다.
|
∑ 익스플로잇 작성! | ||||||||||||
① 공격 스크립트 작성
② ∑xploit |
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함
assassin : "pushing me away"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL18] succubus -> nightmare (plt) (0) | 2011.06.15 |
---|---|
[LEVEL17] zombie_assassin -> succubus (function calls) (0) | 2011.06.12 |
[LEVEL15] giant -> assassin (no stack, no RTL) (0) | 2011.06.10 |
[LEVEL14] bugbear -> giant (RTL2, only execve) (0) | 2011.06.09 |
[LEVEL13] darkknight -> bugbear (RTL1) (0) | 2011.06.08 |
⊙ 문제의 소스를 보자) |
[giant@localhost giant]$ cat assassin.c /* The Lord of the BOF : The Fellowship of the BOF - assassin - no stack, no RTL */
#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 retbayed you!\n"); exit(0); }
if(argv[1][47] == '\x40') { printf("library retbayed you, too!!\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// buffer+sfp hunter memset(buffer, 0, 44); } |
♧ 제목과 같다. No! Stack, No! RTL.. 버퍼+SFP 초기화. 오로지 RET만 덮어 쓸 수 있다. esp에 저장된 복귀 주소를 pop하고 그 주소를 eip에 대입 하게 된다. 복귀 주소를 pop 하였기 때문에 esp+4가 됨으로써 다시 한번 리턴 할 수 있다. |
⊙ 구성도 |
♧ 인스트럭션 코드가 차례대로 실행되고 Return Address를 다시 한번 RET명령 주소로 덮어쓴다. ♧ 다시 한번 RET명령을 호출 함으로서 esp+4가 됨으로 system을 다시 호출 하게 된다.
|
(※ RET명령을 다시 호출 하는 것 외에는 전 단계와 동일 함으로 필요한 주소 찾는 과정은 제외 한다.)
∑ 익스플로잇 작성! | |||||||||
① 공격 스크립트 작성
② ∑xploit |
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함
giant : "one step closer"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL17] zombie_assassin -> succubus (function calls) (0) | 2011.06.12 |
---|---|
[LEVEL16] assassin -> zombie_assassin (fake ebp) (0) | 2011.06.11 |
[LEVEL14] bugbear -> giant (RTL2, only execve) (0) | 2011.06.09 |
[LEVEL13] darkknight -> bugbear (RTL1) (0) | 2011.06.08 |
[LEVEL12] golem -> darkknight (sfp) (1) | 2011.06.08 |
⊙ 문제의 소스를 보자) |
/* The Lord of the BOF : The Fellowship of the BOF - giant - RTL2 */
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
main(int argc, char *argv[]) { char buffer[40]; FILE *fp; char *lib_addr, *execve_offset, *execve_addr; char *ret;
if(argc < 2){ printf("argv error\n"); exit(0); }
// gain address of execve fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r"); fgets(buffer, 255, fp); sscanf(buffer, "(%x)", &lib_addr); fclose(fp);
fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r"); fgets(buffer, 255, fp); sscanf(buffer, "%x", &execve_offset); fclose(fp);
execve_addr = lib_addr + (int)execve_offset; // end
memcpy(&ret, &(argv[1][44]), 4); if(ret != execve_addr) { printf("You must use execve!\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer); } |
♧ evecve의 주소를 구하여 argv[1][44]의 RET Address부분이 execve의 주소와 동일하지 않으면 종료된다. 그럼으로 문제의 제목과 같이 execve를 이용한 RTL(Return-into-Libc) 방법이 사용된다. (전체적인 구성은 [ LEVEL13 ] 과 같음으로 참고 하자.) |
1) 구성도 |
ⓐ execve() 시스템 콜을 호출한 프로세스를 새로운 프로세스로 변경한다. (환경변수 정보 추가 기능)
*execve의 두 번째 인자는 char 포인터 배열 임으로 argv[0]의 "/bin/sh"는 copyed argv[0]를 이용한다. (즉, 이름을 심볼릭 링크하여 argv[0]으로 만듬) |
2) 필요한 주소를 찾아 보자. | ||||||||||||||
① GDB로 execve(), exit() 주소 찾기. ② "/bin/sh" 주소 찾기.
③ execve()의 두 번째 인자로 사용할 copyed argv[0]의 주소 찾기.
|
∑ 익스플로잇 작성! | |||||||||||||
① 공격할 원본 바이너리 파일(giant)에 심볼릭 링크.
(execve의 주소에 "\x0a"를 "00"으로 취급하기 때문에 스크립트 양쪽에 큰따옴표(double quotation)를 붙여준다.
③ ∑xploit
|
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함
bugbear : "new divide"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL16] assassin -> zombie_assassin (fake ebp) (0) | 2011.06.11 |
---|---|
[LEVEL15] giant -> assassin (no stack, no RTL) (0) | 2011.06.10 |
[LEVEL13] darkknight -> bugbear (RTL1) (0) | 2011.06.08 |
[LEVEL12] golem -> darkknight (sfp) (1) | 2011.06.08 |
[LEVEL11] skeleton -> golem (stack destroyer) (0) | 2011.06.08 |
⊙ 문제의 소스를 보자) |
#include <stdio.h> #include <stdlib.h>
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 betrayed you!!\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer); } |
♧ RET이 "\xbf"로 시작 할 수 없다. 즉, RET을 스택영역으로 둘 수 없다. 그렇기 때문에 RTL(Return-into-Libc) 기법을 통한 문제를 문제를 풀도록 하자. (*자세한 내용은 밑에 참조 문서를 참고 하도록 하자.) | |||||
ⓐ 공유 라이브러리의 함수의 위치는 정해져 있다. 시스템마다 위치가 다르기는 하지만 한번 위치가 알려지면 재컴파일되기 전까지는 위치가 같다. ⓑ 쉘코드를 사용하는 대신에 RET지점에 라이브러리 함수( system(), exit(), "/bin/sh")같은 위치값을 넣어주면 그 함수로 점프하게 된다. ⓒ 스택에서 함수 호출은 다음과 같은 모양이다.
ⓓ 간단한 구성은 다음 그림과 같다. | |||||
참조 문서 | |||||
∑ 익스 플로잇 작성! | ||||||||||
① 필요한 함수와 인자의 주소(system, exit, "/bin/sh")를 구해 보자.
② 공격 스크립트 작성
③ ∑xploit
|
※ 사전에 chsh명령 -> bash2로 변경 후 재로그인 함
darkknight : "new attacker"
'워게임(WarGame) > BOF원정대(LOF)' 카테고리의 다른 글
[LEVEL15] giant -> assassin (no stack, no RTL) (0) | 2011.06.10 |
---|---|
[LEVEL14] bugbear -> giant (RTL2, only execve) (0) | 2011.06.09 |
[LEVEL12] golem -> darkknight (sfp) (1) | 2011.06.08 |
[LEVEL11] skeleton -> golem (stack destroyer) (0) | 2011.06.08 |
[LEVEL10] vampire -> skeleton (argv hunter) (0) | 2011.06.07 |
⊙ 문제의 소스를 보자) |
#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 |