/DYNAMICBASE和/NXCOMPAT

大家好,我叫向帆,是C++上海团队的开发者。

null

今天我想谈谈与安全性相关的两个链接器选项:/DYNAMICBASE和/NXCOMPAT。

这两个选项是在VS2005中引入的,旨在提高本机应用程序的整体安全性。

您可以在VS IDE中显式设置这两个选项:

图片[1]-/DYNAMICBASE和/NXCOMPAT-yiteyi-C++库

这两个选项在IDE中有三个可用值:On、Off和Default。

如果使用VS2008向导创建本机C++应用程序,它们将被设置为“on”。

当VS2008升级不支持这些选项的旧版本VC创建的项目时,升级后会将它们设置为“关闭”。

如果您将它们设置为“Default”,链接器会将其视为“Off”。

经过几年的采用,我们计划将VS2010中的“Default”行为改为“On”,以增强安全性。我们想得到你的反馈。

以下是有关这两个选项的详细信息:

1. 动态数据库

/DYNAMICBASE修改可执行文件的头,以指示操作系统是否应在加载时对应用程序进行随机重定基。随机重基被称为ASLR(地址空间布局随机化)。

此选项还意味着“/FIXED:NO”,它将在可执行文件中生成重定位部分。看到了吗 /固定 更多信息。

在VS2008中,如果组件需要Windows Vista,则默认情况下此选项处于启用状态( /子系统 6.0及更高版本)

/DYNAMICBASE:NO可用于显式禁用随机重基。

本文讨论ASLR: http://technet.microsoft.com/en-us/magazine/cc162458.aspx

ASLR仅在Windows Vista和更高版本的操作系统上受支持。在旧操作系统上它将被忽略。

ASLR对应用程序是透明的。使用ASLR,唯一的区别是OS将无条件地重新设置可执行文件的基础,而不是仅在存在基于映像的冲突时才这样做。

2. NXCOMPAT公司

/NXCOMPAT用于指定与DEP兼容的可执行文件 (数据执行预防)

请注意,此选项仅适用于x86可执行文件。如果可执行文件未在WOW64模式下运行,则桌面窗口的非x86体系结构版本(例如x64和IA64)始终强制执行DEP。

以下是对DEP的全面描述:

http://support.microsoft.com/kb/875352

如果组件需要Windows Vista,则默认情况下此选项处于启用状态( /子系统 6.0及更高版本)。

/NXCOMPAT:NO可用于显式指定可执行文件与DEP不兼容。

但是,即使可执行文件没有指定为与DEP兼容,管理员仍然可以启用DEP。因此,您应该始终在DEP打开的情况下测试应用程序。

Windows Vista SP1、Windows XP SP3和Windows Server 2008添加了新的API 设置进程策略 允许开发人员在运行时在其进程上设置DEP,而不是使用链接器选项。有关详细信息,请参见以下链接:

http://blogs.msdn.com/michael_howard/archive/2008/01/29/new-nx-apis-added-to-windows-vista-sp1-windows-xp-sp3-and-windows-server-2008.aspx

