一例cobalt Strike 反射式注入payload的分析

news2024/11/26 4:53:57

一例cobalt Strike payload 反射式dll注入的分析

QakBot(Qbot)与cobalt Strike恶意流量样本分析 | Demon (ggsec.cn)这篇博客中末尾提到了一个cobastrick的payload,这是一段shellcode,主要功能是的解密出一个dll,采用反射式注入的方式启动这个dll。本文主要是分析这段payload,有助于理解reflectiveinject的原理。

反射式注入 reflectiveInject的介绍可参考 反射式dll注入(ReflectiveDLLInjection)_随心动,随风行的博客-CSDN博客_reflectivedllinjection
github上有相应的实现
https://github.com/stephenfewer/ReflectiveDLLInjection

样本信息

MD5: 7c01dd99cee0668afc9b32308b8132f5
SHA1: dd1d89906e903caab123586f9b3369326200aeef
SHA256: 09ffa300c2343d68f7c9cc1a7e8f136c5c99cabd5e69a7326efabfece7aff59d
SHA512: dec9e255cb79c13e40539a024e2ffc290249810f7d51a418e62bf60a37d4cbf546e4662f4559c78a4832e637f71a91cbffbbb5042ba3823e24532c334c8a37ef
CRC32: 124f37e5

分析环境

  • win7 x64 虚拟机

  • IDA Pro6.8

  • OD

  • vs2010

静态分析

对样本进行进行静态分析,主要功能是在内存中解密并执行一段shellcode,将跳转执行,如下图所示
在这里插入图片描述

由上面的分析可知,加密的shellcode大小为0x00033000,在文件中的偏移为0x42,基于上图中的分析,可对这段shellcode进行解密。下面是提取并解密shellcode的代码

#include <stdio.h>
#include <windows.h>

int main(int argc,char** argv){

    FILE* file  = fopen("shellcode.bin","rb");
    DWORD sc_size = 0x00033000;
    DWORD offset = 0x42;
    fseek(file,offset,SEEK_SET);
    char* buf = (char*)malloc(sc_size);
    memset(buf,0,sc_size);

    size_t readbytes = 0;
    while(readbytes < sc_size){
        size_t r = fread(buf + readbytes,1,sc_size-readbytes,file);
        if(r < 0) break;
        readbytes += r;
    }
    fclose(file);

    if (sc_size == readbytes){

        //解密
        DWORD key = 0x04DBA13B;
        DWORD *_buf = (DWORD*)buf;
        DWORD _sc_size = sc_size / sizeof(DWORD);
        for(int i = 0;i< _sc_size;i++){
            _buf[i] ^= key;
            key ^= _buf[i];
        }

        //导出
        FILE* outfile = fopen("shellcode1.bin","wb");
        fwrite(buf,1,sc_size,outfile);
        fclose(outfile);
    }

    free(buf);
    return 0;
}

下面对shellcode1.bin进行分析,这个文件比较特殊的地方是即是一段shellcode,又是一个合法的dll,先使用IDA用binary file模式打开

在这里插入图片描述

进入了sub_8157看一下

上面是以binary方式打开的,下面以pe形式打开定位到这个函数。

0x8157是文件偏移,我们需要转化成VA,使用LordPE的位置计算机计算出VA为0x10008D57

在这里插入图片描述

用OD使用pe模式打开shellcode1.bin,定位到函数 0x10008D57,发现这是dll的一个导出函数,函数名为ReflectiveLoader,功能为一个以shellcode的方式来加加载dll。
在这里插入图片描述

下面我们来分析一个这个函数
首先找到PE的起始位置
在这里插入图片描述

下面这段是shellcode的通用操作,通过PEB找到kernel32.dll在内存中的基址,可参考[原创]PEB结构:获取模块kernel32基址技术及原理分析-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com

LDR_DATA_TABLE_ENTRY 结构体可参考Vergilius Project | _LDR_DATA_TABLE_ENTRY

