【S2E】分析恶意软件
S2E – 分析恶意软件
实际操作了一下。原文参考 【S2E】【翻译】用S2E分析“基于触发的”恶意软件 。
在 S2E 下构建 Windows 7 镜像
S2E 很明确地要求镜像名为 en_windows_7_professional_with_sp1_x86_dvd_u_677056.iso,MSDN 下载需要订阅,所以在 Google 上随便找了个 ed2k 链接下载的。SHA-1 值是:d89937df3a9bc2ec1a1486195fd308cd3dade928 ,下载完后可以用 certutil -hashfile en_windows_7_professional_with_sp1_x86_dvd_u_677056.iso SHA1
来计算 SHA-1 。
1 | PS G:\> certutil -hashfile C:\Users\zhehuiliu\Desktop\en_windows_7_professional_with_sp1_x86_dvd_u_677056.iso SHA1 |
然后将镜像放在某个目录下,运行:
1 | s2e image_build windows-7sp1pro-i386 --iso-dir ${path_to_iso_dir} |
等个三四个小时就好了。
在 VS 中构建 malware-inject 工程
我安装了 VS2017 专业版。
按照博客中的指示,打开 $S2EDIR/source/s2e/guest/windows/s2e.sln
,可以看到解决方案中包含 7 个项目:
创建一个新项目:(选择 添加到解决方案)
在 malware-inject 项目中,使用 nuget 安装 EasyHookNativePackage:
在 malware-inject 项目中创建 inject.c ,写入下列代码:
1 |
|
此时发现,IDE 无法找到 s2e/s2e.h ,根据下面注释中的描述,将 libcommon 添加到 malware-inject 项目的依赖。malware-inject -> 右键 -> 生成依赖项 -> 项目依赖项
1 | // We must add this header file to support writing to S2E's logs. s2e.h resides |
然后,在 malware-inject -> 右键 -> 属性,在包含目录中添加 :$(SolutionDir)libcommon\include;
,引入 s2e/s2e.h 文件。
此外,还需要把 libcommon.lib 导入 malware-inject 工程。这个参考 Visual Studio 2017 项目中引用lib静态库_轻舞飞扬-CSDN博客 。
最后编译 malware-inject 工程。我遇到报错 LNK2019 无法解析的外部符号 __imp__PathFileExistsA@
,所以添加了 #pragma comment(lib, "Shlwapi.lib")
。
最后编译成功:
踩坑
编译项目需要在 Windows 7 32bit 下运行,所以我直接编译了 winxp 版本。我下载好平台工具集 Visual Studio 2017 - Windows XP (v141_xp) 并切换之后,显示找不到 Windows.h 等头文件。网上都是说没安装工具集,反复装了好几遍,最后在 [StackOverflow](c++ - How to compile code for Windows XP in Visual Studio 2017 - Stack Overflow) 上看到了:
This happens when you have customized include/library paths in legacy projects. If you added your own additional paths in project properties, VisualStudio 2017 can’t automatically figure out base paths when switching between platforms/toolsets - normally it automatically puts correct paths there, but if you added customizations, VS won’t touch them.
This is legitimate problem which I ran into myself recently when migrating old project targeted for Windows XP into VS2017. None of the answers or comments listed/linked here so far are helpful. I have all legacy SDKs in VisualStudio 2017 installer, and none of that fixed VS not finding essential includes such as
<windows.h>
. In my case the project was using v120 toolset from VS2013, which is superseded by v140_xp in newer VS.After setting correct platform and toolset understood by VS2017, I did the following to resolve the problem:
- Open project properties, go to VC++ Directories, for ‘Include Directories’ and for ‘Library Directories’, choose
<Inherit from parent or project defaults>
. This will remove your additional paths. - Click ‘Apply’. This will reset include path to something like
$(VC_IncludePath_x86);$(WindowsSdk_71A_IncludePath_x86)
(will vary for SDKs). - Re-add your extra paths here, or better yet - under C/C++/General -> Additional Include Directories and Linker/General -> Additional Library Directories.
- Open project properties, go to VC++ Directories, for ‘Include Directories’ and for ‘Library Directories’, choose
切换到 v141_xp 后,报错
无法解析外部符号 __imp__RtlGetLastErrorString@0 referenced in function _main
,在 Accessing EasyHook FROM Visual Studio - C++ · Issue #95 · EasyHook/EasyHook · GitHub 中找到,是 EasyHook32.lib 没有加载,我手动把 EasyHook32.lib 拷贝到当前项目下就好了。
学习用例1:GetLocalTime-hook 项目
构建 GetLocalTime-hook 项目
新建 GetLocalTime-test 项目。创建 GetLocalTime-hook.cpp ,写入下面代码:
1 | /// |
编译选项设置可以参考前面的,包括:
- 使用 Visual Studio 2017 - Windows XP (v141_xp) 工具集;
- 把输出类型设置为 动态链接库 .dll;
- 安装 EasyHookNativePackage,并把 EasyHook32.lib 拷贝到当前目录;
- 把 libcommon 作为当前项目的依赖项目,并把 libcommon/include 目录添加到当前项目的包含目录;最后引入 libcommon.lib。
到这一步,编译成功后,我们会得到两个文件:
- malware-inject.exe
- GetLocalTime-hook.dll
使用 S2E 测试 GetLocalTime-test
先编写 GetLocalTime-test 测试程序。我不想在 VS 下新建一个工程了,直接在 Dev C++ 下编译下面代码:
1 |
|
将其命名为 test-time.exe。然后将 test-time.exe 拷贝到 S2E 中。
先创建 S2E 工程:
1 | s2e new_project -i windows-7sp1pro-i386 /home/ubuntu/workspace/malware/test-time.exe |
然后将 malware-inject.exe,GetLocalTime-hook.dll 连同 EasyHook32.dll 一起拷贝到刚生成的 S2E 环境下,并在刚生成的项目中创建软链接。
修改 bootstrap.sh:
1 | # ... |
这里因为我改了 dll 的名字,所以在 execute_target
使用的地方和导入的地方都要改一下名字。我的项目中 bootstrap.sh 和作者博客有些不同,应该是版本不同导致的。不过还是按照作者写的改了。
最后启动 S2E:
可以看到最后有 4 个 state,说明 fork 了 4 次。在 debug.txt 中也能看到符号变量:
总结
复现这个例子说明了,使用 S2E 分析 Windows 下的进程是可行的。原文中作者提到,因为在 Windows 下没有类似 s2e.so 类似的内容,所以不能直接将输入符号化。通过 DLL 注入和 hook Windows API 的方式向程序注入符号变量,进行进一步的分析。
WannaCry 的部分暂时没有实践分析,等到后面有机会再进行(挖坑)。