有几种常见的(和不完整的)模式与DEP不兼容(请参阅 http://msdn.microsoft.com/en-us/library/aa366553.aspx 更多信息。)

答。 在堆或堆栈中生成的动态代码

如果应用程序必须从内存页运行代码,则必须分配和设置适当的虚拟内存页 记忆保护 属性。

分配内存时,必须将分配的内存标记为PAGE U EXECUTE、PAGE U EXECUTE U READ、PAGE U EXECUTE U READWRITE或PAGE U EXECUTE U WRITECOPY。通过调用 新的 , 马洛克 中分配内存 函数是不可执行的。应用程序可以使用 虚拟的 函数来分配具有适当内存保护选项的可执行内存。

另一个选项是在通过创建堆时传递HEAPu CREATEu ENABLEu EXECUTE 堆创建。随后HeapAlloc分配的内存将是可执行的。

b。 数据段中的可执行代码

它们应该迁移到一个代码段

安全漏洞比启用DEP时更容易被利用。因此,您应该始终使应用程序与DEP兼容并打开DEP。

以下示例 演示与DEP不兼容的代码。

它还展示了在堆上运行代码的两种与DEP兼容的方法。

在数据段或堆栈中运行代码几乎总是意味着安全漏洞。您必须将代码放在代码段或堆中。

#包括 “windows.h”

#包括

类型定义 无效 (*funType)();

未签名 烧焦 gCode[]={0xC3}; //x86上的“ret”指令

常数 大小代码= 大小 (G代码);

//这些与DEP不兼容

无效 RunCodeOnHeap()

{

未签名 烧焦 *代码= 新的 未签名 烧焦 [gCodeSize];

memcpy(代码,gCode,gCodeSize);

趣味= 重新解释 (代码);

乐趣();

删除 []代码;

}

//这些是DEP兼容的

无效 RunCodeOnHeapCompatible1()

{

未签名 烧焦 *代码=( 未签名 烧焦 *)·VirtualAlloc(NULL,gCodeSize,MEMu COMMIT,PAGEu READWRITE);

memcpy(代码,gCode,gCodeSize);

DWORD flOldProtect公司;

·VirtualProtect(代码、gCodeSize、PAGEu EXECUTEu READ和flOldProtect);

趣味= 重新解释 (代码);

乐趣();

·VirtualFree(代码,0,内存释放);

}

无效 RunCodeOnHeapCompatible2()

{

HANDLE hheap=::HeapCreate(HEAPu CREATEu ENABLEu EXECUTE,0,0);

未签名 烧焦 *代码=( 未签名 烧焦 *)·HeapAlloc(hheap,0,gCodeSize);

memcpy(代码,gCode,gCodeSize);

趣味= 重新解释 (代码);

乐趣();

:堆自由(hheap,0,代码);

·HeapDestroy(hheap);

}

INT depenceptionfilter(LPEXCEPTIONu指针lpInfo)

{

//请检查 http://technet.microsoft.com/en-us/library/bb457155.aspx

//了解更多信息

如果 (lpInfo->ExceptionRecord->ExceptionCode==状态u访问u冲突)&&

lpInfo->异常记录->异常信息[0]==8){

返回 异常执行处理程序;

}

返回 异常u继续u搜索;

}

内景 主()

{

__试试看

{

RunCodeOnHeap();

打印F( “RunCodeOnHeap:好的” );

}

__除外 (DEPExceptionFilter(GetExceptionInformation()))

{

打印F( “RunCodeOnHeap:由于DEP而失败” );

}

__试试看

{

RunCodeOnHeapCompatible1();

打印F( “RunCodeOnHeapCompatible1:好” );

}

__除外 (DEPExceptionFilter(GetExceptionInformation()))

{

打印F( “RunCodeOnHeapCompatible1:由于DEP而失败” );

}

__试试看

{

RunCodeOnHeapCompatible2();

打印F( “RunCodeOnHeapCompatible2:确定” );

}

__除外 (DEPExceptionFilter(GetExceptionInformation()))

{

打印F( “RunCodeOnHeapCompatible2:由于DEP而失败” );

}

}

输出:

cl测试.cpp/链接/nxcompat:no

RunCodeOnHeap:好的

RunCodeOnHeapCompatible1:确定

RunCodeOnHeapCompatible2:确定

cl测试.cpp/link/nxcompat

RunCodeOnHeap:由于DEP而失败

RunCodeOnHeapCompatible1:确定

RunCodeOnHeapCompatible2:确定

总之,“cl test.cpp”相当于“cl test.cpp/link”/nxcompat:no /dynamicbaseVS2010之前:否。我们计划在VS2010中将其更改为“cl test.cpp/link/nxcompat/dynamicbase”。

如果您对这两个选项的默认行为改变有任何顾虑,请毫不犹豫地给出您的反馈。谢谢!

当做,

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享