⊙ 문제의 소스를 보자) |
/* 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 |