UID 2
精华
积分 7736
威望 点
宅币 个
贡献 次
宅之契约 份
最后登录 1970-1-1
在线时间 小时
本帖最后由 元始天尊 于 2014-9-20 21:51 编辑
一、静态代码分析
静态代码分析
vs2010同时支持本地代码和.NET代码的静态分析,下面是例子:
#define E_ACCESSDENIED 0x80000009L
void main()
{
wprintf(L"Error code value is:%s\n",E_ACCESSDENIED);
}
复制代码
该例中的错误是wprintf使用了错误的格式化串,试图把HRESULT类型的值当做%s
下面我们来解决这个问题:菜单->分析->对解决方案运行代码分析,会出现一行警告:
warning : C6067: _Param_(2) 在对“wprintf”调用中必须是字符串地址。实际类型:“long”。
代码分析特性可以通过设置使每次编译的时候都能自动运行它。右键选择项目->属性->代码分析->生成时启用代码分析
SAL标注 VC++ Standard Annotation Language 标准标注语言
VC++静态代码分析引擎中的一个主要限制是无法确定函数输入和输出的数据类型,为此静态分析需要搞清楚函数和调用者之间的传递方式,这正是SAL标注的作用,它允许开发者描述期望的传参类型。SAL标注语法在MSDN网站上属于高级话题。语法格式:_In_z and _Out_z_cap_(_Size)
下面是例子:
#include <windows.h>
#include <stdio.h>
static void FillString(__in WCHAR ch,__in DWORD cchBuffer,__out_ecount(cchBuffer) WCHAR* pwszBuffer)
{
for(DWORD i=0;i<cchBuffer;i++)
{
pwszBuffer[i]=[/i]ch;
}
}
void main()
{
WCHAR wszBuffer[MAX_PATH];
FillString(L'\0',sizeof(wszBuffer),wszBuffer);
}
复制代码
该程序有严重bug:FillString函数期望cchBuffer是pswszBuffer的字符数(正如_out_ecount SAL标注),而不是字节数,这将导致FillString在buffer之后写入数据,会导致缓冲区溢出。当我们使用代码分析时,会自动处理SAL标注,因此会有如下警告:
warning : C6386: 写入到“wszBuffer”时缓冲区溢出: 可写大小为“520”个字节,但可能写入了“1040”个字节。
如今系统api函数基本上都用SAL标注过了,下面是WriteFile函数,我们可以再自己的代码中也使用SAL标注
WINBASEAPI
BOOL
WINAPI
WriteFile(
_In_ HANDLE hFile,
_In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
复制代码
其他分析工具:OACR用于C/C++ DDK驱动开发的静态分析,FxCop用于.NET代码分析
OCAR:Office Auto Code Review,微软早在10年前就开发出来秘密使用
二、运行时代码分析
这部分讲述了应用程序验证工具,它是本地代码运行时分析工具,该工具以来操作系统捕获系统api常规错误。可以捕获的错误如下:
1.堆崩溃,包括缓冲区溢出(overrun)和不足(underrun,指从缓冲区读取的速度>写入缓冲区的速度),和非法内存地址
2.错误的资源句柄,比如已经关闭的句柄,或者空指针,或者不被允许的默认句柄(例如GetCurrentProcess返回句柄)
3.dll模块中的临界区泄露和临界区使用的bug(多次释放、初始化前使用等)
4.orphaned locks(当你调用ExitThread或TerminateThread却没有释放线程回调例程所需的锁)
5.其他错误
主程序appverif.exe 例子:
#include <windows.h>
void main()
{
HANDLE hProcess=OpenThread(THREAD_ALL_ACCESS,FALSE,GetCurrentThreadId());
TerminateProcess(hProcess,EXIT_SUCCESS);
}
复制代码
使用Application Verifier配置好后,用windbg运行,会有如下调试信息:
=======================================
VERIFIER STOP 00000305: pid 0x21F8: Incorrect object type for handle.
000003E0 : Handle value.
0028FAE0 : Object type name. Use du to display it
6202439C : Expected object type name. Use du to display it
00000000 : Not used.
=======================================
PS:此例中的错误大家自行研究
!avrf扩展调试命令