Excuse the ads! We need some help to keep our site up.
List
Description of Address Sanitizer
Address Sanitizer는 Google에서 제공하는 취약점 탐지 도구 입니다.
- 버퍼 오버플로와 Dangling pointer에 접근 할 수 있는 메모리 손상을 발견 할 수 있습니다.
- Address Sanitizer는 compiler instrumentation과 directly-mapped shadow memory를 기반으로 동작합니다.
- AddressSanitizer는 현재 Clang (버전 3.1 이상) 및 GCC (버전 4.8 이상) 에서 구현됩니다 .
- Android의 경우 clang-3.5 이상의 최신버전에서 구현됩니다.
- 개발자들은 해당 옵션을 적용하면 프로그램 동작이 느려진다고 합니다.
"Dangling Pointer"란?
- 포인터가 해제된 메모리 영역을 가리키고 있는 포인터입니다.
Detection
- Use after free (dangling pointer dereference)
- Heap buffer overflow
- Stack buffer overflow
- Global buffer overflow
- Use after return
- Use after scope
- Initialization order bugs
- Memory leaks
The supported operating systems and architectures.
OS | x86 | x86_64 | ARM | ARM64 | MIPS | MIPS64 | PowerPC64 |
---|---|---|---|---|---|---|---|
Linux | O | O | O | O | O | ||
OS X | O | O | |||||
iOS Simulator | O | ||||||
FreeBSD | O | O | |||||
Android | O | O |
Others Sanitizer
Leak Sanitizer:
- Heap leak을 실행 중에 탐지합니다.
Thread Sanitizer
- ThreadSanitizer는 데이터 경쟁(data races)을 실행 중에 탐지합니다.
Memory Sanitizer
- MemorySanitizer는 초기화되지 않은 메모리의 참조를 실행 중에 탐지합니다.
UndefinedBehaviorSanitizer(UBSan)
- 정의되지 않은 행동을 실행 중에 탐지 합니다.
Using AddressSanitizer
Option
Option | Description |
---|---|
-fsanitize=address | AddressSanitizer 활성화 |
-fsanitize=kernel-address | Linux kernel용 AddressSanitizer 활성화 |
-fsanitize=thread | ThreadSanitizer 활성화, |
-fsanitize=leak | LeakSanitizer 활성화, memory leak탐지 |
-fno-omit-frame-pointer | 오류 메시지에서 조금더 상세한 스택 trace 결과를 출력 |
-fsanitize=undefined | UndefinedBehaviorSanitizer 활성화 |
Other options of -fsanitize
Build
clang
clang -o test test.c -fsanitize=address
gcc
gcc -o test test.c -fsanitize=address
Build for Android
Android.mk
LOCAL_CFLAGS := -fsanitize=address -fno-omit-frame-pointer LOCAL_LDFLAGS := -fsanitize=address LOCAL_ARM_MODE := arm
Application.mk
NDK_TOOLCHAIN_VERSION=clang3.5
Application.mk
APP_ABI := armeabi armeabi-v7a x86
AddressSanitizerOnAndroid
Build for ios
- Menu → Product → Scheme → Edit Scheme → Diagnostics → Enable "Address Sanitizer"
Enable "Address Sanitizer" at the XCode
Example
UAF(User after free)
- 다음 코드는 해제된 Heap 영역의 값을 return 하고 있습니다.(User after free)
Example code - UAF.cpp
#include <stdio.h> #include <stdlib.h> #include <string.h> char UAF(){ char *a = new char[100]; delete [] a; return a[1]; } int main() { UAF(); }
- 다음과 같이 프로그램 실행 후 취약성이 탐지되었습니다.
Detected a bug.
lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$ g++ -o UAF UAF.cpp -fsanitize=address lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$ ./UAF ================================================================= ==21446==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b00000af91 at pc 0x0000004007e7 bp 0x7fffea6837d0 sp 0x7fffea6837c0 READ of size 1 at 0x60b00000af91 thread T0 #0 0x4007e6 in UAF() (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x4007e6) #1 0x4007f9 in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x4007f9) #2 0x7fe4206f082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #3 0x4006b8 in _start (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x4006b8) 0x60b00000af91 is located 1 bytes inside of 100-byte region [0x60b00000af90,0x60b00000aff4) freed by thread T0 here: #0 0x7fe420b33caa in operator delete[](void*) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99caa) #1 0x4007ae in UAF() (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x4007ae) #2 0x4007f9 in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x4007f9) #3 0x7fe4206f082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) previously allocated by thread T0 here: #0 0x7fe420b336b2 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x996b2) #1 0x400797 in UAF() (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x400797) #2 0x4007f9 in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/UAF+0x4007f9) #3 0x7fe4206f082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) SUMMARY: AddressSanitizer: heap-use-after-free ??:0 UAF() Shadow bytes around the buggy address: 0x0c167fff95a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c167fff95f0: fa fa[fd]fd fd fd fd fd fd fd fd fd fd fd fd fa 0x0c167fff9600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9610: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9620: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9630: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe ==21446==ABORTING lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$
Heap Buffer Overflow
- 다음 코드는 할당된 Heap 영역을 벋어나는 곳으로 부터 값을 가져옵니다.
Example code - HeapBufferOverflow.cpp
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *a = new char[100]; printf("%c\n",a[101]); delete [] a; }
- 다음과 같이 프로그램 실행 후 취약성이 탐지되었습니다.
Detected a bug.
lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$ g++ -o HeapBufferOverflow HeapBufferOverflow.cpp -fsanitize=address lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$ ./HeapBufferOverflow ================================================================= ==21644==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60b00000aff5 at pc 0x0000004008c8 bp 0x7ffd007ae090 sp 0x7ffd007ae080 READ of size 1 at 0x60b00000aff5 thread T0 #0 0x4008c7 in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/HeapBufferOverflow+0x4008c7) #1 0x7f8e9afb182f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #2 0x4007a8 in _start (/home/lazenca0x0/Documents/Definition/addressSanitizer/HeapBufferOverflow+0x4007a8) 0x60b00000aff5 is located 1 bytes to the right of 100-byte region [0x60b00000af90,0x60b00000aff4) allocated by thread T0 here: #0 0x7f8e9b3f46b2 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x996b2) #1 0x400887 in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/HeapBufferOverflow+0x400887) #2 0x7f8e9afb182f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 main Shadow bytes around the buggy address: 0x0c167fff95a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff95e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c167fff95f0: fa fa 00 00 00 00 00 00 00 00 00 00 00 00[04]fa 0x0c167fff9600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9610: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9620: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9630: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c167fff9640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe ==21644==ABORTING lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$
Stack Buffer Overflow
- 다음 코드는 할당된 Stack 영역을 벋어나는 곳으로 부터 값을 가져옵니다.
Example code - StackBufferOverflow.cpp
#include <stdio.h> int main(){ char stack[100]; printf("%c\n",stack[101]); return 0; }
- 다음과 같이 프로그램 실행 후 취약성이 탐지되었습니다.
Detected a bug.
lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$ g++ -o StackBufferOverflow StackBufferOverflow.cpp -fsanitize=address lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$ ./StackBufferOverflow ================================================================= ==21732==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffceb0c9de5 at pc 0x0000004009e0 bp 0x7ffceb0c9d50 sp 0x7ffceb0c9d40 READ of size 1 at 0x7ffceb0c9de5 thread T0 #0 0x4009df in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/StackBufferOverflow+0x4009df) #1 0x7f7e27cf882f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #2 0x400848 in _start (/home/lazenca0x0/Documents/Definition/addressSanitizer/StackBufferOverflow+0x400848) Address 0x7ffceb0c9de5 is located in stack of thread T0 at offset 133 in frame #0 0x400925 in main (/home/lazenca0x0/Documents/Definition/addressSanitizer/StackBufferOverflow+0x400925) This frame has 1 object(s): [32, 132) 'stack' <== Memory access at offset 133 overflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 main Shadow bytes around the buggy address: 0x10001d611360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d611370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d611380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d611390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d6113a0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 =>0x10001d6113b0: 00 00 00 00 00 00 00 00 00 00 00 00[04]f4 f4 f4 0x10001d6113c0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d6113d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d6113e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d6113f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10001d611400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe ==21732==ABORTING lazenca0x0@ubuntu:~/Documents/Definition/addressSanitizer$
Related information
- https://github.com/google/sanitizers
- https://github.com/google/sanitizers/wiki/AddressSanitizer
- https://en.wikipedia.org/wiki/AddressSanitizer
- https://clang.llvm.org/docs/ThreadSanitizer.html
- https://source.android.com/devices/tech/debug/asan
- https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
- https://clang.llvm.org/docs/LeakSanitizer.html
- https://clang.llvm.org/docs/AddressSanitizer.html
- https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html