笔者目前是初学者,该文章的分析的每一步都是经过实践与参考他人分析报告而输出。
分析时间花了三个星期,文中如有错误,欢迎各位指正。
文件名称 :rdpscan.exe
文件大小 :85504 byte
文件类型 :PE32 executable for MS Windows (console) Intel 80386 32-bit
MD5:d0840aeb2642d718f325a07a4b7f6751
SHA1:ae77ca712670176650b01d30e6fe4801e90fafe2
SHA256:9966826ada8b1f366a9e7b9b1e7c430a2a49dda60eb7025c7481295e3ab7f9e4
文件名称 :ssleay32.dll
文件大小 :67416 byte
文件类型 :data
MD5:27b0374083f46693df15c0e3fffad070
SHA1:0eb87babebc32e526f6128fc4be3686c034c4185
SHA256:948e2def7339cf87071913148705bbba3cd9a8279c6157251036d6fac59983d5
拿到文件后,是个压缩包,进行解压后,发现如下文件。
有个exe文件,查下壳。
无壳,发现是VS2013编写的控制台程序。
rdpscan.exe 因为之前国内厂商已经检测,并且已经添加特征库,所以在线分析会被检测出。
https://www.virustotal.com/gui/file/9966826ada8b1f366a9e7b9b1e7c430a2a49dda60eb7025c7481295e3ab7f9e4/detection
得到的特征为木马后门
ssleay32.dll(shellcode) 由于关键信息数据已加密,静态分析时则无法检测。
https://www.virustotal.com/gui/file/948e2def7339cf87071913148705bbba3cd9a8279c6157251036d6fac59983d5/detection
微步云沙箱检测如下,结果是该文件为安全:
这与自己在本地虚拟机运行时一致,当第一次拿到样本时,当晚就在虚拟机里实际运行,直接提示缺失组件,无法成功运行。
因为后门编译为debug版本,没有找到对应的运行库,无法运行,导致沙箱无法对其进行恶意性行为检测。
https://s.threatbook.cn/report/file/0b5a6f745a47e2cb83c167e1f53f92db38f21e07a73f8600fc58dbc73cd927a7/?env=win7_sp1_enx64_office2013
如果要实际运行,本地需要安装VS2015以上版本后才会自带VC运行库。
直接在网上搜索VCRUNTIME140.dll缺失,会找到一些解决文章, 但是经过实践,都失败了,无法安装运行库。
最后只能退而求其次,安装了VS2015,因为会自带所需运行库。
附一个视频,安装VCRUNTIME140.dll。还未实验,不知道是否能行。
https://www.youtube.com/watch?v=AqxebQEFU64
该rdpscan扫描工具参考了之前网上公布的工具源码,所以按照之前网上的分析步骤,先去源项目的github查下源码。
https://github.com/robertdavidgraham/rdpscan/blob/master/src/main.c
经过仔细对比,在471-190行之间的代码被加入了一个判断,如果条件成立就跳转执行恶意代码。
sub_405040为触发函数,执行完后,如果返回值为0,则直接跳转。
逻辑是只要在命令行里正常输入IP地址后,一回车执行就会设置返回值为0。
接着来到LABEL_20进行分析
暂时没啥用,后面没发现出现。
CreateMutex函数的作用是找出当前系统是否已经存在指定进程的实例,如果没有则创建一个互斥体。
然后得到调用GetLastError得到的错误码,如果执行成功,就直接进入到如下部分:
sub_405940函数的作用是读取ssleay32.dll文件内容,放入之前创建的虚拟内存空间中,之后通过CreateThread新开线程执行,那可以猜测ssleay32.dll为需要执行的后门代码。
IDA打开ssleay32.dll看看
IDA静态分析与ollydbg动态分析时一致,
现在动态分析下,刚分析时需要下的断点
00405D73 |. FFD7 call edi ; kernel32.CreateThread
之后创建了新线程后,该线程就执行了ssleay32.dll内容。shellcode前面是通过FS寄存器找到kernel32.dll基址,之后找到
00C9F45C 75F11222 kernel32.GetProcAddress
00C9F454 75F148D7 kernel32.LoadLibraryA
00C9F450 75F11826 kernel32.VirtualAlloc
这三个函数地址,
此时的基址为0x01F20000,但偏移是不变的。
其中用到的混淆方法是通过kernel32.dll基址加偏移获取到API函数名称时,取出每个字符然后经过循环算术处理后最后与先前设定的硬编码的值进行比较,如果正确,那么此时就是需要使用到的API函数,避免了直接使用硬编码的API名称进行比较来获取到需要的API函数。
接着检测了这三个API函数是否存在软件断点(与0xCC进行比较),如果存在断点就直接跳转到01F3074E(此时的基址为0x01F20000,但偏移是不变的。)然后退出函数。
调用VirustualAlloc创建一段内存空间,并将一段硬编码的内容(加密的代码指令)复制进来,之后再从其余硬编码内容里复制一段内容作为解密时用到的密钥,最后复制进加密的字符串内容,等待后续解密使用。
之后根据密钥对已复制的内容进行解密,解密完毕后,对密钥部分进行清零。
从加密的字符串数据里,解密出KERNEL32.dll,调用LoadLibraryA加载。
之后从加密的字符内容里,解密出KERNEL32.dll里需要用到的API函数名称,调用GetProcAddress获取地址。
函数如下:
00C9F43C 00DB9C00 ASCII "HeapFree"
00C9F43C 00DB9C00 ASCII "InitializeCriticalSection"
00C9F428 00DB9C00 ASCII "LocalAlloc"
00C9F428 00DB9C00 ASCII "LocalFree"
00C9F428 00DB9C00 ASCII "SetUnhandledExceptionFilter"
00C9F428 00DB9C00 ASCII "TerminateThread"
00C9F428 00DB9C00 ASCII "GetCurrentThread"
00C9F428 00DB9C00 ASCII "GetCurrentProcessId"
00C9F428 00DB9C00 ASCII "CreateFileMappingA"
00C9F428 00DB9C00 ASCII "MapViewOfFile"
00C9F428 00DB9C00 ASCII "UnmapViewOfFile"
00C9F428 00DB9C00 ASCII "EnterCriticalSection"
00C9F428 00DB9C00 ASCII "LeaveCriticalSection"
...
00C9F43C 00DB9C00 ASCII "ExitProcess"
接着通过LoadLibraryA加载解密后的字符串USER32.dll
之后从加密的字符内容里,解密出USER32.dll里需要用到的API函数名称,调用GetProcAddress获取地址。
函数如下:
0211FB30 |02239C00 ASCII "GetForegroundWindow"
0211FB44 02239C00 ASCII "EnumChildWindows"
0211FB30 02239C00 ASCII "wsprintfA"
0211FB30 02239C00 ASCII "EnableWindow"
0211FB30 02239C00 ASCII "GetClassNameA"
接着通过LoadLibraryA加载解密后的字符串ADVAPI32.dll
之后从加密的字符内容里,解密出ADVAPI32.dll里需要用到的API函数名称,调用GetProcAddress获取地址。
函数如下:
0211FB30 02239C00 ASCII "RegCreateKeyExW"
0211FB44 02239C00 ASCII "RegQueryValueExW"
0211FB30 02239C00 ASCII "FreeSid"
0211FB44 02239C00 ASCII "SetSecurityDescriptorDacl"
0211FB30 02239C00 ASCII "InitializeSecurityDescriptor"
0211FB30 02239C00 ASCII "SetEntriesInAclW"
0211FB30 02239C00 ASCII "AllocateAndInitializeSid"
0211FB44 02239C00 ASCII "RegOpenKeyExW"
0211FB30 02239C00 ASCII "RegSetValueExW"
0211FB30 02239C00 ASCII "RegDeleteValueW"
0211FB30 02239C00 ASCII "RegNotifyChangeKeyValue"
0211FB30 02239C00 ASCII "RegEnumValueA"
0211FB30 02239C00 ASCII "RegCloseKey"
接着通过LoadLibraryA加载解密后的字符串WS2_32.dll
之后从加密的字符内容里,解密出WS2_32.dll里需要用到的API函数名称,调用GetProcAddress获取地址。
这是一个与网络操作相关的库,猜测有网络通信功能。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)