0x00 前言
经过了前面几节的静态分析,相信大家已经对静态分析已经有了比较深刻的理解。
应该可以比较熟练的阅读一些恶意代码中常见的汇编指令了。
在这一小节继续看一个新样本,尝试动静结合的方式来进行分析。
首先,样本还是上传到了app.any.run上:
样本hash:ae986dd436082fb9a7fec397c8b6e717
app.any.run地址:https://app.any.run/tasks/c5066e3d-974b-499a-971f-954dbf2d5c5d/
0x01 行为分析
将样本下载到本地之后,首先我们在虚拟机中将样本添加exe的后缀,发现样本的图标显示如下:
在本次行为分析中,我选择使用的是火绒剑
启动火绒剑之后,开启监控,然后选择进程过滤
将我们的进程名称添加进去
接着选择动作过滤,暂时不显示注册表操作:
接着运行该恶意样本,样本运行后,会弹出如下的对话框进行提示
该对话框告诉用户,啊我是杀毒软件ESET的更新程序,我现在更新完成了,你的电脑安全啦。
BUT,经验告诉我们,未知程序运行后的对话框、提示框啥的,一个标点符号都不要信。
本样本模仿了ESET杀软弹框,主要目的就是为了迷惑用户,让用户误以为启动的是一个干净的应用程序
除了伪装成杀软迷惑用户,恶意软件还尝尝会伪装成微软官方、office官方等权威机构进行提示以迷惑用户,在分析的时候需要注意此类提示信息。
此时,在火绒剑窗口中,已经显示本程序的所有行为:
蓝色部分很醒目,火绒剑自动标识出了三个可疑行为。
第一个是BA_extract_pe 根据缩写我们可以知道,这个动作表示释放PE文件。
结合上面的file_touch、file_open、file_write、file_chmod等操作,我们可以知道程序会在C:UsersxxxAppDataRoaming这个路径下释放一个名为eset_update.exe的PE文件。
第二个是BA_self_copy 表示自我复制
第三个是BA_register_autorun 表示应用程序通过注册表将自己写入了开机自启动。
我们可以在这个目录下找到对应的文件
顺便说一句,这个目录是一个系统环境变量路径,可以通过%appdata%访问到
除了文件相关的行为,我们继续往下看,还可以看到网络请求相关行为:
根据火绒剑和Fakenet的监控显示,本地主机(192.168.74.128:53)正在不断的向目标主机general-second.org-help.com发起请求。
这是一个非常关键的网络行为,general-second.org-help.com应该就是攻击者服务器的地址。
上次已经使用过了微步,这次我们使用奇安信的查询试试
通过奇安信的情报平台(https://ti.qianxin.com)对该地址进行查询:
可以看到,确实是恶意的C2地址,且被打上了很多标签
根据标签显示,该域名很有可能被APT组织KimSuky所使用,所以该样本,很有可能来源以APT组织KimSuky。
通过行为分析,我们已经可以基本确定样本的一个行为信息:
- 样本会将自身复制到%appdata%路径下并且重命名为eset_update.exe
- 样本会向general-second.org-help.com进行请求。
我们可以根据这些信息,在IDA中进行快速定位。
0x02 完整分析
行为分析之后,一般会通过IDA对样本进行一个整体的分析,毕竟在IDA中看代码,还是会比在调试器中看代码要快很多。
我们在IDA中对样本进行概要的标注之后,即可通过调试器对标注的地方进行快速的验证。
IDA分析的流程主要还是
- 导入表分析
- 字符串分析
- 代码分析(通常从Start函数或者WinMain开始)
导入表分析
使用IDA加载样本,然后切换到Imports窗口中:
导入表中一共有124个API函数,我这里圈出了一些可疑的API。
首先是Reg操作相关的API,恶意软件通常会通过注册表实现一系列的恶意操作,如设置开机自启动、获取一些计算机的基本信息。
除了注册表相关的API,还有CreateFile、GetFileSize、ReadFile等文件操作的API。
这里应该就是通过这些API实现文件的拷贝。
CreateProcessA通常用于创建新进程。
在最下面还有一系列用于网络请求的API
同样的,我们可以对觉得可疑的API双击跟进去,然后交叉引用查找调用位置。
比如我对InternetOpen进行交叉引用,一层一层往上找,最后可以发现通过WinMain函数中StartAddress的sub_401AA0调用,可以来到网络请求的地方。我们可以对sub_401AA0进行初步的标注:
我们可以对导入表中可疑的API进行交叉引用并标注上层、上上层、上上上层的调用位置。
使用同样的方法,对文件操作的API也进行交叉引用。
经过交叉引用发现,文件操作也在sub_401AA0函数中,说明sub_401AA0是一个大函数,等会会是我们分析的重点。
字符串分析
通过shift + f12打开字符串窗口
字符串表一共203个字符串,其中大部分看起来都比较正常。
在字符串表后半部分,可以看到如下与网络请求相关的信息。
以及重命名的文件名称:eset_updata.exe
我们可以对eset_update.exe进行交叉引用,最后确定在WinMain的sub_403600中进行了引用。
同时,我们可以尝试在字符串窗口中搜索我们先前看到的URL地址。但是没有结果,说明该地址是动态解密出来进行请求的。
字符串分析基本上也可以告一段落,接下来开始看代码。
WinMain分析
默认情况下,vc编译的应用程序入口点在WinMain函数。
通过IDA加载的时候,如果程序有WinMain,也会默认停留在该函数。
按下空格键将其转换为正常汇编代码显示
程序最开始会通过CreateMutex尝试创建一个名为<GoogleUpdate_01>的互斥体,接着通过GetLastError获取最后一次错误,这里如果获取到的值不是563h(十进制1379)则跳转到后面的loc_40336C继续执行,否则就退出WinMain,结束进程。
通过查询,我们可以得知GetLastError获取到1379表示本地组已经存在:
我猜这里是攻击者写错了,按道理来讲,这里会判断GetLastError的值是否等于ERROR_ALREADY_EXISTS
这里判断是否等于1379没有实际的意义,不能起到防多开的作用。
经过后来的测试也可以发现,该样本的确可以在本地主机进行多开。
跳转到loc_40336C之后,程序首先会执行call sub_4011E0。
sub_4011E0
进入到sub_4011E0,程序会先判断dword_41F924的值是否为0,如果等于0则跳转到loc_40120F继续执行,且这里我们可以看到,在下面0040121F的地方,程序通过mov dword_41F924,1的方式给dword_41F924赋值为1。所以我们可以知道这里是程序首次运行的时候才会执行的代码。
接着往下看,我们可以直接看下一个跳转的条件,这里是判断LoadLibraryA是否成功加载了制定的库文件。
库文件来源于[ebp+LibFileNmae]
而[ebp+LibFileNmae]在上面赋值给了edx,和ecx一起传到了sub_401040这个函数中。
我们看到ecx的值来源于后面的”NSNSJY3iqq”
所以我们可以猜测sub_401040是一个解密函数,会将后面这个参数解密之后存放到前面那个参数的地址中。
直接上调试器验证一下,我们在win7中使用x32dbg加载该程序。
程序加载之后,会默认停留在ntdll.dll模块中,也就是系统代码中,这里我们直接F9跑到程序的默认入口点
这个时候,神奇的事情出现了,在调试器中,程序默认停留在了003897F5
而不是我们在IDA中看到的winMain地址:00403340
这就是IDA的基地址和OD加载时候的基地址不对应造成的。
IDA加载的时候,会默认以00400000作为基地址,而调试器加载的时候,基地址由操作系统决定。
我们在最开始的时候说过,win7开始,微软增加了地址随机化的功能,所以基地址往往不是默认的00400000.
这个时候,我们就需要修改IDA的基地址显示,使得IDA中的地址可以和x32dbg对应起来。
我们在IDA中选择 Edit->Segments->Rebase Program
此时的基地址位00400000,我们修改为00380000以对应调试器中的基地址。
修改完成之后,IDA中程序的地址会自动改变,winMain地址已经变成了00383340
但是此时还是与调试器默认停留的地址不符合,我们在IDA中按G,跳转到调试器的地址看看:
程序来到了start函数,通常来说,vc编译器编译的程序,有winMain的情况下,start函数属于编译器生成的函数。
我们直接在x32dbg中Ctrl+G,跳转到winMain的入口点并按下F2设置断点:
断点设置成功之后,最前面会显示红色。
此时按下F9,程序就会跑过来,命中断点,停留在winMain函数开始的地方:
这个EIP表示程序当前运行的位置。
我们找到之前在IDA中分析到的加密函数,此时由于我们修改了基地址,该函数已经变成了sub_381040
地址是00381240,我们可以用同样的方法,Ctrl + G跳转过去并设置断点。
断点设置好之后F9运行过来,成功命中断点:
此时,我们可以看到,我们之前在IDA中看到的可疑字符串在ecx中,且edx的地址为:0021F9C4
按照我们之前的推算,该函数运行后会计算ecx的字符串,将解密结果放入到edx。
我们在左下角的内存窗口中按Ctrl + G ,跳转到0021F9C4,此时是空白内存:
F8往下走了之后,可以看到0021F9C4处的确存放了一个解密出来的值。WININET.dll
由此也证明了我们的推算是正确的,我们不必要去详细看sub_381040这个函数的具体实现,只需要知道它的功能是解密参数1,放入到参数2即可。我们回到IDA对调试得到的结果分别进行标注。首先是对sub_381040进行重命名,然后是对上面解密出来的字符串进行标注。
所以这里是判断是否能通过LoadLibrary成功加载WININET.dll。
如果可以成功加载,则跳转到loc_381279,跟到loc_381279之后发现,这下面一大片_memset赋值操作,然后调用了多次我们刚才看到解密函数解密字符串。
解密成功之后调用了多次GetProcAddress,说明这里解密的字符串很有可能是具体的API名称,我们也可以在调试器中进行验证。
我们注意到,这里第二次调用解密函数,是在003813E0这里,于是我们在调试器中对该地址设置断点并跑过来(也可以直接鼠标点中这个地址,然后F4运行过来)
根据我们之前的分析已经知道,调用这个函数的时候,会把ecx的值解密然后放入到edx中。
于是我们在下面的内存窗口中,Ctrl +G 输入 edx,直接跳转到当前edx所指向的地址,这里提示了是0021EF9C
然后我们F8单步执行完这个解密函数,可以看到edx所指的这个地址已经成功解密出了urlmon.dll
解密出urlmon.dll之后,同样的会通过call esi(这里esi存放的是LoadLibraryA的地址)来加载解密出的urlmod.dll
接着程序会来到003813FB这个地方,继续调用解密函数
调用完成之后同样的会将解密得到的字符串放入edx,这里是解密了一个InternetOpenA的API
且我们可以发现,edx的值都是通过[ebp – xxxx] 得到的,在内存窗口中,这些解密的地址值相差的也不远。
我们就直接F8单步往下走,尝试将这一大段的字符串都解密出来,在API和dll都解密成功之后,程序将分别尝试通过LoadLibrary和GetProcAddress来加载dll和获取指定API的地址。
这里同样是通过[ebp-xxxx]的方式来取到刚才解密出的API/dll名称。
来到程序最后,在00381577这里还有一个call,该call执行完之后,就会调用ret结束函数。
我们在IDA中按G键跳转到00381577这个地址,发现该函数调用的是@__security_check_cookie@4
这是编译器为了检查cookie的安全性而生成的,我们暂时可以不用看,直接F8单步过去。然后继续F8往下走,执行retn ,返回到上一层。
至此,我们就分析完了sub_3811E0(修改基地址之前是sub_4011E0)的功能,我们可以回到IDA中对其进行标注。
我们可以看到,sub_3811E0调用完成之后,会通过test eax,eax判断eax的值是否为0,如果eax为0 则跳转到loc_3833BD,跳转过来之后结束winMain的运行。
很明显,eax是不为0的,因为我们在代码中可以看到,sub_3811E0函数的最后,通过mov eax,1的方式给eax赋值为了1,所以此时eax等于1.
eax等于1,那么程序就会连着执行四个call,分别是sub_383600、sub_381580、sub_381770、sub_382790。
我们先跟进到sub_383600。
sub_383600
IDA中双击进入到函数,熟悉的_memset内存分配
然后通过call SHGetFolderPathA获取系统路径,具体获取的值由参数决定。
通过对SHGetFolderPathA的文档查询我们可以知道,该API会根据CSIDL的值来获取不同的路径。
而在本程序中,CSIDL的值是:1Ah,也就是16+10=26
通过IDA最下面的python输入框或计算器都可以很好的进行进制转换,比如在python输入框中输入int(0x1A),即会输出对应的十进制数据。
所以话说回来,我们可以去搜索一下SHGetFolderPathA的CSIDL为26时会获取到哪个路径。
答案就是我们在行为分析中看到的%appdata%路径。
SHGetFolderPathA调用完成之后,程序会调用GetModuleFileNameA以获取当前进程的完整路径,GetModuleFileNameA这个API我们遇到过多次了,这里不再重复讲解。
并且在GetModuleFileNameA调用之后,程序push了三个参数到sub_383320函数。
其中第一个是[ebp + pszPath] ,也就是SHGetFolderPath函数获取到的路径。
第二个参数是aSEsetUpdateExe,IDA已经自动识别出来是%seset_update.exe
第三个参数是[ebp+NewFileName]
这里第二个参数前面的%s比较关键,基本可以推测sub_383320用于将push的第一个参数和第二个参数拼接起来放到第三个参数,也就是[ebp+NewFileName]。这里为什么不猜测sub_383320用于将应用程序拷贝到%appdata%路径并且重命名为eset_update.exe。 是因为我们可以看到GetModuleFileNameA获取到的路径会存放在[ebp+Filename]中,而在调用sub_383320的时候,并没有将[ebp+Filename]作为参数传入,所以sub_383320的功能应该是路径拼接:
跟进到sub_383320之后,发现和我们推算的一致,程序会通过_vsprintf_s进行拼接。
在sub_383320调用完成之后,[ebp+NewFileName]将会存放 %appdata%eset_update.exe
路径拼接之后,程序会通过lea指令,分别将ebp+Filename和ebp+NewFileName赋值给ecx和eax,在后面可以看到,程序会循环对比eax和ecx的值,检查是否匹配,如果匹配,则说明当前程序运行的路径就是%appdata%eset_update.exe。
如果不匹配程序则会在003836D4这里通过jzn short loc_3836F0 跳转到后面继续执行。
跳转过来之后程序会通过sbb 错位运算和 | 1 的运算操作eax。
注意看,此时的eax还是上面的的存放的新路径的值。
这里应该是用于判断拼接的新路径是否成功,如果成功则后面的test eax,eax不为0
计算通过之后,将[ebp+NewFileName]和 [ebp+Filename]作为参数传入到CopyFileA函数中
很明显,这里是准备将程序拷贝过去了
执行拷贝函数之后,程序会尝试将密文XTKYFWJaRnhwtxtkyansit|xaHzwwjsy[jw通过ReName_DecodeSrings函数解密存放到[ebp+SubKey]并且通过下面的RegOpenKeyExA操作该键值。
我们直接在调试器中鼠标点在0038371E这里,F4运行过来,然后在下面的内存窗口中跟随edx
F8单步执行完该函数之后,edx(0054F48C)处的地址成功被赋值为SOFTWAREMicrosoftWindowsCurrentVersionRun
这个键值已经不陌生了,该键值用于操作开机自启动项。
解密成功之后,程序会通过call RegOpenKeyEx打开该键值,如果打开失败则跳转到loc_383782,如果打开成功则继续往后执行。
成功打开的话,程序会将[ebp+NewFileName]的值赋值给ecx,然后通过一个短循环读取ecx到al。
循环读取完成之后,程序就会将[ebp+NewFileName]作为路径写入到上面的注册表键值中以建立一个开机自启动项目。写入的键值名称是后面的eset_update。
写入成功之后通过RegCloseKey关闭注册表。
我们在调试器中在0038377C设置断点并运行过来,然后F8单步往下走一步
此时,我们在注册表编辑器中打开SOFTWAREMicrosoftWindowsCurrentVersionRun,查看是否成功设置,Win+R打开运行窗口,然后输入regedit
一层一层找下来,可以看到已经成写入了开机自启动的注册表中。
成功设置好开机自启动之后,程序会调用GetModuleHandleA和MessageBoxIndirectA以创建一个消息提示框,提示框的标题和显示内容如红框所示,跟我们在行为分析中看到的一样。
成功创建后,该函数结束。
所以该函数的功能是将自身赋值到%appdata%目录下并重命名为eset_update.exe,然后将该路径写入到开机自启动中,键名称为eset_update。最后创建一个对话框以迷惑用户。
我们回到该函数头部,交叉引用回到WinMain函数中并对该函数进行标注:
sub_381580
现在来看第二个函数sub_381580:
在sub_381580函数最开始,程序会通过GetAdaptersInfo来获取当前计算机的网卡信息。
如果获取失败,则跳转到loc_3816E8执行
在loc_3816E8处则会调用GetVolumeInformationA获取磁盘序列号。这里是获取C盘。
成功获取之后,还会调用GetTickCount获取时间以生成一个随机数。
随机数生成成功,存放到esi中,传到后面的_sprintf_s与DstBuf(上面获取网卡存储的地址)进行格式化。
所以sub_381580的功能很简单,就是获取网卡和硬盘信息并与随机数拼接。
sub_381770
00381770函数一进来就可以看到程序在通过GetVersion和GetNativeSystemInfo获取计算机的操作系统版本和位数。
同样的,将获取到的信息格式化成新的字符串:
最后传入到sub_381950做运算,函数结束。
所以sub_381580和sub_381770都是用于获取操作系统的一些基本信息
现在只剩下sub_382790
sub_382790
sub_382790进来之后,可以看到程序调用ReName_DecodeSrings解密了两个字符串,然后调用了RegOpenKeyEx
我们还是直接在003827E5这里设置断点,运行过来,然后在内存窗口中跟随edx,F8执行之后,解密得到ScreenRibbonsDomain
继续F8单步往下走,解密第二个字符串得到:
SOFTWAREMicrosoftWindowsCurrentVersionScreensavers
通过查询资料可得知,SOFTWAREMicrosoftWindowsCurrentVersionScreensavers跟Windows操作系统的屏保相关。目前还不知道攻击者设置键值到这里做什么。
所以在这里我们可以在调试器里接着往后走,然后看到如下的内容:
这个请求地址,就是我们最开始在行为分析里面看到的地址,看来攻击者尝试将改地址写入到注册表地址中,不知道是为了后面方便取C2地址还是有其他高级的操作,要继续往后看才知道。
我们可以在IDA中找到对应的地址:0038286D:
我们双击来到qword_39A620:
点在绿色的十六进制数据上,按下R键:
这里是倒序显示的
反过来刚好就是
general-second.org-help.com
我们在qword_39A620上交叉引用,回到调用的地方,接着看接下来会干什么:
成功赋值之后,会将域名赋值给xmm0,然后赋值给szServerName。
接着通过RegOpenKeyEx打开之前打开过的SOFTWAREMicrosoftWindowsCurrentVersionScreensavers
在最下面,通过RegSetValueEx的方式,将szServerName写入到键值中。
我们在调试器中单步往下走,走到设置注册表键值的地方:
我们单步往下走,执行完成该函数,然后查看该注册表键值:
于是sub_382790的功能我们也搞清楚了,我们回到WinMain中对其进行标注。
这里可以看到,四个函数执行完之后,程序会将szServerName赋值给ecx,然后ecx传入到下面进行操作。此时ecx存放的就是C2地址。
首先一个一个小循环来判断ecx是否有值,然后通过CreateThread创建了一个新线程。新线程地址在StartAddress。
到这里,原始WinMain函数分析完毕,接下来的功能将会在新线程中执行。
新线程分析
StartAddress开始的地方,就给[ebp+SubStr] 赋值了word 39A72C的内容
我们这里并不能直接看出来复制的数据是什么,可以在调试器中设置断点跑过来,可以看到是rn
跳转过来之后,程序通过_memset给[ebp+Str]赋值,然后作为参数传递到了sub_382F30中
且我们可以看到,sub_382F30调用完成之后,会检查eax(返回值)是否为1,如果不等于1,则跳转到loc_3835DB
在loc_3835DB处休眠1分钟,然后又通过jmp跳转到上面loc_383410执行。说明此处是一个大循环。
我们回到sub_382F30的调用处,先通过调试器在此上设置断点,看看参数到底是什么。
通过调试器我们可以看到,此时eax指向0252F7DC,是一片空内存。
由于这样直接看不出什么,我们还是在IDA中跟进到sub_382F30:sub_382F30开头的部分是一堆赋值操作,在00382FA5的地方,可以看到一个硬编码的请求头部:Mozilla/5.0 (Windows NT 10.0; Win64; x64….
继续往下看,程序将dl_ex1.png赋值给了al,然后通过al不断的进行循环操作
一大堆循环操作完成之后,程序会call dword_xxxx
在IDA中查看这些地址,是无数据的,所以很明显,上面的循环会解密数据到这些地方,然后在后面通过call指令调用。
所以我们可以直接在调试器中F7进入到这个函数,单步往下走,看看情况。
将鼠标点到00382FE0(dl_ex1.png赋值的地方)这一行,然后F4跑过来,F8往下单步执行:
这里红色表示会跳转上去,我们直接点到下一行的位置(00382FF4),然后F4跑完该循环,接着继续单步往下走,遇到循环就通过F4的方式跑完这个循环,直到在00383068这一行看到call 381770
381770我们之前分析过,是获取网卡和磁盘信息的函数,所以这里不用再F7跟进进去,直接F8单步执行完该函数。
同样的,这里通过循环处理381770的返回值,我们F4跑完循环,继续F8.
在003830B7的地方看到了call InternetOpen
我们在IDA中按G跳转到003830B7,就是我们刚才看到的call dwrd_xxxx
回到调试器中,往下滑动,发现这几个dword都已经成功解密出了对应的API。
程序通过一系列API对指定的general-second.org-help.com发起网络请求。
请求方式为GET ,参数为:dl_ex1.png?m=9AC9AA87&NOTE=Ni4xIDogOS45fDV8djEuMAo=
这里参数的值就是先前手机到的磁盘信息和网卡信息组合的base64编码。
如果数据成功通过HttpSendRequest发送成功,程序则还会调用InertnetReadFile读取数据
如果发送失败,则会通过jmp跳转到最后关闭网络请求,退出函数。
这里肯定是访问失败的,我们可以手动修改jzn为jz,使得请求失败也会跳转过去。
跳转过来之后,发现程序还会在00383188处call call 0x388268
我们在IDA里面看一下00383188所对应的的call是什么内容
这里发现是_malloc用于开辟内存,所以我们就不用F7跟进到这个函数了,直接F8运行过,这里可以看到,如果InternetReadFile读取成功,则会跳转下去循环解密,如果读取失败则通过jmp跳转到最后关闭请求句柄,结束函数
至此,sub_382F30函数功能分析完毕,我们回到StartAddress对sub_382F30进行标注:
按道理来说,sub_382F30执行完成之后,会将[ebp+Str]赋值,然后下面将[ebp+Str]作为参数调用sub_381890。
在sub_381890函数中,是标准的base64解码函数:
所以我们这里也可以对sub_381890进行标注。
sub_381890调用结束之后,按道理来讲,读取回来的数据会经过base64解码存放到[ebp+String]
从图中可以看到,sub_381890之后会通过lstrlenA以及MultiByteToWideChar实现Unicode与UTF8相互转化。
计算完之后,又是一大堆循环计算,最后调用sub_381AA0
sub_381AA0
首先是通过_memset给变量赋值
然后通过SHGetFolderPathA获取环境变量路径,并且对wzsiqq873j}j进行解密。
由于上面的判定条件在运行的时候会失败,所以此时直接在调试器中对这个地址下断点是过不来的。
我们可以胆子大点,直接在调试器中CTRL+G跳转到00381AA0的首地址(就是00381AA0)
然后右键,选择设置新的运行点。
然后EIP就会设置到381AA0处了
此时我们直接跳转到解密函数调用的地方然后F4跑过来:
执行之后edx就被成功赋值:
这里解密了一个rundll32.exe 说明程序后面可能会下载一个dll文件到本地,然后通过rundll32.exe调用启动dll。
接着解密了一个路径:%temp%tmp.LOG,暂时不知道该文件用于干什么,反正不是从服务器下载文件保存到这里就是收集本地数据保存到这里然后上传。
回到IDA中接着往后看,样本会将传进来的参数通过 | 分割,然后比较分割后的字符串是否有tiger标志。
如果包含了tiger标志,则通过cmd执行指令,这里的指令是服务器下发的。
这里很明显,到了样本的远控模块了。
除了tiger,在后面的代码中我们还能看到一些其他动物的标志,如wolf、snake、bear、monkey等。至此,我们基本已经将这个样本的功能分析完成,该样本属于KimSuky的远控木马,下发的远控指令为一些动物名称。由于目前服务器已经无法响应,不能正常返回数据了,我们分析到这里,该木马基本可以告一段落。
如果对后面远控指令这部分代码有兴趣,也可以继续对每个指令进行深入分析。
0x03 总结
本次分析的样本其实难度并不大,但是篇幅却比较长,但是相信现在大家对汇编指令都比较熟悉了。
由于篇幅较长,关于该样本的一些补充知识,将放在下一篇的开头讲解,在下一节的内容中,也将跳过讲解一些基础的汇编代码,看看如何更快的去分析恶意样本。
发表评论
您还未登录,请先登录。
登录