在这里插入图片描述

从kernerl32.dll的导出表中找到下列几个api的地址

LoadLibraryA 
GetProcAddress 
VirtualAlloc 
VirtualProtect 
LoadLibraryExA 
GetModuleHandleA

在这里插入图片描述

下面这段代码复现了上面通过PEB获取api地址的过程,并导出api的hash表

#include <stdio.h>
#include <windows.h>
#include <winternl.h> 

//计算哈希值
#define ROTR32(value, shift)    (((DWORD) value >> (BYTE) shift) | ((DWORD) value << (32 - (BYTE) shift)))

//重新定义PEB结构。winternl.h中的结构定义是不完整的。
typedef struct _MY_PEB_LDR_DATA {
    ULONG Length;
    BOOL Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
} MY_PEB_LDR_DATA, *PMY_PEB_LDR_DATA;

typedef struct _MY_LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
} MY_LDR_DATA_TABLE_ENTRY, *PMY_LDR_DATA_TABLE_ENTRY;



#define ROTR32(value, shift)    (((DWORD) value >> (BYTE) shift) | ((DWORD) val
ue << (32 - (BYTE) shift)))
//导出api的hash值
void ExportProcAddressHash()
{
    PPEB PebAddress;
    PMY_PEB_LDR_DATA pLdr;
    PMY_LDR_DATA_TABLE_ENTRY pDataTableEntry;
    PVOID pModuleBase;
    PIMAGE_NT_HEADERS pNTHeader;
    DWORD dwExportDirRVA;
    PIMAGE_EXPORT_DIRECTORY pExportDir;
    PLIST_ENTRY pNextModule;
    DWORD dwNumFunctions;
    USHORT usOrdinalTableIndex;
    PDWORD pdwFunctionNameBase;
    PCSTR pFunctionName;
    UNICODE_STRING BaseDllName;
    DWORD dwModuleHash;
    DWORD dwFunctionHash;
    PCSTR pTempChar;

    PebAddress = (PPEB)__readfsdword(0x30);
    pLdr = (PMY_PEB_LDR_DATA)PebAddress->Ldr;
    pNextModule = pLdr->InLoadOrderModuleList.Flink;
    pDataTableEntry = (PMY_LDR_DATA_TABLE_ENTRY)pNextModule;



    while (pDataTableEntry->DllBase != NULL)
    {
        dwModuleHash = 0;
        pModuleBase = pDataTableEntry->DllBase;
        BaseDllName = pDataTableEntry->BaseDllName;
        pNTHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)pModuleBase + ((PIMAGE_DOS_HEADER)pModuleBase)->e_lfanew);
        dwExportDirRVA = pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress;
        //获取下一个模块地址
        pDataTableEntry = (PMY_LDR_DATA_TABLE_ENTRY)pDataTableEntry->InLoadOrderLinks.Flink;


        // 如果当前模块不导出任何函数,则转到下一个模块 加载模块入口
        if (dwExportDirRVA == 0)
        {
            continue;
        }


        //计算dll名的哈希值
        for (int i = 0; i < BaseDllName.Length; i++)
        {
            pTempChar = ((PCSTR)BaseDllName.Buffer + i);
            dwModuleHash = ROTR32(dwModuleHash, 13);

            if (*pTempChar >= 0x61)
            {
                dwModuleHash += *pTempChar - 0x20;
            }
            else
            {
                dwModuleHash += *pTempChar;
            }
        }




        pExportDir = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)pModuleBase + dwExportDirRVA);

        dwNumFunctions = pExportDir->NumberOfNames;
        pdwFunctionNameBase = (PDWORD)((PCHAR)pModuleBase + pExportDir->AddressOfNames);

        for (int i = 0; i < dwNumFunctions; i++)
        {
            dwFunctionHash = 0;
            pFunctionName = (PCSTR)(*pdwFunctionNameBase + (ULONG_PTR)pModuleBase);
            pdwFunctionNameBase++;

            pTempChar = pFunctionName;
            //计算函数名称的hash
            do
            {
                dwFunctionHash = ROTR32(dwFunctionHash, 13);
                dwFunctionHash += *pTempChar;
                pTempChar++;
            } while (*pTempChar);

            printf("%ws 0x%.8X %s 0x%.8X\n",BaseDllName.Buffer,dwModuleHash,pFunctionName,dwFunctionHash);

        }




    }

}

