DecoyMini 技术交流社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4803|回复: 2

[样本分析] [0 DAY IN {REA_TEAM}] 快速分析 Cobalt Strike 加载器和 ShellCode

[复制链接]

172

主题

34

回帖

30

荣誉

Rank: 9Rank: 9Rank: 9

UID
2
积分
339
精华
1
沃币
2 枚
注册时间
2021-6-24

论坛管理

发表于 2021-9-8 15:56:50 | 显示全部楼层 |阅读模式

我在 malwareresearchgroup.slack.com 上发现一个样本,为 CS 加载器,样本哈希值为 2569cc660d2ae0102aa74c98d78bb9409ded24101a0eeec15af29d59917265f3,2021-09-01 19:47:50 被人上传到 VT 上,其中有 37 家检测引擎把它标记为恶意,如下所示:



一、分析加载器

这个加载器是 64 位的 Dll 文件,MinGW 编译,有一个导出函数:



在 IDA 下,ServiceMain 函数将生成一个新线程 (我将其重命名为 f_spawn_shellcode_thread),如下所示:



f_spawn_shellcode_thread 函数干以下几件事:

  • [1] 初始化 xor_key 的值为 jKfXmEkWYshKkZdPhJYS
  • [2] 分配用于存储加密 ShellCode 的堆缓冲区,值为最开始声明的的全局字节数组;
  • [3] 进入解密 ShellCode 循环;
  • [4] 在新线程中解密 ShellCode;



我编写了一简短脚本来提取 ShellCode,以供后面分析:

[pre]
import sys
import pefile

xor_key = "jKfXmEkWYshKkZdPhJYS"

def decode_sc(data, key):
    key_len = len(key)
    data_len = len(data)
    decrypted = bytearray(data_len)

    for i in range(0, data_len):
        decrypted = data ^ key[i%key_len]
         
    print("Decode Done!")
    return decrypted

def extract_sc(input_file):
    encrypted_sc = []
    try:
        print("\r\nFile: " + input_file)
        pe = pefile.PE(input_file)

        for section in pe.sections:
            if b'.rdata\x00\x00' in section.Name:
                rdata_section = bytearray(section.get_data())
         
        size = 0      
        for i in rdata_section:
            if rdata_section[size] == 0x00 and rdata_section[size+1] == 0x00:
                break
            else:
                size += 1
        print("Encrypted bytes size: " + str(size - 24) + " bytes")

        encrypted_bytes = rdata_section[24:size+1]
        for i in range(len(encrypted_bytes)):
            if ((i & 1) == 0):
                encrypted_sc.append(encrypted_bytes)

        key = xor_key.encode('ascii')
        decrypted_sc = decode_sc(encrypted_sc, key)

        with open(sys.argv[1]+"-decrypted", "wb") as out_file:
            out_file.write(decrypted_sc)
        print("Shellcode extracted at " + sys.argv[1]+"-decrypted!\r\n")        

        print("Extract Shellcode Done!")
    except Exception as e:
        print("Error: " + str(e))

if __name__ == '__main__':
    if len(sys.argv) == 2:
        extract_sc(sys.argv[1])
    else:
        print("Usage: cobalt_extract_sc.py <cobalt_loader_dll>")
[/pre]
跑完脚本后,得到的 ShellCode 如下所示:



二、分析 ShellCode

如果我们将原始 ShellCode 加载到 IDA 中并转换为 asm 代码,它将如下图所示。在这段代码的第一个开头,我们可以看到定位 PEB 结构的代码。这让我想到它会使用 PEB 最终来查找 API 的地址。



进入 sub_D2,第一条语句将返回地址分配给 rbp 寄存器。我们知道这个地址是 0xA (push r9),然后我们看到字符串值 wininet 被加载到 0xD5 处的 r14 寄存器。我们看到一个值被分配给 r10 (726774Ch; 726774Ch) 寄存器,接下来是对 rbp 寄存器指向的地址的调用。我认为这些哈希值是与 api 函数相关,ShellCode 会进行计算并与这些值进行比较,从中获取相关的 API 地址。



