Windows下使用AddressSanitizer检测内存访问越界

Windows下AddressSanitizer的使用

简介

AddressSanitizer的功能大致就是各种buffer溢出检测,比如数组越界什么的,可以用来避免一部分未定义行为,最初是做Unix课的作业时用过一次,然后就再也离不开它了……
AddressSanitizer · google/sanitizers Wiki
官方也给了它在Windows下的用法,和Linux、mac OSX中略有不同。AddressSanitizerWindowsPort · google/sanitizers Wiki
遗憾的是另一个也很强大的工具LeakSanitizer在Windows下还用不了。它的功能是检测内存泄漏。

LeakSanitizer is not supported on Windows yet. LeakSanitizer requires being able to stop the process at exit or some other point to scan for live pointers. This is called “StopTheWorld”, and the posix implementation uses ptrace, which is not available on Windows.

不过嘛,有得用总是好的~

环境

需要clang和Visual Studio。
clang+llvm直接去下载编译好的就可以了:
LLVM Download Page,Download LLVM 8.0.0-Pre-Built Binaries-Windows (64-bit),那个sig不用管。然后安装。总之装clang的教程有一大堆。
Visual Studio就不说了……

使用

举例:
test.c:

#include 

int main() {
	int *arr = malloc(sizeof(int)*4);
	arr[10] = -1;
	return 0;
}

cmd命令:

clang test.c -o test.exe -g -fsanitize=address -Xlinker /LIBPATH:C:\llvm\lib\clang\8.0.0\lib\windows -Xlinker clang_rt.asan-x86_64.lib

clang test.c -o test.exe -g 这些都没什么好说的, -fsanitize=address就是启用AddressSanitizer了。
-Xlinker /LIBPATH:C:\llvm\lib\clang\8.0.0\lib\windows

-Xlinker clang_rt.asan-x86_64.lib
是两个传递给链接器的参数,在这里这两个参数被传递给了clang默认使用的链接器,也就是MSVC的链接器link.exe。它们俩的作用就是要求链接器去llvm\lib\clang\8.0.0\lib\windows下找到clang_rt.asan-x86_64.lib。AddressSanitizer实际上是往源文件里插入了一些代码,所以需要链接到这个库。其他不同的链接方式参考AddressSanitizerWindowsPort · google/sanitizers Wiki。
实际上还可以先生成.o文件,再手动使用链接器链接生成.exe文件,但是会麻烦很多,因为需要手动指定很多其他的库,否则会提示找不到一些.lib文件。

clang test.c -c -g -fsanitize=address

使用MSVC的链接器link.exe(位置取决于你的VS的安装路径,比如我的是C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64):

link.exe test.o /LIBPATH:C:\llvm\lib\clang\8.0.0\lib\windows clang_rt.asan-x86_64.lib /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\um\x64" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64"

也可以使用llvm自己的链接器lld-link.exe,位于llvm\bin,设置了环境变量时可以直接用。

lld-link.exe test.o /LIBPATH:C:\llvm\lib\clang\8.0.0\lib\windows clang_rt.asan-x86_64.lib /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\um\x64" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64"

需要链接的几个库的目录,同样取决于VS的安装位置:

/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64" 
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\um\x64" 
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64"

控制台运行test.exe的输出:

==7344==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x12c8dca000d8 at pc 0x7ff77a57107b bp 0x00fb7e4ffb70 sp 0x00fb7e4ffbb8
WRITE of size 4 at 0x12c8dca000d8 thread T0
    #0 0x7ff77a57107a in Ordinal0+0x107a (C:\***\test.exe+0x14000107a)
    #1 0x7ff77a5a1cff in _ubsan_get_current_report_data+0x9cf (C:\***\test.exe+0x140031cff)
    #2 0x7ffbe79c7973 in BaseThreadInitThunk+0x13 (C:\Windows\System32\KERNEL32.DLL+0x180017973)
    #3 0x7ffbe86aa270 in RtlUserThreadStart+0x20 (C:\Windows\SYSTEM32\ntdll.dll+0x18006a270)

Address 0x12c8dca000d8 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow (C:\***\test.exe+0x14000107a) in Ordinal0+0x107a
Shadow bytes around the buggy address:
  0x051df833ffc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x051df833ffd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x051df833ffe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x051df833fff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x051df8340000: fa fa 00 05 fa fa 00 06 fa fa 00 04 fa fa 00 07
=>0x051df8340010: fa fa 00 07 fa fa 00 00 fa fa fa[fa]fa fa fa fa
  0x051df8340020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x051df8340030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x051df8340040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x051df8340050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x051df8340060: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==7344==ABORTING

你可能感兴趣的:(Windows下使用AddressSanitizer检测内存访问越界)