导出的结果如下图所示,得到的hash与样本分析的一致。

在这里插入图片描述

使用VirtualAlloc分配一段内存

在这里插入图片描述

拷贝PE头部到分配的内存

在这里插入图片描述

根据节表将各个节拷贝到内存相应位置
在这里插入图片描述

根据导入表,加载相应的动态库,更新IAT,页面还有解密dll名称和函数名称的操作

在这里插入图片描述

地址重定位

在这里插入图片描述

将.text节属性修改为可执行,定位dll的入口点,执行DllMain(selfHanlde,DLL_PROCESS_ATTCH,.),最后返回DllEntryPoint的地址
在这里插入图片描述

在汇编语言中如何获取当前指令的地址,可以用这种方法,在这个样本中,两次用到了这个技术。

call    $+5    ;将当前指令的下一条指令的地址入栈
pop     eax    ;将栈顶的值给eax,获取当前指令的地址

动态分析

因为样本是一段shellcode,无法自己运行,需要加载,手动完成一个shellcode加载器,开发环境是vs2010,代码如下 :

#include <stdio.h>
#include <windows.h>

int LoadShellCode(int argc,char** argv){
    //打开shellcode文件 
    FILE* file = fopen("shellcode.bin","rb");

    //读取文件大小
    fseek(file,0,SEEK_END);
    size_t filesize = ftell(file);
    rewind(file);

    //分配内存,注意页面属性为PAGE_EXECUTE_READWRITE
    char* buf  = (char*)VirtualAlloc(NULL,filesize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    memset(buf,0,filesize);

    //读取文件内容
    size_t readbytes = 0;
    while(readbytes < filesize){
        size_t r = fread(buf + readbytes,1,filesize-readbytes,file);
        if(r < 0) break;
        readbytes += r;
    }

    //跳转到shellcode起始位置执行
    if(readbytes == filesize){
        _asm{
            jmp buf
        }
    }

    //关闭文件,释放内存
    fclose(file);
    VirtualFree(buf,0,MEM_RELEASE);
    return 0;
}

编译生成LoadShellcode.exe,使用IDA打开,找到上面jmp buf语句的VA为0x004114DA

在这里插入图片描述

使用OD调试LoadShellcode.exe,在0x004114DA处中断

在这里插入图片描述

F7单步进入shellcode,用IDA以binary模式打开shellcode.bin文件,反汇编后的代码与OD中的一致,说明已经成功的跳转到shellcode的起始位置

在这里插入图片描述

解密出来一个PE文件,地址为0x00230042 大小为0x00033000

在这里插入图片描述

使用pchunter将这个PE导出来

在这里插入图片描述

其实这个dll是一个corbastrike payload,我们直接动态调试可获取其CC服务器

在这里插入图片描述

检索这个域名 amajai-technologies.work,就可知道这是一个QakBot家族的恶意样本。

在这里插入图片描述

VT上的搜索结果

在这里插入图片描述

参考资料

QakBot(Qbot)与cobalt Strike恶意流量样本分析 | Demon (ggsec.cn)

Malware-Traffic-Analysis.net - 2020-12-07 - Qakbot (Qbot) infection with Cobalt Strike (Beacon) and spambot activity

反射式dll注入(ReflectiveDLLInjection)_随心动,随风行的博客-CSDN博客_reflectivedllinjection

[原创]PEB结构:获取模块kernel32基址技术及原理分析-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com

Vergilius Project | _LDR_DATA_TABLE_ENTRY
https://github.com/stephenfewer/ReflectiveDLLInjection

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/83944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EC 中的Keyboard Controller

Keyboard Controller简称KBC,它是EC芯片中一个用于处理Keyboard、Mouse的模块,也可以说,它只是一个通道,因为最后处理数据的还是交给EC 8032处理器去处理。KBC只处理挂在EC PS/2接口上的设备,假如接了个usb键盘或鼠标,那可不关它的事。PS/2设备只有两种,即Keyboard和Mou…

React 的设计理念(React 哲学)

文章目录React 的设计理念 的理解解决 CPU 瓶颈解决 IO 瓶颈React 的设计理念 的理解 从 React 官网中的 React 哲学文档中&#xff0c;可以看出 React 目的是实现快速响应 影响快速响应的因素&#xff1a;计算能力和网络延迟&#xff0c;即 CPU 和 IO 的瓶颈 解决 CPU 瓶颈 …

再见 ETH India 2022 建设者们 让我们一起回顾这个美好的建设周

很难超越的1700名黑客马拉松比赛&#xff0c;但是以太坊社区出现并打破了ETH India 2022 的新记录。来自321个城市的2000名与会者在短短的一个周内构建并部署了多达459个项目到以太坊生态系统中。你可能错过了过去一周发生的一切&#xff0c;但幸运的是&#xff0c;我们收集了所…

智能设备带来全新体验,打造未来智能生活

随着科技的快速发展&#xff0c;我们的生活变得越来越智能化&#xff0c;近年来智能设备已经遍布我们生活的各个领域&#xff0c;推动了生产能力和质量&#xff0c;给人们的生活带来了极大的便利。智能设备的出现和发展是时代进步的必然产物&#xff0c;高效、安全、准确性高&a…

【蓝桥杯选拔赛真题50】Scratch小猫跑步 少儿编程scratch图形化编程 蓝桥杯选拔赛真题讲解

目录 scratch小猫跑步 一、题目要求 编程实现 二、案例分析 1、角色分析

mybatis写postgis原生sql需要加强转类型 以及 配置geometry类型转换

mybatis类型转换器处理PostGis数据库geometry类型转换_SomeOtherTime的博客-CSDN博客_java mybatis postgis 在navicate写insert into "district" (name,code,position) VALUES(cesh2i3,ac1v3,SRID4326;MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0))) 不会报错。 在mybat…