为了便于分析和调试,我把 ShellCode 转成 exe,最后得到以下与通过 jmp rax 命令查找 API 函数地址和调用 API 相关的伪代码:



根据上面的伪代码,我们可以看到 ShellCode 会计算两个哈希值,第一个值基于 Dll 的名称,第二个值基于该 Dll 的 API 函数的名称,将这两个值加在一起并与预先计算的哈希值进行比较。

你可以编写脚本来恢复 API 函数,我总是使用 FLARE Teamshellcode_hashes_search_plugin.py。 详细信息可以在 这篇文章 中找到。 使用插件后的最终结果:

[pre]
shellcode_hash: Starting up
[INFO] Starting up  (shellcode_hash_search:run)
shellcode_hash: Processing current segment only: 0x140001000 - 0x140003000
[INFO] Processing current segment only: 0x140001000 - 0x140003000   (shellcode_hash_search:processCode)
shellcode_hash: 0x1400020e7: ror13AddHash32AddDll:0x0726774c kernel32.dll!LoadLibraryA
[INFO] 0x1400020e7: ror13AddHash32AddDll:0x0726774c kernel32.dll!LoadLibraryA   (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x1400020ff: ror13AddHash32AddDll:0xa779563a wininet.dll!InternetOpenA
[INFO] 0x1400020ff: ror13AddHash32AddDll:0xa779563a wininet.dll!InternetOpenA   (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x140002121: ror13AddHash32AddDll:0xc69f8957 wininet.dll!InternetConnectA
[INFO] 0x140002121: ror13AddHash32AddDll:0xc69f8957 wininet.dll!InternetConnectA    (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x140002140: ror13AddHash32AddDll:0x3b2e55eb wininet.dll!HttpOpenRequestA
[INFO] 0x140002140: ror13AddHash32AddDll:0x3b2e55eb wininet.dll!HttpOpenRequestA    (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x14000216a: ror13AddHash32AddDll:0x869e4675 wininet.dll!InternetSetOptionA
[INFO] 0x14000216a: ror13AddHash32AddDll:0x869e4675 wininet.dll!InternetSetOptionA  (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x140002184: ror13AddHash32AddDll:0x7b18062d wininet.dll!HttpSendRequestA
[INFO] 0x140002184: ror13AddHash32AddDll:0x7b18062d wininet.dll!HttpSendRequestA    (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x140002329: ror13AddHash32AddDll:0x56a2b5f0 kernel32.dll!ExitProcess
[INFO] 0x140002329: ror13AddHash32AddDll:0x56a2b5f0 kernel32.dll!ExitProcess    (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x140002345: ror13AddHash32AddDll:0xe553a458 kernel32.dll!VirtualAlloc
[INFO] 0x140002345: ror13AddHash32AddDll:0xe553a458 kernel32.dll!VirtualAlloc   (shellcode_hash_search:lookForOpArgs)
shellcode_hash: 0x140002363: ror13AddHash32AddDll:0xe2899612 wininet.dll!InternetReadFile
[INFO] 0x140002363: ror13AddHash32AddDll:0xe2899612 wininet.dll!InternetReadFile    (shellcode_hash_search:lookForOpArgs)
shellcode_hash: Done
[INFO] Done (shellcode_hash_search:run)
[/pre]


此时可以进行调试以进行进一步的分析,但是,我很快使用 hasherezade 的 tiny_tracer 工具来跟踪 ShellCode:





样本解压密码:
游客,如果您要查看本帖隐藏内容请回复


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

0

主题

1

回帖

0

荣誉

Rank: 1

UID
181
积分
0
精华
0
沃币
0 枚
注册时间
2021-9-23
发表于 2021-9-23 22:51:00 来自手机 | 显示全部楼层
解压密码?
回复

使用道具 举报

0

主题

1

回帖

0

荣誉

Rank: 1

UID
192
积分
0
精华
0
沃币
0 枚
注册时间
2021-9-29
发表于 2021-9-29 11:17:35 | 显示全部楼层
解压密码?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

Archiver|小黑屋|DecoyMini 技术交流社区 ( 京ICP备2021005070号 )

GMT+8, 2024-5-2 09:18 , Processed in 0.062471 second(s), 27 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表