Address Sanitizer와 함께 빌드하기
GCC와 CLANG로 빌드 시 Adress sanitizer를 구성하는 예시이다. 오브젝트 코드 주소를 소스 코드 행 번호와 파일 이름으로 변환하려면 ASAN_OPTIONS=symbolize=1
옵션이 필요하다. GCC 사용 시 권장 방법은 -static-libasan
을 사용하여 ASAN에 정적으로 링크하는 것이다. (ldd
명령어를 이용하여 이를 확인해보자.)
ldd
ldd(List Dynamic Dependencies)는 프로그램이나 공유 라이브러리들이 요구하는 공유 라이브러리(shared libraries)를 출력하는 명령 행(Command Line)프로그램이다.
–version : ldd의 버전을 출력한다.
-v, –verbose : 심볼 버전 정도등 모든 정보를 출력한다.
-d, –data-relocs
-r, –function-relocs
–help : 사용방법을 출력한다.
출처 : joinc - ldd
main.cpp
다음은 스택 오버플로우 취약점이 있는 간단한 소스코드이다.
int main(int argc, char **argv) {
int stack_array[100];
stack_array[1] = 0;
return stack_array[argc + 100]; // BOOM
}
Makefile
.PHONY: using-gcc using-gcc-static using-clang
using-gcc:
g++-4.8 -o main-gcc -lasan -O -g -fsanitize=address -fno-omit-frame-pointer main.cpp && \
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=$(shell which llvm-symbolizer) ./main-gcc
using-gcc-static:
g++-4.8 -o main-gcc-static -static-libstdc++ -static-libasan -O -g -fsanitize=address -fno-omit-frame-pointer main.cpp && \
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=$(shell which llvm-symbolizer) ./main-gcc-static
using-clang:
clang -o main-clang -x c++ -O -g -fsanitize=address main.cpp && \
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=$(shell which llvm-symbolizer) ./main-clang
clang
$ make using-clang
clang -o main-clang -x c++ -O -g -fsanitize=address main.cpp && \
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=/usr/local/bin/>llvm-symbolizer ./main-clang
=================================================================
==25497==ERROR: AddressSanitizer: stack-buffer-overflow on address >0x7fffaeb43014 at pc 0x4b7453 bp 0x7fffaeb42e50 sp 0x7fffaeb42e48
READ of size 4 at 0x7fffaeb43014 thread T0
#0 0x4b7452 in main /home/kkleine/Development/asan-test/main.cpp:5
#1 0x2af489d27ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/>libc-start.c:287
#2 0x4b720c in _start (/home/kkleine/Development/asan-test/>main-clang+0x4b720c)Address 0x7fffaeb43014 is located in stack of thread T0 at offset 436 in >frame
#0 0x4b72ef in main /home/kkleine/Development/asan-test/main.cpp:2This frame has 1 object(s):
[32, 432) ‘stack_array’ <== Memory access at offset 436 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 /home/kkleine/Development>/asan-test/main.cpp:5 main
Shadow bytes around the buggy address:
0x100075d605b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d605c0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x100075d605d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d605e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d605f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100075d60600: 00 00[f3]f3 f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00
0x100075d60610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d60620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d60630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d60640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100075d60650: 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
ASan internal: fe
==25497==ABORTING
make: * [using-clang] Error 1
gcc
$ make using-gcc
g++-4.8 -o main-gcc -lasan -O -g -fsanitize=address >-fno-omit-frame-pointer main.cpp && \
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=/usr/local/bin/>llvm-symbolizer ./main-gcc
=================================================================
==25394== ERROR: AddressSanitizer: stack-buffer-overflow on address >0x7fffd708a284 at pc 0x40080d bp 0x7fffd708a0c0 sp 0x7fffd708a0b8
READ of size 4 at 0x7fffd708a284 thread T0
#0 0x40080c in main /home/kkleine/Development/asan-test/main.cpp:5
#1 0x2b9e16013ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/>libc-start.c:287
#2 0x400688 in _start (/home/kkleine/Development/asan-test/>main-gcc+0x400688)
Address 0x7fffd708a284 is located at offset 436 in frame of T0’s >stack:
This frame has 1 object(s):
[32, 432) ‘stack_array’
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 /home/kkleine/Development>/asan-test/main.cpp:5 main
Shadow bytes around the buggy address:
0x10007ae09400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae09410: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00
0x10007ae09420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae09430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae09440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007ae09450:[f4]f4 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
0x10007ae09460: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae09470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae09480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae09490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007ae094a0: 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 righ 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
ASan internal: fe
==25394== ABORTING
make: * [using-gcc] Error 1
gcc static
$ make using-gcc-static
g++-4.8 -o main-gcc-static -static-libstdc++ -static-libasan -O -g >-fsanitize=address -fno-omit-frame-pointer main.cpp && \
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=/usr/local/bin/>llvm-symbolizer ./main-gcc-static
=================================================================
==25464== ERROR: AddressSanitizer: stack-buffer-overflow on address >0x7fff8f79d214 at pc 0x41ab0b bp 0x7fff8f79d050 sp 0x7fff8f79d048
READ of size 4 at 0x7fff8f79d214 thread T0
#0 0x41ab0a in main /home/kkleine/Development/asan-test/main.cpp:5
#1 0x2b4b32bdaec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/>libc-start.c:287
#2 0x402116 in _start (/home/kkleine/Development/asan-test/>main-gcc-static+0x402116)
Address 0x7fff8f79d214 is located at offset 436 in frame of T0’s >stack:
This frame has 1 object(s):
[32, 432) ‘stack_array’
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 /home/kkleine/Development>/asan-test/main.cpp:5 main
Shadow bytes around the buggy address:
0x100071eeb9f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x100071eeba10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100071eeba40: 00 00[f4]f4 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x100071eeba50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100071eeba90: 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 righ 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
ASan internal: fe
==25464== ABORTING
make: * [using-gcc-static] Error 1
ldd
$ ldd main-*
main-clang:
linux-vdso.so.1 => (0x00007fff2a1fe000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (>0x00007ff4eb80a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff4eb602000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff4eb2fb000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff4eb0f7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (>0x00007ff4eaee1000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff4eab1a000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff4eba63000)
main-gcc:
linux-vdso.so.1 => (0x00007fffe6bae000)
libasan.so.0 => /usr/lib/x86_64-linux-gnu/libasan.so.0 (>0x00007f8b44a0e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8b44648000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (>0x00007f8b44429000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f8b44225000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8b479d8000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (>0x00007f8b4400f000)
main-gcc-static:
linux-vdso.so.1 => (0x00007fffd615b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f29984f3000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (>0x00007f29982d5000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (>0x00007f29980be000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2997cf8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2998732000)
원본 자료 : Github - kwk/Makefile