`
javasee
  • 浏览: 961647 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

安全编码实践三:C/C++静态代码分析工具Prefast

阅读更多

《程序员》5月文章。申明。文章仅代表个人观点,与所在公司无任何联系。

  1. 概述

在前面的安全编码实践的文章里,我们讨论了GS编译选项和<wbr>数据执行保护</wbr>DEP功能。 结论是GS和DEP可以有效的缓解缓存溢出类型的安全漏洞的危害<wbr>。关于这个结论,有两个大家需要值得注意的地方。</wbr>

第一:GS和DEP是缓解(mitigation)措施。<wbr>也就是说,<b>代码本身仍然存在着安全漏洞</b>,只是由于</wbr>GS和DEP降<wbr>低了其危害程度。</wbr>

第二:GS和DEP存在其自身的局限性。例如,GS不是对<wbr>每一个函数都适用,而</wbr>DEP则需要一定的硬件支持。

那么,一个很自然的问题就是,<wbr>有什么工具可以帮助我们在开发过程中,<wbr>及早发现并修补代码中存在的安全漏洞?</wbr></wbr>

答案之一是静态代码分析工具。本文会着重介绍微软提供的C<wbr>/C++</wbr>的静态代码分析工具:Prefast。对于托管代码(m<wbr>anaged code</wbr>),微软提供的静态代码分析工具是FxCop。关于Fx<wbr>Cop</wbr>,我们会在以后的安全编码实践的文章中专门介绍。

  1. Prefast介绍

    2.1历史

Prefast是微软研究院提出的静态代码分析工具。<wbr>主要目的是通过分析代码的数据和控制信息来检测程序中的缺陷。<wbr>需要强调的是,</wbr></wbr>Prefast检测的缺项不仅仅是安全缺陷,<wbr>但是安全缺陷类型是其检测的最为重要的部分。</wbr>Prefast推出<wbr>后在微软内部得到了广泛的使用,并经历了若干格版本的升级。<wbr>现在,微软将这个内部工具商业化,以提供给外部的开发人员使用。</wbr></wbr>

    2.2 如何获得Prefast


目前有两个办法可以获得Prefast工具。

  • Prefast包括在Visual Studio 2005 /2008的团队版本(team edition)中。
  • Prefast包括在Windows驱动程序开发包(Micro<wbr>soft Windows Driver Kits</wbr>)的开发环境中。


需要指出的是,Visual Studio的团队版本的价格要高于Visual Studio个人版本,而Windows驱动程序开发包是免费下<wbr>载的,那它们提供的</wbr>Prefast版本有什么区别?在Visua<wbr>l Studio</wbr>的团队版本中,Prefast是直接和代码的开发过<wbr>程集成的,使用非常方便。并且可以直接根据</wbr>Prefast的输出<wbr>结果创建相应的开发任务。而在</wbr>Windows驱动程序开发包中,<wbr>Prefast</wbr>是作为一个单独的工具提供,没有像Visual Studio团队版本中一样与开发环境集成。

下载Windows驱动程序开发包可以通过http://<wbr>connect.microsoft.com/</wbr>, 注册Microsoft Connect后选择Windows Logo Kit (WLK), Windows Driver Kit (WDK) and Windows Driver Framework (WDF)即可。具体的步骤这里就不详细叙述了。

安装好WDK后Prefast就已经直接在其开发环境下使<wbr>用了。</wbr>

    2.3使用Prefast


在Visual Studio的团队版本中,使用Prefast,打开Proje<wbr>ct Properties --&gt; Configuration Properties --&gt; Code Analysis --&gt;Enable Code Analysis For C/C++ on build</wbr>。选择 Yes(/analyze)即可。具体可参见图1。

如果直接使用CL.exe命令行编译器,采用/<wbr>analyze</wbr>编译选项即可。例如:cl test.cpp -W4 /EHsc /analyze

图1:VSTS中使用Prefast(Code Analysis)

使用在WDK中的Prefast,有以下几个重要命令。

    • 运行Prefast:prefast build -cZ
    • 查看Prefast输出结果:
      • 命令行:prefast list
      • GUI:prefast view


有关在WDK下使用Prefast的详细步骤,<wbr>可以参见微软的</wbr>PREfast Step-by-Step文档【1】。

  1. Prefast输出的警告(warning)信息

上面的介绍可以看出Prefast的使用操作并不难。<wbr>成功应用</wbr>Prefast的关键是要理解其输出的各类警告信息,<wbr>并作出正确的评估和代码修改。文章前面我们提到过,</wbr>Prefas<wbr>t</wbr>检测的不仅仅是安全缺陷,<wbr>但是安全缺陷类型是其检测的最为重要的部分。下面,<wbr>我们就介绍一些和安全漏洞紧密相关的警告信息。<wbr>以下给出的代码例子均来自于微软的文档</wbr></wbr></wbr>Code Analysis for C/C++ Warnings【2】。

警告 C6001: using uninitialized memory <variable>,使用未初始化的变量。

例子:

#include "stdafx.h"

int f( bool b )

{

int i;

if ( b )

{

i = 0;

}

return i; // 当b为假时,变量i未初始化

}


大家也许会问,使用未初始化的变量会导致安全漏洞吗?<wbr>这里我想特别强调的一点是,<wbr>我们前面经常提到的安全漏洞是缓存溢出导致的,<wbr>但是大家千万不要认为缓存溢出是导致安全漏洞的唯一原因。<wbr>有各种各样的代码错误可以导致严重的安全漏洞,<wbr>使用未初始化的变量也是其中的一种。<wbr>关于未初始化的变量如何导致安全漏洞的详细信息超出了本文的范畴<wbr>,有兴趣的读者可以参见微软</wbr></wbr></wbr></wbr></wbr></wbr></wbr>SWI组的博客文章:MS08-<wbr>014 : The Case of the Uninitialized Stack Variable Vulnerability</wbr>【3】

修补:初始化变量。

警告C6029: possible buffer overrun in call to <function>: use of unchecked value,使用未验证的参数可能导致缓存溢出。

例子:

#include "windows.h"

void f(char *buff, DWORD cbLen, DWORD cbRead, HANDLE hFile)

{

if (!ReadFile (hFile, &cbLen, sizeof (cbLen), &cbRead, NULL))

{

// code ...

if (!ReadFile (hFile, buff, cbLen, &cbRead, NULL)) // warning 6029

{

// code ...

}

}

}


在上面这个例子中,第一次的ReadFile得到的cbL<wbr>en</wbr>值,直接作为最大读取的长度传递给第二个ReadFile。<wbr>如果</wbr>cbLen过大的话,就会导致写入buff过多的数据。

修补:验证参数。在第二个ReadFile之前验证cbL<wbr>en</wbr>。

if (cbLen <= sizeof (buff)) // check length

警告C6057: buffer overrun due to number of characters/number of bytes mismatch in call to <function>,字符(characters)<wbr>数目和字节(</wbr>bytes)数目的不匹配导致缓存溢出。

对于ANSI字符串类型,字符数目和字节数目是一致的。<wbr>但是如果字符串的类型是</wbr>UNICODE,<wbr>字节数目就是字符数目的两倍。<wbr>如果在应该传递字符数目的地方传递了字节数目,<wbr>就可能导致缓存溢出。</wbr></wbr></wbr>

例子:

#include<tchar.h>

#include<windows.h>

void f( HINSTANCE hInst, UINT uID )

{

TCHAR buff[128];

if ( LoadString ( hInst, uID, buff, sizeof buff ) ) // warning C6057

{

// code...

}

}


LoadString期望的参数是字符串缓存的字符数目。

修补:正确计算数组中元素的个数。

LoadString ( hInst, uID, buff, (sizeof buff)/(sizeof buff[0]) )

警告C6201: buffer overrun for <variable>, which is possibly stack allocated: index <name> is out of valid index range <min> to <max>,数组索引的越界可能导致缓存溢出。

例子:

void f()

{

int buff[25];

for (int i=0; i <= 25; i++) // i exceeds array bound

{

buff[i]=0; // initialize i

// code ...

}

}


修补:确保数组索引不越界。

警告C6202: buffer overrun for <variable>, which is possibly stack allocated, in call to <function>: length <size> exceeds buffer size <max>,使用缓存区时,给出的长度超出缓存区长度的最大值。<wbr><br></wbr>

例子:

#include <memory.h>

void f( )

{

int intArray[5];

char charArray[5];

memset ((void *)charArray, 0, sizeof intArray);

// code ...

}


修补:正确的缓存长度。这里sizeof intArray应该是sizeof charArray。

警告C6204: possible buffer overrun in call to <function>: use of unchecked parameter <variable>,使用缓存区时,<wbr>直接使用未经检查的参数可能导致缓存溢出。</wbr>

例子:

#include<string.h>

void f(char *pCh)

{

char buff[10];

strcpy(buff, pCh);

}


pCh的值没有验证就直接使用了。

修补:验证传入的参数。加入检查:if (strlen(pCh) >= sizeof buff) return;

限於篇幅,<wbr>我们这里无法一一列举所有和安全缺项紧密相关的重要警告信息,<wbr>例如</wbr></wbr>C6327,C6383,C6386等等。有关Prefas<wbr>t</wbr>输出警告信息的详细列表,可以参见Code Analysis for C/C++ Warnings【2】。

  1. 静态代码分析工具的局限

静态代码分析工具是SDL(安全软件开发周期)<wbr>提出的编码实践中非常重要的一环。但是,<wbr>现实中不存在任何一种工具可以一下子解决所有的安全问题。静态</wbr></wbr>C<wbr>/C++</wbr>代码分析工具是不可能发现代码中的所有安全漏洞的。就像<wbr>GS</wbr>和DEP一样,它也存在自身的局限性。

由于程序控制流和数据流的复杂程度,<wbr>静态代码分析工具不可避免的存在:</wbr>

    • 漏报:我们上面举出的代码例子都是非常简单的。<wbr>随着代码复杂度的增大,尤其是跨函数之间逻辑和数据的交互关系,<wbr>往往给静态代码分析带来极大的困难。</wbr></wbr>
    • 误报:分析信息的不完备,会导致误报警告信息。
  1. 总结

Prefast是微软提供的针对C/C++程序的静态代码<wbr>分析工具,可以有效的检测代码中存在的安全缺陷。<wbr>强烈建议在开发过程中,采用</wbr></wbr>Prefast或其他类型的静态代码<wbr>分析工具,以降低程序中引入(安全)缺陷的可能。</wbr>

  1. 参考文献
    1. PREfast Step-by-Stephttp://www.<wbr>microsoft.com/whdc/DevTools/<wbr>tools/PREfast_steps.mspx</wbr></wbr>Micro<wbr>soft </wbr>http://msdn2.microsoft.com/en-<wbr>us/library/ms680339(VS.85).<wbr>aspx</wbr></wbr>
    2. Code Analysis for C/C++ Warningshttp://msdn2.<wbr>microsoft.com/en-us/library/<wbr>a5b9aa09.aspx</wbr></wbr>Microsoft
    3. MS08-014 : The Case of the Uninitialized Stack Variable Vulnerability, http://blogs.technet.com/swi/<wbr>archive/2008/03/11/the-case-<wbr>of-the-uninitialized-stack-<wbr>variable-vulnerability.aspx</wbr></wbr></wbr>, SWI, Microsoft

    分享到:
    评论

    相关推荐

      C++静态代码分析PreFast

      **C++静态代码分析PreFast** 是一种由微软研究院开发的静态分析工具,主要用于在编译阶段检测C++代码中的潜在缺陷。静态代码分析是一种在程序执行前进行的检查,通过对源代码的数学模型进行分析,查找可能存在的错误...

      C++代码静态分析工具-Prefast

      1.什么是PrefastPrefast是一种代码分析工具,它能够帮助你找到编译器不能找到的错误或者缺陷。Prefast首次被微软集成到VisualStudio2005TeamSuite中去,使用起来非常方便。2.怎么使用Prefast在vs2005TeamSuite中,...

      prefast(微软的C++代码检测工具)

      PREfast(Prefast.exe)是微软公司为驱动程式设计所提供的静态的源代码分析工具(static source code analysis tool),可侦测原始程式码中不易用一般编译器找到的特定类型错误,与Windows DDK 建置环境一同安装。...

      PREfast_annotations.pdf

      微软的PREfast工具,一款静态代码分析工具,通过检查源代码来帮助开发者识别潜在的运行时错误。然而,为了更精确地进行分析并减少误报或漏报,PREfast引入了注解(Annotations)的概念。这些注解能够提供额外的信息...

      vc2005 prefast

      c++代码静态检查的利器!告别程序调试。

      Developing Drivers with the Windows Driver Foundation.pdf

      - 第23章:驱动程序的PREfast,介绍了如何使用PREfast这类代码分析工具来提高驱动代码质量。 - 第24章:静态驱动验证器,讲解了静态驱动验证器(Static Driver Verifier)在驱动验证过程中的使用。 附录中包含了...

      Keeping_Windows_Secure.pdf

      在构建过程中运行的规则数量不断增加,包括静态分析引擎,如OACR/PreFast和Semmle,这些工具能帮助开发者在早期发现潜在的安全问题。同时,利用Azure DevOps等持续集成/持续部署(CI/CD)工具,可以在不影响开发流程...

      ddk帮助文档1主文件winddk.col

      7. vcprefast.chi:可能是关于代码分析工具Prefast的介绍,用于驱动程序的静态代码分析和错误检测。 8. parallel.chi:并行端口驱动程序的开发,例如LPT端口。 9. serial.chi:串行端口驱动程序的开发,如COM端口...

      msvc 2005 compiler prefast

      msvc 2005 compiler prefast

      Driver Annotations in Depth - Part 2 - Slides - 2010.pptx

      在驱动程序开发中,静态分析是一种重要的工具,它可以在编译时发现潜在的错误和不安全的代码行为。Driver Annotations 是一种用于增强静态分析工具功能的方法,特别是针对微软的 PREfast for Drivers (PFD)。这些...

      搭建驱动编译环境DDKWizard+WinDDK+VS2005.pdf

      在创建Driver Object时,不应勾选"Create PREfast configuration",因为PREfast是一种静态分析工具,主要用于检测代码中的潜在问题,对于驱动开发可能不是必需的。 7. **Visual Assist X**: 虽然不是构建环境的必要...

      白盒测试培训

      自动化工具如CPPLint、CPPCheck和PREfast可以帮助检测潜在错误、代码效率和安全性。此外,还介绍了代码质量度量工具,如Simian用于检查冗余代码,CppNcss计算代码复杂度。 接着,课程深入到单元测试领域,探讨了...

      Driver Annotations in Depth - Part 2 - Slides - 2010.pdf

      在 Microsoft 的 PREfast for Drivers (PFD) 工具中,Driver Annotations 被广泛使用,以增强对驱动程序代码的静态分析能力。 1. 注解类型: 基本的注解通常是一个标识符,可能包含“输入”或“输出”的含义。然而...

      Driver Annotations in Depth - Part 2 - Slides - 2008.pdf

      接着,文档探讨了代码分析中“种类”的问题。它指出,并非所有的驱动程序代码都在内核模式下运行,同样,并非所有的内核模式代码都是驱动程序代码。文档推荐选择适当的分析模式,如__kernel_driver用于内核模式的...

      驱动程序的质量测试方法与WHQL认证.pptx

      PREfast for Drivers分析内存泄漏和其他潜在错误;Call Usage Verifier查找初始化错误、IRP堆栈错误等;Static Driver Verifier通过错误分支条件检测执行路径问题;而WinDBG则用于通过双机调试找出导致蓝屏错误的...

      VS2005编译驱动

      选择“Driver”选项,这将启动DDK Wizard,你可以在这里配置驱动程序的详细信息,如选择目标操作系统(XP DDK)并取消勾选“Create PREfast configuration”。 8. 创建项目后,进入项目属性进行进一步的配置,以...

    Global site tag (gtag.js) - Google Analytics