软件沙箱技术 – 安全分析沙箱Cuckoo Sandbox
1.Cockoo的功能
Cockoo Sandbox是开源安全沙箱,基于GPLv3。目的是恶意软件(malware analysis)分析。使用的时候将待分析文件丢到沙箱内,分析结束后输出报告。很多安全设备提供商所谓云沙箱是同类技术,一些所谓Anti-APT产品也是这个概念。和传统AV软件的静态分析相比,Cuckoo动态检测。扔到沙箱的可执行文件会被执行,文档会被打开,运行中检测。和不少开源软件学而优则仕一样,Cookoo搞了一个产品,Red Dragon。这种方式也是挺好的一种做开源软件的运营方式,Snort的SourceFire不就是被思科十几亿收购了吗。
Cuckoo它可以分析的内容有:
1.Windows可执行文件,DLL文件
2.PDF,MSOffice文档
3.URL和HTML文档
4.PHP脚本,VB脚本
5.CPL文件
6.ZIP文件,Jar文件
7.Python文件
可以看出,只是Windows平台,外加一些脚本和文件。
Cuckoo的分析结果包含如下内容:
1.函数以及API调用的Call Trace
2.应用拷贝和删除的文件
3.选定进程的内存镜像
4.分析机的full memory dump
5.恶意软件执行时的截屏
6.分析机产生的网络流量
2.部署和使用
下图是Cuckoo的部署,其实很简单,分为host和guests。
Host(管理机)
负责
管理guests
启动分析工作
网络流量收集等。
host依赖一些开源软件,例如
tcpdump用于Guest网络拦截
Volatility用于内存的dump
Guest(虚拟机)
Guest是通用的虚拟机,Xen、VirtualBox等。它运行Cuckoo的Agent,接收Host发过来的任务(文件)运行后获取信息。
Agent是跨平台的(就是Python脚本)可以运行在Windows、Linux和MAC OS上。它实际是是一个XMLRPC server,等待连接。
Cuckoo使用
Cuckoo提供了python命令行工具。
1.使用cuckoo.py启动引擎。
2.使用submit.py像cuckoo提交待分析应用。
3.引擎会和虚拟机中的Agent通信,运行应用。
4.分析结束后,结果输出到特定目录。
3.Hook引擎
cuckoo使用了通用虚拟机做Guest,本身也没有隔离机制和访问控制机制。它特殊的地方就是Hook机制。核心模块cuckoomon(Cuckoo Sandbox Monitor)的源码在这里。它的作用是Hook在可执行程序上,拦截执行流程。 形式上它是一个DLL,会被inject到待分析的恶意软件和它创建的所有进程中。所谓动态分析,就是Hook后的API,在线收集的运行时信息。主要有两个步骤:
3.1 DLL注入
注入是使用Python实现的,流程如下:
1.使用CreateProcess(CREATE SUSPENDED)启动应用
2.使用CreateRemoteThread和QueueUserAPC API调用LoadLibrary注入cuckoomon.dll。
3.Resume进程的主线程
参照下面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
classProcess:
"""Windows process."""
def inject(self,dll=os.path.join("dll","cuckoomon.dll"),apc=False):
"""Cuckoo DLL injection.
@param dll: Cuckoo DLL path.
@param apc: APC use.
"""
ifself.pid==0:
log.warning("No valid pid specified, injection aborted")
returnFalse
ifnotself.is_alive():
log.warning("The process with pid %d is not alive, injection "
"aborted"%self.pid)
returnFalse
dll=randomize_dll(dll)
ifnotdll ornotos.path.exists(dll):
log.warning("No valid DLL specified to be injected in process "
"with pid %d, injection aborted"%self.pid)
returnFalse
arg=KERNEL32.VirtualAllocEx(self.h_process,
None,
len(dll)+1,
MEM_RESERVE|MEM_COMMIT,
PAGE_READWRITE)
ifnotarg:
log.error("VirtualAllocEx failed when injecting process with "
"pid %d, injection aborted (Error: %s)"
%(self.pid,get_error_string(KERNEL32.GetLastError())))
returnFalse
bytes_written=c_int(0)
ifnotKERNEL32.WriteProcessMemory(self.h_process,
arg,
dll+"\x00",
len(dll)+1,
byref(bytes_written)):
log.error("WriteProcessMemory failed when injecting process "
"with pid %d, injection aborted (Error: %s)"
%(self.pid,get_error_string(KERNEL32.GetLastError())))
returnFalse
kernel32_handle=KERNEL32.GetModuleHandleA("kernel32.dll")
load_library=KERNEL32.GetProcAddress(kernel32_handle,
"LoadLibraryA")
config_path=os.path.join(os.getenv("TEMP"),"%s.ini"%self.pid)
with open(config_path,"w")asconfig:
cfg=Config("analysis.conf")
config.write("host-ip={0}\n".format(cfg.ip))
config.write("host-port={0}\n".format(cfg.port))
config.write("pipe={0}\n".format(PIPE))
config.write("results={0}\n".format(PATHS["root"]))
config.write("analyzer={0}\n".format(os.getcwd()))
config.write("first-process={0}\n".format(Process.first_process))
Process.first_process=False
ifapc orself.suspended:
log.info("Using QueueUserAPC injection")
ifnotself.h_thread:
log.info("No valid thread handle specified for injecting "
"process with pid %d, injection aborted"%self.pid)
returnFalse
ifnotKERNEL32.QueueUserAPC(load_library,self.h_thread,arg):
log.error("QueueUserAPC failed when injecting process "
"with pid %d (Error: %s)"
%(self.pid,
get_error_string(KERNEL32.GetLastError())))
returnFalse
log.info("Successfully injected process with pid %d"%self.pid)
else:
event_name="CuckooEvent%d"%self.pid
self.event_handle=KERNEL32.CreateEventA(None,
False,
False,
event_name)
ifnotself.event_handle:
log.warning("Unable to create notify event..")
returnFalse
log.info("Using CreateRemoteThread injection")
new_thread_id=c_ulong(0)
thread_handle=KERNEL32.CreateRemoteThread(self.h_process,
None,
0,
load_library,
arg,
0,
byref(new_thread_id))
ifnotthread_handle:
log.error("CreateRemoteThread failed when injecting "+
"process with pid %d (Error: %s)"%(self.pid,
get_error_string(KERNEL32.GetLastError())))
KERNEL32.CloseHandle(self.event_handle)
self.event_handle=None
returnFalse
else:
KERNEL32.CloseHandle(thread_handle)
returnTrue
|
3.2 API Hook
1.上一步中主线程恢复后,因为APC callback,Cuckoo Monitor首先被执行。
2.初始化并且安装Hook
Cuckoo对ntdll.dll, kernel32.dll, advapi32.dll,shell32.dll,msvcrt.dll,user32.dll,wininet.dll,ws2_32.dll,mswsock.dll中的170+API进行hook
3.通知分析模块Analyzer(通过命名管道),应用启动。
4.Log将会通过实现配置好的TCP/IP端口发送给Host。
下面是添加Hook的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
inthook_api(hook_t *h,inttype)
{
// table with all possible hooking types
staticstruct{
int(*hook)(hook_t *h,unsignedchar*from,unsignedchar*to);
intlen;
}hook_types[]={
/* HOOK_JMP_DIRECT */{&hook_api_jmp_direct,5},
/* HOOK_NOP_JMP_DIRECT */{&hook_api_nop_jmp_direct,6},
/* HOOK_HOTPATCH_JMP_DIRECT */{&hook_api_hotpatch_jmp_direct,7},
/* HOOK_PUSH_RETN */{&hook_api_push_retn,6},
/* HOOK_NOP_PUSH_RETN */{&hook_api_nop_push_retn,7},
/* HOOK_JMP_INDIRECT */{&hook_api_jmp_indirect,6},
/* HOOK_MOV_EAX_JMP_EAX */{&hook_api_mov_eax_jmp_eax,7},
/* HOOK_MOV_EAX_PUSH_RETN */{&hook_api_mov_eax_push_retn,7},
/* HOOK_MOV_EAX_INDIRECT_JMP_EAX */
{&hook_api_mov_eax_indirect_jmp_eax,7},
/* HOOK_MOV_EAX_INDIRECT_PUSH_RETN */
{&hook_api_mov_eax_indirect_push_retn,7},
#if HOOK_ENABLE_FPU
/* HOOK_PUSH_FPU_RETN */{&hook_api_push_fpu_retn,11},
#endif
/* HOOK_SPECIAL_JMP */{&hook_api_special_jmp,7},
};
// is this address already hooked?
if(h->is_hooked!=0){
return0;
}
// resolve the address to hook
unsignedchar*addr=h->addr;
if(addr==NULL&&h->library!=NULL&&h->funcname!=NULL){
addr=(unsignedchar*)GetProcAddress(GetModuleHandleW(h->library),
h->funcname);
}
if(addr==NULL){
return-1;
}
intret=-1;
// check if this is a valid hook type
if(type>=0&&type<ARRAYSIZE(hook_types)){
// determine whether we're running under win7, if so, we might have to
// follow a short relative jmp and an indirect jump before reaching
// the real address
OSVERSIONINFO os_info={sizeof(OSVERSIONINFO)};
if(GetVersionEx(&os_info)&&os_info.dwMajorVersion==6&&
os_info.dwMinorVersion==1){
// windows 7 has a DLL called kernelbase.dll which basically acts
// as a layer between the program and kernel32 (and related?) it
// allows easy hotpatching of a set of functions which is why
// there's a short relative jump and an indirect jump. we want to
// resolve the address of the real function, so we follow these
// two jumps.
if(!memcmp(addr,"\xeb\x05",2)&&
!memcmp(addr+7,"\xff\x25",2)){
addr=**(unsignedchar***)(addr+9);
}
// the following applies for "inlined" functions on windows 7,
// some functions are inlined into kernelbase.dll, rather than
// kernelbase.dll jumping to e.g. kernel32.dll. for these
// functions there is a short relative jump, followed by the
// inlined function.
if(!memcmp(addr,"\xeb\x02",2)&&
!memcmp(addr-5,"\xcc\xcc\xcc\xcc\xcc",5)){
// step over the short jump and the relative offset
addr+=4;
}
}
DWORD old_protect;
// make the address writable
if(VirtualProtect(addr,hook_types[type].len,PAGE_EXECUTE_READWRITE,
&old_protect)){
if(hook_create_trampoline(addr,hook_types[type].len,h->tramp)){
hook_store_exception_info(h);
uint8_t special=0;
if(h->allow_hook_recursion==1){
special=1;
}
hook_create_pre_tramp(h,special);
// insert the hook (jump from the api to the
// pre-trampoline)
ret=hook_types[type].hook(h,addr,h->pre_tramp);
// if successful, assign the trampoline address to *old_func
if(ret==0){
*h->old_func=h->tramp;
// successful hook is successful
h->is_hooked=1;
}
}
// restore the old protection
VirtualProtect(addr,hook_types[type].len,old_protect,
&old_protect);
}
}
returnret;
}
|
4.躲避的应对
前面软件加壳技术介绍的时候有部分内容关于躲避。恶意软件会创建自进程,在子进程中做实际工作。对于类似Cuckoo这样的动态分析工具就要处理这种情况,在子进程中启动cuckoomon。下图就是应对流程,Monitor在监控到样本创建进程的时候,也会模拟初始化启动时候cuckoo做的事情,显示suspend,然后通知Analyzer。由后者进行DLL的注入。
From 【5】
前文也介绍过进程注入,也就是恶意软件利用周知进程,例如IE,运行自己的恶意逻辑,解决的方法类似。只是监控的不是CreateProcess而是OpenProcess。
【参考】
1.官方网站,http://www.cuckoosandbox.org/
2.Cuckoo Sandbox Book,http://cuckoo.readthedocs.org/en/latest/
3.Hooking functions with Cuckoobox’s hooking engine,http://living-security.blogspot.com/2014/07/hooking-functions-with-cuckooboxs.html
4.开源软件 cuckoo sandbox学习(二) 核心拦截模块源代码导读, http://sevemal.blog.51cto.com/8627322/1397666
5.Haow Sandbox, Cuckoo Sandbox Internal, http://recon.cx/2013/slides/recon2013-Jurriaan%20Bremer-Haow%20do%20I%20sandbox.pdf
软件沙箱技术 – 安全分析沙箱Cuckoo Sandbox相关推荐
- 面向对象软件度量技术的分析与综述----整理
目录 摘要...2 1 引言... 3 2 面向对象软件度量...4 2.1 面向对象的特征...4 2.2 面向对象软件度量方法...4 2.2.1 面向类的度量--CK度量集...5 2 ...
- 软件开发技术职位分析及职业规划
分析 虽然说每个行业都必须要时刻学习,但软件行业技术的可持续性与积累性较差.例如:中医越做越吃香,而多年前的诺基亚开发已被抛弃. 严重青春饭 社交圈很难往上走 连续不离散的无意义学习 上升通道受限于运 ...
- 什么是安全沙箱技术?如何评估应用程序安全性?
近年来,随着移动应用程序的普及和小程序技术的崛起,安全沙箱技术也逐渐受到了广泛的关注和应用,尤其是前端安全沙箱技术(桌面操作系统,浏览器,App,小程序等)快速实践和推进.它们都在不同程度上采用了封闭 ...
- 一文说透安全沙箱技术
在数字经济的东风中,数据安全至关重要.目前已经颁布了包括<数据安全法>.<个人信息保护法>和<数据安全管理办法>在内的国家政策,以促进整个数据要素的发展. 而近年来 ...
- 【多图超详细】从零开始安装配置Cuckoo sandbox并提交样本进行分析
[多图超详细]从零开始安装配置Cuckoo sandbox并提交样本进行分析 文章目录 [多图超详细]从零开始安装配置Cuckoo sandbox并提交样本进行分析 1. 功能介绍 1.1主要功能 1 ...
- Sandbox——沙箱技术,来自chromium开发文档
沙箱技术早在Windows2000的时候就已经出现了,但是因为大部分的人都不会接触到也没有机会应用这种技术,导致大部分的人根本就对这个没有印象.而在一本讲到沙箱技术的书上,上面的翻译是'沙框',当然这 ...
- 什么是“沙箱”技术?
jueee 2009-01-14 12:23:13 221.2.147.* 所谓的沙箱技术,其实就是Sandboxie,360仅仅是挂名,这项核心技术并不是360自主研发的.更加不是首创,因为Sand ...
- 恶意软件分析诀窍与工具箱——对抗“流氓”软件的技术与利器
为什么80%的码农都做不了架构师?>>> 基本信息 作者: (美)Michael Hale Ligh Steven Adair Blake Hartstein ...
- 什么是沙箱技术?与容器有什么区别
沙箱和容器的"隔离"机制 首先,什么是沙箱? 它本身就是一种线下生活现象的虚拟化.现实世界里,小孩子们在沙地.沙滩上用木板隔离出一个方盒子,在盒子里堆砌.创造各种东西 - 城堡.房 ...
- linux沙箱隔离_Linux沙箱技术介绍
在计算机安全领域,沙箱(Sandbox)是一种程序的隔离运行机制,其目的是限制不可信进程的权限.沙箱技术经常被用于执行未经测试的或不可信的客户程序.为了避免不可信程序可能破坏其它程序的运行,沙箱技术通 ...
最新文章
- .Net Remoting 1
- android入门学习一 基本概念
- boost::range模块reversed相关的测试程序
- laravel 重要概念 以及实现方式
- kafka控制台模拟消费_Kafka 详解
- postman使用_postman如何使用集合断言?
- 在oracle中处理日期大全
- 初学JAVA,javaoo小结
- stats | 线性回归(一)——模型表达式和输出结果
- matlab.什么意思,MATLAB是什么意思? matlab是什么软件?
- Java后台POST请求以application/x-www-form-urlencoded;charset=utf-8格式
- Hutool之类型转换类——Convert
- CEFSharp崩溃分析及解决办法
- 一个下载网页视频的方法
- java webservice 500_Webservice调用返回错误500
- 仿今日头条小程序搭建
- stm32 负数_stm32中编码器模式读出“负数”的问题
- 如何在2022年建立自己的NFT市场平台
- 用python画盒图_[519]matplotlib(四)|Python中用matplotlib绘制盒状图(Boxplots)和小提琴图(Violinplots)...
- 公有云 私有云 混合云
热门文章
- week15(字符串集合:Hash、字典树、KMP)
- php元换成万元,元换算万元(元换算成万元换算器)
- 【对数几率回归】matlab实现
- 如何画一个对话气泡框(css实现)
- Pyecharts 猎聘招聘数据可视化
- elementui 表格序号el-table自定义序号事件
- Swarm(bzz)主网于6月21日正式启动 ,BZZ币合约已部署?红利提前来了吗?
- 前端遇到GET https://XXXX net::ERR_HTTP2_PROTOCOL_ERROR 200问题的解决办法
- php页眉,phpword页眉页脚
- MySQL 清除表空间碎片