轻松审计代码安全性,Windows 10有妙招

若是你是软件开发人员,又但愿本身开发的软件安全性高一点,那么当前的Windows 10企业内部预览版(10.0.16253)中就有一个功能能够作到。html

它的位置在“设置 – > Windows Defender – > Windows Defender安全中心 – >应用程序和浏览器控制 – >漏洞保护设置”中,你能够为整个系统或特定程序启用自定义漏洞利用设置。其中有不少不一样的保护特性而且许多均可以在审计模式下打开。在审计模式下,它不是在出现状况时终止进程,而是将事件写入事件日志。对于管理员,这就意味着其会容许软件继续运行,同时可以使咱们意识到这一状况是什么时候发生的。对于但愿经过了解这些状况以此来改进产品的人来讲,它实际上是提供了一个启用安全功能的附加好处,即无需从新编译(在某些状况下),就能告诉你确切的程序代码在当它在运行时遇到问题的位置。在版本10.0.16253中,能够进行审计的保护特性包括:浏览器

任意代码保护 - 防止非图像支持的执行代码和代码页修改(例如VirtualAlloc / VirtualProtect建立/修改的代码)
阻止低完整性图像
阻止远程图像
阻止不受信任的字体
代码完整性守护者
禁用Win32k系统调用
不容许子进程
导出地址过滤 - 将功能修补到另外一个功能的一个常见方法中的一个步骤
导入地址过滤 - 将功能修补到另外一个功能的一个常见方法中的一个步骤
模拟执行
验证API调用(CallerCheck)
验证图像依赖完整性
验证堆栈完整性

要充分利用此功能,咱们须要安装Windows Performance Toolkit。它是Windows SDK安装程序的安装选项之一。当您启用了您感兴趣的设置后,打开管理命令提示符并浏览到Windows Performance Toolkit目录(一般为Program Files(x86) Windows Kits {Version} Windows Performance Toolkit)。您能够经过运行如下两个命令(在替换文件名所需的任何路径以后)启动并开始收集上述漏洞保护设置的跟踪以及解析堆栈跟踪所需的数据:安全

xperf - “PROC_THREAD + LOADER”-f“wdeg_klogger.etl”

xperf -start“WDEG” - “Microsoft-Windows-Security-Mitigations:0xFFFFFFFFFFFFFF:0xFF:'stack'”-f“wdeg_unmerged.etl”

在您运行任何想要收集的方案以后,您能够中止跟踪并将数据与如下内容合并(再次替换文件名所需的任何路径):服务器

xperf -stop -stop“WDEG”-d“wdeg_merged.etl”

而后,您能够删除建立的前两个文件,由于此时您将拥有第三个所需的全部数据。您能够在Windows Performance Analyzer(WPA)中打开生成的etl文件,并查看数据。ide

您可使用wpaPreset文件扩展名保存它,在WPA中加载数据,转到个人预设(在WPA的较新版本中的文件 – >窗口 – >个人存在),选择导入,浏览到保存预设的任何地方,选择它,并双击它以显示视图。另外,您还须要加载符号,以充分利用这一点。您能够在WPA中在File-> Configure Symbols下设置符号; 您须要将其指向msdl.microsoft.com/download/symbols上的Microsoft符号服务器以及您的符号服务器(或您没有符号服务器设置的符号文件的位置)。您能够在加载跟踪时自动配置WPA加载符号,但也能够经过转到文件 – >加载符号来手动加载符号。一旦完成,您将可以轻松地查看堆栈跟踪。它就会像下面这样:oop

如下是在建立上述过程当中我为x64控制台应用程序编译的示例代码:字体

#include #include using namespace std;void* CreateCodeInVirtualMemory(BOOL writable)
{ BYTE code[3] = { 0x33, 0xc0, 0xc3 }; LPVOID result = VirtualAlloc(NULL, sizeof(code), MEM_COMMIT | MEM_RESERVE, writable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); if (result)
{
  memcpy(result, code, sizeof(code));
} else cout << "VirtualAllocEx failed with error " << GetLastError() << endl; return result;
}void CreateCodeInVirtualMemoryAndExecute(BOOL useWritableMemory)
{ LPTHREAD_START_ROUTINE addr = (LPTHREAD_START_ROUTINE)CreateCodeInVirtualMemory(useWritableMemory); if (addr)
{  DWORD result = addr(NULL);
  cout << "Code at 0x" << hex << (void*)addr << " returned " << result << endl;
} else cout << "NULL address was not executed" << endl;
}void ExecuteIllegalMemory()
{
CreateCodeInVirtualMemoryAndExecute(FALSE);
} 
void PrintOptions()
{
cout << "Enter one of the following options:" << endl;
cout << "1 - Execute Memory Not Marked As Executable" << endl;
cout << "2 - Create Code in Virtual Memory" << endl;
cout << "3 - Create Code in Virtual Memory and Execute" << endl;
cout << "0 - Exit" << endl;

}void DecisionLoop()
{ while (true)
{  int selection;
  PrintOptions();
  cin >> selection;  switch (selection)
  {   case 0:    return;   case 1:
ExecuteIllegalMemory();    break;   case 2:
CreateCodeInVirtualMemory(TRUE);    break;   case 3:
CreateCodeInVirtualMemoryAndExecute(TRUE);    break;   default:
cout << "Invalid input" << endl;
  }
}
}int main()
{
DecisionLoop(); return 0;
}

在这里我没有去对它的应用作更多的介绍,但我相信个人抛砖引玉必定可以让更多的人对这一功能产生兴趣。
对于在事件查看器中的应用程序和服务日志中找到的大多数内容,您也能够以相同的方式完成此类操做——单击特定日志的属性,它将具备Provider-Name-Parts / LogName形式的名称。您只须要在xperf命令中使用“Provider-Name-Parts”部分便可。spa

相关文章
相关标签/搜索