[附源码]计算机毕业设计高校学生信息采集系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

虹科案例 | 光热测厚技术助力PSA无底漆涂装方案

法国标致雪铁龙集团&#xff08;PSA Peugeot Citron&#xff09;最开始是生产胡椒研磨机&#xff0c;然后将其产品组合扩展到自行车等&#xff0c;现在已经是欧洲第二大汽车制造商。巴黎郊外的普瓦西&#xff08;Poissy&#xff09; 工厂安装了法国首个紧凑型水性喷漆工艺&…

漏洞预警| ThinkPHP多版本存在远程代码执行漏洞

棱镜七彩安全预警 近日网上有关于开源项目 ThinkPHP 存在远程代码执行漏洞&#xff0c;棱镜七彩威胁情报团队第一时间探测到&#xff0c;经分析研判&#xff0c;向全社会发起开源漏洞预警公告&#xff0c;提醒相关安全团队及时响应。 项目介绍 ThinkPHP是一个快速、兼容而且…

制定项目管理计划的10个步骤

一个协调完美、透明、时间表具体且准确的项目管理计划&#xff0c;将大大有助于你的项目按时完成。以下是制定项目计划的10个基本步骤。 第1步&#xff1a;与利益相关者讨论计划和关键部分 项目计划由活动文件组成&#xff0c;这些文件为所有直接或间接参与项目的人提供指导。…

如何开通股票接口中的StockQuoteRecord功能?

股票接口中的StockQuoteRecord&#xff0c;也就是十档行情快照&#xff0c;在传统的行情软件中只能看到委托数量&#xff0c;而无法知道这些数据是如何形成的。 下面看一下股票接口StockQuoteRecord&#xff08;十档行情快照&#xff09;的说明&#xff1a; 字段名 类型 备…

【数集项目之 MCDF】(三) 仲裁器 arbiter

接下来进行仲裁器 arbiter的设计。根据设计文档&#xff0c;我们知道从输入总共有3个通道&#xff0c;而这三个通道很有可能都接收到数据可以进行发送。而arbiter就是综合优先级、是否有包可以发送等因素&#xff0c;选择一个通道来进行发送。形象的可以将arbiter比喻成“一个多…

FineReport可视化数据分析-图表对象属性

1.概述 1.1 单个系列对象属性 属性 类型 说明 this.points Array 当前系列的所有数据点 this.name String 当前系列的名字&#xff0c;跟图例显示的系列名一致 this.type String 当前系列的图表类型&#xff0c;目前包括的类型如下图所示&#xff1a; 1.2 单个数…

图解TCP_IP 第5版

图解TCP_IP 第5版1.7.1 面向有连接型与面向无连接型1.7.2 电路交换与分组交换1.7.3 单播、广播、多播和任播1.9.1 通信媒介1.9.1 传输速率、带宽和吞吐量1.9.2 网卡1.9.3 中继器与集线器1.9.4 网桥/2 层交换机1.9.5 路由器/3层交换机1.9.6 4~7 层交换机1.9.7 网关2.2.1 TCP/IP …

matplotlib安装及使用

目录 1、Matplotlib简介 2、Matplotlib安装 3、Matplotlib导入 4、Matplotlib基本应用 5、画图种类 5.1、Scatter散点图 5.2、条形图 5.3、等高线图 5.4、Image图片 5.5、3D图像 6、多图合并显示 6.1、Subplot多合一显示 6.2、SubPlot分格显示 6.3、图中图 6.4、…

保护大数据安全的十大行为准则

大数据安全是指在存储、处理和分析过于庞大和复杂的数据集时&#xff0c;采用任何措施来保护数据免受恶意活动的侵害&#xff0c;传统数据库应用程序无法处理这些数据集。大数据可以混合结构化格式(组织成包含数字、日期等的行和列)或非结构化格式(社交媒体数据、PDF 文件、电子…

YourKit Java Profiler 命令行工具自动弹出

YourKit Java Profiler 命令行工具自动弹出 识别处理器和内存从来都不容易。 YourKit为程序开发了两个阶段的开发和开发革命。 YourKit Java Profiler软件的功能和特点&#xff1a; 以任何方式为团队和公司在开发、测试和生产中&#xff0c;以不同的操作系统、本地和远程方式指…

Python多项分布随机数的生成

文章目录二项分布多项分布函数概率密度函数(PDF)备注binomial(n, p)P(k)(nk)pk(1−p)n−kP(k) \binom{n}{k}p^k(1-p)^{n-k}P(k)(kn​)pk(1−p)n−k二项分布poisson([lam])f(k)λke−λk!f(k)\frac{\lambda^ke^{-\lambda}}{k!}f(k)k!λke−λ​泊松分布multinomial(n, pvals)多…

解放双手!推荐一款阿里开源的低代码工具,YYDS!

之前分享过一些低代码相关的文章&#xff0c;发现大家还是比较感兴趣的。之前在我印象中低代码就是通过图形化界面来生成代码而已&#xff0c;其实真正的低代码不仅要负责生成代码&#xff0c;还要负责代码的维护&#xff0c;把它当做一站式开发平台也不为过&#xff01;最近体…

AIOps是什么?为什么用它?

由于快速的数字化转型给 IT 企业组织带来了很大的压力&#xff0c;要求他们更加主动和敏捷&#xff0c;DevOps 原则和实践一直是宝贵的资源。但是&#xff0c;为了保持领先地位&#xff0c;企业需要更强大的解决方案。那么&#xff0c;答案是什么&#xff1f;当然是 AIOps&…